Sign inSign up

whumphrey/pki

By whumphrey

•Updated 6 days ago

A small PKI (Root CA → Intermediate CA → server certificates) packaged as a container

Image
Security
0

283

whumphrey/pki repository overview

⁠KISS PKI

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⁠


⁠Features

  • Two-tier CA created automatically on first start (Root + Intermediate)
  • One-command certificate issuing with IP and DNS SANs, safe renewals that keep the existing key and config
  • Dashboard on HTTP and HTTPS
    • Root CA, intermediate and CA bundle download with SHA-256 fingerprint
    • Live certificate, TLS session and request header panels
    • Upload inspector: check a certificate, chain or key, and whether they match
  • Issued-certificate browser (optional): browse and download certificates, keys and per-host zip files over HTTPS with password protection
  • Web issuing (optional, off by default): issue or renew certificates from the browser
  • Persistent data on the host: the CA survives image updates and rebuilds
  • Runs as a non-root user with configurable UID/GID

⁠Quick start

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:

  1. creates the Root and Intermediate CA if none exists,
  2. issues a certificate for the dashboard itself (pki.<DEFAULT_DOMAIN>) and renews it automatically when fewer than 30 days remain,
  3. publishes the public root CA certificate for download,
  4. starts the dashboard on HTTP (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.

⁠Issuing certificates

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.

⁠Configuration

VariableDefaultPurpose
PKI_UID, PKI_GID1000Container user; owner of files in ./data
PKI_WEB_HOSTpkiDashboard host name (becomes pki.<domain>)
PKI_WEB_IPemptyIP address in the dashboard certificate. Set to the Docker host's LAN IP
PKI_WEB_DNSemptyExtra DNS names, comma separated
PKI_BROWSE_USERadminUser name for the issued-certificate browser
PKI_BROWSE_PASSWORDemptyEnables the issued-certificate browser (min. 12 characters)
PKI_WEB_ISSUEfalsetrue lets the dashboard issue certificates
PKI_HTTP_HOST_PORT8080Host port for HTTP
PKI_HTTPS_HOST_PORT8443Host port for HTTPS

PKI defaults such as DEFAULT_DOMAIN, validity and key sizes live in pki.env.

⁠Commands

CommandPurpose
serveDefault. Initialise if needed and run the dashboard
idleKeep the container running for exec work only, no dashboard
initCreate the CA only
cert <host> [options]Issue or renew a certificate (same options as cert_gen.sh)
shellOpen a shell in the container
helpShow usage

⁠Security notes

  • Treat the dashboard as LAN-only. Do not publish port 8443 to the internet.
  • data/ca contains the root and intermediate private keys. Back it up encrypted and offline.
  • The issued-certificate browser is HTTPS-only, uses Basic authentication, locks out an address after 10 failed logins in 5 minutes, rejects path traversal and logs every download.
  • PKI_WEB_ISSUE=true lets anyone with the browse password sign certificates with your intermediate CA. Leave it off unless you need it.

⁠Backup

tar czf pki-backup-$(date +%Y%m%d).tar.gz data/

⁠Health check

curl http://<docker-host>:8080/__health.json

⁠License

See the GitHub repository⁠.

Tag summary

Content type

Image

Digest

sha256:8938f1ece…

Size

43.1 MB

Last updated

6 days ago

docker pull whumphrey/pki