Production Deployment
Configuration
The API loads configuration from layered TOML files and environment variables:
config/default.toml # Base defaults (always loaded)
config/{APP_ENV}.toml # Environment overlay (optional)
config/local.toml # Local overrides (optional, gitignored)
Environment variables # Highest priority (APOLLON__ prefix)
Set APP_ENV=production to load config/production.toml.
Production Config Overrides
Override these settings for production via environment variables:
Server
| Variable | Production Value | Description |
|---|---|---|
APOLLON__SERVER__HOST | 0.0.0.0 | Bind address |
APOLLON__SERVER__PORT | 3000 | Port (or match your reverse proxy) |
APOLLON__SERVER__TRUST_PROXY | true | Trust X-Forwarded-For behind reverse proxy |
Database
| Variable | Description |
|---|---|
APOLLON__DATABASE__URL | PostgreSQL connection string with production credentials |
APOLLON__TIMESCALE__URL | TimescaleDB connection string with production credentials |
APOLLON__TIMESCALE__MAX_CONNECTIONS | Increase for higher throughput (default: 5) |
APOLLON__TIMESCALE__MIN_CONNECTIONS | Increase for faster cold starts (default: 1) |
Peplink Router
| Variable | Description |
|---|---|
APOLLON__PEPLINK__ROUTER_IP | Actual Peplink router IP (not the default 192.168.50.1) |
APOLLON__PEPLINK__USERNAME | Router admin username |
APOLLON__PEPLINK__PASSWORD | Router admin password |
Security
| Variable | Production Value | Description |
|---|---|---|
APOLLON__CORS__ALLOWED_ORIGINS | https://your-domain.com | Restrict to your domain (comma-separated) |
APOLLON__AUTH__API_KEYS | key1,key2,... | Enable API key authentication |
APOLLON__DOCS__SWAGGER_UI | false | Disable Swagger UI |
APOLLON__DOCS__OPENAPI_JSON | false | Disable OpenAPI JSON endpoint |
APOLLON__DOCS__GRAPHIQL | false | Disable GraphiQL playground |
Optional Services
| Variable | Description |
|---|---|
APOLLON__SENTRY__DSN | Sentry error tracking DSN |
APOLLON__RATE_LIMIT__WINDOW_MS | Rate limiting window (e.g., 900000 for 15 min) |
APOLLON__RATE_LIMIT__MAX_REQUESTS | Max requests per window (e.g., 100) |
APOLLON__FORWARDING__URL | GPS forwarding destination URL |
APOLLON__FORWARDING__TOKEN | GPS forwarding API token |
Logging
| Variable | Production Value | Description |
|---|---|---|
RUST_LOG | info or warn | Log level (avoid debug/trace in production) |
APOLLON__LOGGING__LEVEL | info | Application log level |
Health Monitoring
Health Endpoint
GET /health
The health endpoint checks both database connections:
| Status | HTTP Code | Meaning |
|---|---|---|
| Healthy | 200 OK | Both PostgreSQL and TimescaleDB are reachable |
| Unhealthy | 503 Service Unavailable | One or both databases are unreachable |
The health check executes SELECT 1 against each pool. The /health endpoint is exempt from rate limiting and API key authentication.
Docker Health Check
The container has a built-in health check:
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Monitoring Recommendations
- Point your uptime monitor (e.g., UptimeRobot, Pingdom) at
/health - Alert on HTTP 503 responses
- Monitor container health status via Docker/orchestrator
- Use Sentry (
APOLLON__SENTRY__DSN) for error tracking
Security Checklist
Before deploying to production, verify the following:
Authentication & Authorization
- API keys configured -- Set
APOLLON__AUTH__API_KEYSwith strong, unique keys - No default credentials -- Change all default
apollon/apollondatabase passwords - Peplink credentials -- Use non-default router credentials
Network
- CORS restricted -- Set
APOLLON__CORS__ALLOWED_ORIGINSto your specific domain(s) - TLS termination -- Run behind a reverse proxy (nginx, Caddy) with TLS
- Trust proxy enabled -- Set
APOLLON__SERVER__TRUST_PROXY=truewhen behind a reverse proxy - Database not exposed -- PostgreSQL and TimescaleDB ports not accessible from the internet
Developer Tools
- Swagger UI disabled --
APOLLON__DOCS__SWAGGER_UI=false - OpenAPI JSON disabled --
APOLLON__DOCS__OPENAPI_JSON=false - GraphiQL disabled --
APOLLON__DOCS__GRAPHIQL=false
Rate Limiting
- Rate limiting enabled -- Configure
APOLLON__RATE_LIMIT__WINDOW_MSandAPOLLON__RATE_LIMIT__MAX_REQUESTS
Container Security
- Non-root user -- Container runs as
apollon(UID 1001) by default - Read-only filesystem -- Mount with
--read-onlyand writable tmpfs for/app/cacheand/app/logs - No new privileges -- Run with
--security-opt=no-new-privileges - Resource limits -- Set memory and CPU limits
Data Protection
- Database backups -- Regular PostgreSQL and TimescaleDB backups
- Secrets management -- Database passwords, API keys, and tokens via environment variables or secrets manager (never in config files)
- Sentry configured -- Set
APOLLON__SENTRY__DSNfor production error tracking
Monitoring
- Health check configured -- External uptime monitor on
/health - Log aggregation -- Collect container logs (stdout/stderr)
- Security audit -- Nightly
cargo auditandpnpm auditvia CI (see CI/CD)
Example Docker Run
docker run -d \
--name apollon-api \
--restart unless-stopped \
--read-only \
--tmpfs /app/cache \
--tmpfs /app/logs \
--security-opt no-new-privileges \
--memory 512m \
--cpus 1.0 \
-p 3000:3000 \
-e APP_ENV=production \
-e APOLLON__DATABASE__URL=postgresql://user:pass@db:5432/apollon \
-e APOLLON__TIMESCALE__URL=postgresql://user:pass@tsdb:5433/apollon_tsdb \
-e APOLLON__PEPLINK__ROUTER_IP=10.0.1.1 \
-e APOLLON__PEPLINK__USERNAME=admin \
-e APOLLON__PEPLINK__PASSWORD=secure-password \
-e APOLLON__CORS__ALLOWED_ORIGINS=https://tracking.example.com \
-e APOLLON__AUTH__API_KEYS=key-abc123,key-def456 \
-e APOLLON__DOCS__SWAGGER_UI=false \
-e APOLLON__DOCS__OPENAPI_JSON=false \
-e APOLLON__DOCS__GRAPHIQL=false \
-e APOLLON__SENTRY__DSN=https://examplePublicKey@sentry.io/1 \
-e RUST_LOG=info \
ghcr.io/your-org/apollon/api:latest