Deployment
Docker, CI/CD pipeline, and production infrastructure for the CPI platform.
Infrastructure Overview
| Component | Technology | URL |
|---|---|---|
| Admin Dashboard | React SPA (nginx) | cpi.lovinka.com |
| API | NestJS (Node.js) | api.cpi.lovinka.com |
| Documentation | Fumadocs (Next.js) | docs.cpi.lovinka.com |
| MQTT Broker | Mosquitto | mqtt.cpi.lovinka.com:8883/8885 |
| Database | PostgreSQL 16 + TimescaleDB | Internal |
| Cache | Redis 7 | Internal |
All services run as Docker containers on a Hetzner Cloud VPS behind an nginx reverse proxy with Let's Encrypt SSL.
Docker Images
Images are built and pushed to GitHub Container Registry (GHCR):
| Image | Source |
|---|---|
ghcr.io/lefteq/cpi-api | apps/api/Dockerfile |
ghcr.io/lefteq/cpi-admin | apps/admin/Dockerfile |
ghcr.io/lefteq/cpi-docs | apps/docs/Dockerfile |
All images use multi-stage builds:
- Pruner —
turbo pruneisolates the workspace - Installer — install deps and build
- Runner — minimal production image
CI/CD Pipeline
CI (ci.yml)
Triggered on push to main and pull requests:
- Lint, Typecheck & Build — runs on all PRs and pushes
- Build & Push Docker Images — only on
mainpush, pushes to GHCR - Docker Build Validation — on PRs, validates Docker builds without pushing
Deploy (deploy.yml)
Manual dispatch workflow:
- Generates
.envfile on VPS from GitHub secrets - Pulls Docker images from GHCR
- Restarts services with
docker compose up -d - Runs health checks against production URLs
Production Docker Compose
The production stack (docker/docker-compose.prod.yml) includes:
- cpi-postgres — TimescaleDB with persistent volume
- cpi-redis — Redis with password auth
- cpi-mosquitto — MQTT broker with TLS certificates
- cpi-api — NestJS API (depends on postgres + redis + mosquitto)
- cpi-admin — React SPA served by nginx
- cpi-docs — Next.js documentation site
Database Migrations
Migrations run automatically on API container startup (migrationsRun: true). No manual migration step needed during deployment.
Migration files are in apps/api/src/database/migrations/.
Always ensure the migration files are included in the Docker image. TypeORM will fail to start if migrations are missing.
Environment Variables
Key environment variables for production:
| Variable | Description |
|---|---|
DATABASE_URL | PostgreSQL connection string |
REDIS_HOST, REDIS_PASSWORD | Redis connection |
JWT_SECRET | Web API JWT signing key |
MQTT_JWT_SECRET | MQTT JWT signing key (separate from web) |
MQTT_USERNAME, MQTT_PASSWORD | Internal MQTT credentials |
HMAC_ENCRYPTION_KEY | AES-256 key for HMAC secret encryption at rest |
ADMIN_URL | CORS origin for admin dashboard |
SMTP_* | Email notification settings |
Health Checks
| Service | Endpoint |
|---|---|
| API | GET /api/v1/health |
| Admin | GET / (200 OK) |
| Docs | GET /docs (200 OK) |
| PostgreSQL | pg_isready |
| Redis | redis-cli ping |
Local Development
pnpm docker:up # Start infrastructure
pnpm dev:apps # Start API + Admin
pnpm dev:docs # Start documentation siteSee Getting Started for full setup instructions.