Public HTTPS deploy
Want a real https:// address that customers or judges can reach? This puts a TLS reverse proxy (nginx + Let's Encrypt via certbot) in front of your gateway. It's already built into the compose file — you just supply a domain and a couple of settings in .env.
Once it's set up, two things become reachable:
- a trusted
https://your-domainfor the dashboard and API — handy for a hosted demo - WSS for your node's P2P port — which unlocks the demo storefront's "Pay with browser wallet" button
What you'll need: a domain you control, pointed at this host, with ports 80/443/8228 forwarded to it.
Nginx boots even without a real cert (a temporary self-signed one, generated by nginx-certs-preflight if none exists yet), so docker compose up -d always comes up — but a trusted https:// URL needs the steps below completed against a real, publicly-resolvable domain.
1. Get a domain and point it at this host
Any domain works — a domain you already own, or a free subdomain from any provider that supports it. Once you have one:
- Point its DNS A/AAAA record at this host's public IP.
- Forward ports 80, 443, and 8228 on your router/firewall to this machine's LAN IP. All three are used by
nginx: 80 for the ACME HTTP-01 challenge- HTTPS redirect, 443 for the dashboard/API, 8228 for
fiber-node's P2P/WSS traffic.
- HTTPS redirect, 443 for the dashboard/API, 8228 for
- Confirm it actually resolves from outside your network before continuing —
dig +short $DOMAINfrom a machine that isn't this one, or any public "DNS checker" website.
Using Cloudflare?
Keep this record DNS-only ("grey cloud"), not Proxied ("orange cloud"). Proxied mode terminates TLS at Cloudflare's edge and doesn't forward arbitrary TCP ports like 8228 on the free/pro plan — the WSS path for the browser wallet wouldn't be reachable through it. DNS-only means Cloudflare is just answering DNS queries, no different from any other registrar.
2. Configure and start
Set DOMAIN and CERTBOT_EMAIL either when prompted during npx create-fibergate@latest, or by editing them directly in .env after the fact:
# In .env:
DOMAIN=your-subdomain.example.com
CERTBOT_EMAIL=you@example.com # Let's Encrypt expiry notices
docker compose up -d
docker compose ps # nginx-certs-preflight should show "Exited (0)", nginx "running"3. Get a real certificate (one-time)
Only run this once DNS + port-forwarding from step 1 are actually live — Let's Encrypt needs to reach port 80 on this host from the public internet:
docker compose run --rm certbot-init
docker compose exec nginx nginx -s reloadcertbot-init reads DOMAIN/CERTBOT_EMAIL straight from .env (same values you set in step 2) — there's nothing to fill in or substitute yourself. It's a separate, one-time-only service from the always-running certbot service; see docker-compose.yml's comments on both if you're curious why they're split.
The certbot service keeps running afterward and renews automatically (checks twice daily; Let's Encrypt certs are valid 90 days, renewed around day 60) — nginx reloads itself every 6h to pick up renewed certs, so no manual reload is needed again after this first one.
Changed DOMAIN after nginx already started once?
A plain docker compose exec nginx nginx -s reload is not enough. nginx.conf is only generated from nginx.conf.template via envsubst once, at container startup — reload just re-reads the already-generated file, it doesn't regenerate it. If you change DOMAIN in .env after nginx has already been created once (e.g. you switched domains, or bought a real domain after first testing with a placeholder), run this instead so the container re-reads .env and regenerates nginx.conf pointing at the right cert path:
docker compose up -d --force-recreate nginxVerify:
curl -I https://$DOMAIN # should return a real response (e.g. a redirect to /login),
# no -k/--insecure needed once the cert is trustedLog into the dashboard through this URL and check the response's Set-Cookie header for the Secure attribute (browser dev tools' Application/Storage tab, or curl -v on the login request) — confirms X-Forwarded-Proto is being forwarded and read correctly end to end.
4. Enable WSS for fiber-node (unlocks the browser wallet button)
Optional — only needed for the demo storefront's "Pay with browser wallet" button. Skip this if you only care about the dashboard/API being on HTTPS.
- Edit
docker/fiber-node/config.yml'sannounced_addrs— uncomment the/dns4/...line already there and replaceYOUR-DOMAINwith your realDOMAIN. docker compose restart fiber-node.- Verify the node's pubkey and that a peer can connect through the WSS path (from this host, since
fiber-node's RPC stays loopback-only):bashFull connect/verify flow (from a separate node or the browser wallet itself) is in the official guide this setup is adapted from:curl -s -X POST http://127.0.0.1:8227 \ -H "Content-Type: application/json" \ -d '{"id": 1, "jsonrpc": "2.0", "method": "node_info", "params": []}' | jq -r '.result.pubkey'nervosnetwork/fiber'sdocs/fiber-node-wss.md(pinned to tagv0.9.0-rc6, matching this project's pinnednervos/fiberimage).
Not yet verified against a real domain as of this writing
This setup was built and smoke-tested locally (self-signed cert, DOMAIN=localhost) but not against real Let's Encrypt issuance or a live browser-wallet payment. Both are next steps once a real domain is live.
Something not working? See Troubleshooting.