Guides
Docker Deployment
Run uPKI RA in Docker or Docker Compose with production-ready settings.
Docker Deployment
Environment variables
The Docker image ships with these defaults:
| Variable | Image default | Description |
|---|---|---|
UPKI_DATA_DIR | /data | Data directory path |
UPKI_CA_HOST | upki-ca | CA hostname (ZMQ connection) |
UPKI_CA_PORT | 5000 | CA ZMQ port |
UPKI_RA_HOST | 0.0.0.0 | RA bind address |
UPKI_RA_PORT | 8000 | RA HTTP/HTTPS port |
UPKI_RA_TLS | true | Enable HTTPS (uses ra.crt/ra.key) |
UPKI_RA_SANS | upki-ra | SANs for the RA's own certificate (first boot only) |
Single container
docker run -d \
--name upki-ra \
-p 8000:8000 \
-e UPKI_CA_HOST=upki-ca \
-e UPKI_CA_SEED="${PKI_SEED}" \
-e UPKI_RA_SANS="upki-ra,ra.example.internal" \
-v upki-ra-data:/data \
ghcr.io/circle-rd/upki-ra:latest
Docker Compose (complete stack)
# docker-compose.yml
services:
upki-ca:
image: ghcr.io/circle-rd/upki-ca:latest
restart: unless-stopped
environment:
UPKI_DATA_DIR: /data
UPKI_CA_SEED: ${PKI_SEED}
UPKI_CA_HOST: 0.0.0.0
volumes:
- upki-ca-data:/data
networks:
- pki-net
healthcheck:
test:
- "CMD-SHELL"
- >
python -c "import socket; s=socket.socket(); s.settimeout(2);
s.connect(('127.0.0.1', 5000)); s.close()"
interval: 10s
timeout: 5s
retries: 10
start_period: 15s
upki-ra:
image: ghcr.io/circle-rd/upki-ra:latest
restart: unless-stopped
depends_on:
upki-ca:
condition: service_healthy
environment:
UPKI_DATA_DIR: /data
UPKI_CA_HOST: upki-ca
UPKI_CA_SEED: ${PKI_SEED}
UPKI_RA_TLS: "true"
UPKI_RA_SANS: "upki-ra,${DOMAIN}"
volumes:
- upki-ra-data:/data
ports:
- "8000:8000"
networks:
- pki-net
healthcheck:
test:
- "CMD-SHELL"
- >
python -c "
import os, urllib.request, ssl
tls = os.getenv('UPKI_RA_TLS','true').lower() not in ('false','0','no')
ctx = ssl.create_default_context() if tls else None
if ctx: ctx.check_hostname=False; ctx.verify_mode=ssl.CERT_NONE
urllib.request.urlopen(
('https' if tls else 'http')+'://localhost:8000/api/v1/public/health',
context=ctx, timeout=5)
"
interval: 15s
timeout: 10s
retries: 5
start_period: 30s
volumes:
upki-ca-data:
upki-ra-data:
networks:
pki-net:
internal: true
.env:
PKI_SEED=your-strong-random-seed-here
DOMAIN=ra.example.internal
UPKI_RA_SANS — important caveat
UPKI_RA_SANS is consumed only on the first boot when the RA registers with the CA. Changing it afterwards has no effect until the RA certificate is re-issued (re-registration).Always set all expected hostnames (Docker service name, FQDN, IP) before the first start.Example:
UPKI_RA_SANS=upki-ra,ra.example.internal,192.168.1.5
Data persistence
Mount UPKI_DATA_DIR as a named volume. This directory contains:
ra.crt/ra.key— RA TLS certificate and keyca.crt— downloaded CA certificateacme.db— SQLite ACME state
If the volume is lost, the RA will re-bootstrap on next start (generating a new certificate).