I wanted to setup a mail service on a staging server that would send all outgoing emails to a local mailbox. This avoids sending emails out to real users when running the staging server using production data.
First, install the postfix mail server:
apt install postfix
and choose the "Local only" mail server configuration type.
Then change the following in /etc/postfix/main.cf:
default_transport = error
to:
default_transport = local:root
and restart postfix:
systemctl restart postfix.service
Once that's done, you can find all of the emails in /var/mail/root.
So you can install mutt:
apt install mutt
and then view the mailbox like this:
mutt -f /var/mail/root
The Libravatar mirrors are setup using DNS round-robin which makes it a little challenging to automatically provision Let's Encrypt certificates.
In order to be able to use Certbot's
webroot plugin, I need to
be able to simultaneously host a randomly-named file into the webroot of
each mirror. The reason is that the verifier will connect to
seccdn.libravatar.org, but there's no way to know which of the DNS entries
it will hit. I could copy the file over to all of the mirrors, but that
would be annoying since some of the mirrors are run by volunteers and I
don't have direct access to them.
Thankfully, Scott Helme has shared his elegant
solution:
proxy the .well-known/acme-challenge/ directory from all of the mirrors to a single validation host.
Here's the exact configuration I ended up with.
DNS Configuration
In order to serve the certbot validation files separately from the main
service, I created a new hostname, acme.libravatar.org, pointing to the
main Libravatar server:
CNAME acme libravatar.org.
Mirror Configuration
On each mirror, I created a new Apache vhost on port 80 to proxy the acme challenge
files by putting the following in the existing port 443 vhost config
(/etc/apache2/sites-available/libravatar-seccdn.conf):
<VirtualHost *:80>
    ServerName __SECCDNSERVERNAME__
    ServerAdmin __WEBMASTEREMAIL__
    ProxyPass /.well-known/acme-challenge/ http://acme.libravatar.org/.well-known/acme-challenge/
    ProxyPassReverse /.well-known/acme-challenge/ http://acme.libravatar.org/.well-known/acme-challenge/
</VirtualHost>
Then I enabled the right modules and restarted Apache:
a2enmod proxy
a2enmod proxy_http
systemctl restart apache2.service
Finally, I added a cronjob in /etc/cron.daily/commit-new-seccdn-cert to
commit the new cert to
etckeeper automatically:
#!/bin/sh
cd /etc/libravatar
/usr/bin/git commit --quiet -m "New seccdn cert" seccdn.crt seccdn.pem seccdn-chain.pem > /dev/null || true
Main Configuration
On the main server, I created a new webroot:
mkdir -p /var/www/acme/.well-known
and a new vhost in /etc/apache2/sites-available/acme.conf:
<VirtualHost *:80>
    ServerName acme.libravatar.org
    ServerAdmin webmaster@libravatar.org
    DocumentRoot /var/www/acme
    <Directory /var/www/acme>
        Options -Indexes
    </Directory>
</VirtualHost>
before enabling it and restarting Apache:
a2ensite acme
systemctl restart apache2.service
Registering a new TLS certificate
With all of this in place, I was able to register the cert easily using the webroot plugin on the main server:
certbot certonly --webroot -w /var/www/acme -d seccdn.libravatar.org
The resulting certificate will then be automatically renewed before it expires.