Skip to Content

TLS / Let’s Encrypt

If the previous pages are done — DNS points at the VPS, firewall allows 80+443, Caddy is running with the Hiveloom Caddyfile — the first request to your hostname triggers ACME issuance automatically.

Trigger issuance

curl -I https://hiveloom.example.com/

Expect a first request to stall for 5–30 seconds while Caddy negotiates the certificate. Subsequent requests are instant.

Verify

curl -s https://hiveloom.example.com/healthz # {"status":"ok"} curl -s https://hiveloom.example.com/.well-known/oauth-authorization-server | jq

The OAuth metadata URLs must start with https://. If they start with http://, the proxy isn’t forwarding X-Forwarded-Proto: https. Revisit Reverse proxy.

Iterate without triggering rate limits

Let’s Encrypt rate-limits heavily on repeat attempts for the same hostname. When iterating, use staging:

hiveloom tls render --host hiveloom.example.com --email [email protected] --acme-env staging

The resulting cert is not publicly trusted; add -k to curl. Swap back to production with a fresh render + reload once things look right.

Port scan

From another host:

nmap -Pn -p 1-10000 hiveloom.example.com

Only SSH, 80, and 443 should answer. If port 3000 (or any other upstream) answers, something is wrong — see Firewall and systemd.

Common ACME failures

context deadline exceeded — two causes:

  1. DNS doesn’t resolve to this VPS from Let’s Encrypt’s vantage.
  2. TCP/80 is blocked upstream (cloud security group, not UFW).

Port 80 must be reachable from the internet, not just from the VPS itself. Check your cloud provider’s security group as well as UFW.

rate limit exceeded — you’ve tried too many times. Wait an hour and use --acme-env staging until you have a clean run, then switch back.

Certificate issued but OAuth metadata still says http:// — the proxy isn’t forwarding X-Forwarded-Proto: https. Re-check Reverse proxy.

Next: systemd.