Creating TLS Certificates for Home Use – Part 2

Part 1 was technically correct, but turns out that it’s too manual to be used by me:

  • you have to do it only once a while (once a year, because certs might have a 1 year validity time)
  • you don’t do it if it’s a lot of extra manual work

So here is Part 2 because I found something easier: Step CLI and Step CA.

The main difference to the openssl method (which continues to work): this CA runs as a service. So on the client side, you just need once to connect and then you can get certificates from a single place.

Get the releases and install, either as Debian package or tar file.

Extra step on ARMv7 (and possible all 32 bit architectures): replace “badger” with “badgerv2” in .step/config/ca.json. Also add those “claims” section under “authority” key unless you like the defaults:

    "authority": {
        "claims": {
            "minTLSCertDuration": "5m",
            "maxTLSCertDuration": "168h",
            "defaultTLSCertDuration": "24h",
            "disableRenewal": false,
            "minHostSSHCertDuration": "5m",
            "maxHostSSHCertDuration": "168h",
            "minUserSSHCertDuration": "5m",
            "maxUserSSHCertDuration": "24h"
        "provisioners": [

Then run your CA by

harald@opz3:~$ step-ca .step/config/ca.json --password-file step-ca-pw.txt
 2020/11/19 18:57:55 Serving HTTPS on :8443 …

To set up the client side, install step-cli and then do:

step ca bootstrap --ca-url https://opz3.lan:8443 \ 
                    --fingerprint 8d9345ed9c8f84729fb82005cf36b9e595c7a40efe2db52bee114c2dbdabd63d

The fingerprint you got during ca initialization, or get the root certificate and run a fingerprint:

# on CA server
> step ca root root.crt
> step certificate fingerprint root.crt

Once done, back on the client, getting a certificate is simple:

❯ step ca certificate m75q.lan m75q.crt m75q.key --provisioner-password-file ./pass.txt

and renew like this (–force to overwrite without asking):

❯ step ca renew --force m75q.crt m75q.key
# Or automated and restarting nginx:
❯ step ca renew --daemon --exec "nginx -s reload" m75q.crt m75q.key

Proper docs for step CLI and step CA. There’s also nice examples for mTLS

Update: See which gave me some hints how to decouple the key encryption passwords for the 3 different keys:

  1. the root CA key
  2. the intermediate CA key
  3. the provisioner key

To change the passphrases:

cd $(step path)
cd secret/
cp intermediate_ca_key intermediate_ca_key.original
openssl ec -in intermediate_ca_key.original | openssl ec -out intermediate_ca_key -aes256
read EC key 
read EC key 
Enter PEM pass phrase: <OLD PASSPHRASE>
writing EC key 
writing EC key 
Enter PEM pass phrase: <NEW_PASSPHRASE>
Verifying - Enter PEM pass phrase: <NEW_PASSPHRASE>

Now when you start your CA (via

step-ca .step/config/ca.json

it’ll ask for the passphrase of the intermediate certificate. Repeat for the root certificate. You can remove it to another place as it’s not used.

The JWK provisioner’s encryptedKey (see $(step path)/config/ca.json) still has the original passphrase from the initial setup. Let’s fix this:

❯ cd $(step path)/config
jq -r '.authority.provisioners[] | select(.type=="JWK") | .encryptedKey' ca.json | step crypto jwe decrypt > k.json
Please enter the password to decrypt the content encryption key: 

On the clients side you can now use the decrypted k.json like this:

❯ TOKEN=$(step ca token foo --provisioner "provisioner@name" --key k.json)
✔ Provisioner: provisioner@name (JWK) [kid: -6pq-22r6yaQg]
❯ step ca certificate foo foo.crt foo.key --token $TOKEN 

Update 2020-11-21: This is working so well, I made an Ansible Playbook to make (re-)installs much easier for me:

Renewing certificates is quite simple too (more details here):

step ca renew --daemon --exec "nginx -s reload" internal.crt internal.key

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.