# SmoothSchedule Production Deployment Guide

## Prerequisites

### Server Requirements
- Ubuntu/Debian Linux server
- Minimum 2GB RAM, 20GB disk space
- Docker and Docker Compose installed
- Domain name pointed to server IP: `smoothschedule.com`
- DNS configured with wildcard subdomain: `*.smoothschedule.com`

### Required Accounts/Services
- [x] DigitalOcean Spaces (already configured)
  - Access Key: DO801P4R8QXYMY4CE8WZ
  - Bucket: smoothschedule
  - Region: nyc3
- [ ] Email service (optional - Mailgun or SMTP)
- [ ] Sentry (optional - error tracking)

## Pre-Deployment Checklist

### 1. DigitalOcean Spaces Setup

```bash
# Create the bucket (if not already created)
aws --profile do-tor1 s3 mb s3://smoothschedule

# Set bucket to public-read for static/media files
aws --profile do-tor1 s3api put-bucket-acl \
  --bucket smoothschedule \
  --acl public-read

# Configure CORS (for frontend uploads)
cat > cors.json <<EOF
{
  "CORSRules": [
    {
      "AllowedOrigins": ["https://smoothschedule.com", "https://*.smoothschedule.com"],
      "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
      "AllowedHeaders": ["*"],
      "MaxAgeSeconds": 3000
    }
  ]
}
EOF

aws --profile do-tor1 s3api put-bucket-cors \
  --bucket smoothschedule \
  --cors-configuration file://cors.json
```

### 2. DNS Configuration

Configure these DNS records at your domain registrar:

```
Type    Name                Value                TTL
A       smoothschedule.com  YOUR_SERVER_IP      300
A       *.smoothschedule.com YOUR_SERVER_IP     300
CNAME   www                 smoothschedule.com  300
```

### 3. Environment Variables Review

**Backend** (`.envs/.production/.django`):
- [x] DJANGO_SECRET_KEY - Set
- [x] DJANGO_ALLOWED_HOSTS - Set to `.smoothschedule.com`
- [x] DJANGO_AWS_ACCESS_KEY_ID - Set
- [x] DJANGO_AWS_SECRET_ACCESS_KEY - Set
- [x] DJANGO_AWS_STORAGE_BUCKET_NAME - Set to `smoothschedule`
- [x] DJANGO_AWS_S3_ENDPOINT_URL - Set to `https://nyc3.digitaloceanspaces.com`
- [x] DJANGO_AWS_S3_REGION_NAME - Set to `nyc3`
- [ ] MAILGUN_API_KEY - Optional (for email)
- [ ] MAILGUN_DOMAIN - Optional (for email)
- [ ] SENTRY_DSN - Optional (for error tracking)

**Frontend** (`.env.production`):
- [x] VITE_API_URL - Set to `https://smoothschedule.com/api`

## Deployment Steps

### Step 1: Server Preparation

```bash
# SSH into production server
ssh poduck@smoothschedule.com

# Install Docker (if not already installed)
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
sudo usermod -aG docker $USER

# Install Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# Logout and login again for group changes to take effect
exit
ssh poduck@smoothschedule.com
```

### Step 2: Deploy Backend (Django)

```bash
# Create deployment directory
mkdir -p ~/smoothschedule
cd ~/smoothschedule

# Clone the repository (or upload files via rsync/git)
# Option A: Clone from Git
git clone <your-repo-url> .
git checkout main

# Option B: Copy from local machine
# From your local machine:
# rsync -avz --exclude 'node_modules' --exclude '.venv' --exclude '__pycache__' \
#   /home/poduck/Desktop/smoothschedule2/ poduck@smoothschedule.com:~/smoothschedule/

# Navigate to backend
cd smoothschedule

# Build and start containers
docker compose -f docker-compose.production.yml build
docker compose -f docker-compose.production.yml up -d

# Wait for containers to start
sleep 10

# Check logs
docker compose -f docker-compose.production.yml logs -f
```

### Step 3: Database Initialization

```bash
# Run migrations
docker compose -f docker-compose.production.yml exec django python manage.py migrate

# Create public schema (for multi-tenancy)
docker compose -f docker-compose.production.yml exec django python manage.py migrate_schemas --shared

# Create superuser
docker compose -f docker-compose.production.yml exec django python manage.py createsuperuser

# Collect static files (uploads to DigitalOcean Spaces)
docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput
```

### Step 4: Create Initial Tenant

```bash
# Access Django shell
docker compose -f docker-compose.production.yml exec django python manage.py shell

# In the shell, create your first business tenant:
```

```python
from core.models import Business
from django.contrib.auth import get_user_model

User = get_user_model()

# Create a business
business = Business.objects.create(
    name="Demo Business",
    subdomain="demo",
    schema_name="demo",
)

# Verify it was created
print(f"Created business: {business.name} at {business.subdomain}.smoothschedule.com")

# Create a business owner
owner = User.objects.create_user(
    username="demo_owner",
    email="owner@demo.com",
    password="your_password_here",
    role="owner",
    business_subdomain="demo"
)

print(f"Created owner: {owner.username}")
exit()
```

### Step 5: Deploy Frontend

```bash
# On your local machine
cd /home/poduck/Desktop/smoothschedule2/frontend

# Install dependencies
npm install

# Build for production
npm run build

# Upload build files to server
rsync -avz dist/ poduck@smoothschedule.com:~/smoothschedule-frontend/

# On the server, set up nginx or serve via backend
```

**Option A: Serve via Django (simpler)**

The Django `collectstatic` command already handles static files. For serving the frontend:

1. Copy frontend build to Django static folder
2. Django will serve it via Traefik

**Option B: Separate Nginx (recommended for production)**

```bash
# Install nginx
sudo apt-get update
sudo apt-get install -y nginx

# Create nginx config
sudo nano /etc/nginx/sites-available/smoothschedule
```

```nginx
server {
    listen 80;
    server_name smoothschedule.com *.smoothschedule.com;

    # Frontend (React)
    location / {
        root /home/poduck/smoothschedule-frontend;
        try_files $uri $uri/ /index.html;
    }

    # Backend API (proxy to Traefik)
    location /api {
        proxy_pass http://localhost:80;
        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;
    }

    location /admin {
        proxy_pass http://localhost:80;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
```

```bash
# Enable site
sudo ln -s /etc/nginx/sites-available/smoothschedule /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```

### Step 6: SSL/HTTPS Setup

Traefik is configured to automatically obtain Let's Encrypt SSL certificates. Ensure:

1. DNS is pointed to your server
2. Ports 80 and 443 are accessible
3. Wait for Traefik to obtain certificates (check logs)

```bash
# Monitor Traefik logs
docker compose -f docker-compose.production.yml logs -f traefik

# You should see:
# "Certificate obtained for domain smoothschedule.com"
```

### Step 7: Verify Deployment

```bash
# Check all containers are running
docker compose -f docker-compose.production.yml ps

# Should show:
# - django (running)
# - postgres (running)
# - redis (running)
# - traefik (running)
# - celeryworker (running)
# - celerybeat (running)
# - flower (running)

# Test API endpoint
curl https://smoothschedule.com/api/

# Test admin
curl https://smoothschedule.com/admin/

# Access in browser:
# https://smoothschedule.com - Main site
# https://platform.smoothschedule.com - Platform dashboard
# https://demo.smoothschedule.com - Demo business
# https://smoothschedule.com:5555 - Flower (Celery monitoring)
```

## Post-Deployment

### 1. Monitoring

```bash
# View logs
docker compose -f docker-compose.production.yml logs -f

# View specific service logs
docker compose -f docker-compose.production.yml logs -f django
docker compose -f docker-compose.production.yml logs -f postgres

# Monitor Celery tasks via Flower
# Access: https://smoothschedule.com:5555
# Login with credentials from .envs/.production/.django
```

### 2. Backups

```bash
# Database backup
docker compose -f docker-compose.production.yml exec postgres backup

# List backups
docker compose -f docker-compose.production.yml exec postgres backups

# Restore from backup
docker compose -f docker-compose.production.yml exec postgres restore backup_filename.sql.gz
```

### 3. Updates

```bash
# Pull latest code
cd ~/smoothschedule/smoothschedule
git pull origin main

# Rebuild and restart
docker compose -f docker-compose.production.yml build
docker compose -f docker-compose.production.yml up -d

# Run migrations
docker compose -f docker-compose.production.yml exec django python manage.py migrate

# Collect static files
docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput
```

## Troubleshooting

### SSL Certificate Issues
```bash
# Check Traefik logs
docker compose -f docker-compose.production.yml logs traefik

# Verify DNS is pointing to server
dig smoothschedule.com +short

# Ensure ports are open
sudo ufw allow 80
sudo ufw allow 443
```

### Database Connection Issues
```bash
# Check PostgreSQL is running
docker compose -f docker-compose.production.yml ps postgres

# Check database logs
docker compose -f docker-compose.production.yml logs postgres

# Verify connection
docker compose -f docker-compose.production.yml exec django python manage.py dbshell
```

### Static Files Not Loading
```bash
# Verify DigitalOcean Spaces credentials
docker compose -f docker-compose.production.yml exec django python manage.py shell
>>> from django.conf import settings
>>> print(settings.AWS_ACCESS_KEY_ID)
>>> print(settings.AWS_STORAGE_BUCKET_NAME)

# Re-collect static files
docker compose -f docker-compose.production.yml exec django python manage.py collectstatic --noinput

# Check Spaces bucket
aws --profile do-tor1 s3 ls s3://smoothschedule/static/
aws --profile do-tor1 s3 ls s3://smoothschedule/media/
```

### Celery Not Running Tasks
```bash
# Check Celery worker logs
docker compose -f docker-compose.production.yml logs celeryworker

# Access Flower dashboard
# https://smoothschedule.com:5555

# Restart Celery
docker compose -f docker-compose.production.yml restart celeryworker celerybeat
```

## Security Checklist

- [x] SSL/HTTPS enabled via Let's Encrypt
- [x] DJANGO_SECRET_KEY set to random value
- [x] Database password set to random value
- [x] Flower dashboard password protected
- [ ] Firewall configured (UFW or iptables)
- [ ] SSH key-based authentication enabled
- [ ] Fail2ban installed for brute-force protection
- [ ] Regular backups configured
- [ ] Sentry error monitoring (optional)

## Performance Optimization

1. **Enable CDN for DigitalOcean Spaces**
   - In Spaces settings, enable CDN
   - Update `DJANGO_AWS_S3_CUSTOM_DOMAIN=smoothschedule.nyc3.cdn.digitaloceanspaces.com`

2. **Scale Gunicorn Workers**
   - Adjust `WEB_CONCURRENCY` in `.envs/.production/.django`
   - Formula: (2 x CPU cores) + 1

3. **Add Redis Persistence**
   - Update docker-compose.production.yml redis config
   - Enable AOF persistence

4. **Database Connection Pooling**
   - Already configured via `CONN_MAX_AGE=60`

## Maintenance

### Weekly
- Review error logs
- Check disk space: `df -h`
- Monitor Flower dashboard for failed tasks

### Monthly
- Update Docker images: `docker compose pull`
- Update dependencies: `uv sync`
- Review backups

### As Needed
- Scale resources (CPU/RAM)
- Add more Celery workers
- Optimize database queries
