Concepts

Architecture

How uPKI CA is structured internally and how it communicates with the outside world.

Architecture

Overview

uPKI CA follows a single-process, single-authority model. All external communication happens over ZMQ sockets. There is no HTTP interface, no REST API, and no web UI — by design.

┌─────────────────────────────────────┐
│             uPKI CA process         │
│                                     │
│  ┌──────────┐     ┌──────────────┐  │
│  │ Authority │────▶│ FileStorage  │  │
│  └──────────┘     └──────────────┘  │
│       │                             │
│  ┌────▼────────────────────────┐    │
│  │    ZMQ REP Listeners         │    │
│  │  port 5000 (CA operations)  │    │
│  │  port 5001 (RA registration) │    │
│  └─────────────────────────────┘    │
└─────────────────────────────────────┘
        ▲                  ▲
   uPKI RA / CLI       new RA nodes
   (ZMQ REQ)           (ZMQ REQ)

Core components

Authority

The central singleton class (upki_ca/ca/authority.py). Responsible for:

  • Loading/creating the root key pair and self-signed certificate
  • Maintaining the certificate store and CRL
  • Executing all certificate operations (generate, sign, renew, revoke…)
  • Delegating persistence to the configured storage backend

ZmqListener (port 5000)

Handles all ongoing CA operations from registered RA nodes and admin tools:

  • Certificate sign / generate / renew / revoke / unrevoke / delete
  • CRL generation and retrieval
  • Profile listing and inspection
  • Admin node management (list_admins, add_admin, remove_admin)
  • ACME state synchronisation (acmesync*)

ZmqRegister (port 5001)

Accepts new RA node registrations. This socket is intentionally not protected by mTLS — it uses a shared seed as the authentication mechanism. Once an RA has registered, all further communication goes through port 5000.

Storage backends

BackendStatusUse case
FileStorageProduction-readyDefault. TinyDB for metadata, plain files for PEM data.
MongoStorageStub / experimentalFuture: centralised multi-CA deployments.

Data directory layout

/data (UPKI_DATA_DIR)
├── ca.config.yml       # CA configuration
├── ca.crt              # Root CA certificate (UPKI_CA_CERT_FILE)
├── ca.key              # Root CA private key  (UPKI_CA_KEY_FILE)
├── crl.pem             # Current CRL
├── nodes/              # Node certificates (one subdirectory per CN)
│   └── <cn>/
│       ├── cert.pem
│       └── key.pem
└── db/
    ├── nodes.json      # TinyDB — node metadata
    ├── certs.json      # TinyDB — certificate records
    └── admins.json     # TinyDB — admin list

Startup sequence

  1. Load or create root key + certificate from UPKI_DATA_DIR
  2. Apply configuration from ca.config.yml
  3. Bind ZMQ REP socket on port 5000
  4. Bind ZMQ REP socket on port 5001
  5. Enter event loop — process requests until SIGTERM/SIGINT
Copyright © 2026