{
  "manifest_version": "1.0.0",
  "template": {
    "id": "2c5cdaea-bae6-4cb4-a0ff-9bb3857f86fb",
    "slug": "pterodactyl-game-panel",
    "name": "Pterodactyl | Open Source Game Server Panel",
    "description": "Game server panel, pinned, with your admin account made on first boot.",
    "url": "https://railway.com/deploy/pterodactyl-game-panel",
    "upstream": {
      "image": "ghcr.io/pterodactyl/panel:v1.15.1"
    }
  },
  "services": [
    {
      "name": "Panel",
      "source": {
        "image": "ghcr.io/pterodactyl/panel:v1.15.1"
      },
      "needs_volume": true,
      "volume_mount_path": "/app/var",
      "http": true
    },
    {
      "name": "MariaDB",
      "source": {
        "image": "mariadb:11.8.9"
      },
      "needs_volume": true,
      "volume_mount_path": "/var/lib/mysql",
      "http": false
    },
    {
      "name": "Redis",
      "source": {
        "image": "redis:8.10.1-alpine"
      },
      "needs_volume": false,
      "http": false
    }
  ],
  "required_inputs": [
    {
      "key": "PORT",
      "service": "Panel",
      "description": "Порт, на котором слушает nginx внутри образа. Он зашит в конфигурацию сайта и переменной не читается, поэтому 80 — не настройка, а факт.",
      "secret": false,
      "strategy": "default",
      "default": "80"
    },
    {
      "key": "APP_ENV",
      "service": "Panel",
      "description": "Окружение Laravel. production отключает отладочные подсказки.",
      "secret": false,
      "strategy": "default",
      "default": "production"
    },
    {
      "key": "APP_KEY",
      "service": "Panel",
      "description": "Ключ шифрования Laravel. Им зашифрованы секреты двухфакторной аутентификации и токены узлов. Смена ключа делает их нечитаемыми, и приложение об этом не предупредит.",
      "secret": true,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "APP_URL",
      "service": "Panel",
      "description": "Публичный адрес панели. Отсюда берутся ссылки в письмах и адрес, который панель выдаёт демону Wings в конфигурации узла. Значение с https:// заодно заставляет Laravel строить https-ссылки за прокси Railway.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_domain"
    },
    {
      "key": "DB_HOST",
      "service": "Panel",
      "description": "Адрес MariaDB в приватной сети проекта.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "DB_PORT",
      "service": "Panel",
      "description": "Порт MariaDB.",
      "secret": false,
      "strategy": "default",
      "default": "3306"
    },
    {
      "key": "APP_DEBUG",
      "service": "Panel",
      "description": "Показывать ли трассировку ошибок в браузере. Оставьте false: панель смотрит в интернет, а стектрейс раскрывает пути и переменные.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "LOG_LEVEL",
      "service": "Panel",
      "description": "Порог журналирования. debug у апстрима шумит на каждом запросе.",
      "secret": false,
      "strategy": "default",
      "default": "info"
    },
    {
      "key": "APP_LOCALE",
      "service": "Panel",
      "description": "Язык интерфейса панели.",
      "secret": false,
      "strategy": "default",
      "default": "en"
    },
    {
      "key": "REDIS_HOST",
      "service": "Panel",
      "description": "Адрес Redis в приватной сети проекта.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "railway_private_domain"
    },
    {
      "key": "REDIS_PORT",
      "service": "Panel",
      "description": "Порт Redis.",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    },
    {
      "key": "ADMIN_EMAIL",
      "service": "Panel",
      "description": "Почта администратора. Заменить на свою стоит до первого деплоя: восстановление пароля пойдёт именно на этот адрес.",
      "secret": false,
      "strategy": "default",
      "default": "admin@example.com"
    },
    {
      "key": "CACHE_STORE",
      "service": "Panel",
      "description": "Где панель держит кэш. Redis, а не файлы: файловый кэш пережил бы деплой только на томе.",
      "secret": false,
      "strategy": "default",
      "default": "redis"
    },
    {
      "key": "DB_DATABASE",
      "service": "Panel",
      "description": "Имя базы. Ссылается на сервис MariaDB, менять не нужно.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_PASSWORD",
      "service": "Panel",
      "description": "Пароль базы. Ссылается на сервис MariaDB — оба значения всегда совпадают.",
      "secret": true,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "DB_USERNAME",
      "service": "Panel",
      "description": "Пользователь базы. Ссылается на сервис MariaDB.",
      "secret": false,
      "strategy": "railway_provided",
      "railway_source": "reference_variable"
    },
    {
      "key": "LOG_CHANNEL",
      "service": "Panel",
      "description": "Канал журнала Laravel. stderr — единственный, который виден в логах Railway; значение апстрима (daily) пишет в файл внутри контейнера, куда никто не заглянет.",
      "secret": false,
      "strategy": "default",
      "default": "stderr"
    },
    {
      "key": "MAIL_MAILER",
      "service": "Panel",
      "description": "array принимает письма и выбрасывает. Так сделано осознанно: апстримовский smtp без настроенного сервера роняет в лог полный стектрейс при каждом создании учётной записи. Поставьте smtp — и в админке появится страница «Mail», где задаются сервер, порт и пароль.",
      "secret": false,
      "strategy": "default",
      "default": "array"
    },
    {
      "key": "APP_TIMEZONE",
      "service": "Panel",
      "description": "Часовой пояс расписаний и журналов активности.",
      "secret": false,
      "strategy": "default",
      "default": "UTC"
    },
    {
      "key": "HASHIDS_SALT",
      "service": "Panel",
      "description": "Соль, из которой строятся короткие идентификаторы серверов в адресах. Смена соли меняет адрес каждого сервера — старые ссылки перестанут открываться.",
      "secret": false,
      "strategy": "generate",
      "generate": "random_base64_32"
    },
    {
      "key": "DB_CONNECTION",
      "service": "Panel",
      "description": "Драйвер базы. У Laravel есть отдельный драйвер mariadb, но связку «образ MariaDB + драйвер mysql» использует и тестирует сам Pterodactyl.",
      "secret": false,
      "strategy": "default",
      "default": "mysql"
    },
    {
      "key": "ADMIN_PASSWORD",
      "service": "Panel",
      "description": "Пароль администратора. Сгенерирован для вас — откройте панель и войдите с ним. Смените его внутри панели: шаблон создаёт учётную запись один раз и больше её не трогает.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "ADMIN_USERNAME",
      "service": "Panel",
      "description": "Имя администратора, которого шаблон создаёт при первом запуске. Только строчные буквы, цифры, точка, дефис и подчёркивание.",
      "secret": false,
      "strategy": "default",
      "default": "admin"
    },
    {
      "key": "HASHIDS_LENGTH",
      "service": "Panel",
      "description": "Длина этих идентификаторов.",
      "secret": false,
      "strategy": "default",
      "default": "8"
    },
    {
      "key": "MAIL_FROM_NAME",
      "service": "Panel",
      "description": "Имя отправителя писем панели.",
      "secret": false,
      "strategy": "default",
      "default": "Pterodactyl Panel"
    },
    {
      "key": "SESSION_DRIVER",
      "service": "Panel",
      "description": "Где живут сессии. В Redis — поэтому вход не слетает при обычной работе.",
      "secret": false,
      "strategy": "default",
      "default": "redis"
    },
    {
      "key": "ADMIN_LAST_NAME",
      "service": "Panel",
      "description": "Фамилия администратора в профиле.",
      "secret": false,
      "strategy": "default",
      "default": "Administrator"
    },
    {
      "key": "TRUSTED_PROXIES",
      "service": "Panel",
      "description": "Панель работает за прокси Railway. Без этого Laravel видит адрес прокси вместо адреса посетителя и считает соединение незашифрованным: ломаются и ограничение частоты попыток входа, и проверка капчи.",
      "secret": false,
      "strategy": "default",
      "default": "*"
    },
    {
      "key": "ADMIN_FIRST_NAME",
      "service": "Panel",
      "description": "Имя администратора в профиле.",
      "secret": false,
      "strategy": "default",
      "default": "Panel"
    },
    {
      "key": "QUEUE_CONNECTION",
      "service": "Panel",
      "description": "Очередь фоновых задач: письма, расписания, действия над серверами. Обработчик очереди запущен внутри контейнера панели.",
      "secret": false,
      "strategy": "default",
      "default": "redis"
    },
    {
      "key": "MAIL_FROM_ADDRESS",
      "service": "Panel",
      "description": "Адрес отправителя писем панели.",
      "secret": false,
      "strategy": "default",
      "default": "noreply@example.com"
    },
    {
      "key": "RECAPTCHA_ENABLED",
      "service": "Panel",
      "description": "Капча на форме входа. Pterodactyl поставляет собственную пару публичных ключей, она рабочая — это значение по умолчанию у апстрима. Если капча мешает, поставьте false: страницу настроек, где её можно выключить, вы иначе не откроете, потому что она за входом.",
      "secret": false,
      "strategy": "default",
      "default": "true"
    },
    {
      "key": "APP_SERVICE_AUTHOR",
      "service": "Panel",
      "description": "Адрес, которым подписываются созданные вами яйца (egg) при экспорте. На работу панели не влияет.",
      "secret": false,
      "strategy": "default",
      "default": "noreply@example.com"
    },
    {
      "key": "APP_ENVIRONMENT_ONLY",
      "service": "Panel",
      "description": "false оставляет включённой страницу настроек в админке: название панели, почту и капчу можно менять в браузере, а не переменными. Это же значение стоит в compose-файле самого Pterodactyl.",
      "secret": false,
      "strategy": "default",
      "default": "false"
    },
    {
      "key": "PORT",
      "service": "MariaDB",
      "description": "Порт MariaDB внутри приватной сети проекта.",
      "secret": false,
      "strategy": "default",
      "default": "3306"
    },
    {
      "key": "MARIADB_USER",
      "service": "MariaDB",
      "description": "Пользователь, под которым панель ходит в базу. Создаётся при первом запуске.",
      "secret": false,
      "strategy": "default",
      "default": "pterodactyl"
    },
    {
      "key": "MARIADB_DATABASE",
      "service": "MariaDB",
      "description": "База данных панели. Создаётся при первом запуске; менять после первого деплоя нельзя.",
      "secret": false,
      "strategy": "default",
      "default": "panel"
    },
    {
      "key": "MARIADB_PASSWORD",
      "service": "MariaDB",
      "description": "Пароль этого пользователя. Панель берёт его по ссылке, менять вручную не нужно.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "MARIADB_ROOT_PASSWORD",
      "service": "MariaDB",
      "description": "Пароль root в MariaDB. Панель им не пользуется; нужен только для ручного обслуживания базы.",
      "secret": true,
      "strategy": "generate",
      "generate": "strong_password"
    },
    {
      "key": "PORT",
      "service": "Redis",
      "description": "Порт Redis. Менять незачем — сервис доступен только из приватной сети этого проекта.",
      "secret": false,
      "strategy": "default",
      "default": "6379"
    }
  ],
  "deploy": {
    "mcp": {
      "server": "railway",
      "tool": "deploy_template",
      "args": {
        "template_code": "pterodactyl-game-panel"
      }
    },
    "cli": "railway deploy --template pterodactyl-game-panel",
    "api": {
      "method": "POST",
      "path": "/graphql/v2",
      "body": {
        "query": "mutation templateDeploy($input: TemplateDeployV2Input!) { templateDeployV2(input: $input) { projectId workflowId } }",
        "variables": {
          "input": {
            "templateId": "2c5cdaea-bae6-4cb4-a0ff-9bb3857f86fb",
            "serializedConfig": {
              "buckets": {},
              "services": {
                "6c43fa88-fd3c-49cc-a1b4-decc9d14ac2a": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/pterodactyl.svg",
                  "name": "Panel",
                  "deploy": {
                    "startCommand": "sh -c 'sed -i \"s|^command=/usr/local/sbin/php-fpm -F$|command=/usr/local/sbin/php-fpm -F -O|\" /etc/supervisord.conf; sed -i \"s|^autorestart=true$|autorestart=true\\nstdout_logfile=/dev/stdout\\nstdout_logfile_maxbytes=0\\nstderr_logfile=/dev/stderr\\nstderr_logfile_maxbytes=0|\" /etc/supervisord.conf; printf \"\\ncatch_workers_output = yes\\ndecorate_workers_output = no\\n\" >> /usr/local/etc/php-fpm.conf; ( for i in $(seq 1 60); do n=$(mysql -h \"$DB_HOST\" -P \"$DB_PORT\" -u \"$DB_USERNAME\" -p\"$DB_PASSWORD\" -N -B -e \"select count(*) from users\" \"$DB_DATABASE\" 2>/dev/null) || { sleep 5; continue; }; if [ \"$n\" != \"0\" ]; then echo \"admin bootstrap: $n user(s) already exist, nothing to do\"; break; fi; php /app/artisan p:user:make --admin=1 --email=\"$ADMIN_EMAIL\" --username=\"$ADMIN_USERNAME\" --name-first=\"$ADMIN_FIRST_NAME\" --name-last=\"$ADMIN_LAST_NAME\" --password=\"$ADMIN_PASSWORD\" --no-interaction && break; sleep 5; done ) & exec /bin/ash .github/docker/entrypoint.sh supervisord -n -c /etc/supervisord.conf'",
                    "healthcheckPath": "/auth/login",
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 10
                  },
                  "source": {
                    "image": "ghcr.io/pterodactyl/panel:v1.15.1"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Порт, на котором слушает nginx внутри образа. Он зашит в конфигурацию сайта и переменной не читается, поэтому 80 — не настройка, а факт.",
                      "defaultValue": "80"
                    },
                    "APP_ENV": {
                      "isOptional": false,
                      "description": "Окружение Laravel. production отключает отладочные подсказки.",
                      "defaultValue": "production"
                    },
                    "APP_KEY": {
                      "isOptional": false,
                      "description": "Ключ шифрования Laravel. Им зашифрованы секреты двухфакторной аутентификации и токены узлов. Смена ключа делает их нечитаемыми, и приложение об этом не предупредит.",
                      "defaultValue": "{{APP_KEY}}"
                    },
                    "APP_URL": {
                      "isOptional": false,
                      "description": "Публичный адрес панели. Отсюда берутся ссылки в письмах и адрес, который панель выдаёт демону Wings в конфигурации узла. Значение с https:// заодно заставляет Laravel строить https-ссылки за прокси Railway.",
                      "defaultValue": "https://${{ RAILWAY_PUBLIC_DOMAIN }}"
                    },
                    "DB_HOST": {
                      "isOptional": false,
                      "description": "Адрес MariaDB в приватной сети проекта.",
                      "defaultValue": "${{ MariaDB.RAILWAY_PRIVATE_DOMAIN }}"
                    },
                    "DB_PORT": {
                      "isOptional": false,
                      "description": "Порт MariaDB.",
                      "defaultValue": "3306"
                    },
                    "APP_DEBUG": {
                      "isOptional": false,
                      "description": "Показывать ли трассировку ошибок в браузере. Оставьте false: панель смотрит в интернет, а стектрейс раскрывает пути и переменные.",
                      "defaultValue": "false"
                    },
                    "LOG_LEVEL": {
                      "isOptional": false,
                      "description": "Порог журналирования. debug у апстрима шумит на каждом запросе.",
                      "defaultValue": "info"
                    },
                    "APP_LOCALE": {
                      "isOptional": false,
                      "description": "Язык интерфейса панели.",
                      "defaultValue": "en"
                    },
                    "REDIS_HOST": {
                      "isOptional": false,
                      "description": "Адрес Redis в приватной сети проекта.",
                      "defaultValue": "${{ Redis.RAILWAY_PRIVATE_DOMAIN }}"
                    },
                    "REDIS_PORT": {
                      "isOptional": false,
                      "description": "Порт Redis.",
                      "defaultValue": "6379"
                    },
                    "ADMIN_EMAIL": {
                      "isOptional": false,
                      "description": "Почта администратора. Заменить на свою стоит до первого деплоя: восстановление пароля пойдёт именно на этот адрес.",
                      "defaultValue": "admin@example.com"
                    },
                    "CACHE_STORE": {
                      "isOptional": false,
                      "description": "Где панель держит кэш. Redis, а не файлы: файловый кэш пережил бы деплой только на томе.",
                      "defaultValue": "redis"
                    },
                    "DB_DATABASE": {
                      "isOptional": false,
                      "description": "Имя базы. Ссылается на сервис MariaDB, менять не нужно.",
                      "defaultValue": "${{ MariaDB.MARIADB_DATABASE }}"
                    },
                    "DB_PASSWORD": {
                      "isOptional": false,
                      "description": "Пароль базы. Ссылается на сервис MariaDB — оба значения всегда совпадают.",
                      "defaultValue": "${{ MariaDB.MARIADB_PASSWORD }}"
                    },
                    "DB_USERNAME": {
                      "isOptional": false,
                      "description": "Пользователь базы. Ссылается на сервис MariaDB.",
                      "defaultValue": "${{ MariaDB.MARIADB_USER }}"
                    },
                    "LOG_CHANNEL": {
                      "isOptional": false,
                      "description": "Канал журнала Laravel. stderr — единственный, который виден в логах Railway; значение апстрима (daily) пишет в файл внутри контейнера, куда никто не заглянет.",
                      "defaultValue": "stderr"
                    },
                    "MAIL_MAILER": {
                      "isOptional": false,
                      "description": "array принимает письма и выбрасывает. Так сделано осознанно: апстримовский smtp без настроенного сервера роняет в лог полный стектрейс при каждом создании учётной записи. Поставьте smtp — и в админке появится страница «Mail», где задаются сервер, порт и пароль.",
                      "defaultValue": "array"
                    },
                    "APP_TIMEZONE": {
                      "isOptional": false,
                      "description": "Часовой пояс расписаний и журналов активности.",
                      "defaultValue": "UTC"
                    },
                    "HASHIDS_SALT": {
                      "isOptional": false,
                      "description": "Соль, из которой строятся короткие идентификаторы серверов в адресах. Смена соли меняет адрес каждого сервера — старые ссылки перестанут открываться.",
                      "defaultValue": "{{HASHIDS_SALT}}"
                    },
                    "DB_CONNECTION": {
                      "isOptional": false,
                      "description": "Драйвер базы. У Laravel есть отдельный драйвер mariadb, но связку «образ MariaDB + драйвер mysql» использует и тестирует сам Pterodactyl.",
                      "defaultValue": "mysql"
                    },
                    "ADMIN_PASSWORD": {
                      "isOptional": false,
                      "description": "Пароль администратора. Сгенерирован для вас — откройте панель и войдите с ним. Смените его внутри панели: шаблон создаёт учётную запись один раз и больше её не трогает.",
                      "defaultValue": "{{ADMIN_PASSWORD}}"
                    },
                    "ADMIN_USERNAME": {
                      "isOptional": false,
                      "description": "Имя администратора, которого шаблон создаёт при первом запуске. Только строчные буквы, цифры, точка, дефис и подчёркивание.",
                      "defaultValue": "admin"
                    },
                    "HASHIDS_LENGTH": {
                      "isOptional": false,
                      "description": "Длина этих идентификаторов.",
                      "defaultValue": "8"
                    },
                    "MAIL_FROM_NAME": {
                      "isOptional": false,
                      "description": "Имя отправителя писем панели.",
                      "defaultValue": "Pterodactyl Panel"
                    },
                    "SESSION_DRIVER": {
                      "isOptional": false,
                      "description": "Где живут сессии. В Redis — поэтому вход не слетает при обычной работе.",
                      "defaultValue": "redis"
                    },
                    "ADMIN_LAST_NAME": {
                      "isOptional": false,
                      "description": "Фамилия администратора в профиле.",
                      "defaultValue": "Administrator"
                    },
                    "TRUSTED_PROXIES": {
                      "isOptional": false,
                      "description": "Панель работает за прокси Railway. Без этого Laravel видит адрес прокси вместо адреса посетителя и считает соединение незашифрованным: ломаются и ограничение частоты попыток входа, и проверка капчи.",
                      "defaultValue": "*"
                    },
                    "ADMIN_FIRST_NAME": {
                      "isOptional": false,
                      "description": "Имя администратора в профиле.",
                      "defaultValue": "Panel"
                    },
                    "QUEUE_CONNECTION": {
                      "isOptional": false,
                      "description": "Очередь фоновых задач: письма, расписания, действия над серверами. Обработчик очереди запущен внутри контейнера панели.",
                      "defaultValue": "redis"
                    },
                    "MAIL_FROM_ADDRESS": {
                      "isOptional": false,
                      "description": "Адрес отправителя писем панели.",
                      "defaultValue": "noreply@example.com"
                    },
                    "RECAPTCHA_ENABLED": {
                      "isOptional": false,
                      "description": "Капча на форме входа. Pterodactyl поставляет собственную пару публичных ключей, она рабочая — это значение по умолчанию у апстрима. Если капча мешает, поставьте false: страницу настроек, где её можно выключить, вы иначе не откроете, потому что она за входом.",
                      "defaultValue": "true"
                    },
                    "APP_SERVICE_AUTHOR": {
                      "isOptional": false,
                      "description": "Адрес, которым подписываются созданные вами яйца (egg) при экспорте. На работу панели не влияет.",
                      "defaultValue": "noreply@example.com"
                    },
                    "APP_ENVIRONMENT_ONLY": {
                      "isOptional": false,
                      "description": "false оставляет включённой страницу настроек в админке: название панели, почту и капчу можно менять в браузере, а не переменными. Это же значение стоит в compose-файле самого Pterodactyl.",
                      "defaultValue": "false"
                    }
                  },
                  "networking": {
                    "serviceDomains": {
                      "<hasDomain>:80": {
                        "port": 80
                      }
                    }
                  },
                  "volumeMounts": {
                    "6c43fa88-fd3c-49cc-a1b4-decc9d14ac2a": {
                      "mountPath": "/app/var"
                    }
                  }
                },
                "a72666c5-65a7-4c1e-b43c-bb2eca0638a9": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/mariadb.svg",
                  "name": "MariaDB",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 2
                  },
                  "source": {
                    "image": "mariadb:11.8.9"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Порт MariaDB внутри приватной сети проекта.",
                      "defaultValue": "3306"
                    },
                    "MARIADB_USER": {
                      "isOptional": false,
                      "description": "Пользователь, под которым панель ходит в базу. Создаётся при первом запуске.",
                      "defaultValue": "pterodactyl"
                    },
                    "MARIADB_DATABASE": {
                      "isOptional": false,
                      "description": "База данных панели. Создаётся при первом запуске; менять после первого деплоя нельзя.",
                      "defaultValue": "panel"
                    },
                    "MARIADB_PASSWORD": {
                      "isOptional": false,
                      "description": "Пароль этого пользователя. Панель берёт его по ссылке, менять вручную не нужно.",
                      "defaultValue": "{{MARIADB_PASSWORD}}"
                    },
                    "MARIADB_ROOT_PASSWORD": {
                      "isOptional": false,
                      "description": "Пароль root в MariaDB. Панель им не пользуется; нужен только для ручного обслуживания базы.",
                      "defaultValue": "{{MARIADB_ROOT_PASSWORD}}"
                    }
                  },
                  "volumeMounts": {
                    "a72666c5-65a7-4c1e-b43c-bb2eca0638a9": {
                      "mountPath": "/var/lib/mysql"
                    }
                  }
                },
                "c69031eb-cdfe-4602-ab3e-2a5c2b9d26c6": {
                  "icon": "https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/redis.svg",
                  "name": "Redis",
                  "deploy": {
                    "startCommand": null,
                    "healthcheckPath": null,
                    "restartPolicyType": "ON_FAILURE",
                    "restartPolicyMaxRetries": 2
                  },
                  "source": {
                    "image": "redis:8.10.1-alpine"
                  },
                  "variables": {
                    "PORT": {
                      "isOptional": false,
                      "description": "Порт Redis. Менять незачем — сервис доступен только из приватной сети этого проекта.",
                      "defaultValue": "6379"
                    }
                  },
                  "haTemplateCode": "redis-ha",
                  "haConversionConfig": {
                    "edge": {
                      "label": "Reverse Proxies",
                      "options": [
                        1,
                        2
                      ],
                      "nodeLabel": "HAProxy",
                      "description": "HAProxy instances routing writes to the primary",
                      "defaultValue": 2
                    },
                    "replica": {
                      "label": "Redis Replicas",
                      "options": [
                        2,
                        3,
                        4,
                        5
                      ],
                      "nodeLabel": "Redis",
                      "description": "Nodes running Redis + colocated Sentinel",
                      "defaultValue": 2
                    },
                    "internal": null,
                    "description": "This will convert your Redis instance to an HA cluster with Sentinel failover and HAProxy routing to the primary."
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "post_deploy": {
    "healthcheck": {
      "service": "Panel",
      "method": "GET",
      "path": "/auth/login",
      "expect_status": 200
    }
  },
  "resources": {
    "expected_services": 3,
    "needs_volume": true
  },
  "generated_at": "2026-09-19T16:14:39.735Z",
  "generator_version": "0.1.0",
  "status": "validated",
  "validated_at": "2026-09-19T19:21:22.364Z",
  "success_rate_30d": 1,
  "validation": {
    "last_run_id": "run_05c32846af1c4447995f",
    "checks": [
      {
        "name": "workflow_completed",
        "passed": true
      },
      {
        "name": "all_services_deployed",
        "passed": true
      },
      {
        "name": "healthcheck",
        "passed": true
      },
      {
        "name": "stays_up",
        "passed": true
      }
    ],
    "typical_ready_seconds": 87,
    "typical_build_seconds": 0,
    "typical_start_seconds": 20,
    "slowest_service": "Panel"
  }
}
