Your own private CA authority ? ACME for autoprovisionning ? yep !
Install and configure your own private CA using step-ca and acme.sh on the remote machines
August 10, 2020
sysadmin
certificate authority
step-ca
step-cli
pi-hole
acme.sh
https
self hosting
So you want to self host part 4 ?
So you have a bunch of services on your LAN by now, and they are hosted on private IPs, that bothers you because, well, could be nice to have https and a nice hostname for it no ?
Let’s do it with pi-hole, step-ca and acme.sh. For this example, we’ll add https support to a random nginx server and to the pihole web interface.
Prerequisites:
- 1 pi-hole DNS server
- 1 server with a vanilla nginx installed
- 1 server to install your new CA authority.
On the CA server:
/etc/systemd/system/step-ca.service ( since now debian is systemd by default, I assume most of us still running on other init system will have no trouble writing the init )
[Unit]
Description=step-ca
After=syslog.target network.target
[Service]
User=step
Group=step
ExecStart=/bin/sh -c '/usr/bin/step-ca /home/step/.step/config/ca.json --password-file=/home/step/.step/pwd 2>&1'
Type=simple
Restart=on-failure
RestartSec=10
AmbientCapabilities=CAP_NET_BIND_SERVICE
[Install]
WantedBy=multi-user.target
Now let’s install step-ca and step-cli
echo 'you should check https://github.com/smallstep/cli and https://github.com/smallstep/certificates for the latest releases'
wget https://github.com/smallstep/cli/releases/download/v0.14.6/step-cli_0.14.6_amd64.deb
wget https://github.com/smallstep/certificates/releases/download/v0.14.6/step-certificates_0.14.6_amd64.deb
sudo dpkg -i *.deb
sudo adduser step
sudo passwd -l step
sudo -u step -s
step ca init # put the password created in /home/step/.step/pw
exit
systemctl daemon-reload
systemctl start step-ca
sudo -u step -s
step ca provisioner add acme-provision --type ACME # if you change acme-provision here change it also in the url you use with acme.sh
killall -1 step-ca
step certificate fingerprint $(step path)/certs/root_ca.crt # NOTE THAT, THIS IS YOUR FINGERPRINT CAFP
echo 'next step is to get your new root certificate:'
echo "The new root certificate is in $(step path)/certs/root_ca.crt"
echo 'read the tips to change the default validity period of the certificates you issue'
On the random nginx webserver:
echo 'Use curl get.acme.sh | bash || install acme.sh using git'
echo 'Now you can either use the option --ca-bundle /path/to/root_ca.crt with acme, or add your root CA to the trust on the OS ( see tips )'
acme.sh --server https://YOURCAURLORIP/acme/acme-provision/directory --issue -d THEDOMAINTOPROVISION --nginx
acme.sh --server https://YOURCAURLORIP/acme/acme-provision/directory --install-cert -d THEDOMAINTOPROVISION --key-file WHEREYOUWILLPOINTNGINXFORASSLKEY --fullchain-file WHEREYOUWILLPUTYOURCERTFORNGING --reloadcmd "service nginx force-reload"
echo 'cron for acme renewal should have been setup but double check just in case'
Now configure nginx to add the newly created ssl /etc/nginx/sites-enabled/default
...
# of course the rest of the config is left to you reader, this is just a very simple example to add to an existing block
listen 443 ssl http2;
ssl on;
ssl_certificate WHEREYOUWILLPUTYOURCERTFORNGING;
ssl_certificate_key WHEREYOUWILLPOINTNGINXFORASSLKEY;
...
Let’s add https for the pi-hole web interface:
echo 'follow the tips to add the root_ca.crt to the trusted root CA on the server, then install acme.sh'
mkdir -p /var/www/ssl
mkdir -p /etc/lightttp/certs
echo 'server.modules += ( "mod_alias", "mod_openssl" )' > /etc/lighttpd/external.conf
echo 'alias.url += ( "/.well-known/acme-challenge/" => "/var/www/ssl/.well-known/acme-challenge/" )' >> /etc/lighttpd/external.conf
service lighttpd restart
echo 'you can use your CA url if you set an entry in /etc/hosts, since this machine should not have its dns resolving locally'
acme.sh --server https://YOURCAIP/acme/acme-provision/directory --issue -d YOURPIHOLEDNSENTRY -w /var/www/ssl
acme.sh --server https://YOURCAIP/acme/acme-provision/directory --install-cert -d YOURPIHOLEDNSENTRY --key-file /etc/lighttpd/certs/cert.key --fullchain-file /etc/lighttpd/certs/fullchain.cer --cert-file /etc/lighttpd/certs/cert.cer --reloadcmd "cat /etc/lighttpd/certs/cert.key /etc/lighttpd/certs/cert.cer > /etc/lighttpd/certs/combined.pem;service lighttpd restart"
echo '$HTTP["host"] == "YOURPIHOLEDNSENTRY" {' >> /etc/lighttpd/external.conf
echo ' # Ensure the Pi-hole Block Page knows that this is not a blocked domain' >> /etc/lighttpd/external.conf
echo ' setenv.add-environment = ("fqdn" => "true")' >> /etc/lighttpd/external.conf
echo '' >> /etc/lighttpd/external.conf
echo ' # Enable the SSL engine only for this specific host' >> /etc/lighttpd/external.conf
echo ' $SERVER["socket"] == ":443" {' >> /etc/lighttpd/external.conf
echo ' ssl.engine = "enable"' >> /etc/lighttpd/external.conf
echo ' ssl.pemfile = "/etc/lighttpd/certs/combined.pem"' >> /etc/lighttpd/external.conf
echo ' ssl.ca-file = "/etc/lighttpd/certs/fullchain.cer"' >> /etc/lighttpd/external.conf
echo ' ssl.honor-cipher-order = "enable"' >> /etc/lighttpd/external.conf
echo ' ssl.cipher-list = "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH"' >> /etc/lighttpd/external.conf
echo ' ssl.use-sslv2 = "disable"' >> /etc/lighttpd/external.conf
echo ' ssl.use-sslv3 = "disable" ' >> /etc/lighttpd/external.conf
echo ' }' >> /etc/lighttpd/external.conf
echo '' >> /etc/lighttpd/external.conf
echo ' # Redirect HTTP to HTTPS' >> /etc/lighttpd/external.conf
echo ' $HTTP["scheme"] == "http" {' >> /etc/lighttpd/external.conf
echo ' $HTTP["host"] =~ ".*" {' >> /etc/lighttpd/external.conf
echo ' url.redirect = (".*" => "https://%0$0")' >> /etc/lighttpd/external.conf
echo ' }' >> /etc/lighttpd/external.conf
echo ' }' >> /etc/lighttpd/external.conf
echo '}' >> /etc/lighttpd/external.conf
service lighttpd restart
And now you can visit https://YOURPIHOLEDNSENTRY, https on the pi-hole admin interface !
Additional tips:
- validity period of your certificates:
by default, step-ca issue certificates for 1day, you can either change the acme.sh cron to run every 12h and add –force option to force renewal or you can modify that to a more sane value editing the file $(step path)/config/ca.json, adding the claims section. Example:
{
"type": "ACME",
"name": "acme-provision",
"claims": {
"minTLSCertDuration": "168h",
"maxTLSCertDuration": "8760h",
"defaultTLSCertDuration": "1440h",
"disableRenewal": false
}
}
After modifying the file, reload the daemon or killall -1 step-ca
- install the root CA on a debian server:
To install the certificate on the system, and allow any tool to trust it:
# first upload your root_ca.crt on the server
# then copy it
cp root_ca.crt /usr/local/share/ca-certificates/
# and update the trust store
/usr/sbin/update-ca-certificates
- use step-cli on your laptop/workmachine:
To use step-cli to interact with your step-ca easily from your workstation ( install depends on your OS, see https://github.com/smallstep/cli )
# use the CAFP you got from installing the CA server
step-cli ca bootstrap --fingerprint CAFP --ca-url "CAURL"
# you can then use it to generate a certificate from your workstation:
step-cli ca certificate YOURDOMAIN YOURDOMAIN.crt YOURDOMAIN.key
# or generate a RSA key instead of ECDSA256:
step-cli ca certificate YOURDOMAIN YOURDOMAIN.crt YOURDOMAIN.key --kty RSA --size 4096
# or use step-cli to install the root certificate to the trust store:
step-cli certificate install ~/.step/certs/root_ca.crt
Conclusion:
you now can setup any kind of service privately hosted in your LAN, and use them as you see fit, you just add a local DNS record on the pi-hole admin interface, install your root certificate and acme.sh on the server and enjoy the simplicity of let’s encrypt, but self hosted :)