User Tools

Site Tools


certbot

certbot

Install

install in Jessie

For Debian 8 (Jessie):

apt remove certbot
wget https://dl.eff.org/certbot-auto
mv certbot-auto /usr/local/bin/certbot-auto
chown -c root /usr/local/bin/certbot-auto
chmod -c 0755 /usr/local/bin/certbot-auto

Not sure if adding this is useful: certbot-auto --install-only

install in Stretch

For Debian 9 (Stretch):

[ -f /etc/apt/sources.list.d/stretch-backports.list ] || cat <<'END' > /etc/apt/sources.list.d/stretch-backports.list
# https://backports.debian.org/Instructions/
deb http://deb.debian.org/debian stretch-backports main
END

apt update
apt install certbot python-certbot-apache -t stretch-backports

Get first certificate(s)

This will aslo create the /etc/letsencrypt/ and /var/lib/letsencrypt/ directories if needed

Apache can be configured to listen on specific IPs:ports (Listen IP:port in /etc/apache2/ports.conf).

Or it is possible to use a temporary standalone server started by letsencrypt. The --standalone option will start it on all IPs. The --webroot option starts it only on a specific IP.

Get certificate on specific IP

The python3 -m http.server command with the --bind option can only take a single IP. Without the option, it binds to all IPs.

dir=/var/lib/letsencrypt/tmpwww
ip=1.2.3.4
name="example.com,www.example.com"
email=admin.letsencrypt@example.com

mkdir -p "$dir"
cd "$dir"
python3 -m http.server --bind $ip 80 &
pid=$!

If needed, open firewall on http port 80. Or if scripts exist already, add these hooks to the certbot commands below:

--pre-hook  /etc/letsencrypt/renewal-hooks/pre/fw-certbot-open \
--post-hook /etc/letsencrypt/renewal-hooks/post/fw-certbot-close

Test with dry-run:

certbot-auto certonly --dry-run --webroot --webroot-path "$dir" -d $name -n --agree-tos -m $email

Do it:

certbot-auto certonly --webroot --webroot-path "$dir" -d $name -n --agree-tos -m $email

And finally, stop the standalone web server:

kill $pid

Renewals should now work automatically with the cron job and scripts in /etc/letsencrypt/renewal-hooks/

Renewal-hooks

These will be used automatically on renew if placed in /etc/letsencrypt/renewal-hooks/pre and .../post dirs.

/etc/letsencrypt/renewal-hooks/pre

fw-certbot-open
#!/bin/bash
 
# Open firewall to let certbot renew certificates
 
me=$(basename "$0")
 
logger -t "$me" "Opening port 80 for certbot"
 
iptables -I INPUT -p tcp --dport 80 -j NFLOG --nflog-prefix  "nfl:ok-certbot "
iptables -I INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP for certbot"
certbot-webroot-start
#!/bin/bash
 
# Create webroot and web server for certbot renewal
 
me=$(basename "$0")
 
dir=/var/lib/letsencrypt/tmpwww
ips="1.2.3.4 10.11.12.13" ## <-- IPs to be used for validation
 
mkdir -p "$dir"
cd "$dir"
 
declare -a pids
 
for ip in $ips; do
	logger -t "$me" "Starting server on $ip in $dir"
 
	nohup python3 -m http.server --bind $ip 80 &>/dev/null &
	pid=$!
	pids+=($pid)
	echo "$pid" > "$dir/certbot-webroot-$$-$pid.pid"
done

/etc/letsencrypt/renewal-hooks/post

fw-certbot-open
#!/bin/bash
 
# Removing firewall rules created for certbot renew certificates
 
me=$(basename "$0")
 
logger -t "$me" "Closing port 80 opened for certbot"
 
iptables -D INPUT -p tcp --dport 80 -j NFLOG --nflog-prefix  "nfl:ok-certbot "
iptables -D INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP for certbot"
certbot-webroot-stop
#!/bin/bash
 
# Stop webroot web server used for certbot renewal
 
me=$(basename "$0")
 
dir=/var/lib/letsencrypt/tmpwww
 
for f in $dir/certbot-webroot-*.pid; do
	logger -t "$me" "Stopping server with pid in $f"
	kill $(< "$f") && rm "$f"
	# or?: # kill $(ps ax | grep '[p]ython3 -m http.server' | awk '{print $1}')
done

/etc/letsencrypt/renewal-hooks/deploy

reload
#!/bin/bash
 
# Reloading services to refresh certificates
 
me=$(basename "$0")
 
logger -t "$me" "Reloading postfix to refresh certificates."
postfix reload
(( $? != 0 )) && logger -t "$me" "ERROR with postfix reload."
 
logger -t "$me" "Reloading dovecot to refresh certificates."
doveadm reload
(( $? != 0 )) && logger -t "$me" "ERROR with doveadm reload."
 
logger -t "$me" "Reloading Apache to refresh certificates."
apachectl -t >/dev/null && apachectl graceful
(( $? != 0 )) && logger -t "$me" "ERROR with apachectl."
 
exit 0

Once this has been fixed, these variables might also be used, eg. for logging:

logger -t "$me" "CERTBOT_DOMAIN=$CERTBOT_DOMAIN, CERTBOT_VALIDATION=$CERTBOT_VALIDATION, CERTBOT_TOKEN=$CERTBOT_TOKEN, CERTBOT_AUTH_OUTPUT=$CERTBOT_AUTH_OUTPUT"

Other options:

Add host to existing certificate

View existing cert.

certbot certificates

Copy all hosts in existing cert. into comma-separated list, and add the new host. Then:

certbot --expand -d main.example.com,other.example.com,new.example.com

(Found on How to add a domain to existing certificate generated by Let’s Encrypt/Certbot?)

Configs

ln -sri /etc/letsencrypt/live/HOST.EXAMPLE.COM/cert.pem       /etc/ssl/
ln -sri /etc/letsencrypt/live/HOST.EXAMPLE.COM/fullchain.pem  /etc/ssl/
ln -sri /etc/letsencrypt/live/HOST.EXAMPLE.COM/privkey.pem    /etc/ssl/private/

Postfix main.cf

# postconf -n | grep 'smtpd_tls_.*_file'
smtpd_tls_key_file  = /etc/ssl/private/privkey.pem
smtpd_tls_cert_file = /etc/ssl/fullchain.pem

Proftpd tls.conf

# grep '^\s*TLSRSACertificate' /etc/proftpd/*.conf
# for example in tls.conf :
TLSRSACertificateFile		/etc/ssl/fullchain.pem
TLSRSACertificateKeyFile	/etc/ssl/private/privkey.pem
# Is this also needed?
TLSCACertificateFile		/etc/ssl/fullchain.pem

Dovecot conf.d/10-ssl.conf

  # doveconf -nPS | grep '^\s*ssl_'
  # or to find the file (eg. /etc/dovecot/conf.d/10-ssl.conf)
  # grep -r '^\s*ssl_' /etc/dovecot
ssl_cert=</etc/ssl/fullchain.pem
ssl_key=</etc/ssl/private/privkey.pem

Postgresql 9.6/main/postgresql.conf

Postgresql needs to be able to read these files as user "postgres". So they must be copied into it's config. dir. and chown'ed. Best done with a deploy-hook in /etc/letsencrypt/renewal-hooks/deploy/ :

10-certbot-postgresql
#!/bin/bash
 
## Postgresql needs to be able to read these files as user "postgres".
## So they must be copied into it's config. dir. and chown'ed.
 
verbose=1
 
if (( verbose )); then
	echo "Running $0"
	v_cp="-v"
	v_cw="-c"
fi
 
cp $v_cp /etc/letsencrypt/live/m1.almanet.ch/{fullchain,privkey}.pem /etc/postgresql/9.6/main/
chown $v_cw postgres:postgres /etc/postgresql/9.6/main/*.pem
 
# Reload is not enough! Restart is needed.
# Will not be needed from version 10
 
systemctl restart postgresql
# psql -U postgres -c "SELECT name, setting, sourcefile, sourceline FROM pg_settings WHERE name LIKE 'ssl_%_file'"
# or in the file postgresql.conf:
# grep '^\s*ssl_.*_file' /etc/postgresql/9.6/main/postgresql.conf 
ssl_cert_file = '/etc/postgresql/9.6/main/fullchain.pem'  # (change requires restart)
ssl_key_file  = '/etc/postgresql/9.6/main/privkey.pem'    # (change requires restart)

Use cron instead of systemd timers

I prefer crontab to the default systemd timers. So to disable the timers and use crontab instead:

systemctl --all list-timers
 
systemctl stop    certbot.timer
systemctl disable certbot.timer
systemctl mask    certbot.timer
 
m=$(( RANDOM % 60 )); h=$(( RANDOM % 24 )); d=$(( RANDOM % 7 ))
echo "## Let's Encrypt SSL cert. renewal, once per week" | tee -a /etc/crontab
echo "$m $h * * $d root /usr/bin/certbot -q renew"       | tee -a /etc/crontab
 
# dom=$(( 1+ RANDOM % 31 )) mon=$(( 1+ RANDOM % 12 ))
/docs/dokuwiki/data/pages/certbot.txt · Last modified: 2022-12-13 12:26:37 by mi