This would also be usable on non-%%FreeBSD%% systems.
**This guide uses the official client from the ''%%security/letsencrypt.sh%%'' port**
The [[BernardSpil/LetsEncrypt|guide]] using the !Lets_k_encrypt port\\
The [[BernardSpil/LetsEncrypt.sh|guide]] using the %%LetsEncrypt%%.sh port
You will want to check the [[BernardSpil/LetsEncrypt.sh]] guide for more detail.
===== Prepare user & directories =====
To make life easier all of the challenges (%%LetsEncrypt%% as well as keybase etc) will be hosted in a shared dir ''%%/usr/local/www/.well-known%%'' on the jail running my Apache server. The %%LetsEncrypt%% bits will land in ''%%/etc/ssl/letsencrypt%%'' on the host system. There's no requirement to run the interaction with the %%LetsEncrypt%% servers as root, so these will run as a non-privileged user. This unprivileged user will have to write to the ''%%acme-challenge%%'' and the directory that will contain the keys and certificates.
pw groupadd -n _letsencrypt -g 443
pw useradd -n _letsencrypt -u 443 -g 443 -d /etc/ssl/letsencrypt -w no -s /nonexistent
mkdir -m 770 /etc/ssl/letsencrypt
chown root:_letsencrypt /etc/ssl/letsencrypt
mkdir -p -m 775 /usr/jails/http/usr/local/www/.well-known/acme-challenge
chgrp _letsencrypt /usr/jails/http/usr/local/www/.well-known/acme-challenge
Adapt the ''%%.well-known/acme-challenge%%'' directory to your situation. It is assumed that a webserver is already installed and ''%%/usr/jails/http/usr/local/www%%'' already exists, otherwise the modes on the path elements to ''%%acme-challenge%%'' will be way to wide.
===== LetsEncrypt Script =====
This method uses the [[https://github.com/lukas2511/letsencrypt.sh|script from Lukas Schauer]] which he hosts on [[/GitHub|GitHub]]. This script does not require Python and doesn't have any requirements besides ''%%bash%%'' or ''%%zsh%%''. Download the script and default config from [[/GitHub|GitHub]]
fetch -o /etc/ssl/letsencrypt/letsencrypt.sh https://github.com/lukas2511/letsencrypt.sh/raw/master/letsencrypt.sh
fetch -o /etc/ssl/letsencrypt/config.sh https://github.com/lukas2511/letsencrypt.sh/raw/master/config.sh.example
chgrp _letsencrypt /etc/ssl/letsencrypt/{letsencrypt,config}.sh
The latest version of the script supports ''%%zsh%%'' but you'll have to invoke it as ''%%zsh letsencrypt.sh%%'' or alternatively modify the ''%%!#shebangs%%'' in the scripts.
===== Letsencrypt configuration =====
The default configuration file requires some changes, these are stored in ''%%/etc/ssl/letsencrypt/config.sh%%''
BASEDIR="/etc/ssl/letsencrypt"
WELLKNOWN="/usr/jails/http/usr/local/www/.well-known/acme-challenge"
alias openssl='/usr/local/bin/openssl'
To make use of %%LibreSSL%% (or %%OpenSSL%% from ports) you must add the ''%%alias openssl%%'' to the config script.
===== First run =====
You are now setup to actually run %%LetsEncrypt%%
cd /etc/ssl/letsencrypt
su -m _letsencrypt -c 'zsh ./letsencrypt.sh --cron'
(Replace zsh with bash if that's the shell you have installed)
===== Automate =====
Now you can schedule your certificate renewal job. By default the script will only renew if the remaining validity of your certificates is less than a month. A weekly job would thus be adequate.
As ''%%root%%''
#!/bin/sh
# Run script to renew certs
cd /etc/ssl/letsencrypt
su -m _letsencrypt -c 'zsh ./letsencrypt.sh --cron'
# Deploy certs if they've been renewed
domain="example.net"
targets="mail http"
for jail in ${targets}; do
[ -z "`diff -rq /etc/ssl/letsencrypt/certs/${domain}/fullchain.pem /usr/jails/${jail}/etc/ssl/certs/${domain}.pem`" ] && continue
cp -L "/etc/ssl/letsencrypt/certs/${domain}/privkey.pem" "/usr/jails/${jail}/etc/ssl/priv/${domain}.pem"
cp -L "/etc/ssl/letsencrypt/certs/${domain}/fullchain.pem" "/usr/jails/${jail}/etc/ssl/certs/${domain}.pem"
chmod 400 "/usr/jails/${jail}/etc/ssl/priv/${domain}.pem"
chmod 644 "/usr/jails/${jail}/etc/ssl/certs/${domain}.pem"
# Restart/-load relevant services
[ "${jail}" = "http" ] && jexec ${jail} service apache24 restart
[ "${jail}" = "mail" ] && jexec ${jail} service smtpd restart
done
You'll need to adapt your script for your requirements, this is merely an example of how it //could// be done.