{
  "meta": {
    "version": "PTDL_v2",
    "update_url": null
  },
  "exported_at": "2026-08-14T17:36:04+00:00",
  "name": "Modrinth",
  "author": "contact@chromozone.dev",
  "description": "Egg generico para modpacks de Modrinth.",
  "features": [
    "eula",
    "java_version",
    "pid_limit"
  ],
  "container_version_map": [
    {
      "version": "latest",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.11",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.10",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.9",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.8",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.7",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.6",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.5",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.3",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.21",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.20.6",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.20.5",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_21"
    },
    {
      "version": "1.20.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.20.3",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.20.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.20.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.20",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.19.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.19.3",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.19.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.19.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.19",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.18.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.18.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.18",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_17"
    },
    {
      "version": "1.17.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_16"
    },
    {
      "version": "1.17",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_16"
    },
    {
      "version": "1.16.5",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.16.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.16.3",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.16.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.16.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.16",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.15.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.15.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.15",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.14.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.14.3",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.14.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.14.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.14",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.13.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.13.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.13",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.12.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.12.1",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.12",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.11.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.10.2",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.9.4",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.8.9",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.8.8",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    },
    {
      "version": "1.7.10",
      "docker_image": "ghcr.io/ptero-eggs/yolks:java_8"
    }
  ],
  "file_denylist": [],
  "startup": "java $([[ -f user_jvm_args.txt ]] && printf %s \"@user_jvm_args.txt\") -Xms128M -Xmx{{SERVER_MEMORY}}M -Dterminal.jline=false -Dterminal.ansi=true $([[ ! -f unix_args.txt ]] && printf %s \"-jar `cat .serverjar`\" || printf %s \"@unix_args.txt\")",
  "config": {
    "files": "{\n    \"server.properties\": {\n        \"parser\": \"properties\",\n        \"find\": {\n            \"server-ip\": \"0.0.0.0\",\n            \"server-port\": \"{{server.build.default.port}}\",\n            \"query.port\": \"{{server.build.default.port}}\"\n        }\n    }\n}",
    "startup": "{\"done\":\")! For help, type\"}",
    "logs": "{}",
    "stop": "stop"
  },
  "scripts": {
    "installation": {
      "script": "#!/bin/bash\n# shellcheck disable=SC2155\n# Modrinth Installation Script\n# Server Files: /mnt/server\n\nset -euo pipefail\n\n: \"${SERVER_DIR:=/mnt/server}\"\n: \"${PROJECT_ID:=}\"\n: \"${VERSION_ID:=}\"\n: \"${PAT:=}\"\n\nAUTH_HEADER=()\nif [[ -n \"${PAT}\" ]]; then\n  AUTH_HEADER=(--header=\"Authorization: ${PAT}\")\nfi\n\nif [[ ! -d \"${SERVER_DIR}\" ]]; then\n  mkdir -p \"${SERVER_DIR}\"\nfi\n\nif ! cd \"${SERVER_DIR}\"; then\n  echo \"No se pudo entrar a ${SERVER_DIR}\"\n  exit 1\nfi\n\ninstall_required() {\n  echo \"Instalando paquetes requeridos...\"\n  apt update > /dev/null 2>&1 || { echo \"ERROR: apt update fallo\"; exit 1; }\n  apt install -y wget jq unzip dos2unix > /dev/null 2>&1 || { echo \"ERROR: apt install fallo\"; exit 1; }\n}\n\nMODRINTH_API_URL=\"https://api.modrinth.com/v2\"\n\nget_download() {\n  echo \"Obteniendo informacion del proyecto de Modrinth...\"\n  local PROJECT_DATA\n  PROJECT_DATA=$(wget -q \"${AUTH_HEADER[@]}\" \"${MODRINTH_API_URL}/project/${PROJECT_ID}\" -O -)\n  local PROJECT_TITLE\n  PROJECT_TITLE=$(echo \"${PROJECT_DATA}\" | jq -r '.title // empty')\n  local PROJECT_SUPPORTED\n  PROJECT_SUPPORTED=$(echo \"${PROJECT_DATA}\" | jq -r '.\"server_side\" // empty')\n\n  if [[ -z \"${PROJECT_DATA}\" ]]; then\n    echo \"ERROR: no se pudo obtener informacion del proyecto '${PROJECT_ID}'\"\n    exit 1\n  fi\n\n  if [[ \"${PROJECT_SUPPORTED}\" == \"unsupported\" ]]; then\n    echo \"WARNING: el proyecto '${PROJECT_TITLE}' esta marcado como no soportado para servidor\"\n  fi\n\n  if [[ -z \"${VERSION_ID}\" || \"${VERSION_ID}\" == \"latest\" ]]; then\n    if [[ -n \"${MINECRAFT_VERSION:-}\" && \"${MINECRAFT_VERSION}\" != \"latest\" ]]; then\n      local VERSIONS_DATA\n      VERSIONS_DATA=$(wget -q \"${AUTH_HEADER[@]}\" \"${MODRINTH_API_URL}/project/${PROJECT_ID}/version?game_versions=%5B%22${MINECRAFT_VERSION}%22%5D\" -O - || true)\n      if [[ -n \"${VERSIONS_DATA}\" ]]; then\n        VERSION_ID=$(echo \"${VERSIONS_DATA}\" | jq -r '.[0].id // empty')\n      fi\n    fi\n    if [[ -z \"${VERSION_ID}\" || \"${VERSION_ID}\" == \"latest\" ]]; then\n      VERSION_ID=$(echo \"${PROJECT_DATA}\" | jq -r '.versions[-1] // empty')\n    fi\n    echo \"Usando la version: ${VERSION_ID}\"\n  else\n    if [[ $(echo \"${PROJECT_DATA}\" | jq -r --arg VERSION_ID \"${VERSION_ID}\" '.versions[]? | select(. == $VERSION_ID)') != \"${VERSION_ID}\" ]]; then\n      echo \"ERROR: version id '${VERSION_ID}' no encontrada\"\n      exit 1\n    fi\n  fi\n\n  if [[ -z \"${VERSION_ID}\" ]]; then\n    echo \"ERROR: no se encontro version para '${PROJECT_TITLE}'\"\n    exit 1\n  fi\n\n  local JSON_DATA\n  JSON_DATA=$(wget -q \"${AUTH_HEADER[@]}\" \"${MODRINTH_API_URL}/version/${VERSION_ID}\" -O -)\n  local DOWNLOAD_URL\n  DOWNLOAD_URL=$(echo \"${JSON_DATA}\" | jq -r '.files[]? | select(.primary == true) | .url')\n\n  if [[ -z \"${DOWNLOAD_URL}\" ]]; then\n    echo \"ERROR: no hay URL de descarga para ${VERSION_ID}\"\n    exit 1\n  fi\n\n  echo \"Descargando ${DOWNLOAD_URL}\"\n  wget -q \"${AUTH_HEADER[@]}\" \"${DOWNLOAD_URL}\" -O server.zip || { echo \"ERROR: fallo al descargar server.zip\"; exit 1; }\n}\n\nunpack_zip() {\n  unzip -o server.zip\n  rm -f server.zip\n}\n\njson_download_mods() {\n  echo \"Descargando mods...\"\n  local MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n  jq -c '.files[]? | select(.env.server == \"required\") | {name: .path, url: .downloads[0]}' \"${MANIFEST}\" | while read -r mod; do\n    local FILE_URL\n    FILE_URL=$(echo \"${mod}\" | jq -r '.url // empty')\n    local FILE_NAME\n    FILE_NAME=$(echo \"${mod}\" | jq -r '.name // empty')\n\n    [[ -z \"${FILE_URL}\" ]] && { echo \"ERROR: sin URL para mod ${FILE_NAME}\"; exit 1; }\n    wget -q \"${AUTH_HEADER[@]}\" \"${FILE_URL}\" -P \"${SERVER_DIR}/mods\" || { echo \"ERROR: fallo al descargar mod ${FILE_NAME}\"; exit 1; }\n  done\n}\n\njson_download_overrides() {\n  echo \"Copiando overrides...\"\n  if [[ -d \"${SERVER_DIR}/overrides\" ]]; then\n    chmod -R 755 \"${SERVER_DIR}/overrides/\"*\n    cp -r \"${SERVER_DIR}/overrides/\"* \"${SERVER_DIR}\"\n    rm -r \"${SERVER_DIR}/overrides\"\n  fi\n\n  if [[ -d \"${SERVER_DIR}/server-overrides\" ]]; then\n    chmod -R 755 \"${SERVER_DIR}/server-overrides/\"*\n    cp -r \"${SERVER_DIR}/server-overrides/\"* \"${SERVER_DIR}\"\n    rm -r \"${SERVER_DIR}/server-overrides\"\n  fi\n}\n\njson_download_forge() {\n  echo \"Instalando Forge...\"\n  local MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n  local MC_VERSION\n  MC_VERSION=$(jq -r '.dependencies.minecraft // empty' \"${MANIFEST}\")\n  local RAW_FORGE_VERSION\n  RAW_FORGE_VERSION=$(jq -r '.dependencies.forge // empty' \"${MANIFEST}\")\n\n  [[ -z \"${MC_VERSION}\" || -z \"${RAW_FORGE_VERSION}\" ]] && { echo \"ERROR: dependencias Forge incompletas\"; exit 1; }\n\n  local MC_MAJOR_MINOR\n  MC_MAJOR_MINOR=$(echo \"${MC_VERSION}\" | cut -d. -f1,2)\n\n  FORGE_VERSION=\"${MC_VERSION}-${RAW_FORGE_VERSION}\"\n  if [[ \"${MC_VERSION}\" == \"1.7.10\" || \"${MC_VERSION}\" == \"1.8.9\" ]]; then\n    FORGE_VERSION=\"${FORGE_VERSION}-${MC_VERSION}\"\n  fi\n\n  local FORGE_JAR=\"forge-${FORGE_VERSION}.jar\"\n  [[ \"${MC_VERSION}\" == \"1.7.10\" ]] && FORGE_JAR=\"forge-${FORGE_VERSION}-universal.jar\"\n\n  local FORGE_URL=\"https://maven.minecraftforge.net/net/minecraftforge/forge/${FORGE_VERSION}/forge-${FORGE_VERSION}\"\n  if ! wget -q -O forge-installer.jar \"${FORGE_URL}-installer.jar\"; then\n    local ALT1=\"${FORGE_VERSION}-${MC_VERSION}\"\n    local ALT1_URL=\"https://maven.minecraftforge.net/net/minecraftforge/forge/${ALT1}/forge-${ALT1}\"\n    if wget -q -O forge-installer.jar \"${ALT1_URL}-installer.jar\"; then\n      FORGE_VERSION=\"${ALT1}\"\n    else\n      local ALT2=\"${MC_MAJOR_MINOR}-${RAW_FORGE_VERSION}\"\n      local ALT2_URL=\"https://maven.minecraftforge.net/net/minecraftforge/forge/${ALT2}/forge-${ALT2}\"\n      wget -q -O forge-installer.jar \"${ALT2_URL}-installer.jar\" || { echo \"ERROR: no se pudo descargar instalador Forge\"; exit 1; }\n      FORGE_VERSION=\"${ALT2}\"\n    fi\n  fi\n\n  rm -rf libraries/net/minecraftforge/forge/\n  rm -f unix_args.txt\n\n  java -jar forge-installer.jar --installServer || { echo \"ERROR: fallo instalacion Forge\"; exit 1; }\n\n  if [[ $MC_VERSION =~ ^1\\.(17|18|19|20|21|22|23) || $FORGE_VERSION =~ ^1\\.(17|18|19|20|21|22|23) ]]; then\n    ln -sf libraries/net/minecraftforge/forge/*/unix_args.txt unix_args.txt\n  else\n    local GENERATED_JAR\n    GENERATED_JAR=$(ls forge-${FORGE_VERSION}*.jar 2>/dev/null | head -n 1 || true)\n    if [[ -n \"${GENERATED_JAR}\" ]]; then\n      mv \"${GENERATED_JAR}\" forge-server-launch.jar\n    else\n      mv \"${FORGE_JAR}\" forge-server-launch.jar\n    fi\n    echo \"forge-server-launch.jar\" > .serverjar\n  fi\n\n  rm -f forge-installer.jar\n}\n\njson_download_fabric() {\n  echo \"Instalando Fabric...\"\n  local MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n  local MC_VERSION\n  MC_VERSION=$(jq -r '.dependencies.minecraft // empty' \"${MANIFEST}\")\n  local FABRIC_VERSION\n  FABRIC_VERSION=$(jq -r '.dependencies.\"fabric-loader\" // empty' \"${MANIFEST}\")\n\n  [[ -z \"${MC_VERSION}\" || -z \"${FABRIC_VERSION}\" ]] && { echo \"ERROR: dependencias Fabric incompletas\"; exit 1; }\n\n  local INSTALLER_JSON\n  INSTALLER_JSON=$(wget -q -O - https://meta.fabricmc.net/v2/versions/installer)\n  local INSTALLER_URL\n  INSTALLER_URL=$(echo \"${INSTALLER_JSON}\" | jq -r '.[0].url // empty')\n\n  [[ -z \"${INSTALLER_URL}\" ]] && { echo \"ERROR: sin URL de instalador Fabric\"; exit 1; }\n\n  wget -q -O fabric-installer.jar \"${INSTALLER_URL}\" || { echo \"ERROR: fallo descarga instalador Fabric\"; exit 1; }\n  java -jar fabric-installer.jar server -mcversion \"${MC_VERSION}\" -loader \"${FABRIC_VERSION}\" -downloadMinecraft || { echo \"ERROR: fallo instalacion Fabric\"; exit 1; }\n\n  echo \"fabric-server-launch.jar\" > .serverjar\n  rm -f fabric-installer.jar\n}\n\njson_download_quilt() {\n  echo \"Instalando Quilt...\"\n  local MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n  local MC_VERSION\n  MC_VERSION=$(jq -r '.dependencies.minecraft // empty' \"${MANIFEST}\")\n  local QUILT_VERSION\n  QUILT_VERSION=$(jq -r '.dependencies.\"quilt-loader\" // empty' \"${MANIFEST}\")\n\n  [[ -z \"${MC_VERSION}\" || -z \"${QUILT_VERSION}\" ]] && { echo \"ERROR: dependencias Quilt incompletas\"; exit 1; }\n\n  local INSTALLER_JSON\n  INSTALLER_JSON=$(wget -q -O - https://meta.quiltmc.org/v3/versions/installer)\n  local INSTALLER_URL\n  INSTALLER_URL=$(echo \"${INSTALLER_JSON}\" | jq -r '.[0].url // empty')\n\n  [[ -z \"${INSTALLER_URL}\" ]] && { echo \"ERROR: sin URL de instalador Quilt\"; exit 1; }\n\n  wget -q -O quilt-installer.jar \"${INSTALLER_URL}\" || { echo \"ERROR: fallo descarga instalador Quilt\"; exit 1; }\n  java -jar quilt-installer.jar install server \"${MC_VERSION}\" \"${QUILT_VERSION}\" --download-server --install-dir=./ || { echo \"ERROR: fallo instalacion Quilt\"; exit 1; }\n\n  echo \"quilt-server-launch.jar\" > .serverjar\n  rm -f quilt-installer.jar\n}\n\ninstall_required\n\nif [[ -z \"${PROJECT_ID}\" ]]; then\n  echo \"ERROR: debes definir PROJECT_ID\"\n  exit 1\nfi\n\nif [[ \"${PROJECT_ID}\" != \"zip\" ]]; then\n  get_download\n  unpack_zip\nelse\n  unpack_zip\nfi\n\nif [[ -f \"${SERVER_DIR}/modrinth.index.json\" ]]; then\n  json_download_mods\n  json_download_overrides\n\n  MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n  if [[ $(jq -r '.dependencies.forge' \"${MANIFEST}\") != \"null\" ]]; then\n    json_download_forge\n  fi\n  if [[ $(jq -r '.dependencies.\"fabric-loader\"' \"${MANIFEST}\") != \"null\" ]]; then\n    json_download_fabric\n  fi\nfi\n\nexport_minecraft_version() {\n  if [[ -z \"${MINECRAFT_VERSION:-}\" ]]; then\n    local MANIFEST=\"${SERVER_DIR}/modrinth.index.json\"\n    if [[ -f \"${MANIFEST}\" ]]; then\n      MINECRAFT_VERSION=$(jq -r '.dependencies.minecraft // empty' \"${MANIFEST}\")\n    fi\n  fi\n\n  if [[ -n \"${MINECRAFT_VERSION:-}\" ]]; then\n    export MINECRAFT_VERSION\n    echo \"MINECRAFT_VERSION=${MINECRAFT_VERSION}\" >> \"${SERVER_DIR}/.env\" 2>/dev/null || true\n    echo \"MINECRAFT_VERSION exportada: ${MINECRAFT_VERSION}\"\n  fi\n}\n\nexport_minecraft_version\n\necho\necho \"Instalacion completada correctamente\"\n\n",
      "container": "eclipse-temurin:17-jdk",
      "entrypoint": "bash"
    }
  },
  "variables": [
    {
      "name": "Minecraft Version",
      "description": "Versión de Minecraft determinada en la instalación.",
      "env_variable": "MINECRAFT_VERSION",
      "default_value": "latest",
      "user_viewable": false,
      "user_editable": false,
      "rules": "nullable|string",
      "field_type": "text",
      "source": "installation",
      "defines_version": true
    },
    {
      "name": "Modpack Project ID",
      "description": "ID del proyecto en Modrinth. Por ejemplo, para https://modrinth.com/modpack/fabulously-optimized/ el ID es 1KVo5zza.",
      "env_variable": "PROJECT_ID",
      "default_value": "",
      "user_viewable": true,
      "user_editable": true,
      "rules": "required|string|max:8",
      "field_type": "text",
      "source": "user"
    },
    {
      "name": "Modpack Version ID",
      "description": "ID de la version del modpack en Modrinth. Por ejemplo, para /version/4.7.4 el ID puede ser P9wA6exe. Usa latest para la mas reciente.",
      "env_variable": "VERSION_ID",
      "default_value": "latest",
      "user_viewable": true,
      "user_editable": true,
      "rules": "string|max:8",
      "field_type": "text",
      "source": "user"
    },
    {
      "name": "Modrinth PAT",
      "description": "Personal Access Token de Modrinth para acceder a modpacks privados.",
      "env_variable": "PAT",
      "default_value": "",
      "user_viewable": true,
      "user_editable": true,
      "rules": "nullable|string",
      "field_type": "text",
      "source": "user"
    }
  ]
}
