## Deployment Guide - Campus Safe API (PostgreSQL without Docker)

This guide covers deployment without Docker containers, using PostgreSQL and Gunicorn/Uvicorn.

---

## 1. Development Environment Setup

### Prerequisites

- **Python 3.12+**
- **PostgreSQL 16+** (local installation)
- **pip** and **venv** (Python built-in)

### Installation Steps

#### 1.1 Clone Repository and Create Virtual Environment

```bash
# Navigate to project directory
cd /path/to/campus_safe_api

# Create virtual environment
python3.12 -m venv .venv

# Activate environment
# On Linux/macOS:
source .venv/bin/activate

# On Windows (PowerShell):
.venv\Scripts\Activate.ps1

# On Windows (Command Prompt):
.venv\Scripts\activate.bat
```

#### 1.2 Install Python Dependencies

```bash
pip install --upgrade pip
pip install -r requirements.txt

# Verify installation
pip list | grep -E "fastapi|sqlalchemy|psycopg"
```

#### 1.3 Configure Environment Variables

```bash
# Copy environment template
cp .env.example .env

# Edit .env file with your settings:
# Required:
# DATABASE_URL=postgresql+psycopg://postgres:your_password@localhost:5432/campus_safe
# JWT_SECRET_KEY=your-secret-key-generate-with-openssl-rand-hex-32

# Optional:
# DEBUG=True
# ENVIRONMENT=development
# ALLOWED_ORIGINS=http://localhost:3000,http://localhost:8080
```

#### 1.4 Create PostgreSQL Database and Tables

```bash
# Option 1: Using psql CLI (recommended)
psql -h localhost -U postgres -d campus_safe -f scripts/01_create_database.sql

# Option 2: Using pgAdmin or a SQL editor
# 1. Open scripts/01_create_database.sql
# 2. Execute the entire script

# Option 3: Manual steps
psql -h localhost -U postgres -d campus_safe
campus_safe=> \i scripts/01_create_database.sql
campus_safe=> \q
```

#### 1.5 Populate Database with Sample Data

```bash
# Load sample data (users, reports, events, etc.)
psql -h localhost -U postgres -d campus_safe -f scripts/02_seed_database.sql

# Apply schema and seed hotfixes for compatibility
psql -h localhost -U postgres -d campus_safe -f scripts/03_hotfix_schema_and_seed.sql

# Verify data was loaded
psql -h localhost -U postgres -d campus_safe -c "SELECT COUNT(*) AS total_tables FROM information_schema.tables WHERE table_schema = current_schema();"
```

#### 1.6 Run Development Server

```bash
# Start FastAPI development server with auto-reload
uvicorn app.main:app --reload --port 8000 --host 0.0.0.0

# Server will be available at:
# API: http://localhost:8000
# Swagger UI: http://localhost:8000/api/v1/docs
# ReDoc: http://localhost:8000/api/v1/redoc
```

### Testing Development Setup

```bash
# Test authentication endpoint
curl -X POST http://localhost:8000/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@campus-safe.local","password":"admin123"}'

# Test WebSocket (using wscat or Insomnia)
# URL: ws://localhost:8000/ws/signalements?token=<JWT_TOKEN>
```

---

## 2. Production Environment Setup

### Prerequisites

- **Ubuntu 20.04+** or RHEL/CentOS 8+ (or equivalent Linux)
- **Python 3.12+** compiled from source or via deadsnakes PPA
- **PostgreSQL 16+** (managed or self-hosted)
- **Nginx** (reverse proxy)
- **Systemd** (process management)
- **Git** (for deployment)

### Installation Steps

#### 2.1 System Preparation

```bash
# Update system packages
sudo apt update && sudo apt upgrade -y

# Install system dependencies
sudo apt install -y python3.12 python3.12-venv \
  python3-pip git curl wget build-essential libssl-dev \
  libffi-dev python3-dev postgresql-client

# Verify Python version
python3.12 --version
```

#### 2.2 Create Application User and Directory

```bash
# Create dedicated application user
sudo useradd -m -s /bin/bash campus_safe

# Create application directory
sudo mkdir -p /opt/campus_safe_api
sudo chown -R campus_safe:campus_safe /opt/campus_safe_api

# Switch to application user
sudo su - campus_safe
```

#### 2.3 Clone Repository and Create Virtual Environment

```bash
cd /opt/campus_safe_api

# Clone repository (using git clone)
git clone https://github.com/your-org/campus_safe_api.git .

# OR copy files manually via scp/sftp
# scp -r local_path/ campus_safe@server:/opt/campus_safe_api/

# Create Python virtual environment
python3.12 -m venv .venv

# Activate environment
source .venv/bin/activate

# Install dependencies
pip install --upgrade pip
pip install -r requirements.txt

# Exit virtual environment (temporarily)
deactivate
```

#### 2.4 Database Configuration

```bash
# Switch back to regular user or use sudo
sudo su -

# Test PostgreSQL connection
psql -h your-db-host -U postgres -d campus_safe -c "SELECT 1;"

# Create production database and tables
psql -h your-db-host -U postgres -d campus_safe -f /opt/campus_safe_api/scripts/01_create_database.sql

# Load sample data (optional for production)
psql -h your-db-host -U postgres -d campus_safe -f /opt/campus_safe_api/scripts/02_seed_database.sql

# Apply schema and seed hotfixes (recommended)
psql -h your-db-host -U postgres -d campus_safe -f /opt/campus_safe_api/scripts/03_hotfix_schema_and_seed.sql

# Create readonly user for application (recommended)
psql -h localhost -U postgres -d campus_safe << EOF
CREATE ROLE campus_safe_app LOGIN PASSWORD 'strong_password_here';
GRANT CONNECT ON DATABASE campus_safe TO campus_safe_app;
GRANT USAGE ON SCHEMA public TO campus_safe_app;
GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA public TO campus_safe_app;
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO campus_safe_app;
EOF

# Update .env to use the readonly user
# DATABASE_URL=postgresql+psycopg://campus_safe_app:strong_password_here@your-db-host:5432/campus_safe
```

#### 2.5 Configure Environment Variables

```bash
sudo su - campus_safe
cd /opt/campus_safe_api

# Create and edit .env file with production values
cat > .env << 'EOF'
# Application
APP_NAME="Campus Safe API"
ENVIRONMENT=production
DEBUG=False

# Database (use readonly user for app)
DATABASE_URL=postgresql+psycopg://campus_safe_app:encrypted_password@db.example.com:5432/campus_safe

# Security
JWT_SECRET_KEY=your-secret-key-min-32-chars-openssl-rand-hex-32
JWT_ALGORITHM=HS256
ACCESS_TOKEN_EXPIRE_MINUTES=60
REFRESH_TOKEN_EXPIRE_DAYS=7

# CORS
ALLOWED_ORIGINS=https://frontend.example.com,https://app.example.com

# Files
FILES_SERVER_URL=https://files.example.com
FILES_SERVER_API_KEY=secure-api-key-for-file-server
MAX_FILE_SIZE_MB=10

# Logging
LOG_LEVEL=INFO
EOF

# Restrict file permissions
chmod 600 .env
```

#### 2.6 Create Systemd Service File

```bash
# Create Gunicorn service
sudo tee /etc/systemd/system/campus_safe_api.service > /dev/null << 'EOF'
[Unit]
Description=Campus Safe API (Gunicorn + Uvicorn)
After=network.target

[Service]
Type=notify
User=campus_safe
WorkingDirectory=/opt/campus_safe_api
Environment="PATH=/opt/campus_safe_api/.venv/bin"

# Start command: Gunicorn with 4 Uvicorn workers
ExecStart=/opt/campus_safe_api/.venv/bin/gunicorn \
  --workers 4 \
  --worker-class uvicorn.workers.UvicornWorker \
  --bind 0.0.0.0:8000 \
  --timeout 120 \
  --access-logfile /var/log/campus_safe_api/access.log \
  --error-logfile /var/log/campus_safe_api/error.log \
  --log-level info \
  app.main:app

# Restart policy
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target
EOF

# Create log directory
sudo mkdir -p /var/log/campus_safe_api
sudo chown -R campus_safe:campus_safe /var/log/campus_safe_api

# Reload systemd daemon and enable service
sudo systemctl daemon-reload
sudo systemctl enable campus_safe_api

# Start the service
sudo systemctl start campus_safe_api

# Verify service is running
sudo systemctl status campus_safe_api
```

#### 2.7 Configure Nginx Reverse Proxy

```bash
# Create Nginx configuration
sudo tee /etc/nginx/sites-available/campus_safe_api > /dev/null << 'EOF'
upstream campus_safe_app {
    server 127.0.0.1:8000;
}

# Redirect HTTP to HTTPS
server {
    listen 80;
    server_name api.campus-safe.example.com;
    return 301 https://$server_name$request_uri;
}

# HTTPS server block
server {
    listen 443 ssl http2;
    server_name api.campus-safe.example.com;

    # SSL certificates (generated with letsencrypt)
    ssl_certificate /etc/letsencrypt/live/api.campus-safe.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.campus-safe.example.com/privkey.pem;
    
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    # Gzip compression
    gzip on;
    gzip_types application/json text/plain;
    gzip_min_length 1000;

    # Proxy settings
    location / {
        proxy_pass http://campus_safe_app;
        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
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_read_timeout 86400;
    }

    # Security headers
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;
    add_header X-XSS-Protection "1; mode=block" always;
}
EOF

# Enable site
sudo ln -sf /etc/nginx/sites-available/campus_safe_api /etc/nginx/sites-enabled/

# Test Nginx configuration
sudo nginx -t

# Restart Nginx
sudo systemctl restart nginx
```

#### 2.8 SSL Certificate Setup (Let's Encrypt)

```bash
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx

# Generate certificate
sudo certbot certonly --standalone -d api.campus-safe.example.com

# Auto-renewal (Certbot handles this automatically)
sudo systemctl enable certbot.timer
```

### Verification and Testing

```bash
# Check service status
sudo systemctl status campus_safe_api

# View logs
sudo journalctl -u campus_safe_api -f

# Test API endpoint
curl -X GET https://api.campus-safe.example.com/api/v1/docs

# Test authentication
curl -X POST https://api.campus-safe.example.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@campus-safe.local","password":"admin123"}'

# Test WebSocket (using wscat)
npm install -g wscat
wscat -c "wss://api.campus-safe.example.com/ws/signalements?token=<JWT_TOKEN>"
```

---

## 3. Monitoring and Maintenance

### Log Monitoring

```bash
# Real-time logs
sudo journalctl -u campus_safe_api -f

# Nginx access logs
sudo tail -f /var/log/nginx/access.log

# Gunicorn logs
sudo tail -f /var/log/campus_safe_api/error.log
```

### Database Backups

```bash
# Daily backup script
cat > /usr/local/bin/backup_campus_safe.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/backups/campus_safe"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)

mkdir -p $BACKUP_DIR
pg_dump -h your-db-host -U backup_user -d campus_safe > $BACKUP_DIR/campus_safe_$TIMESTAMP.sql
gzip $BACKUP_DIR/campus_safe_$TIMESTAMP.sql

# Keep only last 30 days
find $BACKUP_DIR -type f -mtime +30 -delete
EOF

chmod +x /usr/local/bin/backup_campus_safe.sh

# Schedule daily backups at 2 AM
sudo crontab -e
# Add: 0 2 * * * /usr/local/bin/backup_campus_safe.sh
```

### Health Checks

```bash
# Simple health check script
cat > /usr/local/bin/campus_safe_health.sh << 'EOF'
#!/bin/bash
API_URL="https://api.campus-safe.example.com"

# Check API
curl -sf $API_URL/api/v1/docs > /dev/null || {
  echo "API is down!"
  systemctl status campus_safe_api
}

# Check database
psql -h db-host -U check_user -d campus_safe -c "SELECT 1;" > /dev/null || {
  echo "Database is down!"
}

echo "All systems operational"
EOF

chmod +x /usr/local/bin/campus_safe_health.sh
```

---

## 4. Production Migration Checklist

- [ ] All system dependencies installed
- [ ] Python 3.12+ verified
- [ ] Virtual environment created and dependencies installed
- [ ] PostgreSQL database created and accessible
- [ ] Database DDL script executed
- [ ] Sample data loaded (optional)
- [ ] Environment variables (.env) configured securely
- [ ] Gunicorn service created and enabled
- [ ] Nginx reverse proxy configured
- [ ] SSL certificates generated (Let's Encrypt)
- [ ] API endpoints tested (curl/Postman)
- [ ] WebSocket connectivity tested
- [ ] Logs monitored and rotating
- [ ] Database backups configured
- [ ] Monitoring/alerting set up

---

## 5. Troubleshooting

### API won't start

```bash
# Check service status
sudo systemctl status campus_safe_api

# View detailed logs
sudo journalctl -u campus_safe_api -n 50

# Test database connection manually
python3 -c "
import asyncio
from app.db.database import engine
asyncio.run(engine.execute('SELECT 1'))
"
```

### Database connection errors

```bash
# Verify PostgreSQL is running
psql -h localhost -U postgres -d campus_safe -c "SELECT 1;"

# Check credentials in .env
grep DATABASE_URL .env

# Test connection from app
cd /opt/campus_safe_api
source .venv/bin/activate
python3 << 'EOF'
import asyncio
from sqlalchemy import text
from sqlalchemy.ext.asyncio import create_async_engine

async def test_db():
    engine = create_async_engine("postgresql+psycopg://user:pass@host/db")
    async with engine.connect() as conn:
        result = await conn.execute(text("SELECT 1"))
        print("DB Connection OK:", result.fetchone())

asyncio.run(test_db())
EOF
```

### WebSocket connection issues

```bash
# Ensure Nginx is configured for WebSocket upgrade headers
grep -A 5 "proxy_http_version" /etc/nginx/sites-available/campus_safe_api

# Test WebSocket endpoint
curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" \
  https://api.campus-safe.example.com/ws/signalements?token=test
```

---

## 6. Performance Tuning

### Gunicorn Workers

```bash
# Calculate optimal worker count: (2 * CPU_COUNT) + 1
# For 4 cores: (2 * 4) + 1 = 9 workers

# Edit service file to adjust workers
--workers 9
```

### PostgreSQL Connection Pool

```bash
# In app/core/config.py, adjust:
# pool_size=10         # Min connections
# max_overflow=20      # Max additional connections
```

### Nginx Caching

```bash
# Add to Nginx config for static endpoints
location ~* ^/api/v1/(calendriers|preferences|postes)$ {
    proxy_cache_valid 200 10m;
    proxy_pass http://campus_safe_app;
}
```

---

## Database Schema Documentation

The database consists of 21 tables organized by domain:

### Core Tables (5)
- `utilisateurs` - User accounts
- `roles` - Role definitions
- `sessions` - Active sessions
- `preferences` - User preferences
- `equipes` - Teams

### Report Management (4)
- `signalements` - Incident reports
- `signalement_timeline` - Status history
- `signalement_pieces_jointes` - Report attachments
- `notes_internes` - Internal staff notes

### Communication (2)
- `discussions` - Conversations
- `messages` - Individual messages

### Social (4)
- `postes` - Forum posts
- `commentaires` - Comments
- `reactions` - Emoji reactions
- `rapports` - Additional reports

### Calendar (2)
- `calendriers` - Events
- `inscriptions_evenements` - Event registrations

### Resources (2)
- `ressources` - Educational resources
- `faq` - FAQ entries
- `contact_urgence` - Emergency contacts

All tables use UUID primary keys and include timestamps (date_creation, date_modification).

---

## WebSocket Real-Time Features

The API provides production-ready WebSocket support for real-time updates via the `/ws/{canal}` endpoint.

### Available Channels

```
- signalements           → All report updates (GESTIONNAIRE+ only)
- signalement:{id}      → Specific report updates (Owner + GESTIONNAIRE+)
- discussion:{id}       → Messages in a specific discussion
- discussions           → New discussion notifications (all authenticated)
- calendriers           → Event updates (all authenticated)
- dashboard            → Admin dashboard updates (GESTIONNAIRE+ only)
- admin                → System alerts (ADMIN_SYSTEME only)
- user:{user_id}       → Personal notifications (your own channel)
```

### Example WebSocket Client

```javascript
// WebSocket connection with JWT authentication
const token = localStorage.getItem('access_token');
const ws = new WebSocket(`wss://api.campus-safe.example.com/ws/signalements?token=${token}`);

ws.onmessage = (event) => {
  const event_data = JSON.parse(event.data);
  console.log('Real-time update:', event_data);
};

ws.onerror = (error) => {
  console.error('WebSocket error:', error);
};

ws.onclose = () => {
  console.log('WebSocket connection closed');
  // Implement reconnection logic
};
```

---

**Last Updated:** March 2026
**Version:** 1.0.0 - PostgreSQL + No Docker