Domains, TLS & Cloudflare
A public Haven needs a domain and HTTPS. This page covers the DNS + TLS layout that keeps cookies, CORS and CSP painless.
The recommended hostname layout
Section titled “The recommended hostname layout”Put everything on one registrable domain:
| Hostname | Points at | Purpose |
|---|---|---|
crimson.example.com | client (:8080) | the website |
backend.crimson.example.com | backend (:8000) | the API |
dev.crimson.example.com / dev-backend.… | the dev stack | staging |
docs.crimson.example.com | GitHub Pages | this documentation |
Same registrable domain = same-site cookies, easy CORS (ALLOWED_ORIGINS), simple CSP.
Option A — Cloudflare (recommended)
Section titled “Option A — Cloudflare (recommended)”Cloudflare gives you free DNS, TLS and a tunnel that avoids opening ports.
- Add your domain to Cloudflare and point your registrar at Cloudflare’s nameservers.
- Cloudflare Tunnel (no inbound ports): install
cloudflaredon your server, create a tunnel, and map public hostnames to local services:~/.cloudflared/config.yml tunnel: <tunnel-id>ingress:- hostname: crimson.example.comservice: http://localhost:8080- hostname: backend.crimson.example.comservice: http://localhost:8000- service: http_status:404Terminal window cloudflared tunnel run - TLS is terminated at Cloudflare’s edge. Make sure the backend trusts the forwarded
headers (
FORWARDED_ALLOW_IPS=*) so it seeshttpsand the real client IP.
Option B — A reverse proxy with Let’s Encrypt
Section titled “Option B — A reverse proxy with Let’s Encrypt”If you’d rather terminate TLS yourself, Caddy is the simplest (automatic certs):
# Caddyfilecrimson.example.com { reverse_proxy localhost:8080}backend.crimson.example.com { reverse_proxy localhost:8000}nginx + Certbot works too — just ensure it sets X-Forwarded-Proto/X-Forwarded-Host
so the backend emits https:// URLs.
CORS, after you have domains
Section titled “CORS, after you have domains”Tell the backend which origin the client lives on:
ALLOWED_ORIGINS=https://crimson.example.comUnset, it falls back to a built-in dev list — lock it down in production.
The docs site (this very site)
Section titled “The docs site (this very site)”docs.example.com is hosted on GitHub Pages, separately from your servers:
- In the
crimson-docsrepo,public/CNAMEalready contains your docs hostname. - In Settings → Pages, set the source to GitHub Actions (the included
workflow deploys on push to
main). - Add a DNS record for the docs hostname:
- With Cloudflare: a
CNAMEfromdocs→<your-org>.github.io(set to DNS only / grey-cloud initially while Pages provisions its certificate, then you may proxy it).
- With Cloudflare: a
- GitHub provisions an HTTPS certificate automatically once DNS resolves.
A quick sanity checklist
Section titled “A quick sanity checklist”- Client loads over HTTPS at its hostname.
-
https://backend.…/healthreturns ok over HTTPS. -
ALLOWED_ORIGINSincludes the client’s HTTPS origin. - The backend sees
X-Forwarded-Proto: https(no mixed-content blocks on streams). -
docs.…serves the documentation.