# Monaco USA Portal - Standalone Production Deployment

This is a standalone deployment package for the Monaco USA Portal. No source code cloning required.

## Prerequisites

- Linux server (Ubuntu 22.04+ recommended)
- Docker Engine 24.0+
- Docker Compose v2.20+
- Nginx installed and configured for SSL
- Domain name with DNS pointing to your server

## Quick Start

### 1. Download the deployment files

Create a directory and download the deployment files:

```bash
mkdir -p /opt/monacousa
cd /opt/monacousa

# Download files from your deployment source
# Example: copy from Gitea, scp, etc.
```

You need these files:
- `docker-compose.yml`
- `.env.example`
- `init.sql`
- `kong.yml.template`
- `setup.sh`

### 2. Configure environment

```bash
# Copy the example environment file
cp .env.example .env

# Edit with your settings
nano .env
```

At minimum, configure:
- `DOMAIN` - Your domain name (e.g., `portal.monacousa.org`)
- SMTP settings (optional but recommended for emails)

### 3. Run setup script

```bash
# Make setup script executable
chmod +x setup.sh

# Run setup - this generates secrets and kong.yml
./setup.sh
```

The setup script will:
- Generate secure random passwords and JWT tokens
- Create `kong.yml` from the template with your API keys
- Validate your configuration

### 4. Start the services

```bash
docker compose up -d
```

### 5. Configure Nginx

Add proxy configuration for your domain. Example:

```nginx
# Portal - main site
server {
    listen 443 ssl http2;
    server_name portal.monacousa.org;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }
}

# API - Supabase services
server {
    listen 443 ssl http2;
    server_name api.portal.monacousa.org;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    location / {
        proxy_pass http://127.0.0.1:8000;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }
}

# Studio - Supabase dashboard (optional)
server {
    listen 443 ssl http2;
    server_name studio.portal.monacousa.org;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    # Add basic auth for security
    auth_basic "Supabase Studio";
    auth_basic_user_file /etc/nginx/.htpasswd;

    location / {
        proxy_pass http://127.0.0.1:3001;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        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;
        proxy_cache_bypass $http_upgrade;
    }
}
```

Reload nginx:
```bash
nginx -t && systemctl reload nginx
```

### 6. Verify deployment

```bash
# Check all containers are running
docker compose ps

# Check database initialization
docker compose logs db

# Check for any errors
docker compose logs -f
```

### 7. Access the portal

Open `https://portal.monacousa.org` in your browser. On first visit, you'll be redirected to `/setup` to create the initial admin account.

## Architecture

```
Internet
    │
    └─► Nginx (SSL/Reverse Proxy)
            │
            ├─► portal.domain.com:443 ──► localhost:3000 ──► Portal (SvelteKit)
            ├─► api.domain.com:443 ──► localhost:8000 ──► Kong ──► Auth/REST/Storage
            └─► studio.domain.com:443 ──► localhost:3001 ──► Studio (Dashboard)

Internal Docker Network
    │
    ├─► Kong API Gateway (port 8000)
    │       ├─► Auth (GoTrue)
    │       ├─► REST (PostgREST)
    │       ├─► Storage API
    │       └─► Realtime
    │
    └─► PostgreSQL Database
```

## Exposed Ports

| Service | Port | Purpose |
|---------|------|---------|
| Portal | 127.0.0.1:3000 | Main web application |
| Kong | 127.0.0.1:8000 | Supabase API gateway |
| Studio | 127.0.0.1:3001 | Supabase dashboard (optional) |

All ports are bound to localhost only for security. Use nginx to expose them.

## Files Description

| File | Purpose |
|------|---------|
| `docker-compose.yml` | All service definitions |
| `.env` | Your configuration (from .env.example) |
| `init.sql` | Database schema and migrations |
| `kong.yml.template` | API gateway config template |
| `kong.yml` | Generated API gateway config (created by setup.sh) |
| `setup.sh` | Setup script for secrets and validation |

## Management Commands

```bash
# Start all services
docker compose up -d

# Stop all services
docker compose down

# View logs
docker compose logs -f

# View specific service logs
docker compose logs -f portal
docker compose logs -f db

# Restart a specific service
docker compose restart portal

# Check resource usage
docker stats

# Enter database shell
docker compose exec db psql -U postgres
```

## Updating

To update the portal to a new version:

```bash
# Pull the latest image
docker compose pull portal

# Restart the portal service
docker compose up -d portal
```

## Backup

### Database backup

```bash
# Create backup
docker compose exec db pg_dump -U postgres postgres > backup_$(date +%Y%m%d).sql

# Restore backup
docker compose exec -T db psql -U postgres postgres < backup_YYYYMMDD.sql
```

### Full backup (including storage)

```bash
# Stop services first for consistent backup
docker compose stop

# Backup volumes
docker run --rm -v monacousa_db-data:/data -v $(pwd):/backup alpine \
    tar czf /backup/db-data-backup.tar.gz -C /data .

docker run --rm -v monacousa_storage-data:/data -v $(pwd):/backup alpine \
    tar czf /backup/storage-data-backup.tar.gz -C /data .

# Start services
docker compose up -d
```

## Important Notes

### Environment Variables

The portal uses **dynamic environment variables** which are read at runtime. This means:
- You can change `.env` values and restart containers without rebuilding
- The pre-built Docker image works with any configuration
- JWT tokens and API keys must be generated using `./setup.sh`

### First-Time Setup

On first access to the portal, you'll be redirected to `/setup` where you create the initial admin account. This only happens when the `members` table is empty.

### Database Initialization

The `init.sql` file:
- Creates all database schemas, tables, views, and functions
- Sets up Row Level Security (RLS) policies
- Grants appropriate permissions to database roles
- Runs automatically on first container start

If you need to reset the database:
```bash
docker compose down -v  # WARNING: Deletes all data!
docker compose up -d
```

### Rebuilding the Portal (If Needed)

If you're building from source instead of using the pre-built image, ensure environment variables are passed during build for static features. For most deployments, the pre-built image with runtime env vars is recommended.

## Troubleshooting

### Containers not starting

```bash
# Check logs for errors
docker compose logs

# Check if ports are in use
netstat -tlnp | grep -E ':(3000|3001|8000)'
```

### Database connection errors

```bash
# Check database is healthy
docker compose ps db

# Check database logs
docker compose logs db

# Verify database is accepting connections
docker compose exec db pg_isready -U postgres
```

### API 401 Unauthorized errors

This usually means the API keys don't match. Run setup again:

```bash
./setup.sh
docker compose restart kong
```

### API 403 Forbidden errors

This means the database permissions (GRANTs) are missing. This is fixed in the init.sql, but if you see this on an existing deployment, run:

```bash
docker compose exec db psql -U postgres -c "
GRANT SELECT, INSERT, UPDATE ON public.members TO authenticated;
GRANT SELECT ON public.membership_statuses TO authenticated;
GRANT SELECT ON public.membership_types TO authenticated;
GRANT SELECT ON public.members_with_dues TO authenticated;
GRANT SELECT, INSERT ON public.dues_payments TO authenticated;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.events TO authenticated;
GRANT SELECT, INSERT, UPDATE, DELETE ON public.event_rsvps TO authenticated;
GRANT SELECT ON public.events_with_counts TO authenticated;
"
```

### "Your account is not properly configured" error

This occurs when a user can authenticate but can't query their member profile. Usually a database permission issue - see the 403 fix above.

### Portal not loading

```bash
# Check portal logs
docker compose logs portal

# Verify kong is routing correctly
docker compose exec portal wget -qO- http://kong:8000/rest/v1/ || echo "Kong not reachable"
```

### Nginx 502 Bad Gateway

Check if the Docker containers are running:
```bash
docker compose ps
curl http://127.0.0.1:3000  # Should return HTML
curl http://127.0.0.1:8000  # Should return JSON
```

## Security Recommendations

1. **Secure your .env file**
   ```bash
   chmod 600 .env
   ```

2. **Protect Supabase Studio with auth**
   ```bash
   # Generate password file for nginx
   htpasswd -c /etc/nginx/.htpasswd admin
   ```

3. **Regular updates**
   - Keep Docker and host OS updated
   - Regularly pull latest portal images

4. **Monitor logs**
   - Set up log rotation (configured in docker-compose.yml)
   - Consider centralized logging

## Support

For issues and questions:
- Check logs: `docker compose logs -f`
- GitHub/Gitea issues
- Email: support@monacousa.org
