Skip to content

Latest commit

 

History

History
365 lines (281 loc) · 27.8 KB

https.md

File metadata and controls

365 lines (281 loc) · 27.8 KB
title HTTPS и сертификаты
description HTTPS для панели GameAP: самоподписанный сертификат командой gameapctl panel https, сертификат из файлов, автоматический выпуск через Let’s Encrypt по http-01 и dns-01, продление и работа за обратным прокси.
layout default
lang ru
category Администрирование
order 333

Панель умеет обслуживать HTTPS самостоятельно, без обратного прокси. Сертификат можно взять из файлов, задать прямо в конфигурации или получать автоматически через Let's Encrypt. Быстрее всего начать с самоподписанного сертификата, который выпускается одной командой gameapctl, — см. Настройка через gameapctl.

Настройки задаются в config.env — /etc/gameap/config.env в Linux (~/.config/gameap/config.env при установке без root), C:\gameap\web\config.env в Windows. После изменения нужен перезапуск: gameapctl panel restart.

Источники сертификата

Панель выбирает источник сама, в таком порядке:

  1. ACME — если заданы ACME_ENABLED=true, ACME_EMAIL и ACME_DOMAINS.
  2. Файлы — если заданы TLS_CERT_FILE и TLS_KEY_FILE.
  3. Значения в конфигурации — если заданы TLS_CERT и TLS_KEY.
  4. Нет сертификата — панель работает только по HTTP.

Проверяются именно пары: один TLS_CERT_FILE без TLS_KEY_FILE не считается заданным источником и молча игнорируется.

gameapctl соблюдает тот же порядок: gameapctl panel https enable отказывается работать при настроенном ACME, потому что панель всё равно проигнорирует сертификат на диске, а gameapctl panel https disable выключает и то и другое.

HTTPS слушается на порту из HTTPS_PORT (по умолчанию 443) и только при наличии сертификата. HTTP на HTTP_PORT работает всегда. Собственное значение панели для HTTP_PORT — 8025, но gameapctl panel install записывает HTTP_PORT=80 при системной установке и HTTP_PORT=8025 при пользовательской — какой порт использует именно ваша установка, смотрите в config.env.

Сертификат панели никак не связан с сертификатами gRPC, по которым панель общается с демонами. Те выпускаются внутренним центром сертификации автоматически, ACME на них не распространяется. Подробнее — GRPC API.

Настройка через gameapctl

Панель завершает TLS сама, поэтому настраивать веб-сервер не нужно. Одна команда выпускает самоподписанный сертификат, прописывает его в config.env и перезапускает панель:

gameapctl panel https enable
gameapctl panel https status
gameapctl panel https disable

Сертификат покрывает настроенный HTTP_HOST, имя хоста машины, все адреса её сетевых интерфейсов и loopback (localhost, 127.0.0.1, ::1); срок действия — 825 дней. Повторный запуск оставляет сертификат, который всё ещё покрывает все запрошенные имена и не истекает в ближайшее время, — исключение, уже принятое в браузере, сохраняется. Поскольку сертификат самоподписанный, браузеры не доверяют ему, пока он не добавлен в хранилище доверенных сертификатов на каждой машине, с которой открывают панель; скопируйте его по пути, который печатает status.

Собственный сертификат подставляется флагами --cert и --key. Файлы остаются на месте — укажите флагами рабочие файлы внешнего ACME-клиента, и панель подхватит каждое продление при перезапуске.

Флаг Назначение
--cert Путь к PEM-сертификату вместо самоподписанного; требует --key
--key Путь к закрытому ключу для --cert
--domain Домен, который должен покрывать сертификат. Повторяемый; заменяет обнаруженные имена
--ip IP-адрес, который должен покрывать сертификат. Повторяемый; заменяет обнаруженные адреса
--port Порт HTTPS: 443, с --scope=user — 8443
--days Срок действия самоподписанного сертификата в днях, по умолчанию 825
--force-https Перенаправлять HTTP-запросы на HTTPS (TLS_FORCE_HTTPS). Без флага остаётся как настроено
--force Перевыпустить самоподписанный сертификат, даже если текущий ещё подходит
--scope Область установки, system или user; по умолчанию определяется по состоянию установки

HTTP продолжает отвечать на своём порту. Включайте --force-https только когда уверены, что порт HTTPS доступен, — иначе вы потеряете доступ к панели отовсюду, где цель перенаправления заблокирована.

Оба слушателя обслуживает один процесс, и панель завершается, если не может загрузить сертификат, на который настроена. Поэтому enable проверяет, что панель поднялась и отдаёт именно тот сертификат, который только что записан, а если нет — возвращает предыдущий config.env и перезапускает панель с ним.

disable удаляет переменные TLS из config.env (а если действует ACME — и переменные ACME_*) и перезапускает панель на обычном HTTP. disable --purge дополнительно удаляет сертификат и ключ, выпущенные gameapctl; сертификат, переданный через --cert, не трогается.

status печатает область установки, путь к конфигурации, адреса HTTP и HTTPS, источник сертификата, фактически отдаваемый сертификат и срок его действия.

Где gameapctl хранит выпущенный сертификат:

Область Сертификат Закрытый ключ Порт по умолчанию
system /etc/gameap/certs/panel.crt /etc/gameap/certs/panel.key 443
user ~/.config/gameap/certs/panel.crt ~/.config/gameap/certs/panel.key 8443
Windows C:\gameap\web\certs\panel.crt C:\gameap\web\certs\panel.key 443

Сертификат из файлов

TLS_CERT_FILE=/etc/gameap/certs/panel.crt
TLS_KEY_FILE=/etc/gameap/certs/panel.key
HTTPS_PORT=443

Это пути, которые gameapctl использует сам при системной установке; при пользовательской — ~/.config/gameap/certs/, в Windows — C:\gameap\web\certs. Вместо ручной правки config.env подключайте собственный сертификат командой gameapctl panel https enable --cert=<путь> --key=<путь> — она записывает переменные и затем проверяет, что панель поднялась и отдаёт этот сертификат, а при неудаче откатывает конфигурацию. Без такой проверки неверная пара останавливает панель: она завершается, если не может загрузить настроенный сертификат.

В файле сертификата должна быть полная цепочка: сам сертификат, затем промежуточные. Без промежуточных часть клиентов не сможет проверить подпись.

Файлы читаются при запуске. После замены сертификата панель нужно перезапустить — сама она изменения в файлах не отслеживает.

Сертификат прямо в конфигурации

Удобно, когда конфигурация раскладывается системой управления секретами и лишние файлы на диске нежелательны.

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=[email protected]
ACME_DOMAINS=panel.example.com
ACME_CHALLENGE_TYPE=http-01
TLS_FORCE_HTTPS=true

Что нужно:

  • домены из ACME_DOMAINS должны резолвиться в адрес этого сервера;
  • запрос на порт 80 должен доходить до панели — центр сертификации обращается именно на него;
  • панель обслуживает путь /.well-known/acme-challenge/ самостоятельно, на своём HTTP-порту.

Центр сертификации всегда обращается на порт 80. Установка, выполненная gameapctl panel install в системной области, уже слушает его (HTTP_PORT=80). Если панель на другом порту — собственное значение панели 8025, а установщик при занятом 80-м берёт первый свободный из 8025, 8026, … — проверьте HTTP_PORT в config.env и либо задайте HTTP_PORT=80, либо пробросьте 80-й порт на порт панели средствами системы:

iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8025

Вместо 8025 в --to-port подставьте значение HTTP_PORT из config.env.

Такое правило живёт только до перезагрузки. Сохраните его штатными средствами файрвола дистрибутива — теми, что восстанавливают правила при загрузке, — либо вместо проброса поставьте перед панелью обратный прокси, слушающий 80-й порт.

Порт 80 нужен не только при первом выпуске: подтверждение повторяется при каждом продлении, поэтому закрывать его потом нельзя.

При установке без root панель не может занять порт 80 сама — непривилегированному процессу это не разрешено. Подтверждение всё равно проходит, если 80-й порт проброшен на HTTP-порт панели или перед панелью стоит обратный прокси: путь /.well-known/acme-challenge/ панель обслуживает на своём HTTP-порту. Если проброса нет, используйте там dns-01.

Способ http-01 не выпускает сертификаты на поддомены с подстановкой (*.example.com) — для них нужен dns-01.

Подтверждение по dns-01

Нужен, если панель не доступна из интернета по порту 80 или требуется сертификат с подстановкой.

Из встроенных провайдеров поддерживается только Cloudflare. Остальные подключаются плагинами: в этом случае в ACME_DNS_PROVIDER указывается <идентификатор-плагина>:<имя-провайдера>.

ACME_ENABLED=true
ACME_EMAIL=[email protected]
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.

Let's Encrypt через gameapctl

Вместо ручной правки config.env можно воспользоваться мастером:

gameapctl panel https letsencrypt setup

Он спросит домены, адрес почты и способ подтверждения, запишет настройки в config.env и перезапустит панель.

Раньше команда называлась gameapctl panel letsencrypt. Эта форма пока работает как устаревший псевдоним, но в --help не показывается; используйте gameapctl panel https letsencrypt.

Тот же вызов без вопросов:

gameapctl panel https letsencrypt setup --non-interactive \
  --domains=panel.example.com \
  [email protected] \
  --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 Не задавать вопросов, а завершиться с ошибкой при нехватке параметров
--scope Область установки, system или user; по умолчанию определяется по состоянию установки

Отключение:

gameapctl panel https 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 на HTTP_PORT, а прокси — обслуживать 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
gameapctl panel https enable завершается с «ACME is enabled» ACME имеет приоритет над сертификатом на диске. Сначала выполните gameapctl panel https letsencrypt disable
Панель не запускается после ручной правки TLS_* Она не может загрузить настроенный сертификат или ключ. Исправьте пару или уберите переменные; gameapctl panel https enable --cert=<путь> --key=<путь> избегает этого, проверяя результат и откатывая изменения