QCecuring - Enterprise Security Solutions

Public CA vs Private CA

Shivam Sharma

Key Takeaways

  • Public CAs are for external-facing services — their root certificates are pre-installed in every browser and OS trust store
  • Private CAs are for internal services — mTLS, VPN, Wi-Fi, service mesh — where you control both endpoints
  • Private CAs give you full control over certificate policy, validity periods, and issuance speed without per-certificate cost
  • Never use a private CA certificate on a public-facing server — browsers will reject it with an untrusted error

A Public CA is a certificate authority whose root certificate is pre-installed in browser and operating system trust stores (Mozilla NSS, Apple Keychain, Microsoft Root Program). Certificates it issues are automatically trusted by any client worldwide. A Private CA is one you operate yourself — its root certificate exists only in trust stores you explicitly configure (your domain-joined machines, your mobile fleet, your service mesh). Certificates from a private CA are meaningless to the outside world but give you complete control over issuance policy, validity periods, and certificate content for internal systems.


Why it matters

  • Trust scope determines architecture — public CAs work for anything the internet touches (websites, APIs, email). Private CAs work for anything you control both sides of (internal mTLS, VPN authentication, corporate Wi-Fi).
  • Cost at scale — public CA certificates cost $0 (Let’s Encrypt) to $500+/year (EV). Private CA certificates cost nothing per issuance — you pay for infrastructure, not per-cert fees. At 10,000 internal services, this matters.
  • Issuance speed — public CAs require domain validation (seconds to minutes) or organization validation (days). Private CAs issue instantly — no external validation needed because you already trust yourself.
  • Policy control — public CAs follow CA/Browser Forum rules (max 397-day validity, no internal names, no IP-only SANs for public trust). Private CAs follow whatever policy you define — 24-hour certs, internal hostnames, custom extensions.
  • Compliance boundaries — some regulations require certificates issued by audited public CAs for customer-facing services. Others require private CAs for internal systems to avoid exposing internal infrastructure names in Certificate Transparency logs.

How it works

Public CA issuance:

  1. CSR generation — generate key pair and CSR on your server with the public domain name as SAN.
  2. Domain validation — CA verifies you control the domain via HTTP challenge, DNS record, or email to admin contact.
  3. Issuance — CA signs the certificate. It’s logged in Certificate Transparency (CT) logs — publicly visible.
  4. Deployment — install on your web server. Any browser in the world trusts it immediately.
  5. Renewal — repeat before expiry (90 days for Let’s Encrypt, 397 days max for commercial CAs).

Private CA issuance:

  1. CA setup — deploy your CA infrastructure (Root CA offline, Issuing CA online) with your chosen key algorithm and policy.
  2. Trust distribution — push the Root CA certificate to all internal trust stores (GPO for Windows, MDM for mobile, ConfigMap for Kubernetes).
  3. CSR or auto-enrollment — internal services request certificates via SCEP, EST, ACME, or Active Directory auto-enrollment.
  4. Issuance — your CA signs immediately. No external validation. No CT logging. No public visibility.
  5. Deployment — install on internal services. Only devices with your Root in their trust store will accept it.

In real systems

Let’s Encrypt for public services:

certbot certonly --nginx -d api.example.com -d www.example.com
# Free, automated, 90-day validity
# Certificate appears in CT logs — anyone can see you issued it

step-ca for internal mTLS:

# Initialize private CA
step ca init --name "Internal CA" --dns ca.internal --address :443

# Issue certificate for internal service
step ca certificate svc.internal svc.crt svc.key --not-after 24h

# Services present certs to each other — mutual TLS

step-ca supports ACME, so internal services can use certbot or cert-manager against your private CA with the same automation patterns as Let’s Encrypt.

AWS Private CA for cloud workloads:

aws acm-pca issue-certificate \
  --certificate-authority-arn arn:aws:acm-pca:us-east-1:123456789:certificate-authority/abc \
  --csr fileb://service.csr \
  --signing-algorithm SHA256WITHRSA \
  --validity Value=365,Type=DAYS
# $400/month per CA + $0.75 per certificate
# HSM-backed, highly available, no infrastructure to manage

Kubernetes with cert-manager — both CAs:

# Public: Let's Encrypt for ingress
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
---
# Private: step-ca for service mesh mTLS
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: internal-ca
spec:
  acme:
    server: https://ca.internal/acme/acme/directory

Where it breaks

Private CA cert on a public-facing server — a team deploys an internal service to a public endpoint but uses a certificate signed by the private CA. Every external user sees “Your connection is not private” (ERR_CERT_AUTHORITY_INVALID). The certificate is cryptographically valid but the browser has no reason to trust your private Root. This happens during migrations when internal services become external without updating the certificate source.

Public CA for internal services — unnecessary exposure — using Let’s Encrypt for internal service-to-service communication means your internal hostnames appear in Certificate Transparency logs. Anyone can enumerate your internal service names (payments.internal.example.com, admin-api.staging.example.com). It also means you depend on external infrastructure (Let’s Encrypt availability, DNS validation) for internal communication. If your DNS provider has an outage, internal cert renewal fails. Private CAs have no external dependencies.


Operational insight

Certificate Transparency creates an asymmetry between public and private CAs that teams often overlook. Every certificate issued by a public CA is logged in append-only CT logs — searchable by anyone via crt.sh or similar tools. This is a security feature for the public web (it catches mis-issuance), but it’s an information leak for organizations that use public CAs for internal services. Attackers routinely monitor CT logs to discover subdomains, staging environments, and internal service names. If you issue a public certificate for jenkins.internal.corp.example.com, that name is now public knowledge. Private CAs don’t log to CT — your internal topology stays private. Use public CAs only for services that are already publicly discoverable.


Ready to Secure Your Enterprise?

Experience how our cryptographic solutions simplify, centralize, and automate identity management for your entire organization.

Stay ahead on cryptography & PKI

Get monthly insights on certificate management, post-quantum readiness, and enterprise security. No spam.

We respect your privacy. Unsubscribe anytime.