Concepts
Why nothing inside the network is trusted without proof, and how to run the CA that makes it possible.
This book is a working reference for putting mutual TLS between every internal component of a self-hosted environment, backed by a private certificate authority you run yourself. It opens with the case for doing it, then walks through standing up the CA, issuing and installing certificates, enforcing mTLS at the proxy layer, and, the part that actually determines whether this is sustainable, keeping renewal boring. Each configuration page names the pattern it represents so it can be adapted to other services and other hosts.
Why internal traffic shouldn't be trusted
The oldest assumption in network security is also the most dangerous one: that traffic is safe because it originated inside the perimeter. "It's coming from another host on our network" gets treated as if it were safe. It isn't, necessarily. It's just from a location, and locations are exactly what an attacker inherits the moment they compromise a single host.
On a flat internal network where services trust each other by IP or simply by being reachable, one compromised host can easily extend to the whole environment. The attacker pivots from the box they landed on to every service that assumedassumes internal callers wereare trustworthy, because nothing along the way askedasks them to prove anything. The blast radius of a single foothold is everything.
Mutual TLS (mTLS) breaks that assumption. It requires both ends of every internal connection to present a certificate proving who they are, issued by an authority both sides trust. A backend service configured for mTLS doesn't just encrypt the connection; it refuses to talk to a client that can't present a valid certificate. Being on the network is no longer enough. You have to hold a key.
The distinction from ordinary TLS matters and is often blurred:
- Regular TLS (one-way): the server proves its identity to the client, and the connection is encrypted. This is what a browser hitting a website does. The client is anonymous.
- Mutual TLS (two-way): the server proves its identity to the client and the client proves its identity to the server. Neither side talks to a party it can't verify.
For internal service-to-service traffic, one-way TLS solves the wrong half of the problem. Encryption alone stops eavesdropping, but it does nothing to stop an unauthorized host from connecting. mTLS is what turns "the traffic is encrypted" into "only known, authenticated components can communicate at all." That is the property that contains a compromise instead of letting it cascade.
Why a private certificate authority
Certificates need an issuer both ends trust. For public websites that's a public CA like Let's Encrypt. For internal service identity, a public CA is the wrong tool:
- Public CAs won't issue for internal names. Your internal services have names like
service.int.examplethat don't exist in public DNS and that no public CA will ever certify. Internal identity needs an issuer that will. - You want short lifetimes and full control. A private CA lets you issue certificates that live weeks, not years, and rotate constantly, which shrinks the value of a stolen key. You set the policy.
- The CA becomes your internal root of trust. Every host is configured to trust one CA, and from then on "do you hold a certificate this CA signed?" is the single question that gates internal communication. That root of trust is yours to run, not rented.
A private CA is, in effect, the identity system for machines, the same role Keycloak plays for users. Users authenticate to an identity provider; services authenticate to each other with certificates from the CA. Both answer the same underlying question: prove you are who you claim to be before I trust you.
Why step-ca
The CA in this environment is step-ca from Smallstep. The reasons it fit:
- Self-hostable and lightweight. It runs as a single service on an internal host, with no dependency on anyone else's infrastructure. For a self-hosted, privacy-focused environment, the machine identity root shouldn't live in someone else's cloud any more than the user identity root should.
- Built around short-lived certificates. step-ca's whole design philosophy is issue-often, expire-fast, automate-renewal, which is exactly the posture that makes stolen certs low-value. It makes the secure path the easy path.
- Standards-based and ACME-capable. It issues ordinary X.509 certificates and can speak ACME, so the knowledge and the certificates work with standard tooling (nginx, curl, anything that speaks TLS).
- Right-sized. It gives you a real CA, root, intermediate, provisioners, issuance policy, without standing up an enterprise PKI suite that would be absurd at this scale.
The honest tradeoff, and it's a real one: you now own a root of trust. If the CA's signing key is compromised, an attacker can mint certificates that every host will trust, so the CA host and its key material matter more than almost anything else in the environment. And because the certificates are short-lived by design, renewal must be automated and must work, or certificates silently expire and internal communication breaks all at once. Running a private CA trades "certificates I never think about" for "a small identity system I am responsible for operating." That trade is worth it for the containment it buys, but it is a trade, not a free win. The last page of this book is about the automation that makes the renewal half of that trade safe.
What the following pages cover
- How it fits the architecture: the CA's place, the trust chain, and the two-certificate model behind every internal connection.
- Standing up the CA: initializing step-ca, the issuance policy, running it as a service.
- Issuing and installing certificates: bootstrapping a host into the trust domain, and the two certificate types every mTLS connection uses.
- Enforcing mTLS at nginx: the config on both ends that turns "no valid certificate" into "no connection."
- Keeping renewal boring: the automation that makes certificate expiry a non-event.
- What I'd tell someone starting out: the lessons, including the ones learned the hard way.