Let’s Encrypt certificates for internal servers
You want to get a TLS Certificate from Let’s Encrypt for an internal Nethserver installation that can’t be reached (specifically, can’t be reached on port 80) from the Internet. But the built-in support for Let’s Encrypt certs requires that your server be publicly accessible on port 80.
Nethserver 7 includes the capability to automatically obtain and renew a trusted TLS certificate from Let’s Encrypt. This is a very useful capability, but due to the method it uses to validate your control over your domain name, it isn’t suitable for internal servers that can’t be reached from the Internet. Fortunately, Let’s Encrypt supports another validation method that’s much more suitable for this use case.
The built-in Let’s Encrypt support relies on the HTTP-01 validation mechanism. For this to work, the Let’s Encrypt servers need to be able to connect to http://your_fqdn/.well-known/acme-challenge/pseudorandomfilename and obtain the right content from that URL. If your server isn’t accessible from the Internet, with port 80 open to the Internet, this won’t work.
The alternate validation mechanism is the DNS-01 validator. In this method, a DNS TXT record is created for _acme-challenge.your_fqdn, with a long pseudorandom string as its contents. This method is only practical for automated use if your DNS host provides an API to allow client software to update your DNS records automatically. Although this validator is supported by the official client, Certbot, it has better support from some of the third-party clients.
Here, I’m going to describe how to use acme.sh to obtain a cert using DNS validation, assuming your DNS is hosted at Cloudflare. Cloudflare provides DNS hosting at no cost, and they have a robust, well-supported API which works well for these purposes. However, acme.sh supports the APIs of a number of DNS hosts; the list, along with instructions for use, can be found in the adme.sh wiki. All the commands below will be run as root from the shell on your Neth server.
First, install acme.sh:
curl https://get.acme.sh | sh
This will download the script, install it in ~/.acme.sh/, and adjust your PATH to include that directory. Log out and back in.
Next, you’ll need to set some configuration database entries:
config setprop pki CrtFile /etc/pki/tls/certs/cert.pem
config setprop pki ChainFile /etc/pki/tls/certs/chain.pem
config setprop pki KeyFile /etc/pki/tls/private/privkey.pem
Then, you’ll need to set the environment variables corresponding to your DNS validation credentials. The example below is for Cloudflare; this is where you’d need to make adjustments if you use a different supported DNS host–see the link above to the acme.sh wiki for details.
Your API key can be obtained through your user control panel on Cloudflare. Cloudflare offers two keys, one with read-only access, and the other with full control. You’ll need to use the one with full control. The email address above is the address you used to register for Cloudflare.
Issue the certificate
Next, actually issue the certificate:
acme.sh --issue --dns dns_cf -d your_fqdn -d your_other_fqdn --cert-file /etc/pki/tls/certs/cert.pem --ca-file /etc/pki/tls/certs/chain.pem --key-file /etc/pki/tls/private/privkey.pem --renew-hook "/sbin/e-smith/signal-event certificate-update"
This command will issue your certificate, specify the paths for the cert, key, and chain files to be copied to, and indicate that
signal-event certificate-update is to be run whenever this cert renews. You can include as many FQDNs in the cert as you want by just adding more
-d fqdn parameters. As above, if you aren’t using Cloudflare, change
dns_cf to the appropriate one for your DNS host, as described at the wiki linked above.
Activate the certificate
Finally, since the renew-hook doesn’t run when the certificate is first issued, you’ll need to run that yourself. This will only be needed the first time you issue the certificate; renewals will run this command automatically:
That’s it! Your certificate is issued, and will renew automatically every 60 days.