Sign inSign up

toutzn/twit-pki-client

By toutzn

•Updated 6 months ago

Automated Certificate Lifecycle Manager sidecar. Auto-renews x509 certs without ACME challenges.

Image
Networking
Security
0

276

toutzn/twit-pki-client repository overview

⁠TWIT PKI Client 🛡️

A lightweight, fully automated Certificate Lifecycle Manager designed to run as a Docker Sidecar alongside your applications. Built on Alpine Linux, this image interacts with the TWIT PKI Manager to seamlessly bootstrap and auto-renew internal x.509 certificates without requiring inbound ACME HTTP challenges.

Docker Pulls Docker Image Size


⁠🎯 What it does

Instead of complex ACME port forwarding, this client uses an "Inside-Out" Bootstrapping model:

  1. Init: It generates a unique private key locally, creates a CSR, and uses an ephemeral PKI_TOKEN (JWK) to authenticate against the PKI Manager to obtain the first certificate.
  2. Daemon Mode: It stays alive and checks the certificate's expiration at a given interval (default 24h).
  3. Auto-Renew: When the certificate is about to expire, it automatically re-authenticates using the mathematically signed properties of its current certificate to acquire a new one.
  4. Action Hooks: Upon successful renewal, it can execute a POST_RENEW_HOOK (like restarting a Docker container or sending a SIGHUP) to ensure the target application loads the new certificate.

⁠⚙️ Environment Variables

VariableRequiredDefaultDescription
PKI_URLYesThe full URL to the /1.0/sign endpoint of your PKI Manager Project (e.g. https://pki.corp.local/api/root/1.0/sign)
PKI_DOMAINYesThe exact Common Name (CN) / Domain for the certificate
PKI_TOKENNo*A JWK One-Time Token (Only required for the very first initialization)
CERT_DIRNo/certsPath inside the container where the files (app.crt, app.key) are generated
RENEW_DAYSNo30Request renewal when the certificate expires in less than X days
POST_RENEW_HOOKNoA system shell command executed only after a successful renewal. See Architecture Patterns below.
CHECK_INTERVALNo86400Sleep interval in seconds between certificate checks (Default: 24h)

⁠🏗️ Architecture Deployments (Docker Compose)

Depending on your target application (the webserver that actually needs the certificate), you should choose one of three strategies for your docker-compose.yml.

⁠1. Nginx / Apache (SIGHUP Soft-Reload) 🏆

The most elegant way for classic webservers. The Sidecar shares the PID namespace with Nginx and sends a soft-reload signal, preventing any traffic drops. No Docker-Socket required.

services:
  nginx_server:
    image: nginx:alpine
    volumes:
      - shared-certs:/etc/nginx/certs:ro

  pki_sidecar:
    image: toutzn/twit-pki-client:latest
    pid: "service:nginx_server" # 👈 IMPORTANT: Share PID namespace
    environment:
      - PKI_URL=https://pki.corp.../1.0/sign
      - PKI_DOMAIN=web.pki.test
      - PKI_TOKEN=eyJhb...
      - POST_RENEW_HOOK=kill -s SIGHUP 1   # 💥 HOOK: Soft reload Nginx
    volumes:
      - shared-certs:/certs:rw

volumes:
  shared-certs:
⁠2. Traefik (Zero-Hook Hot-Reload) 🚀

Traefik's Dynamic Configuration Provider automatically watches its mounted certificate directories via Inotify. As soon as the PKI Sidecar updates the .crt file, Traefik hot-reloads it in milliseconds.

services:
  pki_sidecar:
    image: toutzn/twit-pki-client:latest
    environment:
      - PKI_URL=https://pki.corp.../1.0/sign
      - PKI_DOMAIN=gateway.pki.test
      - PKI_TOKEN=eyJhb...
      - POST_RENEW_HOOK="" # 💥 HOOK: Blank, Traefik natively watches files!
    volumes:
      - shared-certs:/certs:rw
# The Traefik container simply mounts "shared-certs:/certs:ro"
⁠3. Native Docker Restart (Generic / WUD) 🪚

For apps that cannot reload certificates on the fly (e.g. Node.js apps, Watchtower/WUD). The Sidecar controls the host Docker Daemon via a socket mount and issues a direct Docker restart command to the target container.

services:
  pki_sidecar:
    image: toutzn/twit-pki-client:latest
    environment:
      - PKI_URL=https://pki.corp.../1.0/sign
      - PKI_DOMAIN=app.pki.test
      - PKI_TOKEN=eyJhb...
      - POST_RENEW_HOOK=docker restart my_target_app_1 # 💥 HOOK: Hard restart
    volumes:
      - shared-certs:/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock # 👈 IMPORTANT: Host socket mount!

⁠🔒 File Permissions

The twit-pki-client creates cryptographic keys with secure 0600 permissions. If your target container runs as a strict non-root user (e.g., uid 1000), you may need to adjust the permissions so the target app can read app.crt and app.key. You can easily accomplish this by adding a chown chain directly into the POST_RENEW_HOOK:

POST_RENEW_HOOK=chown 1000:1000 /certs/app.* && docker restart my_app_1


Maintained by Toutzn⁠ - Built for the TWIT PKI Ecosystem.

Tag summary

Content type

Image

Digest

sha256:c85e8e33c…

Size

21.2 MB

Last updated

6 months ago

docker pull toutzn/twit-pki-client