Skip to main content

Building a selfhosted CA for my homelab

I run multiple applications in my homelab. Some within docker containers, some in Kubernetes and some running in VMs. Most applications support TLS or have it enabled by default but are using self signed certificates. This means I get a warning when loading the page. For external servers I’m using Lets Encrypt which is great, but not designed for internal use. In this post I’ll implement a self hosted Certificate Authority.

I’ve decided to use Step CA as it seems to be the most simple solution with most of the technical stuff taken care of by the tool. We’ll use the container for this which is smallstep/step-ca on Dockerhub. Let’s get into how to set this up.

Setting up the Step CA server

Using the below docker run command, spin up the step-ca container:

docker run -it -v /mnt/dockerConfigs/step-ca:/home/step -p 9000:9000 -e "DOCKER_STEPCA_INIT_NAME=HOMELAB" -e "DOCKER_STEPCA_INIT_DNS_NAMES=localhost,vmpdock03" -e "DOCKER_STEPCA_INIT_REMOTE_MANAGEMENT=true" -e "DOCKER_STEPCA_INIT_ACME=true" smallstep/step-ca

Once the container has started, note down the CA username and password as well as the fingerprint.

Edit the ca.json file under configs/ ensure you add this to the authority section. This allows you to issue certificates with an expiry of up to a year.

"claims": {
		    "minTLSCertDuration": "5m",
		    "maxTLSCertDuration": "8760h",
		    "defaultTLSCertDuration": "24h"
		}

Change the run command to a deamon so it runs without grabbing the console.

Install the step-cli

wget https://dl.step.sm/gh-release/cli/docs-ca-install/v0.23.2/step-cli_0.23.2_amd64.deb && dpkg -i step-cli_0.23.2_amd64.deb 

Bootstrap the cli:

step ca bootstrap --ca-url https://vmpdock03:9000 --fingerprint [FINGERPRINT FROM DOCKER OUTPUT]

Install the certificate on your PC

step certificate install $HOME/.step/certs/root_ca.crt

Install the certificate in the browser (if it doesn’t get it from the system store)

Securing TrueNAS with the new CA

Create a signed certificate for installation. In this case I’ll create one for TrueNAS. TrueNAS doesn’t have native ACME support so I’m going to make make the cert expire after a year.

step ca certificate truenas.lab.home truenas.crt truenas.key --not-after=8760h

It will ask which provisioner to use, given we aren’t on the truenas box we can’t use ACME. We will use “admin (JWK)”.

Upload the certificate and key to TrueNAS using System>Certificates ensure the type is set to “Import Certificate”. Copy and paste the certificate and private key.

Change the GUI SSL Certificate to the one just uploaded. System>General>GUI SSL Certificate. Restart the web service.

Once you visit the TrueNAS URL and click on the padlock, you should see “Secured by HOMELAB”.

July 2024 update: My TrueNAS certificate expired after a year and it was a nightmare to fix. When the cert expires and nginx restarts, it won’t serve on port 443 and I had 80 redirecting to 443.

SSH into TrueNAS, edit /etc/nginx/nginx.conf and comment the line that rewrites http to https. Stop nginx. Issue a new cert. Start nginx and update the cert using a http connection. Edit the nginx config to re-enable the http redirection

Secure nginx using ACME

On a couple of servers I have nginx installed as a reverse proxy. Let’s enable SSL using the ACME protocol. I’ve chosen certbot as the tool for interacting with ACME.

Jump onto a server with Nginx installed. Install certbot and certbot nginx plugin.

NOTE: I’ll make certbot part of my packer process later on so it’s already included on all servers.

apt install certbot python3-certbot-nginx

Copy the CA cert to the server (again, will include this in base image). Run the below command to automatically fetch and apply an SSL certificate for nginx.

sudo REQUESTS_CA_BUNDLE=/home/km/root_CA.crt certbot -d rundeck.lab.home --server https://192.168.20.107:9000/acme/acme/directory --nginx --register-unsafely-without-email

Secure Proxmox using ACME

Proxmox has ACME support already built in, to use this do the following:

SSH into the Proxmox box and run

cp /root/root_CA.crt /usr/local/share/ca-certificates/homelab.crt
update-ca-certificates
pvenode acme account register default kaine@example.com --directory https://192.168.20.107:9000/acme/acme/directory

This will have enabled the support for ACME using our CA. Order a certificate for the Proxmox server:

pvenode acme cert order