Self-generated certificate is good for bootstrapping purpose but sooner than later we need a valid SSL certificate for all services (IMAPS, HTTPS, DoT etc).
1. Install
pacman -S certbot certbot-nginx
2.1 Manual generation
Init the certificate generation
certbot certonly --manual -d "*.costan.ro" -d "costan.ro"
The above tool spits out a DNS challenge that we need to set as a DNS TXT record.
Set the DNS TXT record
It depends on your DNS provider but usually is as simple as adding a new record.
grep acme /etc/nsd/zones/costan.ro
_acme-challenge IN TXT "PDFYVU1v3Jlo6Yeo50-LHiokC8PwNeZl_-FCz13CKPs"
Check using local DNS server first (mind @ns.costan.ro local DNS server at the end)
dig +short TXT _acme-challenge.costan.ro @ns.costan.ro
PDFYVU1v3Jlo6Yeo50-LHiokC8PwNeZl_-FCz13CKPs
Wait for DNS propagation and check using public (or default) DNS server. This "wait" part is important otherwise LetsEncrypt won't be able to resolve the DNS challenge and SSL generation process will fail.
dig +short TXT _acme-challenge.costan.ro @8.8.8.8
PDFYVU1v3Jlo6Yeo50-LHiokC8PwNeZl_-FCz13CKPs
Finish the certificate generation
Once the DNS TXT change is propagated press "ENTER" and certbot tool will generate all certificate files.
List the certificate
certbot certificates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: costan.ro Serial Number: 4f6208230dcfb39f339295c19a5eb7781fa Key Type: ECDSA Domains: *.costan.ro Expiry Date: 2023-03-19 12:40:17+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/costan.ro/fullchain.pem Private Key Path: /etc/letsencrypt/live/costan.ro/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Usage
Change configuration files for all public services (Postfix, Dovecot, Nsd, etc) and point to newly generated fullchain.pem and privkey.pem files.
postconf -n | grep -E "smtpd_tls_.*_file"
smtpd_tls_cert_file = /etc/letsencrypt/live/costan.ro/fullchain.pem smtpd_tls_key_file = /etc/letsencrypt/live/costan.ro/privkey.pem
doveconf ssl_cert ssl_key
ssl_cert = </etc/letsencrypt/live/costan.ro/fullchain.pem ssl_key = </etc/letsencrypt/live/costan.ro/privkey.pem
Checker
And last, check installed SSL cert using an SSLlabs online checker or openssl tool.
openssl s_client -connect www.costan.ro:443
2.2 Semi-automated renewal
Config file
Basic config files with a few cmd line settings.
cat /etc/letsencrypt/cli.ini
key-type = ecdsa email = letsencrypt@costan.ro authenticator = manual agree-tos = true
Auth script
This script will update _acme-challenge in DNS config, sign and reload the zone.
cat /etc/letsencrypt/renewal-hooks/auth.sh
#!/usr/bin/env sh echo CERTBOT_DOMAIN=$CERTBOT_DOMAIN echo CERTBOT_VALIDATION=$CERTBOT_VALIDATION echo CERTBOT_REMAINING_CHALLENGES=$CERTBOT_REMAINING_CHALLENGES echo CERTBOT_ALL_DOMAINS=$CERTBOT_ALL_DOMAINS echo Sed: replace _acme_challenge in /etc/nsd/zones/$CERTBOT_DOMAIN ...: sed -Ei "s/_acme-challenge(.+)\"(.+)\"/_acme-challenge\1\"$CERTBOT_VALIDATION\"/" /etc/nsd/zones/$CERTBOT_DOMAIN echo NSD: sign/reload $CERTBOT_DOMAIN zone... cd /etc/nsd/zones/ ldns-signzone -n -p -e 20240316174119 costan.ro Kcostan.ro.+008+03304 Kcostan.ro.+008+19957 nsd-control reconfig nsd-control reload $CERTBOT_DOMAIN echo Wait for DNS propagation... sleep 15s echo "DONE."
Renew
And finally the magic command.
certbot renew --manual-auth=/etc/letsencrypt/renewal-hooks/auth.sh -v
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Processing /etc/letsencrypt/renewal/costan.ro.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Certificate is due for renewal, auto-renewing... Plugins selected: Authenticator manual, Installer None Renewing an existing certificate for *.costan.ro Performing the following challenges: dns-01 challenge for costan.ro Running manual-auth-hook command: /etc/letsencrypt/renewal-hooks/auth.sh Hook '--manual-auth-hook' for costan.ro ran with output: CERTBOT_DOMAIN=costan.ro CERTBOT_VALIDATION=uY5-sXNpcCtIQoVmA7jy-kIg4-ipseBLjjOzyoTQzpI CERTBOT_REMAINING_CHALLENGES=0 CERTBOT_ALL_DOMAINS=costan.ro Sed: replace _acme_challenge in /etc/nsd/zones/costan.ro ...: NSD: sign/reload costan.ro zone... reconfig start, read /etc/nsd/nsd.conf ok ok Wait for DNS propagation... DONE. Waiting for verification... Cleaning up challenges - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Congratulations, all renewals succeeded: /etc/letsencrypt/live/costan.ro/fullchain.pem (success) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Testing
certbot certificates
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: costan.ro Serial Number: 3fc9af33d62a240238dc4c1fb3a3dc616e6 Key Type: ECDSA Domains: *.costan.ro Expiry Date: 2023-06-14 10:13:39+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/costan.ro/fullchain.pem Private Key Path: /etc/letsencrypt/live/costan.ro/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
2.3 Fully-automated renewal
TBD: in 3 months, before the expiry date above
3. References
Updates
- [2023-03-16] - manual renew of wildcard certificate