diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml new file mode 100644 index 0000000..35aede2 --- /dev/null +++ b/docker-compose.coolify.yml @@ -0,0 +1,57 @@ +services: + backend: + build: + context: ./backend + dockerfile: Dockerfile + environment: + - OPENROUTER_API_KEY=${OPENROUTER_API_KEY} + - JWT_SECRET=${JWT_SECRET} + - APP_URL=${APP_URL:-https://ai.allucanget.biz} + - APP_NAME=${APP_NAME:-AI Allucanget} + - CORS_ORIGINS=${CORS_ORIGINS:-https://ai.allucanget.biz} + volumes: + - app-data:/app/data + networks: + - app-network + healthcheck: + test: [ "CMD", "curl", "-f", "http://localhost:12000/health" ] + interval: 30s + timeout: 10s + retries: 3 + start_period: 5s + expose: + - "12000" + + frontend: + build: + context: ./frontend + dockerfile: Dockerfile + environment: + - FLASK_SECRET_KEY=${FLASK_SECRET_KEY} + - BACKEND_URL=${BACKEND_URL:-http://backend:12000} + depends_on: + backend: + condition: service_healthy + networks: + - app-network + expose: + - "12001" + + nginx: + image: nginx:alpine + volumes: + - ./nginx/docker-compose.conf:/etc/nginx/conf.d/default.conf:ro + depends_on: + - backend + - frontend + networks: + - app-network + expose: + - "80" + +networks: + app-network: + driver: bridge + +volumes: + app-data: diff --git a/docs/7-deployment-view.md b/docs/7-deployment-view.md index 5acd00e..25b4de9 100644 --- a/docs/7-deployment-view.md +++ b/docs/7-deployment-view.md @@ -96,11 +96,11 @@ All services are containerized and orchestrated with `docker compose`: If using Coolify instead of Docker Compose: -1. **Backend Service**: Nixpacks build with base directory `/backend`, port 12000 -2. **Frontend Service**: Nixpacks build with base directory `/frontend`, port 12001 -3. **Reverse Proxy**: Coolify's built-in proxy or custom Nginx config -4. **Data Persistence**: Volume mount at `/app/data` for DuckDB +1. **Recommended Path**: Deploy `docker-compose.coolify.yml` as one Coolify Docker Compose resource +2. **Public Entry Point**: Route domain to `nginx` service on port 80; backend and frontend stay internal +3. **Data Persistence**: Named volume keeps DuckDB data at `/app/data` +4. **Fallback Path**: Use separate Nixpacks services only when one-stack Compose deploy is not suitable -**Note**: Both services must be on the same Coolify server or cluster for service-to-service communication via `http://localhost:12000` or service DNS names (depending on Coolify's networking setup). +**Note**: In Compose-based Coolify deployment, frontend reaches backend through Docker DNS at `http://backend:12000`. In Nixpacks-based deployment, use Coolify internal networking or colocate both services. **See**: [Coolify Deployment Guide](./deployment/coolify.md) for detailed instructions. diff --git a/docs/deployment/coolify.md b/docs/deployment/coolify.md index 9b8d5eb..c1412b5 100644 --- a/docs/deployment/coolify.md +++ b/docs/deployment/coolify.md @@ -8,10 +8,10 @@ The application supports two deployment approaches: ### Option 1: Docker Compose (Recommended) -- **Best for**: Local development, consistent environments, simplified deployment -- **See**: [Docker Compose Deployment Guide](./docker-compose.md) +- **Best for**: Coolify deployments, local development, consistent environments +- **Compose file**: `docker-compose.coolify.yml` in Coolify, `docker-compose.yml` locally - **Key benefits**: - - Same containerized environment locally and in production + - Same containerized services locally and in production - Built-in service orchestration and networking - Easy volume management for data persistence - Better debugging and log viewing @@ -24,7 +24,7 @@ The application supports two deployment approaches: - Requires separate services setup in Coolify UI - Manual environment variable configuration per service -This guide covers **Option 2 (Nixpacks)**. For **Option 1 (Docker Compose)**, see the [Docker Compose Deployment Guide](./docker-compose.md). +This guide covers both Coolify paths. Use **Option 1 (Docker Compose)** for new deployments. Use **Option 2 (Nixpacks)** only if you need separate Coolify services instead of one stack. ## Architecture Overview @@ -46,6 +46,55 @@ Coolify's built-in reverse proxy routes traffic: - Git repository pushed to `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git` - Domain configured to point to your Coolify server +## Option 1: Deploy with Docker Compose in Coolify + +Use Coolify's **Docker Compose** resource with the dedicated compose file `docker-compose.coolify.yml`. + +### Step 1: Create Docker Compose Resource + +1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Docker Compose** +2. Connect your Git repository (`git.allucanget.biz`) +3. Select the `ai.allucanget.biz` repository and `main` branch +4. Set **Compose File** to `docker-compose.coolify.yml` +5. Set **Base Directory** to `/` +6. Select the `nginx` service as the public-facing service on port `80` +7. Click **Create Resource** + +### Step 2: Configure Environment Variables + +Add these in Coolify before first deploy: + +| Variable | Service | Example | +| -------------------- | ---------- | --------------------------- | +| `OPENROUTER_API_KEY` | `backend` | `sk-or-v1-...` | +| `JWT_SECRET` | `backend` | `openssl rand -hex 32` | +| `APP_URL` | `backend` | `https://ai.allucanget.biz` | +| `APP_NAME` | `backend` | `AI Allucanget` | +| `CORS_ORIGINS` | `backend` | `https://ai.allucanget.biz` | +| `FLASK_SECRET_KEY` | `frontend` | `openssl rand -hex 32` | +| `BACKEND_URL` | `frontend` | `http://backend:12000` | + +### Step 3: Configure Domain and Proxy + +1. Attach domain `ai.allucanget.biz` to `nginx` service +2. Enable **Auto HTTPS** in Coolify +3. Let Coolify terminate TLS and forward traffic to `nginx:80` + +`docker-compose.coolify.yml` does not publish host ports `80/443`. This avoids conflicts with Coolify's own proxy while keeping backend and frontend reachable over internal Docker network. + +### Step 4: Persistent Storage + +`docker-compose.coolify.yml` uses named volume `app-data` for DuckDB persistence at `/app/data`. No extra host bind mount needed for default setup. + +### Step 5: Deploy and Verify + +1. Start deployment in Coolify +2. Confirm `backend` becomes healthy +3. Open `https://ai.allucanget.biz/health` or proxied health route configured in Coolify +4. Open main domain and verify frontend loads + +## Option 2: Deploy with Nixpacks in Coolify + ## Step 1: Create Backend Service 1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** @@ -56,9 +105,11 @@ Coolify's built-in reverse proxy routes traffic: 6. **CRITICAL: Set Base Directory to `/backend`** — this tells Nixpacks to look in the `backend/` subdirectory for `requirements.txt` and the Python application 7. Set **Ports Exposed** to `12000` 8. Set **Start Command** to: + ```txt uvicorn app.main:app --host 0.0.0.0 --port 12000 ``` + 9. Click **Create Resource** > **Important:** Nixpacks copies the **contents** of the Base Directory to `/app/` in the container. When Base Directory is `/backend`, the `backend/` folder wrapper is removed — only `app/`, `tests/`, and `requirements.txt` are copied. Therefore the start command uses `app.main:app` (not `backend.app.main:app`). @@ -84,13 +135,14 @@ Add these as **Runtime** environment variables in Coolify: 5. **CRITICAL: Set Base Directory to `/frontend`** — this tells Nixpacks to look in the `frontend/` subdirectory for `requirements.txt` and the Python application 6. Set **Ports Exposed** to `12001` 7. Set **Start Command** to: + ```txt gunicorn app.main:app --bind 0.0.0.0:12001 --workers 2 --timeout 120 ``` + 8. Click **Create Resource** > **Note:** The frontend uses `requirements.txt` for production dependencies and `requirements-dev.txt` for development dependencies (like pytest). Nixpacks will automatically detect and install only the production dependencies. - > **Important:** Nixpacks copies the **contents** of the Base Directory to `/app/` in the container. When Base Directory is `/frontend`, the `frontend/` folder wrapper is removed — only `app/`, `tests/`, and `requirements.txt` are copied. Therefore the start command uses `app.main:app` (not `frontend.app.main:app`). ### Frontend Environment Variables @@ -167,6 +219,18 @@ If you want to persist DuckDB data: ## Troubleshooting +### Docker Compose deployment fails in Coolify + +- Verify Coolify uses `docker-compose.coolify.yml`, not local `docker-compose.yml` +- Verify public domain points to `nginx` service on port `80` +- Do not publish host ports `80:80` or `443:443` inside Coolify stack + +### Backend healthcheck stays unhealthy + +- Check backend logs in Coolify +- Verify `OPENROUTER_API_KEY` and `JWT_SECRET` are set +- Verify volume mount at `/app/data` is writable + ### Backend won't start - Check that `OPENROUTER_API_KEY` is set @@ -207,6 +271,8 @@ All required environment variables: ## Deployment Checklist - [ ] Repository pushed to Git +- [ ] For Docker Compose: Coolify resource uses `docker-compose.coolify.yml` +- [ ] For Docker Compose: domain points to `nginx` service on port `80` - [ ] Backend service created with correct base directory (`/backend`) - [ ] Backend environment variables configured - [ ] Frontend service created with correct base directory (`/frontend`)