Skip to content

Runbook — certificate renewal

Short version: there is no self-managed cert rotation on this fleet — the only public TLS is the cloudflared token tunnel on pi-home, and Cloudflare issues + renews the edge certificates automatically. This runbook documents what TLS actually exists, what is and is not automated, and the few things to check.

What TLS exists (and who manages it)

surface cert / key managed by renews
Public HTTPS (beszel.jmrdez.com, 2fauth, linkding, …) Cloudflare edge certificate Cloudflare automatically (Cloudflare)
cloudflared → origin origin cert / SSH token tunnel token token-based, long-lived
Netbird / WireGuard tunnels (wg-direct, wgr-vpsnet, wgrescue) WireGuard keys (pre-shared / self-gen) us (static, wg peers) not certs — rotate manually if leaked
Befzel hub / beszel agent - application n/a

There is no certbot, Caddy automated TLS, or ACME client anywhere on the fleet — public certs ride the Cloudflare edge.

Therefore, "renovate the certs" means:

  1. Nothing to renew for public sites. Cloudflare serves its edge cert automatically. If a domain shows an expired/unknown cert, the issue is the DNS/route in Cloudflare Zero Trust, not a cert expiry — debug that.

  2. Keep cloudflared up to date — it is pinned with --no-autoupdate, so the tunnel binary does not self-update. Check it isn't falling behind:

    # pi-home (native unit)
    cloudflared version
    systemctl status cloudflared          # "run" port up, no cert errors
    journalctl -u cloudflared -n 50 --no-pager
    
    Upgrade deliberately (pin the new version), then restart. A stale binary is the realistic "cert" failure — not a leaf cert expiry.

  3. Test that public endpoints present a valid cert:

    curl -sI https://beszel.jmrdez.com | head -1    # 200 / 403 expected per route
    echo | openssl s_client -connect beszel.jmrdez.com:443 2>/dev/null \
      | openssl x509 -noout -dates | grep notAfter
    

  4. WireGuard keys are not certificates but live in /etc/wireguard/. If a key is compromised, regenerate both ends of the tunnel (see node-rebuild) — there is no expiry, so nothing auto-forces this.

If you are about to add real ACME to something

The fleet deliberately has no public origin servers; everything is behind the tunnel. If a future service needs its own cert, add ACME with the DNS-01 challenge through Cloudflare's API (no public port needed for http-01), and then this runbook gets a real section. Until then, there is nothing to run.