= 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 [[https://httpd.apache.org/docs/2.4/bind.html|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
#!/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"
#!/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
#!/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"
#!/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
#!/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 [[https://github.com/certbot/certbot/issues/6722|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:
certbot-auto renew --cert-name $name --force-renewal
--test-cert
See them all with ''certbot-auto --help all | less''
See also:
* [[https://docs.python.org/3.5/library/http.server.html#http-server-cli]] "By default, server uses the current directory. The option -d/--directory ( new in version 3.7 ) specifies a directory to which it should serve the files. For example, the following command uses a specific directory: ''python -m http.server --directory /tmp/'' "
* [[https://github.com/certbot/certbot/issues/255|Standalone configurator: Dealing with existing processes that are listening on some, but not all, interfaces · Issue #255 · certbot/certbot]]
* [[https://github.com/certbot/certbot/issues/1515|Bind on a specific interface · Issue #1515 · certbot/certbot]] ( https://github.com/certbot/certbot/issues/1515#issuecomment-193790398 )
* [[https://github.com/certbot/certbot/pull/5990|Add support for specifying source_address to ClientNetwork. by signop · Pull Request #5990 · certbot/certbot]]
* [[https://github.com/certbot/certbot/issues/3489|Ability to set source IP · Issue #3489 · certbot/certbot]]
* [[https://github.com/certbot/certbot/pull/6007|WIP commit of adding a --source-address flag. by signop · Pull Request #6007 · certbot/certbot]]
== 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 [[https://superuser.com/questions/1432541|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=
#!/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 ))
{{tag>public linux debian systemd ssl}}