A small PKI (Root CA → Intermediate CA → server certificates) packaged as a container
283
A small, self-hosted PKI in a container: Root CA → Intermediate CA → server certificates, built on plain OpenSSL and shell scripts, with a Python dashboard to download the root CA, inspect certificates and TLS sessions, and (optionally) browse and issue certificates from the browser.
Made for home labs and small offline networks. No CA database, no CRL, no OCSP, no daily complexity:
docker compose exec pki pki cert nas --ip 192.168.1.10
Source, full documentation and issues: https://github.com/nitr8/spki
Get docker-compose.yml from the GitHub repository, then create a .env file next to it:
cat > .env <<'EOF'
PKI_UID=1000
PKI_GID=1000
PKI_WEB_IP=192.168.1.50
PKI_BROWSE_PASSWORD=choose-a-long-passphrase
EOF
chmod 600 .env
docker compose up -d
docker compose logs -f pki
On first start the container:
pki.<DEFAULT_DOMAIN>) and renews it automatically when fewer than 30 days remain,8080) and HTTPS (8443).Open http://<docker-host>:8080/, download the root CA and trust it on your clients. Then use https://<docker-host>:8443/ for the full dashboard.
docker compose exec pki pki cert nas --ip 192.168.1.10
docker compose exec pki pki cert nas --ip 192.168.1.10 --dns files.acme.test
docker compose exec pki pki cert nas --ip 192.168.1.10 --force # renew
Results land in data/issued/<fqdn>/. Install <fqdn>.fullchain.pem and <fqdn>.key.pem on the device.
| Variable | Default | Purpose |
|---|---|---|
PKI_UID, PKI_GID | 1000 | Container user; owner of files in ./data |
PKI_WEB_HOST | pki | Dashboard host name (becomes pki.<domain>) |
PKI_WEB_IP | empty | IP address in the dashboard certificate. Set to the Docker host's LAN IP |
PKI_WEB_DNS | empty | Extra DNS names, comma separated |
PKI_BROWSE_USER | admin | User name for the issued-certificate browser |
PKI_BROWSE_PASSWORD | empty | Enables the issued-certificate browser (min. 12 characters) |
PKI_WEB_ISSUE | false | true lets the dashboard issue certificates |
PKI_HTTP_HOST_PORT | 8080 | Host port for HTTP |
PKI_HTTPS_HOST_PORT | 8443 | Host port for HTTPS |
PKI defaults such as DEFAULT_DOMAIN, validity and key sizes live in pki.env.
| Command | Purpose |
|---|---|
serve | Default. Initialise if needed and run the dashboard |
idle | Keep the container running for exec work only, no dashboard |
init | Create the CA only |
cert <host> [options] | Issue or renew a certificate (same options as cert_gen.sh) |
shell | Open a shell in the container |
help | Show usage |
data/ca contains the root and intermediate private keys. Back it up encrypted and offline.PKI_WEB_ISSUE=true lets anyone with the browse password sign certificates with your intermediate CA. Leave it off unless you need it.tar czf pki-backup-$(date +%Y%m%d).tar.gz data/
curl http://<docker-host>:8080/__health.json
See the GitHub repository.
Content type
Image
Digest
sha256:8938f1ece…
Size
43.1 MB
Last updated
6 days ago
docker pull whumphrey/pki