TLS certificate renewal responsibility for self-hosted Ghost
0 reputation · 13 Oct 2021, 20:39 UTC
0 reputation · 13 Oct 2021, 20:39 UTC
Self-hosted Ghost does not manage DNS records or TLS certificates. Domain resolution must complete via A, AAAA or CNAME records before requests reach the host, and certificate validation is handled outside core, typically by a reverse proxy in front of the Node.js process.
The operator must decide how certificate renewal is performed and how the proxy is reloaded, because Ghost provides no built-in guidance for ACME validation or renewal reliability. Managed hosting abstracts this, so the decision is specific to self-hosted deployments.
Which renewal model is assumed for a standard self-hosted deployment with Nginx or Caddy? Does Ghost core require specific proxy headers or server_name configuration to remain accessible after renewal? When does responsibility for port 80 accessibility for HTTP-01 challenges end with Ghost and begin with the proxy?
35275 reputation · 13 Oct 2021, 21:11 UTC
Ghost operates as a Node.js application usually listening on a local interface (default port 2368). It assumes that a reverse proxy handles SSL termination. Therefore, Ghost is not involved in ACME challenges (HTTP-01 or DNS-01), nor does it need to restart when a certificate is renewed.
nginx -s reload upon successful renewal to pick up the new certificates.To ensure Ghost remains accessible and secure after a renewal, the proxy must pass specific headers to Ghost. Ghost uses these to determine if the connection is secure and what the correct URL is.
# Example Nginx headers for Ghost proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme;
The responsibility for port 80 accessibility ends with Ghost and begins with the proxy. If you use the HTTP-01 challenge, the proxy must be configured to allow external traffic on port 80 to the .well-known/acme-challenge/ path. If the proxy is behind a firewall or load balancer, that infrastructure must also forward port 80 to the proxy instance.
This guide assumes a standard Linux-based VPS deployment. If you are using Docker, the boundary remains the same, but the proxy container must map ports 80 and 443 to the host. It is uncertain whether you are using a DNS-01 challenge; if so, port 80 accessibility is not required for the renewal process.
Use comments to ask for clarification. Post a solution as an answer.
6,680 reputation · 14 Oct 2021, 06:48 UTC
Ghost core has no ACME integration and never sees the HTTP-01 challenge. The challenge must be served by the reverse proxy before traffic reaches the Node process, so port 80 accessibility is a proxy and firewall responsibility, not Ghost's.
For Nginx the standard self-hosted model is Certbot managing certificates with explicit ssl_certificate paths and a manual reload after renewal. Caddy handles issuance and reload automatically when the Caddyfile domain directives are unchanged. Ghost remains accessible after renewal as long as X-Forwarded-Proto, X-Forwarded-For and Host are passed through and config.url matches the public domain.