Description
step-ca (anciennement "step certificates") est un serveur de PKI privé open source qui fait trois choses principales :
- Autorité de certification X.509 : émet des certificats HTTPS pour vos services internes (homelab, k8s, microservices)
- Serveur ACME : expose le protocole ACMEv2 (comme Let's Encrypt, mais en privé)
- Autorité SSH : émet des certificats SSH (pour se passer de
authorized_keys)
Caractéristiques :
- ✅ Certificats courts (24-72h) avec rotation auto = si un cert fuite, il expire vite
- ✅ Multi-provisioners : ACME, OAuth OIDC (Keycloak, Okta, Azure AD), X5C, JWK, AWS/GCP/Azure instance identity, SCEP
- ✅ Compatible avec tous les ACME clients : Caddy, Traefik, certbot, acme.sh, win-acme, Apache, Nginx
- ✅ Backends DB : Badger (défaut), BoltDB, MySQL, PostgreSQL
- ✅ Clés RSA, ECDSA, EdDSA
- ✅ Peut agir comme intermédiaire d'une CA racine existante
- ✅ API REST + CLI
steppour scripter - ✅ Single binary
step-ca+ companion CLIstep
Positionnement : c'est l'alternative moderne à mkcert, cfssl, et aux scripts bash maison pour générer des certs. La grosse différence : step-ca est un serveur que vos services contactent pour obtenir un cert automatiquement (via ACME), pas un outil local.
Cas d'usage typiques :
- Homelab : certs HTTPS auto-signés pour tous vos services (sans popup de sécurité)
- Kubernetes / microservices : certs mTLS auto-renouvelés entre pods
- SSH sans mot de passe : certs SSH pour 50 serveurs, plus de clés à distribuer
- VPN mTLS : certs pour OpenVPN, WireGuard
- API gateway : certs clients pour authentifier des tiers
Différence avec Let's Encrypt : Let's Encrypt ne signe que pour des domaines publics vérifiables par DNS/HTTP. step-ca signe pour n'importe quel nom (interne, RFC1918, *.lan, etc.).
Public cible : admins qui veulent industrialiser la gestion des certificats (renouvellement auto, expiration courte, zero-touch), au-delà de la simple poignée de certs Let's Encrypt.
Installation
Option 1 : Docker Compose (serveur ACME privé)
# docker-compose.yml
version: '3.8'
services:
step-ca:
image: smallstep/step-ca:0.30
container_name: step-ca
restart: unless-stopped
entrypoint: /bin/sh
command: -c "step ca init --name='Internal CA' --dns='ca.example.com,ca.internal' --address=:9000 --provisioner='admin' --password-file=/home/step/secrets/password && step ca $(cat /home/step/secrets/args.txt)"
volumes:
- ./step:/home/step
- ./certs:/certs
ports:
- "9000:9000" # ACME + API
networks:
- pki
step-ca-renewer:
image: smallstep/step-ca:0.30
container_name: step-ca-renewer
restart: unless-stopped
entrypoint: /bin/sh
command: -c "while true; do step ca renew --daemon; sleep 12h; done"
volumes_from:
- step-ca
networks: [pki]
networks:
pki:
driver: bridge
⚠️ En prod, on génère généralement les clés hors Docker (sur la machine hôte) puis on monte les volumes. Voir la doc officielle.
Installation native (recommandée pour un CA)
# Linux wget https://github.com/smallstep/certificates/releases/download/v0.30.2/step-ca_0.30.2_amd64.deb sudo dpkg -i step-ca_0.30.2_amd64.deb # macOS brew install step # Init (une seule fois, crée la CA) step ca init \ --name "Internal Lab CA" \ --dns "ca.example.com,ca.local" \ --address ":9000" \ --provisioner "admin" \ --password-file ./ca-password.txt # Lancer step ca $(cat ./step-args.txt) # Lit la config générée par init
Variante : certs pour Caddy / Traefik (ACME)
# Caddyfile - Caddy utilise step-ca comme CA privée
{
acme_ca https://ca.example.com:9000/acme/acme/directory
acme_ca_root /path/to/ca-root.crt
}
app.internal {
respond "Hello from internal service"
}
# traefik.yml - Même chose pour Traefik
certificatesResolvers:
stepca:
acme:
caServer: https://ca.example.com:9000/acme/acme/directory
caCertificates: /path/to/ca-root.crt
storage: /acme.json
httpChallenge:
entryPoint: web
Configuration
- Initialiser la CA :
step ca init(crée~/.step/avec clés + config) - Démarrer step-ca : port 9000 par défaut, ACME sur
/acme/acme/directory - Distribuer la CA root : copier
~/.step/certs/root_ca.crtsur tous les clients (ou ajouter à la trust store) - Créer un provisioner pour chaque méthode d'auth (ACME, OIDC, JWK...)
- Pour les clients : utiliser
step ca certificate <hostname>(one-shot) ou un client ACME (renouvellement auto) - SSH :
step sshgénère des clés + certs à usage de l'utilisateur
# Exemple : cert pour un service web interne step ca certificate "app.internal" app.crt app.key \ --provisioner "admin" \ --san "app.internal" \ --not-after 720h # Exemple : cert SSH pour un user step ssh certificate [email protected] $(step ssh keygen) \ --provisioner "admin"
Alternatives
Open Source
- mkcert — Certs auto-signés locaux, simple mais pas de serveur
- cfssl (Cloudflare) — PKI en CLI/JSON, pas de serveur ACME
- HashiCorp Vault PKI — Secret manager + PKI dans la même boîte
- Dogtag (Red Hat) — CA enterprise complète, très complexe
- OpenXPKI — CA modulaire
- ejbca — CA Java enterprise
- Let's Encrypt (staging) — pour tester en sous-domaine public, pas interne
Propriétaires
- Smallstep Enterprise — la version commerciale de step-ca (multi-CA, OCSP, HA)
- Microsoft AD CS — Active Directory Certificate Services
- Venafi — gestion de PKI enterprise
- Keyfactor — PKI + IoT
Sécurité
- Certs courts : durée par défaut 24h pour les certs, 24h pour les provisioners
- HSM support (optionnel) : clés stockées sur YubiHSM, AWS CloudHSM, GCP HSM
- OCSP : step-ca peut servir des réponses OCSP
- CRL : Certificate Revocation List gérée
- Audit logs : toutes les émissions loggées
- mTLS pour l'API admin
- Provisioners multiples : un par contexte (ACME public, OIDC pour employés, etc.)
- Pas de stockage de clés privées : step-ca délègue la génération de clé au client (jamais transmise)
💡 Bonne pratique : séparer la CA root (offline, jamais sur le réseau) de la CA intermédiaire (en ligne, signe les certs). Si l'intermédiaire est compromise, on peut la revoquer sans tout refaire.
