Lets Encrypt - Set Separate Certificate Server with DNS-01 Challenge
Introduction
This contribution, like the last one, deals with a personal issue - the curing of my infrastructure.
I use Lets Encrypt certificates for my servers, both for my mail and web servers. All that TLS can talk, also uses TLS incl. Lets Encrypt.
Basically, this is very pleasant, as I receive free certificates through Lets Encrypt and can be automatically renewed by automating them in large parts.
To date, I mainly use the HTTP-01 Challenge. This allows it to validate specific domains (e.g. blog.justinritter.de) and then issue a certificate. However, the disadvantage is that I usually have to stop my web servers at this time and therefore my services are not available for a few seconds. There are also alternatives, but I do not use them so far.
The great disadvantage, however, is that I have to renew the certificates every time on several servers, which makes me unnecessary work.
For this reason, I will set up a separate certification server, which, with the DNS-01 challenge provided by Let's Encrypt, manages, reissues and lastly distributes all my server certificates.
As a result, I can run all my certificates with Wildcard certificates, so I effectively only need 1 certificate per domain and I can continue to renew the certificates fully automatically with a plugin for a DNS provider.
Requirements
I won't start here from 0. I assume that a properly set up server is already present (in my case based on Debian).
It should be noted here that the server later contains the most important data. If the server is taken over, your certificates are gone and, if necessary, penetration lines can also have access to your DNS system (if you use a plugin).
In my case, therefore, the server is hosted in my home network, only accessible in it and has no services running at it.
Furthermore, it is necessary to have a domain which can be reached publicly. Lets Encrypt does not issue internal certificates (for private IP addresses).
Installation
Installation Certbot
To receive certificates, the so-called Certbot is required.
This can be easily added to the repository or installed in my case by snapd.
sudo apt install python3-certbot
Here it is possible to quickly see if the Certbot is available - the following command is executed:
certbot --version
After entering the command I receive the following version:
certbot 2.4.0
If no result should come, the Certbot could not be installed correctly. If everything is good, you will also see a version number. Important is that the version must be higher 2.0! - Alternatively, you can install SNAP Certbot.
Installation of the Netcup plugin
The following step could look different for you:
In order to be able to install the certificates automatically, it is necessary in my case to install my provider Plugin (Netcup).
There is no plugin for me native of ACME, but "only" a community plugin. I have to install this with Python. I need a little extra work for this:
sudo pip3 install certbot-dns-netcup
Once the plugin is installed, I create a file with the data of my DNS provider to use the API.
vi /Pfad/zur/datei/.netcup-credentials.ini
dns_netcup_customer_id = 12345
dns_netcup_api_key = NETCUP_API_KEY
dns_netcup_api_password = NETCUP_API_PASSWORT
After that, rights are restricted
chmod 0600 /pfad/zur/datei/.netcup-credentials.ini
These steps can vary as you said if you use something other than netcup.
Generating a (wildcard) certificate
Lastly, certificates can be created. In my case, I just want to retrieve them but not install them. I also take care of the installation myself so that they are rolled out on all servers that need the certificates.
For this, the following command is entered:
sudo certbot certonly --authenticator dns-netcup --dns-netcup-credentials /pfad/zur/Credentials-Datei.ini --dns-netcup-propagation-seconds 900 --keep-until-expiring --non-interactive --expand --server https://acme-v02.api.letsencrypt.org/directory -d 'domain.de' -d '*.domain.de' --agree-tos --email mail@deine-email.de
Once this command is finished, you should get a confirmation that everything worked. You can then distribute the certificates to the affected servers.
In my case, this is done by NFS within my Control Plane. If you are interested in further action, you can read more. Otherwise, the following section is no longer interesting for you.
Prepare NFS on target server
In order to be able to use the certificates on the other servers, the infrastructure must first be built.
In my case, I would like to use NFS because I only work in the Controlplane network anyway, here should nobody be, the certificates can be easily exchanged via NFS. NFS is also the easiest to set up.
First a NFS server is installed on the target server
sudo apt install nfs-kernel-server
After this has been installed, an export is set up to which the Deployment Server must access. In my case, the deployment server is on my control plan via NAT and accesses the target server via the 192.168.50.0/24 and 192.168.51.0/24 network.
In the following I configure an export for the network 192.168.50.0/24. The deployment server accesses the target network via NAT via address 192.168.50.1/24 and the target server is in the network with address 192.168.50.10/24.
Create export on target server
To create an NFS export under Debian, the file "/etc/exports" is adjusted. Before that, a folder is created to be used for NFS. This is where the certificates come later.
mkdir /nfs/zielserver
chown nobody:nogroup /nfs/zielserver
chmod 777 /nfs/zielserver
vi /etc/exports
Once this has been done, the following text is written into the exports file:
/nfs/zielserver 192.168.50.1(rw,sync,no_subtree_check)
This creates the release. If you want to explain the flags in more detail, you can docu view.
As soon as this has happened, the command sudo service nfs-server restart
the service restarted. I don't think about things like the firewall configuration. In principle, the port 2049 is used, so of course it should be open. For example, with the following command.
sudo ufw allow in on <interface> from 192.168.50.1/24 to any port 2049
Once this has been done, the Share Deploy server can be hung. The /etc/fstab file is adjusted for this.
Here, too, I refer to the docue, as the functionality of NFS at Ubuntuusers (and this is hanging) is excellently described.
192.168.50.10:/nfs/zielserver /nfs/localcerts nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
Last with a mount -a
re-read the file and the share should then be available.
Automation and Deployment
In order to be able to automaitize the certificates adapted to me, I wrote a small script that allows to work with a JSON Config. This is find here.
This script is copied to a directory of your choice on the Deployment Server and then later called to the command at Certbot. At first, however, the Config must be created. In the following I give a small example of a domain on my server. More info can be found in the repo or alternatively you can simply write an email :).
{
"pure-smart.de":
[
{
"wildcard": true,
"base": true,
"domains": [
"*"
],
"target": [
"/nfs/publicServices/certificates/pure-smart.de/"
]
}
]
}
Further domains can also be inserted in the COnfig and SUbdomains can also be distinguished, this is described on Github in the Repo. We give the config when calling and then the certificates are automatically pushed to the NFS Shares. Soon I will have services restarted, but this is still in work and comes in an update.
Create and roll out certificates
Lastly, the certificate is requested as described above in the command, with the following addition:
sudo certbot certonly --authenticator dns-netcup --dns-plugin-credentials /dns/.credentials.ini --dns-plugin-propagation-seconds 900 --keep-until-expiring --non-interactive --expand --server https://acme-v02.api.letsencrypt.org/directory -d 'domain.tld' -d '*.domain.tld' --agree-tos --email mail@deinemail.tld --deploy-hook '/opt/deploy.py -domainspath="$RENEWEDLINEAGE" -reneweddomains="$RENEWEDDOMAINS"'
That was :) - After the certificates have been retrieved, you should find them in the target directories.
Back…