diff --git a/backend/nixpacks.toml b/backend/nixpacks.toml new file mode 100644 index 0000000..7889ce6 --- /dev/null +++ b/backend/nixpacks.toml @@ -0,0 +1,13 @@ +# Nixpacks configuration for the FastAPI backend + +[phases.setup] +nixpkgsArchive = "88a9d1386465831607986442fd9c8c0e7a1b2f5" +aptPkgs = ["git"] + +[phases.install] +# Nixpacks auto-detects Python and runs pip install -r requirements.txt + +[build] + +[deploy] +startCommand = "uvicorn backend.app.main:app --host 0.0.0.0 --port 8000" diff --git a/docs/deployment/coolify.md b/docs/deployment/coolify.md new file mode 100644 index 0000000..5e7ecc2 --- /dev/null +++ b/docs/deployment/coolify.md @@ -0,0 +1,197 @@ +# Coolify Deployment Guide + +This guide covers deploying `ai.allucanget.biz` using [Coolify](https://coolify.io) from the repository `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git`. + +## Architecture Overview + +The application consists of two Python services: + +| Service | Framework | Port | Description | +| -------- | ----------------- | ---- | ------------------------------------------ | +| Backend | FastAPI + uvicorn | 8000 | REST API, auth, AI generation, DuckDB | +| Frontend | Flask + gunicorn | 5000 | SSR web UI, session auth, proxy to backend | + +Coolify's built-in reverse proxy routes traffic: + +- `/api/*` → Backend (port 8000) +- `/` → Frontend (port 5000) + +## Prerequisites + +- A Coolify instance (self-hosted or Cloud) +- Git repository pushed to `https://git.allucanget.biz/allucanget/ai.allucanget.biz.git` +- Domain configured to point to your Coolify server + +## Step 1: Create Backend Service + +1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** +2. Connect your Git repository (`git.allucanget.biz`) +3. Select the `ai.allucanget.biz` repository +4. Choose the `main` branch +5. Set **Build Pack** to `nixpacks` +6. Set **Base Directory** to `/backend` +7. Set **Ports Exposed** to `8000` +8. Set **Start Command** to: + ```txt + uvicorn backend.app.main:app --host 0.0.0.0 --port 8000 + ``` +9. Click **Create Resource** + +### Backend Environment Variables + +Add these as **Runtime** environment variables in Coolify: + +| Variable | Description | Example | +| -------------------- | ------------------------------------ | ------------------------------------ | +| `OPENROUTER_API_KEY` | OpenRouter API key for AI generation | `sk-or-v1-...` | +| `JWT_SECRET` | Secret key for JWT token signing | Generate with `openssl rand -hex 32` | +| `APP_URL` | Public URL of the backend | `https://api.ai.allucanget.biz` | +| `APP_NAME` | Application name | `AI Allucanget` | +| `CORS_ORIGINS` | Comma-separated allowed origins | `https://ai.allucanget.biz` | + +## Step 2: Create Frontend Service + +1. In Coolify, click **Add Resource** → **Deploy a new resource** → **Git** +2. Select the same repository +3. Choose the `main` branch +4. Set **Build Pack** to `nixpacks` +5. Set **Base Directory** to `/frontend` +6. Set **Ports Exposed** to `5000` +7. Set **Start Command** to: + ```txt + gunicorn frontend.app.main:app --bind 0.0.0.0:5000 --workers 2 --timeout 120 + ``` +8. Click **Create Resource** + +### Frontend Environment Variables + +Add these as **Runtime** environment variables in Coolify: + +| Variable | Description | Example | +| ------------------ | ----------------------------------------- | -------------------------------------------------------------- | +| `FLASK_SECRET_KEY` | Flask session cookie signing key | Generate with `openssl rand -hex 32` | +| `BACKEND_URL` | Internal URL to reach the backend service | `http://localhost:8000` (or use Coolify's internal networking) | + +## Step 3: Configure Reverse Proxy + +Coolify provides a built-in reverse proxy. Configure routing rules: + +### Backend Proxy Rules + +- **Domain**: `api.ai.allucanget.biz` (or subdomain of your choice) +- **Port**: `8000` +- **Path**: `/api/*` → forward to backend + +### Frontend Proxy Rules + +- **Domain**: `ai.allucanget.biz` +- **Port**: `5000` +- **Path**: `/` → forward to frontend + +### Nginx Configuration (Optional) + +If you need custom Nginx configuration, create `nginx/coolify.conf`: + +```nginx +# Reverse proxy configuration for Coolify +# This file is for reference — Coolify's built-in proxy handles routing + +# Backend API proxy +location /api/ { + proxy_pass http://backend:8000; + 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; +} + +# Frontend proxy +location / { + proxy_pass http://frontend:5000; + 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; +} +``` + +## Step 4: SSL/TLS + +Enable HTTPS in Coolify for both services: + +1. Go to each service's settings +2. Enable **Auto HTTPS** (Let's Encrypt) +3. Configure domain names +4. Coolify automatically handles certificate renewal + +## Step 5: Persistent Storage (Optional) + +If you want to persist DuckDB data: + +1. In Coolify, go to the **Backend** service +2. Navigate to **Persistent Storage** +3. Add a volume mount: + - **Host Path**: `/data` (or any path on the host) + - **Container Path**: `/app/data` + - **Type**: `Bind Mount` or `Volume` + +## Troubleshooting + +### Backend won't start + +- Check that `OPENROUTER_API_KEY` is set +- Verify `JWT_SECRET` is a sufficiently long random string +- Check logs in Coolify's **Logs** tab + +### Frontend can't reach backend + +- Ensure `BACKEND_URL` points to the correct internal URL +- If both services are on the same Coolify server, use `http://localhost:8000` +- Check that the backend service is running and healthy + +### CORS errors + +- Set `CORS_ORIGINS` to include your frontend domain +- Example: `https://ai.allucanget.biz` + +### Nixpacks build fails + +- Verify the base directory is correct (`/backend` or `/frontend`) +- Check that `requirements.txt` exists in the base directory +- Review build logs in Coolify + +## Environment Variable Summary + +All required environment variables: + +| Variable | Service | Required | +| -------------------- | -------- | -------------------------------- | +| `OPENROUTER_API_KEY` | Backend | Yes | +| `JWT_SECRET` | Backend | Yes | +| `APP_URL` | Backend | Yes | +| `APP_NAME` | Backend | No (defaults to "AI Allucanget") | +| `CORS_ORIGINS` | Backend | Yes | +| `FLASK_SECRET_KEY` | Frontend | Yes | +| `BACKEND_URL` | Frontend | Yes | + +## Deployment Checklist + +- [ ] Repository pushed to Git +- [ ] Backend service created with correct base directory (`/backend`) +- [ ] Backend environment variables configured +- [ ] Frontend service created with correct base directory (`/frontend`) +- [ ] Frontend environment variables configured +- [ ] SSL certificates enabled +- [ ] Domain names configured +- [ ] Health checks passing +- [ ] Logs reviewed for errors + +## Nixpacks Configuration + +The project includes Nixpacks configuration files for both services: + +- `nixpacks.toml` — Shared configuration (Python version, packages) +- `backend/nixpacks.toml` — Backend-specific (uvicorn, port 8000) +- `frontend/nixpacks.toml` — Frontend-specific (gunicorn, port 5000) + +Nixpacks automatically detects Python projects and installs dependencies from `requirements.txt`. No additional configuration is needed for basic deployments. diff --git a/frontend/nixpacks.toml b/frontend/nixpacks.toml new file mode 100644 index 0000000..ab05610 --- /dev/null +++ b/frontend/nixpacks.toml @@ -0,0 +1,13 @@ +# Nixpacks configuration for the Flask frontend + +[phases.setup] +nixpkgsArchive = "88a9d1386465831607986442fd9c8c0e7a1b2f5" +aptPkgs = ["git"] + +[phases.install] +# Nixpacks auto-detects Python and runs pip install -r requirements.txt + +[build] + +[deploy] +startCommand = "gunicorn frontend.app.main:app --bind 0.0.0.0:5000 --workers 2 --timeout 120" diff --git a/nginx/coolify.conf b/nginx/coolify.conf new file mode 100644 index 0000000..524e2df --- /dev/null +++ b/nginx/coolify.conf @@ -0,0 +1,73 @@ +# Nginx reverse proxy configuration for Coolify deployment +# Place this in /etc/nginx/conf.d/ai.allucanget.biz.conf or use Coolify's built-in proxy + +# Backend API proxy +upstream backend { + server 127.0.0.1:8000; +} + +# Frontend proxy +upstream frontend { + server 127.0.0.1:5000; +} + +server { + listen 80; + server_name ai.allucanget.biz www.ai.allucanget.biz; + + # Redirect HTTP to HTTPS + return 301 https://$host$request_uri; +} + +server { + listen 443 ssl http2; + server_name ai.allucanget.biz www.ai.allucanget.biz; + + # SSL configuration (managed by Let's Encrypt / Certbot) + ssl_certificate /etc/letsencrypt/live/ai.allucanget.biz/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/ai.allucanget.biz/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers HIGH:!aNULL:!MD5; + + # Security headers + add_header X-Frame-Options "SAMEORIGIN" always; + add_header X-Content-Type-Options "nosniff" always; + add_header X-XSS-Protection "1; mode=block" always; + add_header Referrer-Policy "strict-origin-when-cross-origin" always; + + # Backend API proxy + location /api/ { + proxy_pass http://backend; + 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; + + # WebSocket support (if needed in future) + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + } + + # Frontend proxy + location / { + proxy_pass http://frontend; + 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; + + # Static files caching + location ~* \.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { + proxy_pass http://frontend; + expires 30d; + add_header Cache-Control "public, immutable"; + } + } + + # Health check endpoint + location /health { + proxy_pass http://backend; + proxy_set_header Host $host; + } +} diff --git a/nixpacks.toml b/nixpacks.toml new file mode 100644 index 0000000..acc6c68 --- /dev/null +++ b/nixpacks.toml @@ -0,0 +1,14 @@ +# Nixpacks configuration for ai.allucanget.biz +# Shared settings for both backend and frontend services + +[phases.setup] +nixpkgsArchive = "88a9d1386465831607986442fd9c8c0e7a1b2f5" +aptPkgs = ["git"] + +[phases.install] +# Nixpacks auto-detects Python and runs pip install -r requirements.txt +# No custom commands needed here + +[build] + +[deploy]