Skip to content

Custom domains and TLS

In this guide you serve a web app on your own hostname over HTTPS.

  • A web app (domains aren’t available for tcp, internal or process apps) that you have the developer role on.
  • Control of the hostname’s DNS.
  • Port 80 reachable from the internet. Let’s Encrypt validates over HTTP.
Terminal window
PANEL=https://panel.example.com
H='Authorization: Bearer gsl_xxxxxxxxxxxxxxxx'
J='Content-Type: application/json'
Terminal window
curl -s $PANEL/system/info -H "$H" | jq '{publicIp, privateIps}'

Behind NAT, or with several addresses, set PUBLIC_IP=<address> in /etc/gisila/.env and restart gisila-panel so the panel shows the right one.

Add an A record (and AAAA for IPv6) for api.example.com pointing at that address. If you use Cloudflare, keep the record DNS only until the certificate is issued, or issuance through HTTP-01 may fail.

Terminal window
dig +short api.example.com
Terminal window
curl -sX POST $PANEL/apps/42/domains/ -H "$H" -H "$J" \
-d '{"hostname": "api.example.com", "isPrimary": true}'
# → {"id": 9, "hostname": "api.example.com", "ssl_status": "none", ...}

The worker rewrites the app’s Nginx vhost. Hostnames are lowercased. A hostname already attached to another app returns 409 domain_in_use.

Terminal window
curl -sX POST $PANEL/apps/42/domains/9/ssl -H "$H"
# → {"detail": "Certificate issuance queued."}

The agent runs certbot --nginx -d api.example.com and reloads Nginx. ssl_status goes from pending to issued, or to failed. certbot’s own timer renews the certificate. Call the same route again to re-issue it.

Terminal window
curl -sX DELETE $PANEL/apps/42/domains/9 -H "$H"

The vhost is rewritten without it. The certificate files stay in /etc/letsencrypt until you delete them with certbot.

Terminal window
curl -s $PANEL/apps/42/domains/ -H "$H" | jq '.results[] | {hostname, ssl_status}'
curl -sI https://api.example.com | head -1

If ssl_status is failed:

  • dig +short api.example.com must return this server’s address.
  • Port 80 must be open. Check GET /firewall/ if you restricted the web ports to a CDN’s ranges.
  • Read the worker log: journalctl -u gisila-worker -n 100.