As Let’s Encrypt doesn’t support wildcard certificates (yet) you may have to share your certificate between hosts. One such scenario could be if you run a Nginx Reverse Proxy and need a certificate for a domain on both the proxy host and the backend. One example is when running ZNC. In a normal situation you would buy a wildcard certificate and place the cert on both hosts. But with a Reverse Proxy in front, and only one public IP that would be impossible when using Let’s Encrypt as it would only allow you to generate certs on the proxy host.
To solve this you can create a share between the Nginx Reverse Proxy and the backend host over NFS, then update the cert on the backend (if needed) via a cronjob. In our case we needed a .pem file of all the Let’s Encrypt .pem files togheter to be able to host ZNC over SSL. In this guide “Nginx” is the reverse proxy server, and ZNC is the backend where we placed the ZNC server. Here is how it’s done.
-
Install NFS Server on the Proxy frontend, Nginx.
$~: sudo apt install nfs-kernel-server -y
-
Setup an exports file
$~: sudo nano /etc/exports
and place the folder that you want to share in that file
# /etc/exports: the access control list for filesystems which may be exported # to NFS clients. See exports(5). # # Example for NFSv2 and NFSv3: # /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check) # # Example for NFSv4: # /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check) # /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check) # /etc/letsencrypt 192.168.6.178(ro,async,no_root_squash,no_wdelay,no_subtree_check)
-
Set up which hosts that are allowed access, could be several
# /etc/hosts.allow: list of hosts that are allowed to access the system. # See the manual pages hosts_access(5) and hosts_options(5). # # Example: ALL: LOCAL @some_netgroup # ALL: .foobar.edu EXCEPT terminalserver.foobar.edu # # If you're going to protect the portmapper use the name "rpcbind" for the # daemon name. See rpcbind(8) and rpc.mountd(8) for further information. # portmap: 192.168.6.178 , 192.168.10.111 lockd: 192.168.6.178 , 192.168.10.111 rquotad: 192.168.6.178 , 192.168.10.111 mountd: 192.168.6.178 , 192.168.10.111 statd: 192.168.6.178 , 192.168.10.111
192.168.10.111 is just an extra host in our configuration which also have access to the Let’s Encrypt certs
-
Don’t forget to deny everything else
# /etc/hosts.deny: list of hosts that are _not_ allowed to access the system. # See the manual pages hosts_access(5) and hosts_options(5). # # Example: ALL: some.host.name, .some.domain # ALL EXCEPT in.fingerd: other.host.name, .other.domain # # If you're going to protect the portmapper use the name "rpcbind" for the # daemon name. See rpcbind(8) and rpc.mountd(8) for further information. # # The PARANOID wildcard matches any host whose name does not match its # address. # # You may wish to enable this to ensure any programs that don't # validate looked up hostnames still leave understandable logs. In past # versions of Debian this has been the default. ALL: PARANOID
-
Now restart NFS
$~: service nfs-kernel-server restart
-
Now go to the backend (ZNC) and add this in /etc/fstab
# NFS 192.168.16.201:/etc/letsencrypt/ /mnt/letsencrypt nfs auto 0 0
-
Create the mount dir on the backend
$~: sudo mkdir /mnt/letsencrypt
-
Install NFS on the backend
$~: sudo apt install nfs-common -y
-
Now mount the folder
$~: sudo mount -a
-
Check that it’s working
$~: sudo ll /mnt/letsencrypt
If the dir is listed and you can see all the certs that exists on the Nginx server then everything is OK.
Now we have to be sure that the certs are updated correctly so that they don’t become invalid in case they get updated. To do this we add a simple cronjob that checks if the parent file is older than the one in the mounted Let’s Encrypt dir. This isn’t needed on all setups, but ZNC especially demands a certain .pem file which contains all the Let’s Encrypt .pem files.
-
Before we create the script we have to generate the file
$~: cat /mnt/letsencrypt/live/irc.domain.se/{privkey,cert,chain}.pem > /home/user/.znc/znc.pem
-
Then start generating the script
$~: sudo nano /var/scripts/zncssl.sh
#!/bin/bash if [[ "/home/user/.znc/znc.pem" -ot "/mnt/letsencrypt/live/irc.domain.se/fullchain.pem" ]] then cat /mnt/letsencrypt/live/irc.domain.se/{privkey,cert,chain}.pem > /home/user/.znc/znc.pem fi
-
Make the file executable and add it as a cronjob that runs after the renew script for Let’s Encrypt is run (preferably)
$~: sudo chmod +x /var/scripts/zncssl.sh && crontab -e
-
Add this line to the crontab
42 18 * * * /var/scripts/zncssl.sh > /dev/null
-
Now use the znc.pem that we created as the SSLCertFile in ZNC
$~: sudo nano /home/techuser/.znc/configs/znc.conf
-
And add this line to your config
SSLCertFile = /home/user/.znc/znc.pem
-
Now everything is done, congrats you now have a free SSL from Let’s Encrypt on two hosts
If you later want to add more backends to access the Let’s Encrypt certs just add them to the /etc/hosts.allow file like we did in this guide.
Feel free to comment, and let us know if you find any errors in this guide.