The Nuisance of “Your connection is not private”
After auditing the security of over 10 internal servers in a previous project, I discovered a common reality: 90% of developers still use HTTP for management dashboards or rely on self-signed certificates. The problem is, no one remembers the expiration dates to renew them.
Every time you access an admin page and the browser shows that dreaded red slash, it feels unprofessional. However, using Let’s Encrypt on an internal network is a massive headache. You have to configure DNS-01 challenges or open ports to the Internet—something isolated networks don’t allow. That’s when I found step-ca.
Comparing Internal SSL Management Options
I tried several methods before settling on the final solution. Here is what I learned:
1. OpenSSL (Manual)
This is the traditional way: create a Root CA and use it to sign Certificate Signing Requests (CSRs).
- Pros: No complex server setup required.
- Cons: A nightmare to manage. If you have 50 microservices, remembering expiration dates to manually sign each one is an impossible and error-prone task.
2. HashiCorp Vault (Enterprise Grade)
Vault has a very powerful PKI engine and a complete API.
- Pros: Enterprise-grade security with a massive feature set.
- Cons: Overkill. Setting up a HashiCorp Vault Cluster just to issue SSL for a few internal servers is like using a tractor to go grocery shopping.
3. Smallstep (step-ca) – The Balanced Choice
This is the solution I’m currently applying to medium-sized projects and personal Homelabs.
- Pros: Supports the ACME protocol just like Let’s Encrypt. It enables 100% automated issuance and renewal via a smooth CLI.
- Cons: Requires a small amount of resources (VPS or Container) to maintain the CA service.
Why is step-ca worth using?
The “killer feature” of step-ca is that it tricks tools like Nginx or Caddy. These web servers think they are talking to Let’s Encrypt, but in reality, they are connecting to a CA server right inside your LAN. You get the convenience of automation without opening any ports to the Internet.
Detailed step-ca Deployment Guide
Step 1: Install step-cli
First, you need the step command-line toolkit. On Ubuntu, run the following commands:
wget https://github.com/smallstep/cli/releases/download/v0.24.4/step-cli_0.24.4_amd64.deb
sudo dpkg -i step-cli_0.24.4_amd64.deb
Next, install the main server:
wget https://github.com/smallstep/certificates/releases/download/v0.24.2/step-ca_0.24.2_amd64.deb
sudo dpkg -i step-ca_0.24.2_amd64.deb
Step 2: Initialize the Certificate Authority
Run the initialization command and follow the prompts:
step ca init
Note these important parameters:
- Deployment Type: Select
Standalone. - CA Name: e.g.,
Lab-Internal-CA. - DNS Names: Enter the IP or Domain of the CA server (e.g.,
ca.internal.lan). - Password: Never forget this password, as it protects the Root Key.
Step 3: Run the CA Server
You can activate the CA using the command:
step-ca $(step path)/config/ca.json
Pro tip: Set it up as a systemd service. Never run it temporarily in tmux; if the server crashes without you knowing, all future SSL renewals will fail.
Step 4: Install the Root Certificate
To prevent browser errors, you must install the root_ca.crt file on client machines. This file is located at ~/.step/certs/root_ca.crt.
The fastest way on another Linux machine is to use the command:
step certificate install root_ca.crt
Full Automation with ACME
To avoid running commands for every new service, enable the ACME feature:
step ca provisioner add acme --type ACME
If you use Caddy, the configuration is as simple as this:
app.internal.lan {
reverse_proxy localhost:8080
tls {
ca https://ca.internal.lan:9000/acme/acme/directory
ca_root /path/to/root_ca.crt
}
}
Caddy will automatically handle certificate retrieval and renewal. You can sleep soundly without worrying about certificates expiring in the middle of the night.
Important Notes for Managing an Internal CA
After running this for a while, I’ve learned three big lessons:
- Backup the Root Key: Losing the Root Key means you’ll have to reinstall the entire CA and re-trust every client machine. Keep it safe in Bitwarden or a secure USB drive.
- Adjust the Expiration: By default,
step-caonly issues 24-hour certificates to enhance security. If your auto-renewal system isn’t stable yet, increase this to 90 days in theca.jsonfile. - Secure the CA Server: This is the heart of your system. Secure the CA Server by limiting SSH access and closing all unnecessary ports. If the CA is compromised, an attacker can spoof any domain on your network.
Summary
Building an internal CA isn’t difficult if you choose the right tools. step-ca not only makes your system more professional but also fundamentally solves security issues within a LAN. If you’re managing a Homelab or a company’s internal system, give it a try today.
