Deployment
Quick start (Docker Compose)
git clone https://github.com/mattmezza/monlight.git
cd monlight
cp deploy/secrets.env.example deploy/secrets.env
# Edit deploy/secrets.env with your API keys
docker compose up -d
This pulls pre-built images from GHCR (~15MB each). Services are available at ports 5010-5013.
Building from source
Use the monitoring compose file to build locally:
docker compose -f deploy/docker-compose.monitoring.yml up --build -d
This builds all four services from source using multi-stage Docker builds (Zig build stage + Alpine 3.21 runtime).
Reverse proxy (nginx)
An example nginx config is provided at deploy/nginx.conf.example. Key points:
- TLS termination at nginx
- Error tracker, log viewer, and metrics collector behind basic auth
- Browser relay must not have basic auth (browsers need direct access; auth is via DSN keys)
location /error-tracker/ {
auth_basic "Monitoring";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://127.0.0.1:5010/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
# Browser relay - NO basic auth (public endpoint)
location /browser-relay/ {
proxy_pass http://127.0.0.1:5013/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
Backups
deploy/backup.sh creates consistent SQLite backups using the .backup command (safe for WAL-mode databases).
./deploy/backup.sh # Back up all databases
./deploy/backup.sh errors # Back up only errors.db
./deploy/backup.sh logs metrics # Specific databases
| Variable | Default | Description |
|---|---|---|
BACKUP_DIR | deploy/backups | Where backups are stored |
DATA_DIR | deploy/data | Where live databases reside |
RETENTION_COUNT | 7 | Daily backups to keep per database |
Each backup runs PRAGMA integrity_check to verify validity. Old backups beyond RETENTION_COUNT are automatically pruned.
Recommended crontab:
0 3 * * * /path/to/deploy/backup.sh >> /var/log/monlight-backup.log 2>&1
The script has a commented-out section for S3-compatible upload (AWS, MinIO, Contabo).
Upgrades
deploy/upgrade.sh performs rolling upgrades with health verification:
./deploy/upgrade.sh # Upgrade all services
./deploy/upgrade.sh error-tracker # Single service
./deploy/upgrade.sh --no-backup --no-pull # Skip backup and git pull
| Flag | Description |
|---|---|
--no-pull | Skip git pull |
--no-backup | Skip pre-upgrade backup |
--force | Continue past health check failures |
The script:
- Tags current Docker images as
:rollback - Runs
backup.sh(unless--no-backup) - Pulls latest code (unless
--no-pull) - For each service: rebuilds, restarts, polls
/healthfor up to 60 seconds - On failure: prints exact rollback commands
Manual rollback:
git checkout <previous-commit>
docker compose -f deploy/docker-compose.monitoring.yml build <service>
docker compose -f deploy/docker-compose.monitoring.yml up -d --no-deps <service>
Smoke tests
deploy/smoke-test.sh runs end-to-end tests against all four services. Uses the test compose file with offset ports (15010-15013) and hardcoded test credentials.
docker compose -f deploy/docker-compose.test.yml up --build -d
./deploy/smoke-test.sh
docker compose -f deploy/docker-compose.test.yml down -v
Tests cover: health checks, error submission and deduplication, metrics ingestion, DSN key management, browser relay forwarding, CORS, source map upload, rate limiting, and graceful shutdown.
Resource limits
Each service runs within a 30MB Docker memory limit. The full stack uses under 50MB RAM.
| Service | Memory limit | Docker image size |
|---|---|---|
| Error Tracker | 30MB | <20MB |
| Log Viewer | 30MB | <20MB |
| Metrics Collector | 30MB | <20MB |
| Browser Relay | 30MB | <20MB |
CI enforces the 20MB image size limit. Docker images fail to publish if they exceed this threshold.
Releases
Releases are managed via the root Makefile:
make release-error-tracker V=1.0.0 # Single service
make release-services V=1.0.0 # All 4 Zig services
make release-python V=1.0.0 # Python SDK to PyPI
make release-js V=1.0.0 # JS SDK to npm
make release-all V=1.0.0 # Everything
make versions # Show current versions
Each release target bumps the version in source files, commits, tags, and pushes. CI handles building and publishing based on the tag:
| Tag pattern | CI action |
|---|---|
error-tracker-v* | Build + push Docker image to GHCR |
log-viewer-v* | Build + push Docker image to GHCR |
metrics-collector-v* | Build + push Docker image to GHCR |
browser-relay-v* | Build + push Docker image to GHCR |
python-v* | Publish to PyPI |
js-v* | Publish to npm |
Docker network
All services communicate on an internal Docker network (monlight). The browser relay connects to the error tracker and metrics collector via internal hostnames (http://error-tracker:8000, http://metrics-collector:8000). Only the exposed ports (5010-5013) are accessible from outside Docker.