Set Up a Local Certificate Authority
Set Up a Local Certificate AuthorityScience & Technology
kairenner-gh/slates
Last update 2 mo. agoCreated on the 23rd of March 2026

Why Let's Encrypt Cannot Help With Local Hostnames

Let's Encrypt validates domain ownership by making an HTTP request to your domain (HTTP-01 challenge) or by checking a DNS record you control (DNS-01 challenge). Both require a publicly reachable hostname. Your internal services — nextcloud.home.example.com resolving to 192.168.1.50 — are not reachable from the public internet, so Let's Encrypt cannot issue certificates for them. Without a trusted certificate, every browser on every device shows a warning every time anyone visits an internal service. Running step-ca as your own private CA eliminates that permanently.

Install step-ca and Initialize the CA

Download the step CLI tool and step-ca server from Smallstep's releases page for your architecture (arm64 for Raspberry Pi 5, armv7 for older models). Install the binaries to /usr/local/bin. Run step ca init to start an interactive setup: choose a name fo

Add the Root Certificate to Your Trust Stores

The root certificate file is at $(step path)/certs/root_ca.crt. On Linux, copy it to /usr/local/share/ca-certificates/ with a .crt extension and run sudo update-ca-certificates. On macOS, open Keychain Access, drag in the certificate, double-click it, and

Issue a Certificate for a Local Service

With step-ca running, use the step CLI to request a certificate for your service. Run step ca certificate nextcloud.home.example.com nextcloud.crt nextcloud.key — step will contact the CA, authenticate via the provisioner password, and write the signed ce

Configure the ACME Endpoint for Automatic Renewal

step-ca can serve an ACME endpoint so that Caddy uses the same ACME protocol it uses with Let's Encrypt, but against your local CA instead. In your CA configuration file (~/.step/config/ca.json), add an ACME provisioner. In the Caddyfile, add a tls block

Understand Mutual TLS for Internal Services

Mutual TLS (mTLS) means both sides of a connection present certificates — the server proves its identity to the client, and the client proves its identity to the server. This is more powerful than password authentication for service-to-service communicati

Steps to Trust the CA on All Devices

0%

Linux: copy root_ca.crt to /usr/local/share/ca-certificates and run update-ca-certificates

macOS: import into Keychain and set to Always Trust

Windows: import into Trusted Root Certification Authorities via certmgr.msc

iOS: install profile via Safari, then enable full trust in Settings under Certificate Trust Settings

Android: install via Settings > Security > Install from storage

If you ever need to rotate the root CA — because the key was compromised or the cert is expiring — you must redistribute the new root certificate to every device's trust store before the old one expires. Plan for this from the start. Keep a list of every device you trusted the CA on. Treat the root CA private key with the same care as a master password — it can sign any certificate your devices will trust without question.

What Comes Next

Your CA issues certificates using public-key cryptography — a root key signs an intermediate key, which signs your service keys. Those signatures are the building blocks you have been taking on faith until now. A password manager holds the secrets that protect those keys, and it turns out that self-hosting your password vault on your own infrastructure is a satisfying next step in this chain.