Update: I (re)(re)setup Step CA in my homelab, hopefully for the last time! The following is from 2024-10-19 with updates from this week’s learnings.


I recently (re)setup a Step CA instance in my homelab.

By default, the root certificate generated by Step CA has a validity of 10 years, but I wanted that to be longer. So:

docker run --rm -it \
	-v ~/app-data/step-ca:/home/step smallstep/step-ca \
	step certificate create "SelfHostedCA" root_ca.crt root_ca_key \
	--profile root-ca \
	--not-after 2100-01-01T00:00:00Z \
	--no-password \
	--insecure

# Validate the actual expiration on the root certificate.
openssl x509 -in stepca/certs/root_ca.crt -noout -text

I then generated an intermediate {cert, key} pair:

docker run --rm -it \
	-v ~/app-data/step-ca:/home/step smallstep/step-ca \
	step ca init \
	--root root_ca.crt \
	--key root_ca_key \
	--password-file /home/step/secrets/password \
	--provisioner-password-file /home/step/secrets/provisioner_password

Couple of interesting things to note:

  • By default, Step CA uses the same password for both the intermediate pair and the first provisioner. I instead wanted to keep them separate, for no good reason to be honest, so I set that up using the two password parameters. (I just put 32-character random strings in the two files.)
  • The intermediate pair can always be regenerated from the root {cert, key} pair, similar to how I did above, so I didn’t create any backups for the former.
  • I moved the root key and the admin provisioner’s password to my password manager.

I found the following useful as well:

# Setup an ACME provisioner, for Traefik in my case.
docker run --rm -it \
	-v ~/app-data/step-ca:/home/step smallstep/step-ca \
	step ca provisioner add acme \
	--type ACME

# On a client device.
step ca bootstrap \
	--ca-url https://web-server-1.lan.ketanvijayvargiya.com:12001 \
	--fingerprint ...

# Generate an ad hoc certificate for some service. (See the long expiration - totally not recommended from a security perspective!)
step ca certificate pve.internal pve.crt pve.key \
	--not-after 2030-01-01T00:00:00Z