Let's encrypt certs for internal hosts with HTTP challenge

Okay, so this is the #howto for dealing with this situation, this post is divided in 2 parts:

  • Problem: This describe a situation where this approach could come handy.
  • Solution: Implementation for solving the problem, I like to explain things in deep so when I came back and re-read myself I can just go straight an solve the problem.

As a way of clarifying things, the following naming conventions will be used:

  • Your public IP for this example is 123.123.123.123
  • proxy.my.domain.com will be used as the gateway/firewall/proxy server FQDN
  • internal1.my.domain.com, internal2.my.domain.com, internal3.my.domain.com will be used as the internal servers FQDN

Problem

You have a public domain, but you cannot manage the DNS related stuff, instead you’re obliged to ask a third party for any change regarding your domain
You depend on a DNS provider which doesn’t provide an DNS validation for acme-dns
You only have one public IP

Solution

This solutions has the following requirements

Also all this servers must have a common SSH key, you can find a way for accomplishing this here:

That being said, let’s begin:

  1. As stated in the default documentation, you need to open port 80 on proxy.my.domain.com (Assuming this host is associated to your public IP), to archive this go to [Network Services] -> [ httpd] -> [Edit] and allow the red interface.
    It is also necessary to ask your DNS provider to create for you one A record for each of your internal servers FQDN pointing to your public IP. You can check this by doing a DNS lookup over Google DNS like this:

     # dig +nocmd +noall +answer proxy.my.domain.com @8.8.8.8
     proxy.my.domain.com.	3599	IN	A	123.123.123.123
    
     # dig +nocmd +noall +answer internal1.my.domain.com @8.8.8.8
     internal1.my.domain.com.	3599	IN	A	123.123.123.123
    
     # dig +nocmd +noall +answer internal2.my.domain.com @8.8.8.8
     internal2.my.domain.com.	3599	IN	A	123.123.123.123
    
     # dig +nocmd +noall +answer internal3.my.domain.com @8.8.8.8
     internal3.my.domain.com.	3599	IN	A	123.123.123.123
    
  2. Connect to proxy.my.domain.com using SSH

  3. Make sure you can connect through SSH from proxy.my.domain.com to each internal server as root. This is needed since the script will need to copy files inside /etc/letsencrypt/, modify some properties and also use the commands /usr/libexec/nethserver/cert-list and signal-event certificate-update, all this on each internal server.

  4. Install python3, python3 devel, and python3 virtualenv. This can be done in NS 7.5 with the following command yum install python36.x86_64 python36-virtualenv python36-devel.x86_64. Please bear in mind that this package names may change.

  5. Create a python virtual environment for the script by issuing virtualenv-3 /opt/letsencrypt-cert-upd/env/

  6. Create the script file with the following commands mkdir -p /opt/letsencrypt-cert-upd/src/ and touch /opt/letsencrypt-cert-upd/src/copy-upd-cert.py

  7. Add the following code to the file /opt/letsencrypt-cert-upd/src/copy-upd-cert.py

  8. Create and edit the following file with this command nano /etc/e-smith/events/certificate-update/S80push_certs, put this inside /opt/letsencrypt-cert-upd/env/bin/python3.6 /opt/letsencrypt-cert-upd/src/copy-upd-cert.py. You can use any other file editor such as vim.

  9. Add a the property TransferToServers on pki object, this property will contain a comma separated list of the servers that will get a copy of the certificate. In order to do this use the following command config setprop pki TransferToServers 'interna1l.my.domain.com,internal2.my.domain.com,internal3.my.domain.com'

  10. On the web UI go to [ Server certificate] -> [ Request a new Let’s Encrypt certificate] -> [ REQUEST LET’S ENCRYPT CERTIFICATE]

That’s it, you can check if everything went smoothly by going to /etc/letsencrypt/ and checking if all servers has the *.pem certificate files. Also on the web UI of each server, in [ Server certificate] you can see the certificate being used as default.

@davidep, @alefattorini, as promised here is the #howto, please tell me if I have to do any further steps.

7 Likes

Hi Juan Carlos,

I wrote a howto on that subject. It is in French but with lot of screen captures.

Have a look: https://www.micronator.org/affaires/produit/nethserver-101cahier-04certificatletsencrypt/

You can use Google translate: https://translate.google.com/?hl=fr#view=home&op=translate&sl=auto&tl=es&text=Le%20Cahier-04%20du%20cours%20NethServer-101%20décrit%20la%20marche%20à%20suivre%20pour%20installer%20gratuitement%2C%20sur%20un%20serveur%20LOCAL%2C%20un%20certificat%20émis%20par%20Let’s%20Encrypt%20pour%20des%20communications%20TLS%2FSSL.

Michel-André

2 Likes

Hi again Juan Cralos,

My howto is based on the following:

There are other ways of getting Let’s Encrypt certs:
https://wiki.nethserver.org/doku.php?id=userguide:let_s_encrypt_for_internal_servers
https://wiki.nethserver.org/doku.php?id=userguide:let_s_encrypt_acme-dns

Michel-André

1 Like

@michelandre I checked both guides, they are well documented and I found them easy to understand, but in my case I couldn’t use DNS validation since my DNS provider doesn’t support any of the APIs listed on acme.sh documentation.

For the record I strongly recommend that any person needing to get a Let’s Encrypt certificate to first check the default documentation, then to try using either Let’s Encrypt for Internal Servers or Let’s Encrypt and acme-dns guides.

1 Like

Great work @jfernandez! I wikified your post and moved it to this new thread. Could you edit it and add some background information, explaining the problem?

1 Like

Sure, send me the link.

I was meaning this :slight_smile:

Let's encrypt certs for internal hosts with HTTP challenge

I like the idea of a prop!

Why installing additional dependencies?

It is possible to run scp to push certs to internal servers and ssh to run signal-event on internal servers from a simple Bash script.

1 Like

Is true, but I have zram enabled on all my servers, which also run a python script for turning on and off this feature and I’m more comfortable writing scripts in python. But is true that you can archive the same by using bash.

Very good howto. Thank you so much man