Domains & TLS
Point a real domain at an app, get automatic Let's Encrypt HTTPS, and cut over from an old host with zero downtime using DNS-01.
Domains & TLS
HostSSH runs a managed proxy (Traefik) on each Node that terminates HTTPS and gets Let's Encrypt certificates for you. You never edit a proxy config or run certbot. This guide covers attaching a domain, how certificates are issued, and how to cut over from an existing host without an HTTPS gap.
1. Attach a domain to an App
When you deploy, set the domain and the port your app listens on:
$ hostssh deploy --name shop --source ./shop --domain shop.example.com --port 3000
or in the dashboard's Deploy drawer, fill Domain and Port. That's it — the Agent:
- ensures the managed proxy (
hostssh-proxy) is running, - stamps routing labels on your container (
Host(shop.example.com) → :3000), - and the proxy requests a certificate and starts serving HTTPS.
Point your DNS at the Node's public IP (an A record) and the site is live over HTTPS.
2. How certificates are issued
The managed proxy supports two ACME challenge types. HostSSH picks automatically:
HTTP-01 (default)
The proxy proves control of the domain by answering a challenge on port 80. This works out of the box and needs nothing but DNS already pointing at the Node and port 80 reachable.
- Requirement: the domain's
Arecord must resolve to this Node before the certificate can issue. If it doesn't, Let's Encrypt returns NXDOMAIN and the proxy backs off. - If a cert is stuck self-signed: point the DNS at the box, then run
hostssh proxy up --forceto clear the backoff and force a fresh challenge. The cert issues in ~10–30s. (This is guard G10; see Troubleshooting.)
DNS-01 (for zero-downtime cutovers and wildcards)
The proxy proves control by creating a temporary DNS TXT record via your DNS provider's API.
This is the production path because it can issue a certificate before the domain points
at the Node — so there's no HTTPS gap during a migration — and it can issue wildcard
certificates (*.example.com).
Enable it by giving the proxy a scoped Cloudflare token:
HOSTSSH_ACME_DNS_PROVIDER=cloudflareHOSTSSH_ACME_DNS_TOKEN=<a Cloudflare Zone:DNS:Edit token>
Set these in the dashboard (the token is held server-side and sealed — a cutover becomes a dashboard action, and the token never appears on a command line) or in the Agent's systemd environment. With DNS-01 configured, the proxy issues via the DNS challenge and falls back to HTTP-01 automatically if the token is missing, so nothing regresses.
Recommended production posture: put the domain behind Cloudflare (orange-cloud, proxied), set SSL mode to Full (strict), and let DNS-01 supply the trusted origin certificate. This is orange-cloud-safe and supports wildcards. For many client custom domains at scale, use Cloudflare for SaaS (edge certs per client via CNAME).
3. Zero-downtime cutover from an old host
The whole point of DNS-01 is that you can prepare the new box completely before flipping any traffic. The safe sequence:
- Deploy the App to the HostSSH Node with its real domain and env, while DNS still points at your old host. It's running and gated, just not receiving public traffic yet.
- Pre-issue the certificate via DNS-01 while DNS still points away. Verify it's real and
trusted without changing DNS:
The$ curl --resolve shop.example.com:443:<node-ip> https://shop.example.com -I HTTP/2 200--resolveflag makescurltalk to the new Node as if DNS already pointed there. - Cut over the DNS — change the
Arecord to the Node's IP (TTL 300). Because the cert is already issued, HTTPS works from the first request. HostSSH also lights up an uptime monitor for the domain automatically. - Watch, then decommission. Keep the old host running (stopped, not deleted) for a soak
window so rollback is instant — just flip the
Arecord back. Once you're confident, remove the old app.
The dashboard's cutover action does the DNS flip for you (when you've connected a Cloudflare token), records the previous record for rollback, and health-checks the domain after the flip — rolling DNS back automatically if the new target fails its check.
4. Multiple domains and subdomains
www+ apex: deploy with the apex domain, then add thewwwhost as an additional route (or a CNAME to the apex). Both get certificates.- App subdomains / multi-tenant: HostSSH supports wildcard routing for multi-tenant apps
(
*.yourapp.com) — the DNS-01 wildcard cert covers every tenant subdomain. See your app's tenant settings. - Public expose (quick tunnels): to expose a port publicly without a full DNS setup — for a
demo or an internal tool — use the Expose feature, which provisions a Cloudflare tunnel and
a
*.apps.hostssh.comhostname. See the Access page in the dashboard.
5. Managing the proxy directly
On the box, a few commands help when debugging:
| Command | What it does |
|---|---|
hostssh proxy status | Is the managed proxy running? |
hostssh proxy up | Ensure the proxy is running (idempotent). |
hostssh proxy up --force | Recreate the proxy — clears a stuck ACME backoff. |
hostssh proxy down | Stop the managed proxy. |
Issued certificates persist in a Docker volume (hostssh-acme), so restarting or recreating the
proxy never loses them, and that volume is included in backups.
6. Common questions
Do I need to open ports? The managed proxy needs 80 and 443 reachable. HTTP-01 needs 80; DNS-01 doesn't, but 80/443 still serve traffic. The Agent's firewall opens these by default.
My cert is self-signed / browser warns. DNS isn't pointing at the box yet (HTTP-01 can't
validate), or the token is missing (DNS-01 can't run). Fix DNS or add the token, then
hostssh proxy up --force. See Troubleshooting.
Can I bring my own certificate? The managed proxy is built around automatic Let's Encrypt. For a custom cert, terminate TLS at Cloudflare (Full strict) with a HostSSH origin cert, which is the recommended posture anyway.
Renewals? Automatic. The proxy renews before expiry. HostSSH also auto-creates TLS-expiry monitors so a silent renewal failure surfaces as an alert rather than an outage.
Next steps
- Cut over a whole app from Coolify/Vercel → Migrating to HostSSH
- Watch the domain's uptime → Monitoring & alerts