Files
aoc/DEPLOY.md
Tomas Kracmar fe95dfcfce
All checks were successful
Release / build-and-push (push) Successful in 21s
CI / lint-and-test (push) Successful in 25s
docs: update AGENTS.md, README.md, DEPLOY.md, ROADMAP.md for v1.7.14 security features
2026-04-27 16:52:35 +02:00

146 lines
4.9 KiB
Markdown

# Production Deployment Guide
## Overview
AOC runs as a set of Docker containers orchestrated by Docker Compose:
- **nginx** — reverse proxy, TLS termination, static file serving
- **backend** — FastAPI application (Gunicorn + Uvicorn workers)
- **mongo** — MongoDB data store (not exposed externally)
- **valkey** — Redis-compatible cache and async job queue (not exposed externally)
## Prerequisites
- Docker Engine 24+ and Docker Compose plugin
- A server with ports 80/443 reachable from your users
- TLS certificates (place in `nginx/ssl/` or use Let's Encrypt)
- A valid `.env` file at the repo root (see `.env.example`)
## Quick start
1. **Clone / pull the latest release**
```bash
git checkout v1.7.14
```
2. **Copy and edit environment variables**
```bash
cp .env.example .env
# Edit .env and fill in real credentials
```
3. **Set the release version**
```bash
export AOC_VERSION=v1.7.14
```
4. **Deploy**
```bash
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
```
5. **Verify**
```bash
curl http://localhost/health
curl http://localhost/api/events
```
## Updating to a new release
```bash
export AOC_VERSION=v1.7.14
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
```
## Enabling HTTPS
### Option A: Use your own certificates
1. Place `cert.pem` and `key.pem` in `nginx/ssl/`
2. Uncomment the HTTPS server block in `nginx/nginx.conf`
3. Uncomment the HTTP → HTTPS redirect server block
4. Reload nginx:
```bash
docker compose -f docker-compose.prod.yml exec nginx nginx -s reload
```
### Option B: Let's Encrypt with Certbot
Replace the `nginx` service in `docker-compose.prod.yml` with a Certbot-friendly setup (e.g., use the `nginx-proxy` + `acme-companion` stack) or mount the Certbot certificates into `nginx/ssl/`.
## Security Hardening
- MongoDB is **not exposed** to the host — only the backend container can reach it.
- Valkey/Redis is **not exposed** to the host — only the backend container can reach it.
- The backend runs as a non-root (`aoc`) user inside the container.
- nginx adds security headers (`X-Frame-Options`, `X-Content-Type-Options`, etc.).
- Keep `.env` out of version control — it is listed in `.gitignore`.
- Set `AUTH_ENABLED=true` and configure `AUTH_ALLOWED_ROLES` or `AUTH_ALLOWED_GROUPS` to restrict access to admin/security roles.
- Set explicit `CORS_ORIGINS` — do not use `*` in production when auth is enabled.
- Set `DOCS_ENABLED=false` to hide OpenAPI docs (`/docs`, `/openapi.json`).
- Configure `WEBHOOK_CLIENT_SECRET` to validate Graph webhook notifications.
- Set `LLM_ALLOWED_DOMAINS` if using AI features (e.g. `api.openai.com,*.openai.azure.com`).
- Set `SIEM_ALLOWED_DOMAINS` if using SIEM forwarding.
- Review `METRICS_ALLOWED_IPS` — defaults to private networks + loopback.
## Azure Key Vault (Optional)
To eliminate long-lived secrets from `.env`:
1. Create an Azure Key Vault and add these secrets:
- `aoc-client-secret` — your Graph app `CLIENT_SECRET`
- `aoc-llm-api-key` — your `LLM_API_KEY` (if using AI)
- `aoc-mongo-uri` — your `MONGO_URI`
- `aoc-webhook-client-secret` — your `WEBHOOK_CLIENT_SECRET`
2. Uncomment `azure-identity` and `azure-keyvault-secrets` in `backend/requirements.txt`
3. Set `AZURE_KEY_VAULT_NAME=your-keyvault-name` in `.env`
4. Grant the container identity `Get` permission on secrets:
- If using Azure Container Instances / AKS: assign a managed identity
- If using VM: assign a managed identity or use a service principal
- If using local Docker: authenticate via `az login` on the host
5. Rebuild and redeploy:
```bash
docker compose -f docker-compose.prod.yml up -d --build
```
## Rollback
```bash
export AOC_VERSION=v1.7.13
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d
```
## Monitoring
- Prometheus metrics: `http://your-host/metrics` (IP-restricted by default)
- Health check: `http://your-host/health`
- Container logs:
```bash
docker compose -f docker-compose.prod.yml logs -f backend
docker compose -f docker-compose.prod.yml logs -f nginx
docker compose -f docker-compose.prod.yml logs -f mongo
docker compose -f docker-compose.prod.yml logs -f valkey
```
## Troubleshooting
- **Auth warning in logs**: "AUTH_ENABLED is true but no AUTH_ALLOWED_ROLES or AUTH_ALLOWED_GROUPS are configured" — set these to restrict access.
- **CORS issues**: Set `CORS_ORIGINS` to your exact frontend origin(s). Wildcard with auth enabled disables credentials.
- **Rate limiting 429s**: Check Redis/Valkey connectivity. The rate limiter fails closed (returns 429) when Redis is down.
- **LLM errors**: Verify `LLM_BASE_URL` is in `LLM_ALLOWED_DOMAINS` if the allowlist is configured.
- **SIEM not forwarding**: Verify `SIEM_WEBHOOK_URL` uses HTTPS and is in `SIEM_ALLOWED_DOMAINS`.