docs: update all documentation to reflect current project state
This commit is contained in:
+26
-17
@@ -1,41 +1,47 @@
|
||||
# Caddy Configuration
|
||||
|
||||
Caddy handles SSL termination and routes to the application services.
|
||||
Caddy handles SSL termination and routes to the application services running on `172.20.1.238`.
|
||||
|
||||
## Caddyfile Example
|
||||
|
||||
```caddy
|
||||
coop.hobokenchicken.com {
|
||||
# Frontend (Next.js)
|
||||
handle_path /* {
|
||||
reverse_proxy localhost:3000
|
||||
handle /* {
|
||||
reverse_proxy 172.20.1.238:3000
|
||||
}
|
||||
|
||||
# API routes
|
||||
handle_path /api/* {
|
||||
reverse_proxy localhost:3001
|
||||
# API routes — use handle (NOT handle_path) to preserve /api/ prefix
|
||||
handle /api/* {
|
||||
reverse_proxy 172.20.1.238:3002
|
||||
}
|
||||
|
||||
# Webhooks
|
||||
handle_path /webhooks/* {
|
||||
reverse_proxy localhost:3001
|
||||
handle /webhooks/* {
|
||||
reverse_proxy 172.20.1.238:3002
|
||||
}
|
||||
|
||||
# WebSocket support
|
||||
handle_path /socket.io/* {
|
||||
reverse_proxy localhost:3001
|
||||
handle /socket.io/* {
|
||||
reverse_proxy 172.20.1.238:3002
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> **Critical:** Use `handle` (not `handle_path`) for `/api/*` and `/webhooks/*`. `handle_path` strips the path prefix, which breaks Express routing.
|
||||
|
||||
## Docker Compose (no nginx)
|
||||
|
||||
Services bind to localhost only (`127.0.0.1`):
|
||||
Services bind as follows:
|
||||
|
||||
- **Frontend**: `127.0.0.1:3000`
|
||||
- **Backend**: `127.0.0.1:3001`
|
||||
- **Postgres**: `5432` (internal only)
|
||||
- **Redis**: `6379` (internal only)
|
||||
- **Frontend**: `0.0.0.0:3000` (bridge network, accessible from Caddy)
|
||||
- **Backend**: `localhost:3002` (host network, accessible from Caddy via host IP)
|
||||
- **Postgres**: `127.0.0.1:5432` (localhost only)
|
||||
- **Redis**: `127.0.0.1:6379` (localhost only)
|
||||
|
||||
## Backend Port
|
||||
|
||||
Backend runs on **port 3002** (not 3001). Caddy must proxy to `172.20.1.238:3002`.
|
||||
|
||||
## Start Stack
|
||||
|
||||
@@ -43,8 +49,11 @@ Services bind to localhost only (`127.0.0.1`):
|
||||
# Start services
|
||||
docker-compose up -d
|
||||
|
||||
# Verify
|
||||
curl http://localhost:3001/health
|
||||
# Verify backend
|
||||
curl http://172.20.1.238:3002/health
|
||||
|
||||
# Verify frontend
|
||||
curl http://172.20.1.238:3000
|
||||
```
|
||||
|
||||
Caddy automatically provisions SSL and routes traffic.
|
||||
|
||||
+116
-112
@@ -10,15 +10,16 @@
|
||||
│ HTTPS (443)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ CoopCredits Server │
|
||||
│ CoopCredits Server (172.20.1.238) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Nginx │ │ Frontend │ │ Backend │ │ PostgreSQL │ │
|
||||
│ │ (80) │──│ (Next.js) │──│ (Express) │──│ (5432) │ │
|
||||
│ │ Caddy │ │ Frontend │ │ Backend │ │ PostgreSQL │ │
|
||||
│ │ (reverse) │──│ (Next.js) │ │ (Express) │──│ (5432) │ │
|
||||
│ │ Proxy │ │ :3000 │ │ :3002 │ │ │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────┬───────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────┐ │ ┌──────────────┐ │
|
||||
│ │ Redis │◀────────┘ │ Anchor CLI │ │
|
||||
│ │ (6379) │ │ (Optional) │ │
|
||||
│ │ Redis │◀────────┘ │ (Ko-fi) │ │
|
||||
│ │ (6379) │ │ (Webhooks) │ │
|
||||
│ └──────────────┘ └──────────────┘ │
|
||||
└──────────────────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
@@ -33,80 +34,115 @@
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
> **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 authentication for website login
|
||||
- **Access**: HTTP on local network, may have remote access enabled
|
||||
- **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 backend
|
||||
- **Access**: HTTP on local network
|
||||
- **API Key**: Required for backend queries
|
||||
- **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 requesting content, webhooks for status updates
|
||||
- **Access**: HTTP on local network
|
||||
- **API Key**: Required for backend integration
|
||||
|
||||
### CoopCredits Server
|
||||
- **Public Access**: coop.hobokenchicken.com (HTTPS)
|
||||
- **Internal Services**: Only accessible via Nginx reverse proxy
|
||||
- **Database**: PostgreSQL on localhost only
|
||||
- **Cache**: Redis on localhost only
|
||||
- **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 → Nginx → Frontend → Backend → Plex OAuth (172.20.1.220:32400)
|
||||
↓
|
||||
User authenticated, JWT issued
|
||||
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 → Nginx → Backend → Solana Devnet
|
||||
↓
|
||||
Database updated
|
||||
↓
|
||||
WebSocket → User notified
|
||||
Plex → Tautulli → Webhook → Caddy → Backend → PostgreSQL
|
||||
↓
|
||||
WatchEvent + Transaction created
|
||||
Socket.io → User notified
|
||||
```
|
||||
|
||||
### 3. Content Request
|
||||
```
|
||||
User → Nginx → Frontend → Backend → Overseer API (172.20.1.225:5055)
|
||||
User → Caddy → Frontend → Backend → Overseer API (172.20.1.225:5055)
|
||||
↓
|
||||
Request created, $COOP reserved
|
||||
Request created, $COOP deducted immediately
|
||||
ContentRequest stored as PENDING
|
||||
↓
|
||||
Webhook on approval → Burn $COOP
|
||||
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. **Local Network**: All services communicate over HTTP (trusted network)
|
||||
2. **External Access**: Only Nginx exposed (ports 80/443)
|
||||
3. **Internal Services**: Not accessible from external network
|
||||
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**: Secret verification recommended
|
||||
2. **Overseer API**: API key authentication
|
||||
3. **Plex OAuth**: Standard OAuth 2.0 flow
|
||||
4. **JWT**: Secure tokens for session management
|
||||
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. **Wallet Keys**: Encrypted with AES-256-GCM in database
|
||||
2. **Database**: Not exposed externally
|
||||
3. **Redis**: Password protected, localhost only
|
||||
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
|
||||
|
||||
```bash
|
||||
# Web traffic
|
||||
# Web traffic (Caddy handles SSL)
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
|
||||
@@ -114,102 +150,70 @@ sudo ufw allow 443/tcp
|
||||
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
|
||||
sudo ufw deny 3001/tcp # Backend
|
||||
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
|
||||
|
||||
### Internal Network (coop-internal)
|
||||
- Containers can communicate with each other
|
||||
### Bridge Network (coop-network)
|
||||
- Frontend container uses this
|
||||
- Isolated from external network
|
||||
- Used for: frontend ↔ backend ↔ database
|
||||
- Connects: frontend ↔ Caddy proxy
|
||||
|
||||
### External Network (coop-external)
|
||||
- Allows containers to reach local services
|
||||
- Subnet: 172.20.2.0/24
|
||||
- Used for: backend → Tautulli/Overseer/Plex
|
||||
|
||||
## SSL/TLS
|
||||
|
||||
SSL/TLS is handled by an external reverse proxy (e.g., Caddy). The application stack runs HTTP only on port 80 internally.
|
||||
### 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
|
||||
- Nginx: `docker/nginx/logs/`
|
||||
- Backend: Docker logs (`docker-compose logs backend`)
|
||||
- Frontend: Docker logs (`docker-compose logs frontend`)
|
||||
- Backend: `docker logs coop-backend`
|
||||
- Frontend: `docker logs coop-frontend`
|
||||
- Database: Inside container (`/var/log/postgresql/`)
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# Backend health
|
||||
curl https://coop.hobokenchicken.com/health
|
||||
curl http://localhost:3002/health
|
||||
|
||||
# Database connection
|
||||
docker-compose exec postgres pg_isready -U coop
|
||||
docker exec coop-postgres pg_isready -U coop
|
||||
|
||||
# Service status
|
||||
docker-compose ps
|
||||
docker ps
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot reach local services
|
||||
1. Check Docker network: `docker network inspect coop-credits_coop-external`
|
||||
2. Verify IP connectivity: `docker exec coop-backend ping 172.20.1.255`
|
||||
3. Check firewall rules: `sudo ufw status`
|
||||
|
||||
### Webhook not received
|
||||
1. Verify Tautulli can reach CoopCredits:
|
||||
```bash
|
||||
curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": true}'
|
||||
```
|
||||
2. Check Nginx logs: `tail -f docker/nginx/logs/access.log`
|
||||
3. Check backend logs: `docker-compose logs -f backend`
|
||||
|
||||
### CORS errors
|
||||
1. Verify CORS_ORIGINS in .env includes your domain
|
||||
2. Check backend is sending correct headers
|
||||
3. Nginx should pass through CORS headers
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Nginx Tuning
|
||||
- `worker_processes auto` - Use all CPU cores
|
||||
- `worker_connections 1024` - High connection limit
|
||||
- `gzip on` - Compress responses
|
||||
- `proxy_cache` - Cache static assets
|
||||
|
||||
### Database Tuning
|
||||
- Connection pooling via Prisma
|
||||
- Redis for session caching
|
||||
- Indexed queries on user_id, created_at
|
||||
|
||||
### Frontend Optimization
|
||||
- Next.js static generation where possible
|
||||
- Image optimization
|
||||
- Code splitting
|
||||
|
||||
## Backup and Recovery
|
||||
|
||||
### Database Backup
|
||||
```bash
|
||||
# Automated backup script
|
||||
docker-compose exec -T postgres pg_dump -U coop coop_credits > backup_$(date +%Y%m%d).sql
|
||||
# Automated backup
|
||||
docker exec -T coop-postgres pg_dump -U coop coop_credits > backup_$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
### Wallet Recovery
|
||||
- Private keys are encrypted in database
|
||||
- Backup keys stored securely (encrypted)
|
||||
- Recovery requires encryption key from .env
|
||||
|
||||
### Configuration Backup
|
||||
- `.env` file (contains all secrets)
|
||||
- `docker/nginx/ssl/` certificates
|
||||
- `docker-compose.prod.yml` service config
|
||||
- `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
|
||||
|
||||
+76
-159
@@ -5,9 +5,10 @@ This guide covers setting up CoopCredits with your existing Plex/Tautulli/Overse
|
||||
## Prerequisites
|
||||
|
||||
- Server running Docker and Docker Compose
|
||||
- Access to 172.20.1.0/24 network
|
||||
- Access to `172.20.1.0/24` network
|
||||
- API keys from Tautulli and Overseer
|
||||
- Domain name (coop.hobokenchicken.com) pointing to your server
|
||||
- Domain name (`coop.hobokenchicken.com`) pointing to your server
|
||||
- Ko-fi account with store items set up (optional, for credit purchases)
|
||||
|
||||
## Network Overview
|
||||
|
||||
@@ -38,72 +39,64 @@ git clone <repository> coop-credits
|
||||
cd coop-credits
|
||||
```
|
||||
|
||||
### 2. Run Infrastructure Setup
|
||||
|
||||
```bash
|
||||
./deployment/setup-infrastructure.sh
|
||||
```
|
||||
|
||||
This script will:
|
||||
- Test connectivity to your services (Plex, Tautulli, Overseer)
|
||||
- Generate a secure `.env` file
|
||||
- Output configuration instructions
|
||||
|
||||
**Note:** SSL/TLS is handled by your external reverse proxy (Caddy). The application runs HTTP on port 80 internally.
|
||||
|
||||
### 3. Configure Environment
|
||||
|
||||
Edit the generated `.env` file:
|
||||
### 2. Configure Environment
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
nano .env
|
||||
```
|
||||
|
||||
Add your API keys:
|
||||
Required environment variables:
|
||||
|
||||
```env
|
||||
# Get from Tautulli: Settings > Web Interface > API
|
||||
TAUTULLI_API_KEY=your-tautulli-api-key
|
||||
# Database
|
||||
DATABASE_URL="postgresql://coop:coop_password@localhost:5432/coop_credits?schema=public"
|
||||
|
||||
# Get from Overseer: Settings > General > API Key
|
||||
OVERSEER_API_KEY=your-overseer-api-key
|
||||
# Server
|
||||
PORT=3002
|
||||
API_URL=https://coop.hobokenchicken.com
|
||||
FRONTEND_URL=https://coop.hobokenchicken.com
|
||||
|
||||
# Get from https://plex.tv/claim or Plex settings
|
||||
# JWT Secret (generate: openssl rand -hex 32)
|
||||
JWT_SECRET=your-random-secret
|
||||
|
||||
# Plex OAuth
|
||||
PLEX_CLIENT_ID=your-plex-client-id
|
||||
PLEX_CLIENT_SECRET=your-plex-client-secret
|
||||
PLEX_REDIRECT_URI=https://coop.hobokenchicken.com/auth/callback
|
||||
|
||||
# Tautulli
|
||||
TAUTULLI_URL=http://172.20.1.255:8181
|
||||
TAUTULLI_API_KEY=your-tautulli-api-key
|
||||
|
||||
# Overseer
|
||||
OVERSEER_URL=http://172.20.1.225:5055
|
||||
OVERSEER_API_KEY=your-overseer-api-key
|
||||
|
||||
# Ko-fi (optional — for credit purchases)
|
||||
KOFI_VERIFICATION_TOKEN=your-kofi-verification-token
|
||||
|
||||
# Security
|
||||
ENCRYPTION_KEY=$(openssl rand -base64 32)
|
||||
```
|
||||
|
||||
### 4. Setup Solana
|
||||
### 3. Deploy
|
||||
|
||||
```bash
|
||||
npm run setup:solana
|
||||
docker-compose up -d --build
|
||||
|
||||
# Initialize database (first time only)
|
||||
docker exec coop-backend npx prisma db push --accept-data-loss
|
||||
```
|
||||
|
||||
This will:
|
||||
- Install Solana CLI
|
||||
- Create a devnet wallet
|
||||
- Request airdrop
|
||||
- Output the private key for your `.env` file
|
||||
### 4. Configure Caddy
|
||||
|
||||
Copy the `SOLANA_MINT_AUTHORITY_KEYPAIR` into your `.env` file.
|
||||
See `docs/CADDY-CONFIG.md`. Key points:
|
||||
- Backend runs on **port 3002**
|
||||
- Use `handle` (not `handle_path`) for `/api/*`
|
||||
- Proxy `/webhooks/*` to backend
|
||||
|
||||
### 5. Deploy Solana Program
|
||||
|
||||
```bash
|
||||
cd anchor-program
|
||||
anchor build
|
||||
anchor deploy
|
||||
```
|
||||
|
||||
Update `SOLANA_PROGRAM_ID` in `.env` with the deployed program ID.
|
||||
|
||||
### 6. Deploy
|
||||
|
||||
```bash
|
||||
./deployment/deploy-production.sh
|
||||
```
|
||||
|
||||
### 8. Configure Tautulli Webhook
|
||||
### 5. Configure Tautulli Webhook
|
||||
|
||||
1. Open Tautulli: http://172.20.1.255:8181
|
||||
2. Go to **Settings > Notification Agents**
|
||||
@@ -134,7 +127,7 @@ Update `SOLANA_PROGRAM_ID` in `.env` with the deployed program ID.
|
||||
|
||||
**Triggers:** Enable **Watched**
|
||||
|
||||
### 9. Configure Overseer Webhook
|
||||
### 6. Configure Overseer Webhook
|
||||
|
||||
1. Open Overseer: http://172.20.1.225:5055
|
||||
2. Go to **Settings > Notifications**
|
||||
@@ -142,7 +135,7 @@ Update `SOLANA_PROGRAM_ID` in `.env` with the deployed program ID.
|
||||
|
||||
**Configuration:**
|
||||
- Webhook URL: `https://coop.hobokenchicken.com/webhooks/overseer`
|
||||
- Authorization Header: `Bearer your-webhook-secret-from-env`
|
||||
- Content Type: `application/json`
|
||||
|
||||
**JSON Payload:**
|
||||
```json
|
||||
@@ -156,24 +149,33 @@ Update `SOLANA_PROGRAM_ID` in `.env` with the deployed program ID.
|
||||
|
||||
**Events:** Enable **Request Approved** and **Request Declined**
|
||||
|
||||
### 7. Configure Ko-fi Webhook (Optional)
|
||||
|
||||
1. Go to ko-fi.com → **Settings > Webhooks**
|
||||
2. Set **Webhook URL** to: `https://coop.hobokenchicken.com/webhooks/kofi`
|
||||
3. Save
|
||||
|
||||
Create store items:
|
||||
- $5 item → link: `https://ko-fi.com/s/YOUR_ITEM_ID`
|
||||
- $10 item → link: `https://ko-fi.com/s/YOUR_ITEM_ID`
|
||||
|
||||
Update frontend preset links in `frontend/src/app/dashboard/components/BuyCreditsModal.tsx`
|
||||
|
||||
### 8. Set Admin User
|
||||
|
||||
```bash
|
||||
docker exec coop-postgres psql -U coop -d coop_credits -c "UPDATE users SET is_admin = true WHERE plex_username = 'YOUR_USERNAME';"
|
||||
```
|
||||
|
||||
## Verification
|
||||
|
||||
### Test Connectivity
|
||||
|
||||
```bash
|
||||
./deployment/health-check.sh
|
||||
```
|
||||
# Backend health
|
||||
curl https://coop.hobokenchicken.com/health
|
||||
|
||||
### Watch Mode
|
||||
|
||||
```bash
|
||||
./deployment/health-check.sh --watch
|
||||
```
|
||||
|
||||
### Manual Tests
|
||||
|
||||
**Test Tautulli webhook:**
|
||||
```bash
|
||||
# Test Tautulli webhook manually
|
||||
curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
@@ -190,88 +192,6 @@ curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
}'
|
||||
```
|
||||
|
||||
**Test API:**
|
||||
```bash
|
||||
curl https://coop.hobokenchicken.com/api/health
|
||||
```
|
||||
|
||||
## Firewall Configuration
|
||||
|
||||
If using UFW:
|
||||
|
||||
```bash
|
||||
# Allow web traffic
|
||||
sudo ufw allow 80/tcp
|
||||
sudo ufw allow 443/tcp
|
||||
|
||||
# Allow backend to reach local network
|
||||
sudo ufw allow from 172.20.2.0/16 to 172.20.1.0/24
|
||||
|
||||
# Deny direct access to internal services
|
||||
sudo ufw deny 3000/tcp
|
||||
sudo ufw deny 3001/tcp
|
||||
sudo ufw deny 5432/tcp
|
||||
sudo ufw deny 6379/tcp
|
||||
|
||||
# Enable firewall
|
||||
sudo ufw enable
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Cannot reach local services
|
||||
|
||||
1. Check Docker network:
|
||||
```bash
|
||||
docker network inspect coop-credits_coop-external
|
||||
```
|
||||
|
||||
2. Test connectivity from container:
|
||||
```bash
|
||||
docker exec coop-backend ping 172.20.1.255
|
||||
```
|
||||
|
||||
3. Verify firewall rules:
|
||||
```bash
|
||||
sudo ufw status verbose
|
||||
```
|
||||
|
||||
### Webhooks not working
|
||||
|
||||
1. Check Nginx logs:
|
||||
```bash
|
||||
tail -f docker/nginx/logs/access.log
|
||||
```
|
||||
|
||||
2. Check backend logs:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml logs -f backend
|
||||
```
|
||||
|
||||
3. Test webhook manually:
|
||||
```bash
|
||||
curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": true}'
|
||||
```
|
||||
|
||||
### Database connection issues
|
||||
|
||||
1. Check database status:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml ps postgres
|
||||
```
|
||||
|
||||
2. View database logs:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml logs postgres
|
||||
```
|
||||
|
||||
3. Test connection:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml exec postgres pg_isready -U coop
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Update Application
|
||||
@@ -279,48 +199,45 @@ sudo ufw enable
|
||||
```bash
|
||||
cd /opt/coop-credits
|
||||
git pull
|
||||
./deployment/deploy-production.sh
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
### Backup Database
|
||||
|
||||
```bash
|
||||
# Automated backup
|
||||
docker-compose -f docker-compose.prod.yml exec -T postgres pg_dump -U coop coop_credits > backup_$(date +%Y%m%d).sql
|
||||
docker exec -T coop-postgres pg_dump -U coop coop_credits > backup_$(date +%Y%m%d).sql
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# All services
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
docker-compose logs -f
|
||||
|
||||
# Specific service
|
||||
docker-compose -f docker-compose.prod.yml logs -f backend
|
||||
docker-compose logs -f backend
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml restart backend
|
||||
docker-compose restart backend
|
||||
docker-compose restart frontend
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Changed all default passwords in `.env`
|
||||
- [ ] Changed default PostgreSQL password
|
||||
- [ ] External reverse proxy (Caddy) configured for SSL
|
||||
- [ ] Firewall rules configured
|
||||
- [ ] Tautulli webhook secret set
|
||||
- [ ] Overseer webhook secret set
|
||||
- [ ] JWT secret is random and secure
|
||||
- [ ] Database not exposed externally
|
||||
- [ ] Redis password set
|
||||
- [ ] Encryption key is random and backed up
|
||||
- [ ] Solana mint authority key backed up securely
|
||||
- [ ] Ko-fi verification token set (if using purchases)
|
||||
|
||||
## Support
|
||||
|
||||
For issues:
|
||||
1. Check health: `./deployment/health-check.sh`
|
||||
2. Review logs: `docker-compose -f docker-compose.prod.yml logs`
|
||||
3. Check documentation in `docs/INFRASTRUCTURE.md`
|
||||
1. Check logs: `docker-compose logs -f`
|
||||
2. Review environment variables
|
||||
3. Verify all services are running: `docker ps`
|
||||
|
||||
+80
-132
@@ -1,35 +1,5 @@
|
||||
# CoopCredits Troubleshooting Guide
|
||||
|
||||
## Installation Warnings
|
||||
|
||||
### NPM Deprecation Warnings
|
||||
|
||||
When running `npm install`, you may see warnings like:
|
||||
|
||||
```
|
||||
npm WARN deprecated inflight@1.0.6: This module is not supported...
|
||||
npm WARN deprecated glob@7.2.0: Old versions of glob are not supported...
|
||||
npm WARN deprecated @walletconnect/sign-client@2.19.0: ...
|
||||
```
|
||||
|
||||
**These are safe to ignore.** These warnings come from:
|
||||
- Transitive dependencies (dependencies of dependencies)
|
||||
- Solana wallet adapter packages that haven't updated yet
|
||||
- Legacy packages still used by the Anchor framework
|
||||
|
||||
**Critical fix applied:**
|
||||
- ✅ Next.js updated from 14.0.4 to 14.2.15 (security vulnerability patched)
|
||||
|
||||
**What you can do:**
|
||||
```bash
|
||||
# The warnings don't affect functionality
|
||||
# To suppress them during install:
|
||||
npm install --silent
|
||||
|
||||
# Or use --legacy-peer-deps if needed:
|
||||
npm install --legacy-peer-deps
|
||||
```
|
||||
|
||||
## Common Issues
|
||||
|
||||
### Database Connection Failed
|
||||
@@ -48,21 +18,6 @@ sleep 5
|
||||
docker-compose exec postgres pg_isready -U coop
|
||||
```
|
||||
|
||||
### Solana Program Build Fails
|
||||
|
||||
**Error:** `anchor build` fails with Rust errors
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Update Rust
|
||||
cd anchor-program
|
||||
rustup update
|
||||
|
||||
# Rebuild
|
||||
anchor clean
|
||||
anchor build
|
||||
```
|
||||
|
||||
### Webhooks Not Receiving
|
||||
|
||||
**Error:** Tautulli/Overseer webhooks not triggering
|
||||
@@ -75,16 +30,18 @@ anchor build
|
||||
|
||||
2. Check webhook URL in Tautulli/Overseer settings
|
||||
|
||||
3. Check Nginx logs:
|
||||
3. Check Caddy routes `/webhooks/*` to backend port 3002
|
||||
|
||||
4. Check backend logs:
|
||||
```bash
|
||||
tail -f docker/nginx/logs/access.log
|
||||
docker logs --tail 50 coop-backend
|
||||
```
|
||||
|
||||
4. Test webhook manually:
|
||||
5. Test webhook manually:
|
||||
```bash
|
||||
curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"test": true}'
|
||||
-d '{"action":"watched","user_id":"1","rating_key":"1","session_key":"1","media_type":"movie","title":"Test","started":1,"stopped":3601,"percent_complete":90}'
|
||||
```
|
||||
|
||||
### Cannot Reach Local Services (172.20.1.x)
|
||||
@@ -93,85 +50,72 @@ anchor build
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Test connectivity from backend container
|
||||
docker exec coop-backend ping 172.20.1.255
|
||||
# Verify backend is in host network mode
|
||||
docker inspect coop-backend | grep NetworkMode
|
||||
# Should show: "host"
|
||||
|
||||
# Check Docker network
|
||||
docker network ls
|
||||
docker network inspect coop-credits_coop-external
|
||||
# Test connectivity from host
|
||||
ping 172.20.1.255
|
||||
|
||||
# Verify firewall rules
|
||||
sudo ufw status
|
||||
# Check backend logs
|
||||
docker logs --tail 50 coop-backend
|
||||
|
||||
# Verify env vars
|
||||
docker exec coop-backend env | grep TAUTULLI
|
||||
docker exec coop-backend env | grep OVERSEER
|
||||
```
|
||||
|
||||
### Wallet Creation Fails
|
||||
> Backend must use `network_mode: host` to reach `172.20.1.x` subnet. Docker bridge networking cannot route to this subnet.
|
||||
|
||||
**Error:** `Failed to create wallet` or Solana errors
|
||||
### Ko-fi Webhook Not Working
|
||||
|
||||
**Error:** Payments not crediting users
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check Solana configuration
|
||||
solana config get
|
||||
1. Verify `KOFI_VERIFICATION_TOKEN` env var is set in backend container:
|
||||
```bash
|
||||
docker exec coop-backend env | grep KOFI
|
||||
```
|
||||
|
||||
# Ensure you're on devnet
|
||||
solana config set --url devnet
|
||||
2. Check Ko-fi webhook settings — URL should be:
|
||||
```
|
||||
https://coop.hobokenchicken.com/webhooks/kofi
|
||||
```
|
||||
|
||||
# Check balance
|
||||
solana balance
|
||||
3. Check backend logs for verification token mismatch
|
||||
|
||||
# Request airdrop if needed
|
||||
solana airdrop 2
|
||||
4. Check admin **Donations** tab to see if payments arrive as UNCLAIMED (email mismatch)
|
||||
|
||||
### BigInt JSON Serialization Error
|
||||
|
||||
**Error:** `Do not know how to serialize a BigInt`
|
||||
|
||||
**Solution:** This is fixed in `backend/src/index.ts` with:
|
||||
```typescript
|
||||
(BigInt.prototype as any).toJSON = function () {
|
||||
return this.toString();
|
||||
};
|
||||
```
|
||||
|
||||
If you still see it, ensure the patch is loaded before any route handlers.
|
||||
|
||||
### CORS Errors in Browser
|
||||
|
||||
**Error:** `Access-Control-Allow-Origin` errors
|
||||
|
||||
**Solution:**
|
||||
1. Check `FRONTEND_URL` in backend `.env` matches your actual URL
|
||||
2. Verify CORS_ORIGINS includes your domain
|
||||
2. Verify CORS origins include your domain in `backend/src/index.ts`
|
||||
3. Restart backend after changes
|
||||
|
||||
### High Memory Usage
|
||||
### Rate Limiting (429 Too Many Requests)
|
||||
|
||||
**Symptom:** Server slows down or OOM errors
|
||||
**Error:** Dashboard shows "Slow down, chicken!" or fails to load
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Check what's using memory
|
||||
docker stats
|
||||
|
||||
# Restart services
|
||||
docker-compose -f docker-compose.prod.yml restart
|
||||
|
||||
# Increase swap if needed
|
||||
sudo fallocate -l 2G /swapfile
|
||||
sudo chmod 600 /swapfile
|
||||
sudo mkswap /swapfile
|
||||
sudo swapon /swapfile
|
||||
```
|
||||
|
||||
## Docker Build Issues
|
||||
|
||||
### Backend Build Fails: Cannot redeclare block-scoped variable
|
||||
|
||||
**Error:** `error TS2451: Cannot redeclare block-scoped variable 'signature'`
|
||||
|
||||
**Solution:** Fixed in source. If you see this, pull the latest code.
|
||||
|
||||
### Backend: Prisma Client could not locate Query Engine
|
||||
|
||||
**Error:** `PrismaClientInitializationError: Prisma Client could not locate the Query Engine`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
# Regenerate Prisma client with correct binary target
|
||||
cd backend
|
||||
npx prisma generate
|
||||
|
||||
# Rebuild backend container
|
||||
docker-compose up -d --build backend
|
||||
```
|
||||
- Rate limit is 1000 requests per 15 minutes per IP
|
||||
- If you hit it, wait a few minutes
|
||||
- The dashboard makes several parallel calls on load — this is normal
|
||||
|
||||
### Frontend Build Fails: Module not found
|
||||
|
||||
@@ -184,23 +128,7 @@ docker-compose up -d --build backend
|
||||
}
|
||||
```
|
||||
|
||||
### Frontend: Prerender Error on /login
|
||||
|
||||
**Error:** `Error occurred prerendering page "/login"`
|
||||
|
||||
**Solution:** This was caused by zustand persist middleware accessing localStorage during SSR. Fixed by wrapping providers with dynamic import `ssr: false`.
|
||||
|
||||
### Frontend: Cannot find module 'next-themes'
|
||||
|
||||
**Error:** `Module not found: Can't resolve 'next-themes'`
|
||||
|
||||
**Solution:**
|
||||
```bash
|
||||
cd frontend
|
||||
npm install next-themes
|
||||
```
|
||||
|
||||
### Docker Compose: Public Directory Not Found
|
||||
### Docker Build: Public Directory Not Found
|
||||
|
||||
**Error:** `failed to calculate checksum: "/app/frontend/public": not found`
|
||||
|
||||
@@ -210,25 +138,45 @@ mkdir -p frontend/public
|
||||
touch frontend/public/.gitkeep
|
||||
```
|
||||
|
||||
### Request Stuck on PENDING
|
||||
|
||||
**Error:** Request never updates from PENDING status
|
||||
|
||||
**Solution:**
|
||||
1. Check Overseer webhook is configured correctly
|
||||
2. In admin dashboard, go to **The Feed Queue** tab and click **SYNC**
|
||||
3. Or manually sync from dashboard's Requests tab
|
||||
4. Check backend logs for Overseer API errors
|
||||
|
||||
### Disk Space Not Updating
|
||||
|
||||
**Error:** Silo bar shows old values after downloading large files
|
||||
|
||||
**Solution:**
|
||||
- Disk space is cached for 30 seconds
|
||||
- Wait 30 seconds and refresh
|
||||
- The bar updates automatically on dashboard load
|
||||
|
||||
## Getting Help
|
||||
|
||||
1. Check health status:
|
||||
1. View all logs:
|
||||
```bash
|
||||
./deployment/health-check.sh
|
||||
docker-compose logs -f
|
||||
```
|
||||
|
||||
2. View all logs:
|
||||
2. Check specific service:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
docker-compose logs -f backend
|
||||
docker-compose logs -f frontend
|
||||
```
|
||||
|
||||
3. Check specific service:
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml logs -f backend
|
||||
```
|
||||
|
||||
4. Verify environment:
|
||||
3. Verify environment:
|
||||
```bash
|
||||
# Check all required env vars are set
|
||||
grep -E '^\w+=' .env | wc -l
|
||||
```
|
||||
|
||||
4. Check database:
|
||||
```bash
|
||||
docker exec coop-postgres psql -U coop -d coop_credits -c "SELECT COUNT(*) FROM users;"
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user