Add Nixpacks configuration files for backend and frontend services; create Coolify deployment guide and Nginx reverse proxy configuration
Co-authored-by: Copilot <copilot@github.com>
This commit is contained in:
@@ -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"
|
||||||
@@ -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.
|
||||||
@@ -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"
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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]
|
||||||
Reference in New Issue
Block a user