HTTPS и сертификаты
Панель умеет обслуживать HTTPS самостоятельно, без обратного прокси. Сертификат можно взять из файлов, задать прямо в конфигурации или получать автоматически через Let’s Encrypt.
Настройки задаются в config.env — /etc/gameap/config.env в Linux, C:\gameap\web\config.env
в Windows. После изменения нужен перезапуск: gameapctl panel restart.
Источники сертификата
Панель выбирает источник сама, в таком порядке:
- ACME — если заданы
ACME_ENABLED=true,ACME_EMAILиACME_DOMAINS. - Файлы — если заданы
TLS_CERT_FILEиTLS_KEY_FILE. - Значения в конфигурации — если заданы
TLS_CERTиTLS_KEY. - Нет сертификата — панель работает только по HTTP.
Проверяются именно пары: один TLS_CERT_FILE без TLS_KEY_FILE не считается заданным
источником и молча игнорируется.
HTTPS слушается на порту из HTTPS_PORT (по умолчанию 443) и только при наличии сертификата.
HTTP на HTTP_PORT (по умолчанию 8025) работает всегда.
Сертификат панели никак не связан с сертификатами gRPC, по которым панель общается с демонами. Те выпускаются внутренним центром сертификации автоматически, ACME на них не распространяется. Подробнее — GRPC API.
Сертификат из файлов
TLS_CERT_FILE=/etc/gameap/certs/panel.crt
TLS_KEY_FILE=/etc/gameap/certs/panel.key
HTTPS_PORT=443
В файле сертификата должна быть полная цепочка: сам сертификат, затем промежуточные. Без промежуточных часть клиентов не сможет проверить подпись.
Файлы читаются при запуске. После замены сертификата панель нужно перезапустить — сама она изменения в файлах не отслеживает.
Сертификат прямо в конфигурации
Удобно, когда конфигурация раскладывается системой управления секретами и лишние файлы на диске нежелательны.
TLS_CERT=LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...
TLS_KEY=LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0t...
Принимается как обычный PEM, так и PEM в кодировке base64 — панель определяет формат сама.
Поскольку формат config.env не поддерживает многострочные значения, на практике используется
base64:
base64 -w0 panel.crt
base64 -w0 panel.key
Let’s Encrypt
Панель содержит встроенный клиент ACME: сертификат выпускается и продлевается без внешних утилит вроде certbot.
| Переменная | По умолчанию | Назначение |
|---|---|---|
ACME_ENABLED |
false |
Включение автоматического выпуска |
ACME_EMAIL |
"" |
Адрес для уведомлений об истечении. Обязателен |
ACME_DOMAINS |
"" |
Домены через запятую. Обязательны |
ACME_CHALLENGE_TYPE |
http-01 |
Способ подтверждения: http-01 или dns-01 |
ACME_DNS_PROVIDER |
"" |
Провайдер DNS, только для dns-01 |
ACME_DIRECTORY_URL |
боевой ACME | Адрес каталога ACME |
ACME_RENEWAL_THRESHOLD |
720h |
За сколько до истечения продлевать. По умолчанию 30 суток |
ACME_RENEWAL_CHECK_INTERVAL |
12h |
Как часто проверять срок |
ACME_PROPAGATION_TIMEOUT |
180s |
Сколько ждать распространения DNS-записи при dns-01 |
ACME_STORAGE_PATH |
acme |
Каталог для сертификатов и ключа учётной записи ACME |
ACME включается только при одновременно заданных
ACME_ENABLED=true,ACME_EMAILиACME_DOMAINS, а дляdns-01— ещё иACME_DNS_PROVIDER. Если чего-то не хватает, панель запустится без ACME и без ошибки. Проверить, что получилось, можно по состоянию в админке.
Подтверждение по http-01
Способ по умолчанию. Ничего, кроме доступности панели из интернета, не требует.
ACME_ENABLED=true
ACME_EMAIL=admin@example.com
ACME_DOMAINS=panel.example.com
ACME_CHALLENGE_TYPE=http-01
TLS_FORCE_HTTPS=true
Что нужно:
- домены из
ACME_DOMAINSдолжны резолвиться в адрес этого сервера; - запрос на порт 80 должен доходить до панели — центр сертификации обращается именно на него;
- панель обслуживает путь
/.well-known/acme-challenge/самостоятельно, на своём HTTP-порту.
Панель по умолчанию слушает порт 8025, а центр сертификации всегда обращается на 80. Само по себе это не совпадает. Либо задайте
HTTP_PORT=80, либо пробросьте 80-й порт на порт панели средствами системы:iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8025Это самая частая причина, по которой выпуск по
http-01не проходит.
Порт 80 нужен не только при первом выпуске: подтверждение повторяется при каждом продлении, поэтому закрывать его потом нельзя.
Способ http-01 не выпускает сертификаты на поддомены с подстановкой (*.example.com) — для
них нужен dns-01.
Подтверждение по dns-01
Нужен, если панель не доступна из интернета по порту 80 или требуется сертификат с подстановкой.
Из встроенных провайдеров поддерживается только Cloudflare. Остальные подключаются плагинами:
в этом случае в ACME_DNS_PROVIDER указывается <идентификатор-плагина>:<имя-провайдера>.
ACME_ENABLED=true
ACME_EMAIL=admin@example.com
ACME_DOMAINS=panel.example.com,*.example.com
ACME_CHALLENGE_TYPE=dns-01
ACME_DNS_PROVIDER=cloudflare
CLOUDFLARE_DNS_API_TOKEN=токен_из_панели_cloudflare
Токен создаётся в Cloudflare с правом Zone → DNS → Edit для нужной зоны. Кроме
CLOUDFLARE_DNS_API_TOKEN принимаются CF_DNS_API_TOKEN, CLOUDFLARE_API_TOKEN и CF_API_TOKEN,
а также устаревшая пара «глобальный ключ + почта»: CLOUDFLARE_API_KEY вместе с CLOUDFLARE_EMAIL.
Предпочтительнее токен с ограниченными правами.
Если DNS-записи распространяются медленно, увеличьте ACME_PROPAGATION_TIMEOUT.
Настройка через gameapctl
Вместо ручной правки config.env можно воспользоваться мастером:
gameapctl panel letsencrypt setup
Он спросит домены, адрес почты и способ подтверждения, запишет настройки в config.env
и перезапустит панель.
Тот же вызов без вопросов:
gameapctl panel letsencrypt setup --non-interactive \
--domains=panel.example.com \
--email=admin@example.com \
--challenge=http-01
Полезные флаги:
| Флаг | Назначение |
|---|---|
--challenge |
http-01 или dns-01 |
--domains |
Домены через запятую |
--email |
Адрес учётной записи ACME |
--dns-provider |
Провайдер DNS для dns-01 |
--env |
Дополнительные строки КЛЮЧ=ЗНАЧЕНИЕ в config.env — для доступов к DNS |
--staging |
Тестовый каталог Let’s Encrypt |
--non-interactive |
Не задавать вопросов, а завершиться с ошибкой при нехватке параметров |
Отключение:
gameapctl panel letsencrypt disable
Команда удаляет из config.env переменные ACME_* и перезапускает панель. Флаг --purge-certs
объявлен, но пока не реализован — выпущенные сертификаты остаются на диске.
Отладка выпуска
У боевого каталога Let’s Encrypt жёсткие ограничения на число попыток для одного домена, и исчерпать их при настройке легко. Пока настройка не заработала, используйте тестовый каталог:
ACME_DIRECTORY_URL=https://acme-staging-v02.api.letsencrypt.org/directory
Его сертификаты браузер считает недоверенными, зато ограничения несравнимо мягче. Когда выпуск
пройдёт, уберите эту переменную, удалите содержимое каталога из ACME_STORAGE_PATH и перезапустите
панель, чтобы получить боевой сертификат.
Продление
Панель проверяет срок каждые ACME_RENEWAL_CHECK_INTERVAL (по умолчанию раз в 12 часов) и продлевает
сертификат, когда до истечения остаётся меньше ACME_RENEWAL_THRESHOLD (по умолчанию 30 суток).
Отдельная задача в планировщике или cron не нужна.
Сертификаты, ключ учётной записи ACME и служебные данные хранятся в каталоге ACME_STORAGE_PATH
внутри файлового хранилища панели. Если FILES_DRIVER=s3, они попадают в S3 — это то, что позволяет
нескольким экземплярам панели использовать один сертификат.
Состояние сертификата
Текущее состояние доступно администратору по адресу GET /api/admin/letsencrypt/status:
{
"enabled": true,
"state": "active",
"challenge_type": "http-01",
"domains": ["panel.example.com"],
"not_after": "2026-10-30T12:00:00Z",
"last_renewal_at": "2026-08-01T12:00:00Z",
"next_renewal_check_at": "2026-08-02T00:00:00Z"
}
Возможные значения state:
| Значение | Что означает |
|---|---|
disabled |
ACME выключен |
pending |
Сертификат ещё не выпущен |
active |
Сертификат выпущен и действителен |
renewing |
Идёт продление |
failed |
Последняя попытка не удалась, причина в last_error |
Перенаправление на HTTPS
TLS_FORCE_HTTPS=true
Все запросы по HTTP получают перенаправление 301, кроме /.well-known/acme-challenge/ — иначе
подтверждение по http-01 перестало бы работать.
Эта же переменная влияет на два других механизма: заголовок HSTS начинает отдаваться, даже если
TLS завершается на обратном прокси, и адрес источника для CORS вычисляется со схемой https.
Панель за обратным прокси
Если TLS завершается на nginx, Traefik или другом прокси, сертификаты в панели настраивать не нужно
— оставьте ACME_ENABLED=false и не задавайте TLS_*. Панель будет работать по HTTP на 8025,
а прокси — обслуживать HTTPS.
Что при этом важно:
- Прокси должен передавать заголовок
X-Forwarded-Proto: https, иначе панель не поймёт, что соединение защищено, и не отдаст HSTS. - Заголовки
X-Forwarded-Protoи заголовок изAUDIT_CLIENT_IP_HEADERпрокси должен перезаписывать, а не дополнять: панель доверяет им без проверки отправителя. - Порт 31718 через прокси обычно не проходит — демоны должны подключаться к панели напрямую.
Задайте
GRPC_EXTERNAL_HOSTс адресом, по которому панель доступна демонам. - Если публичный адрес отличается от
HTTP_HOST, перечислите его вHTTP_ALLOWED_ORIGINS.
Частые ошибки
| Признак | Причина |
|---|---|
| Панель запустилась, но HTTPS не слушается | Не задана пара переменных целиком либо не хватает одной из обязательных ACME_* |
state: failed при http-01 |
Порт 80 недоступен извне, домен не резолвится в этот сервер или его перехватывает другой сервис |
state: failed при dns-01 |
Нет прав у токена DNS или запись не успела распространиться — увеличьте ACME_PROPAGATION_TIMEOUT |
| Выпуск перестал работать после нескольких попыток | Исчерпан лимит боевого каталога Let’s Encrypt. Перейдите на тестовый каталог и настройте на нём |
| Браузер ругается на цепочку | В TLS_CERT_FILE только сертификат без промежуточных |
| Сертификат заменили, но отдаётся старый | Файлы читаются при запуске — нужен gameapctl panel restart |