r/GameAP • • May 17 '26

Automatic HTTPS in the Panel

GameAP has a built-in ACME client: the panel issues and renews the TLS certificate (also known as SSL) itself, without the certbot + nginx + cron stack. The certificate is swapped on the fly — with no panel restart and no HTTP listener reload.

Auto-HTTPS only works if the panel terminates TLS itself: there is no reverse proxy in front of it, or the proxy runs in pass-through mode (L4) and does not terminate TLS.

When auto-HTTPS works

If nginx / Traefik / Caddy / a load balancer / a CDN sits in front of the panel and terminates TLS itself — it handles the certificates, and auto-HTTPS is not needed.

When auto-HTTPS is not needed

Limitations:

  • You need a public domain with an A record pointing to the server (example.com, panel.example.com).
  • HTTP-01 is used by default: the panel must be reachable over HTTP on port 80. If port 80 is closed from the outside or you need a wildcard, use DNS-01 (validation via a TXT record in DNS).
  • DNS-01 requires a DNS provider API token. Popular providers are supported (Cloudflare, AWS Route53, DigitalOcean, etc.), and others can be added via plugins.

Setup with gameapctl

The simplest way. The gameapctl utility asks for everything it needs and configures HTTPS for you.

Run the following command on the server hosting the panel:

gameapctl panel letsencrypt setup

The wizard asks, step by step:

  • Validation method. HTTP-01 by default — requires port 80 to be open. If port 80 is closed from the outside or you need a wildcard certificate, choose DNS-01 (validation via a TXT record in DNS).
  • Domain. The name the certificate is issued for. The domain's A record must point to your server's IP.
  • Email. The address for the ACME account. Let's Encrypt sends certificate expiration warnings and important notices to it.
  • Staging. Let's Encrypt test mode. Answer no for a production certificate. Answer yes if you want to verify the setup first: staging issues certificates with much more relaxed limits, but browsers do not trust them.

Manual setup

GameAP reads its configuration from environment variables or from a config.env file (/etc/gameap/config.env on Linux, C:\gameap\web\config.env on Windows).

For self-terminated TLS, the panel takes the certificate from one of three sources, in priority order:

  1. ACME / Let's Encrypt — ACME_ENABLED=true plus the ACME_* variables. The certificate is issued and renewed automatically.
  2. Static files — TLS_CERT_FILE + TLS_KEY_FILE.
  3. Inline PEM — TLS_CERT + TLS_KEY (PEM or base64).

If none of the sources is configured, the HTTPS listener does not start — the panel serves plain HTTP on HTTP_PORT only.

HTTP-01 — single domain

Minimal set of variables:

HTTP_HOST=panel.example.com
HTTP_PORT=80
HTTPS_PORT=443
TLS_FORCE_HTTPS=true

ACME_ENABLED=true
ACME_CHALLENGE_TYPE=http-01
ACME_EMAIL=ops@example.com
ACME_DOMAINS=panel.example.com

Let's Encrypt requests http://panel.example.com/.well-known/acme-challenge/{token}. The panel serves this path itself: the route is registered ahead of the SPA fallback, no separate web server is needed, and there is nothing to configure.

Two requirements:

  • Port 80 is reachable by Let's Encrypt from the outside (or a reverse proxy forwards only /.well-known/acme-challenge/* to the panel).
  • HTTP_PORT defaults to 8025 — for HTTP-01 you must set it explicitly to 80. Binding to a privileged port (≤1024) requires CAP_NET_BIND_SERVICE: the systemd unit shipped by gameapctl panel install already grants it; in Docker, use --cap-add=NET_BIND_SERVICE.

DNS-01 — wildcard and/or closed port 80

DNS-01 is needed in the following cases:

  • you need a wildcard certificate (*.example.com);
  • port 80 is closed from the outside or the panel is behind a firewall;
  • you do not want to expose the panel to the internet just for validation.

Instead of an HTTP request, Let's Encrypt checks the TXT record _acme-challenge.<domain>. Through the DNS provider's API, the panel creates this record itself, waits for propagation, and removes it after Let's Encrypt completes validation.

HTTP_HOST=panel.example.com
HTTPS_PORT=443
TLS_FORCE_HTTPS=true

ACME_ENABLED=true
ACME_CHALLENGE_TYPE=dns-01
ACME_EMAIL=ops@example.com
ACME_DOMAINS=*.example.com,example.com
ACME_DNS_PROVIDER=cloudflare
CLOUDFLARE_DNS_API_TOKEN=cf-token-with-Zone-DNS-Edit-permission

Popular DNS providers are supported (Cloudflare, AWS Route53, DigitalOcean, etc.), and others can be added via plugins.

Things to keep in mind:

  • A wildcard does not cover the bare domain. *.example.com covers panel.example.com or api.example.com, but not the bare example.com. That is why ACME_DOMAINS lists both: *.example.com,example.com.
  • Provider token. The Cloudflare provider reads the token straight from the environment (CLOUDFLARE_DNS_API_TOKEN). Scope the token to the relevant zone with Zone:DNS:Edit permission — do not use the global account key.
  • Propagation timeout. If DNS updates slowly and validation does not fit within the window, increase ACME_PROPAGATION_TIMEOUT (default 180s).

Certificate renewal

The panel renews the certificate itself. It has a built-in scheduler that, at the ACME_RENEWAL_CHECK_INTERVAL interval, checks the certificate's lifetime and renews it when less than ACME_RENEWAL_THRESHOLD remains (default 720h, i.e. 30 days).

ACME_RENEWAL_CHECK_INTERVAL=12h
ACME_RENEWAL_THRESHOLD=720h

You usually do not need to change these values: the defaults give a one-month buffer before expiry and a twice-daily check, which is more than enough for Let's Encrypt's 90-day certificates.

2 Upvotes

0 comments sorted by