# Coolify Deployment Configuration — ERP Nutzfahrzeuge --- ## Overview This document describes how to deploy the ERP Nutzfahrzeuge system on Coolify using Docker Compose. The system consists of 4 services: | Service | Image | Port | Health Check | |---------|-------|------|-------------| | Backend | Custom (Python 3.13-slim) | 8000 | `GET /api/v1/health` | | Frontend | Custom (Node 18-alpine) | 3000 | `GET /` | | PostgreSQL | `postgres:16-alpine` | 5432 | `pg_isready` | | Redis | `redis:7-alpine` | 6379 | `redis-cli ping` | --- ## Coolify Resource Setup ### Step 1: Create Resource 1. In Coolify, create a new resource 2. Select **Docker Compose** as the resource type 3. Connect your Forgejo/Git repository 4. Set the base directory to the project root 5. Coolify will detect `docker-compose.yml` automatically ### Step 2: Configure Environment Variables 1. Navigate to resource → **Environment Variables** 2. Add all variables from `.env.example` (see `deploy/env.md` for descriptions) 3. **Critical variables:** - `JWT_SECRET` — generate with `openssl rand -hex 32` - `POSTGRES_PASSWORD` — strong password for database - `CORS_ORIGINS` — production frontend URL (e.g., `https://erp.your-domain.com`) - `NEXT_PUBLIC_API_URL` — production backend URL (e.g., `https://api.your-domain.com/api/v1`) 4. **Optional but feature-dependent:** - `OPENROUTER_API_KEY` — required for AI features (OCR, retouch, copilot) - `MOBILE_DE_API_KEY` + `MOBILE_DE_SELLER_ID` — required for mobile.de integration 5. Click **Save** and redeploy ### Step 3: Configure Health Check In the resource settings: | Setting | Value | |---------|-------| | Health check path | `/api/v1/health` | | Health check port | `8000` | | Health check interval | `30s` | | Health check timeout | `5s` | | Health check retries | `3` | > **Note:** The health check targets the backend service. Docker Compose health checks are also defined per-service in `docker-compose.yml`. ### Step 4: Configure Persistent Storage Docker Compose volumes are defined in `docker-compose.yml`: | Volume | Mount Point | Purpose | |--------|-------------|---------| | `uploads` | `/data/uploads` (backend) | User file uploads (images, documents) | | `pgdata` | `/var/lib/postgresql/data` (postgres) | Database data | | `redisdata` | `/data` (redis) | Redis persistence (AOF) | In Coolify: 1. Ensure persistent storage is enabled for the resource 2. Verify volume names match the compose file 3. For production, consider using a managed PostgreSQL instance instead of the containerized one ### Step 5: Configure Domains / Routing 1. **Backend API:** - Set domain: `api.your-domain.com` (or subpath) - Port: `8000` - This is the primary entry point for Coolify health checks 2. **Frontend:** - Set domain: `erp.your-domain.com` (or root domain) - Port: `3000` - Next.js standalone server 3. **CORS:** - Set `CORS_ORIGINS` to the frontend domain - Set `NEXT_PUBLIC_API_URL` to the backend domain ### Step 6: Deploy 1. Click **Deploy** in Coolify 2. Wait for all services to build and start 3. Verify health checks pass (green status for all services) 4. Test endpoints: - `GET https://api.your-domain.com/api/v1/health` → 200 `{"status":"ok"}` - `GET https://erp.your-domain.com/` → 200 (frontend loads) - `GET https://api.your-domain.com/openapi.json` → 200 (API schema) --- ## Coolify Service Type - **Type:** Docker Compose (multi-service) - **Compose file:** `docker-compose.yml` (project root) - **Build:** Coolify builds images from `backend/Dockerfile` and `frontend/Dockerfile` - **Pre-built images:** `postgres:16-alpine`, `redis:7-alpine` --- ## Port Mapping | Service | Internal Port | External Port | Notes | |---------|---------------|---------------|-------| | Backend | 8000 | 8000 | FastAPI + uvicorn (4 workers) | | Frontend | 3000 | 3000 | Next.js standalone server | | PostgreSQL | 5432 | — (internal only) | Not exposed externally | | Redis | 6379 | — (internal only) | Not exposed externally | > In Coolify, only expose backend (8000) and frontend (3000) via domains. PostgreSQL and Redis should remain internal to the Docker network. --- ## Build Configuration ### Backend - **Base image:** `python:3.13-slim` - **System packages:** libpango, libcairo, libjpeg, libpng (for WeasyPrint + Pillow) - **Python venv:** `/opt/venv` - **Entry:** `uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 4` ### Frontend - **Base image:** `node:18-alpine` (multi-stage) - **Build:** `npm ci && npm run build` (standalone output) - **Entry:** `node server.js` - **Requires:** `output: 'standalone'` in `next.config.js` --- ## Post-Deploy Verification 1. All 4 containers are running and healthy 2. `GET /api/v1/health` → 200 `{"status":"ok"}` 3. Frontend loads at production URL 4. Login flow works: `POST /api/v1/auth/login` 5. CORS headers present for frontend origin 6. No errors in container logs 7. File uploads work (test upload to `/data/uploads`) 8. Database queries return expected data --- ## Troubleshooting | Issue | Cause | Solution | |-------|-------|----------| | Backend health check fails | DB not ready | Check `postgres` container health; increase `start_period` | | WeasyPrint errors | Missing system libs | Verify `libpango`, `libcairo` installed in backend image | | Frontend build fails | Missing `output: 'standalone'` | Add `output: 'standalone'` to `next.config.js` | | CORS errors | Wrong `CORS_ORIGINS` | Set to exact frontend domain (no trailing slash) | | AI features fail | Missing `OPENROUTER_API_KEY` | Set API key in Coolify environment variables | | mobile.de fails | Missing credentials | Set `MOBILE_DE_API_KEY` and `MOBILE_DE_SELLER_ID` | --- ## Rollback See `deploy/rollback.md` for the full rollback procedure. Quick rollback in Coolify: 1. Navigate to resource → **Deployments** 2. Find last known-good deployment 3. Click **Redeploy** 4. Verify health check passes