SSL Certificate Renewal Notes
SSL Certificate Renewal Notes
This note records a simple SSL certificate workflow with
certbot: acquire, verify, renew, and deploy.
The example domain is api.example.com. Replace it with
your own domain.
Acquire A Certificate
For a standalone HTTP-01 challenge, port 80 must be
reachable and not occupied by another process:
1 | sudo certbot certonly --standalone -d api.example.com |
If Caddy already owns port 80, first consider letting
Caddy manage its own certificates, or using DNS-01 / a properly served
webroot. The standalone alternative below causes downtime and is only
for this port-conflict branch, not every service on the host.
Create certbot-caddy-stop.sh in your working
directory:
1 |
|
Create certbot-caddy-start.sh:
1 |
|
Install the inspected scripts as root-owned hooks, then request the certificate with those hooks:
1 | sudo install -o root -g root -m 0755 certbot-caddy-stop.sh /usr/local/sbin/certbot-caddy-stop |
The marker restores Caddy only if it was active before the attempt. Certbot normally runs the post-hook after renewal attempts even when validation fails; a killed process or host failure can still prevent it. After an interrupted run, inspect Caddy and the marker and restore service manually if needed. Serialize renewal jobs using this pair; the shared marker is not designed for concurrent Certbot instances. Hook files and all ancestor directories must not be writable by unprivileged users.
Check The Certificate
1 | sudo certbot certificates |
Enable Renewal
1 | sudo systemctl enable --now certbot.timer |
For the Caddy-conflict branch, check that the certificate’s
/etc/letsencrypt/renewal/api.example.com.conf retains the
standalone authenticator and the intended pre/post hook paths before
relying on the timer. An existing certificate obtained without these
hooks needs its renewal configuration updated using the installed
Certbot version’s supported reconfiguration workflow. Keep the hooks off
lineages that do not require this downtime.
Run a dry test (the pre/post hooks may stop and restart Caddy):
1 | sudo certbot renew --dry-run |
Deploy Hook
Some services cannot read directly from
/etc/letsencrypt/live/..., or they need certificate files
copied into a service-owned directory.
Example hook for a service called myapp. Confirm that
the actual service identity is a member of group myapp and
that all parent directories allow traversal by that group. Here the
directory remains root-owned, with read/traverse access for the service
group; the private key is never world-readable. Replace the
domain/group/service names for your deployment. Save the following as
deploy-myapp-cert.sh:
1 |
|
Install it as a deploy hook:
1 | sudo install -o root -g root -m 0755 deploy-myapp-cert.sh \ |
Verify the directory/key owner, group and mode, then test certificate
reads as the actual service identity. A successful copy does not prove
the service can read the key or supports reload. Plain
renew --dry-run does not normally run deploy hooks; use the
installed version’s --run-deploy-hooks support deliberately
(it can reload the real service). This example does not provide atomic
replacement of the certificate/key pair; coordinate readers or use the
service’s documented deployment mechanism when concurrent reads matter.
No live issuance, renewal or myapp reload was tested here.