Concepts
Architecture
How uPKI RA is structured and how it bridges ACME clients with the uPKI CA.
Architecture
Overview
uPKI RA is a FastAPI application that speaks ACME v2 on one side and ZMQ on the other. It is stateful: all ACME objects (accounts, orders, authorizations, certificates) are stored in a local SQLite database.
┌──────────────────────────────────────────────────┐
│ uPKI RA process │
│ │
│ ┌──────────────────────────────────────────┐ │
│ │ FastAPI / uvicorn │ │
│ │ │ │
│ │ /acme/* (public — RFC 8555) │ │
│ │ /api/v1/* (private — mTLS required) │ │
│ │ /api/client/* (client — mTLS required) │ │
│ │ /api/public/* (public — no auth) │ │
│ └──────────────┬───────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────┐ │
│ │ RegistrationAuthority │ │
│ │ (ZMQ REQ client → CA port 5000) │ │
│ └──────────────────────────────────────────┘ │
│ │ │
│ ┌──────────────▼───────────────────────────┐ │
│ │ SQLiteStorage │ │
│ │ accounts / orders / authorizations / │ │
│ │ challenges / certificates │ │
│ └──────────────────────────────────────────┘ │
└──────────────────────────────────────────────────┘
▲ │
ACME clients ZMQ REQ
(Traefik, etc.) CA port 5000
Core components
RegistrationAuthority
The main orchestrator (upki_ra/registration_authority.py). Initialises the ZMQ connection to the CA, manages bootstrapping, and exposes the ACME and admin operations to the route handlers.
Route modules
| Module | Path prefix | Auth | Description |
|---|---|---|---|
acme_api.py | /acme/ | JWS (ACME) | Full ACME v2 protocol |
public_api.py | /api/v1/public/ | None | Health check, CA cert download |
private_api.py | /api/v1/ | mTLS | Admin operations (issue, revoke…) |
client_api.py | /api/client/ | mTLS | Client-facing certificate operations |
SQLite storage
All ACME state lives in a single SQLite database file. Tables mirror ACME objects:
accounts— ACME accounts (JWK, contact, status)orders— Certificate orders (identifiers, status, expiry)authorizations— Per-identifier authorizationschallenges— HTTP-01/TLS-ALPN-01 challengescertificates— Issued certificate PEM and metadata
ZMQ connector
The RA maintains a persistent zmq.REQ socket to the CA on port 5000. All certificate operations are serialised as JSON and sent synchronously (request–reply).
Data directory layout
/data (UPKI_DATA_DIR)
├── ra.config.yml # RA configuration
├── ra.crt # RA TLS certificate
├── ra.key # RA TLS private key
├── ca.crt # CA certificate (downloaded from CA on bootstrap)
└── acme.db # SQLite ACME state
Startup sequence
- Parse CLI flags / environment variables
- Connect ZMQ REQ socket to CA port 5000
- Auto-bootstrap: if no
ra.crtfound, register with CA port 5001 and obtain a certificate - Configure uvicorn with the RA's TLS certificate (if
UPKI_RA_TLS=true) - Mount all route modules on the FastAPI app
- Start uvicorn event loop