DHIS2 certification assessments and W3C Verifiable Credential issuance.
- Docker and Docker Compose v2+
- Node.js 24+ (for running tests or scripts outside Docker)
graph TB
User([User / Assessor / Admin])
Public([Public Verifier])
subgraph Traefik["Traefik (TLS + Routing)"]
direction LR
R1["Host + PathPrefix /api/v1, /health → API"]
R2["Host + catch-all → Client"]
end
subgraph App["Application"]
Client["Client<br/>React + nginx"]
API["API<br/>NestJS"]
end
subgraph Data["Data Stores"]
DB[(PostgreSQL)]
Redis[(Redis)]
end
Vault["OpenBao Vault<br/>(optional)"]
User --> Traefik
Public --> Traefik
Traefik --> Client
Traefik --> API
API --> DB
API --> Redis
API --> Vault
cp .env.example .envThe defaults work as-is for local development. The seed creates an admin user with credentials printed to the migration container logs.
docker compose up --build -dThis runs:
| Service | Port | What it does |
|---|---|---|
dhis2-cert-db |
5432 | PostgreSQL 18 |
dhis2-cert-redis |
6379 | Redis 7 |
dhis2-cert-migrations |
— | Runs TypeORM migrations + seeds, then exits |
dhis2-cert-api |
3001 | NestJS API with hot reload (nest start --debug --watch) |
dhis2-cert-client |
3000 | Vite dev server with HMR |
The compose.override.yaml is auto-merged by Docker Compose — it swaps production images for local builds, mounts source code for hot reload, and exposes ports on 127.0.0.1.
# API health
curl http://localhost:3001/health/live
# Client
open http://localhost:3000API docs (Swagger): http://localhost:3001/api/v1/docs
For testing Vault-backed signing instead of ephemeral keys:
docker compose --profile vault up --build -dSet USE_VAULT=true in .env. The dev Vault runs in -dev mode with a root token of dev-root-token and auto-initializes the transit engine.
If you prefer running the API and client natively (DB and Redis still in Docker):
# Start only the infrastructure
docker compose up -d dhis2-cert-db dhis2-cert-redis
# API
cd api
npm ci
npm run migration:run
npm run seed
npm run start:dev
# Client (separate terminal)
cd client
npm ci
npm start# Logs
docker compose logs -f dhis2-cert-api
docker compose logs dhis2-cert-migrations
# Rebuild after Dockerfile changes
docker compose up --build -d
# Stop
docker compose down
# Stop and wipe volumes (full reset)
docker compose down -v
# Skip migrations on restart
SKIP_MIGRATIONS=true docker compose up -d
# Re-run seeds only
docker compose run --rm dhis2-cert-migrations sh -c "npm run seed"# API unit tests
cd api && npm test
# Client unit tests
cd client && npm test
# E2E (requires dev stack running)
cd client && npm run test:e2eapi/ NestJS backend (TypeORM, JWT auth, W3C VCs)
client/ React frontend (DHIS2 UI, Vite)
docker/ Init scripts, Vault config, nginx config
compose.yaml Base config (production-oriented)
compose.override.yaml Dev overrides (auto-merged)
compose.prod.yaml Production security hardening