(λ (x) (create x) '(knowledge))

Simple SSL

Easy-RSA makes SSL Easy ยท December 26th, 2023

I've spent a long time putting off upgrading my homelab's services with SSL for a while now. I had a hand rolled PKI with multiple CA's way back when I first started homelabbing, but it became way too cumbersome to keep track of and work with. And despite having those old notes and setup scripts, it was all just very fragile and arcane. Remembering openssl invocation flags is just not high up on my list of important information. Attempting to port the notes over to my org-mode zettelkasten and fix what has long since expired really just never felt worth doing. This is a home lab! It doesn't NEED SSL, there's nobody using these things but me! So I let it languish.

And I ended up with Zabbix, and pihole, and grocy, and several other little web applications that could easily support a simple SSL certs not using them. Passwords going across the air in plain text out of laziness. It's the worst possible scenario. So I fixed it! And I'm glad I did because it was the perfect bite sized project to squeeze in right at the end of the year thanks to the magic that is easy-rsa. Frankly, whether you need a simple or complex PKI setup easy-rsa makes it so damn easy that there is literally no excuse to not do this. Seriously, it took less than an hour to piece it all together and fix.

Here I'll walk you through what I did to setup a very simple single node CA and throw some certs on my lighttpd servers. On Alpine you can install easy-rsa with apk add easy-rsa, this gets installed to /usr/share/easy-rsa. You'll want to cp -r that directory somewhere else to work on it.

In the new directory, cp vars.example -> vars then modify the following values. You can change anything you want here, it's kind of up to you. I left most of these as defaults aside from the location (because Maine is amazing). Realistically we shouldn't have a primary CA that doesn't expire for 10 years that issues our certs, we should use this to create a sub ca, but this is a homelab! We want simple and maintainable, not complex and confusing.

set_var EASYRSA_REQ_COUNTRY "US"
  set_var EASYRSA_REQ_PROVINCE "Maine"
  set_var EASYRSA_REQ_CITY "Portland"
  set_var EASYRSA_REQ_ORG "LambdaCreate"
  set_var EASYRSA_REQ_EMAIL "administration@lambdacreate.space"
  set_var EASYRSA_REQ_OU "LC"
  set_var EASYRSA_KEYSIZE 4096
  set_var EASYRSA_ALGO "ec"
  set_var EASYRSA_DIGEST "sha512"
  set_var EASYRSA_CA_EXPIRE 3650
  set_var EASYRSA_CERT_EXPIRE 825
  set_var EASYRSA_CRL_DAYS 180
  set_var EASYRSA_PRE_EXPIRY_WINDOW 90

Once configured, you need to build your PKI structure, then generate and issue your primary CA certificate. Walk through any prompts for the key creation, it'll be very simple prompts for password and serial numbering format.

./easyrsa init-pki
  ./easyrsa build-ca

You should end up with two files that define your CA.

pki/ca.crt
  pki/private/ca.key

The crt file is the public certificate for your new PKI, this is used to verify the certificates you issue and should be copied to remote systems. And then ca.key file is the private key of the CA that is used to sign and create new certificates. It is very important, and you should guard it as you would any other secret. If compromised you're redoing all of this. Fortunately, it isn't that much work anyways.

'

Now with the ca.crt created you'll want to copy it to any remote clients. SCP that sucker over to any client machines you have, or simply install it into the machine you're working on. I personally like to rename it from ca to the DN of the certificate information so I can quickly identify the certificate. Placing this cert into /usr/local/share/ca-certificates gives it a proper place to live, and appending it to /etc/ssl/certs/ca-certificates.crt with tee allows your system to load it like any other ca certificate in your chain.

sudo cp pki/ca.crt /usr/local/share/ca-certificates/lc.crt
  sudo cat /usr/local/share/ca-certificates/lc.crt | sudo tee -a /etc/ssl/certs/ca-certificates.crt
  sudo update-ca-certificates

Congrats that's all you need to setup the CA! Now lets do something useful with it, I said SSL certs at the beginning, so let's make one for my Zabbix server. First I'll need to generate a full chain certificate with no password, named to match the service the web host is providing.

easyrsa build-server-full zabbix nopass

Then I'll need to create a fullchain certificate, to do this I'll just combine the key of the new certificate, the crt of the new certificate, and the crt of the CA together into a PEM file, in that order.

cat pki/private/zabbix.key pki/issued/zabbix.crt pki/ca.crt > zabbix.pem

We just need to scp the generated .pem file to the /etc/ssl/certs/ directory on the Zabbix server and then add a quick snippet to the lighttpd.conf file to utilize it, and upgrade HTTP sessions to HTTPS. Just make sure that mod_openssl and mod_redirect are enabled, and then you can append this config snippet to the bottom of the conf file to start leveraging those SSL certs.

$SERVER["socket"] == ":443" {
			  ssl.engine = "enable"
			  ssl.pemfile = "/etc/ssl/certs/zabbix.pem"
	}

	#Redirect any http url to https at the same dest
	$SERVER["socket"] == ":80" {
	          $HTTP["host"] =~ "(.*)" {
	          url.redirect = ( "^/(.*)" => "https://%1/$1" )
	          }
	}

And that's it! Absolutely bite sized, and totally not something to put off for several years because the first time you did it was confusing and messy.

Bio

(defparameter *Will_Sinatra* '((Age . 31) (Occupation . DevOps Engineer) (FOSS-Dev . true) (Locale . Maine) (Languages . ("Lisp" "Fennel" "Lua" "Go" "Nim")) (Certs . ("LFCS"))))

"Very little indeed is needed to live a happy life." - Aurelius