Troubleshooting & FAQ

Fix the common problems — 502s, stuck certificates, failed deploys, offline nodes, license grace — with the exact command to run.

Troubleshooting & FAQ

Most problems have a known cause and a one-line fix. Start with hostssh doctor on the box — it's a non-destructive preflight that usually tells you exactly what's wrong before you change anything.

$ hostssh doctor

The named guards (G1, G8, G10…) below are the failures we've hit and permanently fixed forward, so they either can't recur or have a clear remedy. Developers can read the full catalog in docs/dev/build-guards.md.


Home / office Nodes (no public IP)

The box joined the fleet but I cannot reach an app on it

Cause: the agent is pull-only. A residential/CGNAT Node heartbeats without inbound ports; publishing an app needs a Cloudflare Tunnel. Fix: hostssh doctor — if reachability says private/CGNAT and cloudflared is warn, follow tunnel-first join (cloudflared + HOSTSSH_CF_TUNNEL + cloudflared.service).


Deploys

My app 502s right after deploy — "connection refused" {#g1}

Cause (G1): a Next.js-style server bound to an IPv6-only address because HOSTNAME wasn't set. Status: HostSSH now injects HOSTNAME=0.0.0.0 for web apps by default, and the deploy's HTTP readiness gate fails a bad bind instead of shipping it. If you still see this, make sure you're not overriding HOSTNAME yourself, and set a --readiness-path so the gate can catch it.

My app was up, then started 502ing later {#g2}

Cause (G2): the process died but the container's PID 1 stayed alive, so nothing restarted it. Status: every deployed app gets a health check and a restart policy; a dead listener is detected and restarted automatically. If it keeps flapping, the app itself is crashing — check hostssh logs <app> --follow.

A redeploy lost my environment variables {#g3}

Cause (G3): env stored on the container instead of the platform. Status: env lives on the App row in the control plane and is injected into every deploy, so it survives redeploys. Edit it in App Settings → Environment Variables. If a value is missing, it was never saved — re-add it there.

A redeploy only shipped one file / reverted other pages {#g4}

Cause (G4): a stored-Dockerfile / surgical-overlay deploy (a Coolify pattern). Status: HostSSH always deploys from source — no overlay deploys. Commit your full build recipe to the repo.

My deploy failed and took the site down

It shouldn't — a failed gate rolls back to your previous version automatically (G8). If your site is down after a failed deploy, the previous version was already broken, or the app has no prior good version. Check hostssh logs <app> and redeploy a known-good ref.

My Dockerfile build fails on an env check {#g11}

Cause (G11): your build step (e.g. a Next.js env:check) validates environment at build time, but the values are only in the runtime env, or your .dockerignore strips the env file. Fix: pass --env/--env-file on the deploy, and make sure .dockerignore doesn't exclude the env file the build needs. Use the hostpack builder if you'd rather not manage this.


Domains & certificates

My certificate is self-signed / the browser warns {#g10}

Cause (G10): the ACME challenge can't validate. Either DNS isn't pointing at the box yet (HTTP-01 can't answer), or you're using DNS-01 without a token configured. Fix:

  1. Confirm the domain's A record points at this Node's IP.
  2. Then clear the stuck backoff:
    $ hostssh proxy up --force
    
    The cert issues in ~10–30s. For zero-downtime cutovers, configure DNS-01 so the cert issues before DNS points at the box.

My domain doesn't resolve / times out

Check the A record points at the Node, ports 80/443 are open (hostssh firewall status), and the managed proxy is running (hostssh proxy status).


Nodes & the fleet

A Node shows as offline / degraded

It stopped heartbeating (degraded >3 min, offline >15 min). Check the box is up, the hostssh-agent service is running (systemctl status hostssh-agent), and it can reach the control plane. hostssh doctor diagnoses the wiring.

A Node reads as a "dead box" with 0% everywhere {#g9}

Cause (G9): a node with no Agent (or a very stale one) has no metrics to show. Status: the fleet now shows "—" for unknown values instead of a misleading 0%. Install/update the Agent to get real telemetry.

Disk is filling up

Open the Fleet drawer's disk panel and run cleanup (preview first). It safely reclaims old images and build cache without touching your data. See Monitoring & alerts.


Licensing

The Agent says my license is in "grace" or "expired"

The Agent verifies a signed license and keeps an offline grace clock so a brief control-plane outage never takes your box down. If it's drifting toward expired:

  • Grace: the control plane was briefly unreachable; it recovers on the next successful refresh.
  • Expired: re-activate with hostssh license activate --key HSSH-…, or check that the Agent has the license public key configured (a dev build without the embedded key can't verify refreshes). See Licensing.

A gated command exits with code 12

That command (deploy, db, proxy, the agent daemon, …) needs an active license. Recovery commands (capture, restore, status, doctor, firewall) are never gated — you can always get your data out. Activate a license to restore full function.


Secrets & databases

My app can't reach its database

Use the private Mesh address in DATABASE_URL (e.g. 10.10.0.2:5432), not a public IP, and confirm the Mesh peer is healthy on the Mesh page. If you see auth errors (Postgres 28P01), make sure the connection targets the canonical database container, not a stray one.

My secret value shows as masked / empty

That's correct — secret values are sealed and never displayed. To change one, edit it in App Settings and redeploy. If the app behaves as though the value is empty, confirm the Agent has HOSTSSH_ENC_KEY set (it needs the key to open sealed envelopes).


Getting help

  • hostssh doctor first — it explains most problems without changing anything.
  • hostssh logs <app> --follow for app-level crashes.
  • The Audit log (hostssh audit) shows what actions ran and verifies the chain wasn't tampered with.
  • If something contradicts these docs, that's a bug — the docs track the product commit by commit.