Production-grade setup (root CA with intermediate CA) Linux

 

Production-grade setup (root CA with intermediate CA) Linux


🔐 1. Architecture (What changes vs basic setup)

Instead of:

Root CA → Server / Client certs

Production uses:

Root CA (offline, highly protected)
        ↓
Intermediate CA (online, signs certs)
        ↓
Server & Client Certificates

Why this matters

  • Root key is never exposed → reduces catastrophic compromise risk

  • You can rotate/revoke intermediates without replacing root

  • Enables scalable issuance across environments


🧱 2. Directory Structure (OpenSSL CA layout)

mkdir -p ~/pki/{root,intermediate}
cd ~/pki

# Root CA structure
mkdir -p root/{certs,crl,newcerts,private}
chmod 700 root/private
touch root/index.txt
echo 1000 > root/serial

# Intermediate CA structure
mkdir -p intermediate/{certs,crl,csr,newcerts,private}
chmod 700 intermediate/private
touch intermediate/index.txt
echo 1000 > intermediate/serial
echo 1000 > intermediate/crlnumber

🏛️ 3. Create Root CA (OFFLINE)

cd ~/pki/root

# Root private key (VERY sensitive)
openssl genrsa -out private/root.key 4096

# Root certificate (self-signed)
openssl req -x509 -new -nodes \
-key private/root.key \
-sha256 -days 3650 \
-out certs/root.crt

🔴 Best practice

  • Store root key offline (USB, HSM, air-gapped machine)

  • Never use it directly to sign server/client certs


🏗️ 4. Create Intermediate CA

cd ~/pki/intermediate

# Generate intermediate key
openssl genrsa -out private/intermediate.key 4096

# Create CSR
openssl req -new \
-key private/intermediate.key \
-out csr/intermediate.csr

Now sign it using the root CA:

cd ~/pki/root

openssl x509 -req \
-in ../intermediate/csr/intermediate.csr \
-CA certs/root.crt \
-CAkey private/root.key \
-CAcreateserial \
-out ../intermediate/certs/intermediate.crt \
-days 1825 -sha256

🔗 5. Create Certificate Chain

cat intermediate/certs/intermediate.crt root/certs/root.crt > intermediate/certs/ca-chain.crt

This chain is critical for:

  • NGINX trust

  • Client validation


🌐 6. Issue Server Certificate (via Intermediate)

cd ~/pki/intermediate

# Server key
openssl genrsa -out private/server.key 2048

# CSR
openssl req -new \
-key private/server.key \
-out csr/server.csr

Sign with intermediate:

openssl x509 -req \
-in csr/server.csr \
-CA certs/intermediate.crt \
-CAkey private/intermediate.key \
-CAcreateserial \
-out certs/server.crt \
-days 825 -sha256

👤 7. Issue Client Certificate

# Client key
openssl genrsa -out private/client.key 2048

# CSR
openssl req -new \
-key private/client.key \
-out csr/client.csr

# Sign
openssl x509 -req \
-in csr/client.csr \
-CA certs/intermediate.crt \
-CAkey private/intermediate.key \
-CAcreateserial \
-out certs/client.crt \
-days 825 -sha256

⚙️ 8. NGINX Production mTLS Config

server {
    listen 443 ssl;
    server_name your_domain;

    # Server cert + full chain
    ssl_certificate /etc/nginx/certs/server.crt;
    ssl_certificate_key /etc/nginx/certs/server.key;

    # Trust chain for client verification
    ssl_client_certificate /etc/nginx/certs/ca-chain.crt;

    # Enforce mTLS
    ssl_verify_client on;
    ssl_verify_depth 2;

    # Strong TLS
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;

    # Pass client identity upstream
    proxy_set_header X-Client-Cert $ssl_client_cert;
    proxy_set_header X-Client-Verify $ssl_client_verify;
    proxy_set_header X-Client-DN $ssl_client_s_dn;

    location / {
        proxy_pass http://backend;
    }
}

🔍 9. Identity & Authorization (Often Missed)

mTLS ≠ authorization.

After TLS succeeds, you should:

  • Extract client identity:

    • $ssl_client_s_dn

    • $ssl_client_i_dn

  • Enforce rules:

    • Only specific CNs or OUs allowed

    • Map cert → user/service

Example:

if ($ssl_client_s_dn !~ "CN=trusted-client") {
    return 403;
}

🚫 10. Revocation (CRL / OCSP)

Generate CRL

openssl ca -gencrl -out crl/intermediate.crl

Configure NGINX

ssl_crl /etc/nginx/certs/intermediate.crl;

Why important

  • You can revoke compromised client certs

  • Without this, certs remain valid until expiry


🔐 11. Key Security Practices

  • Use HSM or KMS (AWS KMS, HashiCorp Vault)

  • Rotate:

    • Intermediate CA every ~1–3 years

    • Server/client certs every ~60–90 days

  • Restrict file permissions:

chmod 600 *.key

📦 12. Automation (What real systems use)

Manual OpenSSL doesn’t scale. Production setups typically use:

  • HashiCorp Vault → dynamic cert issuance

  • cert-manager → Kubernetes-native automation

  • Smallstep Step CA → modern lightweight CA


⚠️ Common Production Pitfalls

  • ❌ Using root CA directly

  • ❌ No revocation mechanism

  • ❌ Long-lived client certs

  • ❌ No identity mapping (authZ gap)

  • ❌ Missing SAN (modern TLS ignores CN)


🧠 Final Mental Model

Think of production mTLS as three layers:

  1. Trust → Root + Intermediate CA chain

  2. Authentication → TLS handshake verifies certs

  3. Authorization → App decides “who is allowed”


If you want, I can go deeper into:

  • Full OpenSSL config files (openssl.cnf) for CA policies

  • Kubernetes mTLS (Istio / Linkerd)

  • Or a real-world architecture (API gateway + microservices)

Comments

Popular posts from this blog

Differences Between Ubuntu 24.04.2 LTS and Ubuntu 25.04

Kapardak Bhasma: A Comprehensive Review and use

Vanga Bhasma: A Traditional Ayurvedic Metallic Formulation and use