Files
coop/docs/INFRASTRUCTURE.md
T

9.7 KiB

CoopCredits Infrastructure Documentation

Network Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│                          External Access                                  │
│                        coop.hobokenchicken.com                            │
└─────────────────────────────────┬───────────────────────────────────────┘
                                  │ HTTPS (443)
                                  ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                           CoopCredits Server (172.20.1.238)               │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  ┌──────────────┐  │
│  │   Caddy      │  │   Frontend   │  │   Backend    │  │  PostgreSQL  │  │
│  │  (reverse)   │──│  (Next.js)   │  │  (Express)   │──│   (5432)     │  │
│  │   Proxy      │  │   :3000      │  │   :3002      │  │              │  │
│  └──────────────┘  └──────────────┘  └──────┬───────┘  └──────────────┘  │
│                                              │                           │
│                    ┌──────────────┐         │          ┌──────────────┐  │
│                    │    Redis     │◀────────┘          │   (Ko-fi)    │  │
│                    │   (6379)     │                     │  (Webhooks)  │  │
│                    └──────────────┘                     └──────────────┘  │
└──────────────────────────────────┬──────────────────────────────────────┘
                                   │
                                   │ Local Network (172.20.1.0/24)
        ┌──────────────────────────┼──────────────────────────┐
        │                          │                          │
        ▼                          ▼                          ▼
┌──────────────┐          ┌──────────────┐          ┌──────────────┐
│     Plex     │          │   Tautulli   │          │   Overseer   │
│172.20.1.220  │          │172.20.1.255  │          │172.20.1.225  │
│  :32400      │          │   :8181      │          │   :5055      │
└──────────────┘          └──────────────┘          └──────────────┘

Important: Backend runs in network_mode: host to reach Tautulli/Overseer on 172.20.1.0/24. Docker bridge networking cannot route to this subnet.

Service Details

Caddy Reverse Proxy (Separate Machine)

  • Handles: SSL termination (Let's Encrypt), routing
  • Routes:
    • /* → Frontend :3000
    • /api/* → Backend :3002 (preserves /api/ prefix — use handle, not handle_path)
    • /webhooks/* → Backend :3002

Frontend (coop-frontend, port 3000)

  • Next.js 16 with standalone output
  • Bridge network — exposed on 0.0.0.0:3000
  • Static files served from .next/standalone

Backend (coop-backend, port 3002)

  • Express.js API
  • Host network mode — required to reach 172.20.1.x services
  • Connects to: PostgreSQL on localhost:5432, Redis on localhost:6379
  • Health check: GET /health on localhost:3002

PostgreSQL (coop-postgres, port 5432)

  • User: coop
  • Database: coop_credits
  • Password: coop_password (change in production)
  • Health check: pg_isready

Redis (coop-redis, port 6379)

  • Used for: Session store, Socket.io adapter
  • No auth in current config (trusted local network)

Plex Server (172.20.1.220:32400)

  • Purpose: Content streaming and user authentication
  • Integration: OAuth 2.0 login for website

Tautulli (172.20.1.255:8181)

  • Purpose: Plex analytics and watch event tracking
  • Integration: Webhook notifications to CoopCredits on watch events
  • API Key: Required for backfill queries

Overseer (172.20.1.225:5055)

  • Purpose: Content request management
  • Integration: API for creating requests, webhooks for status updates
  • API Key: Required for search and request creation
  • Disk Space: Used for dynamic pricing scarcity calculation

Communication Flow

1. User Authentication

User → Caddy → Frontend → Backend → Plex OAuth (172.20.1.220:32400)
                                              ↓
                                   User authenticated, JWT issued
                                   Session stored in PostgreSQL

2. Watch Event Processing

Plex → Tautulli → Webhook → Caddy → Backend → PostgreSQL
                                          ↓
                                   WatchEvent + Transaction created
                                   Socket.io → User notified

3. Content Request

User → Caddy → Frontend → Backend → Overseer API (172.20.1.225:5055)
                                          ↓
                              Request created, $COOP deducted immediately
                              ContentRequest stored as PENDING
                                          ↓
                              Overseer webhook → Backend → Status updated

4. Ko-fi Purchase

User → Ko-fi Store → Payment → Ko-fi Webhook → Caddy → Backend
                                                              ↓
                                               KofiPayment record created
                                               If email matches user →
                                               Transaction (PURCHASE) + credits added
                                               Socket.io → User notified

Security Considerations

Network Security

  1. Backend host mode — Required for local network access, but exposes host network
  2. Caddy handles SSL — Only HTTPS externally
  3. Internal services — PostgreSQL/Redis not exposed externally (except through Docker ports)

API Security

  1. Tautulli Webhook — Optional secret verification (TAUTULLI_WEBHOOK_SECRET)
  2. Overseer Webhook — No secret currently configured
  3. Plex OAuth — Standard OAuth 2.0 flow
  4. JWT — Secure tokens with nonce for session deduplication
  5. Rate Limiting — 1000 requests per 15 minutes per IP

Data Security

  1. No wallet keys — Solana removed, no private keys stored
  2. Database — Localhost only, password protected
  3. Redis — Localhost only
  4. Ko-fi verification — Token check on webhook endpoint

Firewall Configuration

# Web traffic (Caddy handles SSL)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

# Internal service access (from Docker containers)
sudo ufw allow from 172.20.0.0/16 to 172.20.1.0/24

# Block external access to internal services
sudo ufw deny 3000/tcp    # Frontend (should be localhost only)
sudo ufw deny 3002/tcp    # Backend (should be localhost only)
sudo ufw deny 5432/tcp    # PostgreSQL
sudo ufw deny 6379/tcp    # Redis

Docker Network Configuration

Bridge Network (coop-network)

  • Frontend container uses this
  • Isolated from external network
  • Connects: frontend ↔ Caddy proxy

Host Network (backend only)

  • Backend container uses network_mode: host
  • Shares host's network stack
  • Required to reach 172.20.1.x services (Tautulli, Overseer)
  • Connects directly to PostgreSQL/Redis on localhost

Monitoring and Logging

Log Locations

  • Backend: docker logs coop-backend
  • Frontend: docker logs coop-frontend
  • Database: Inside container (/var/log/postgresql/)

Health Checks

# Backend health
curl http://localhost:3002/health

# Database connection
docker exec coop-postgres pg_isready -U coop

# Service status
docker ps

Backup and Recovery

Database Backup

# Automated backup
docker exec -T coop-postgres pg_dump -U coop coop_credits > backup_$(date +%Y%m%d).sql

Configuration Backup

  • .env file (contains all secrets)
  • docker-compose.yml service config
  • Caddy config (on separate machine)

Troubleshooting

Cannot reach local services

  1. Check backend is in host network mode: docker inspect coop-backend | grep NetworkMode
  2. Verify IP connectivity from host: ping 172.20.1.255
  3. Check backend logs: docker logs --tail 50 coop-backend

Webhook not received

  1. Verify Caddy routes /webhooks/* to backend
  2. Check backend logs for webhook handler output
  3. Test manually: curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli -d '{"test":true}'

CORS errors

  1. Verify FRONTEND_URL and API_URL in .env
  2. Check backend CORS origins include your domain
  3. Caddy should pass through headers without modification