docs: update all documentation to reflect current project state

This commit is contained in:
2026-04-23 14:35:08 -04:00
parent 8b31045dcf
commit 3029ce7053
9 changed files with 566 additions and 639 deletions
+9 -17
View File
@@ -8,9 +8,9 @@ DATABASE_URL="postgresql://coop:CHANGE_PASSWORD@localhost:5432/coop_credits?sche
POSTGRES_PASSWORD="CHANGE_THIS_PASSWORD"
# Server
PORT=3001
PORT=3002
NODE_ENV=development
API_URL=http://localhost:3001
API_URL=http://localhost:3002
FRONTEND_URL=http://localhost:3000
# JWT Secret (generate with: openssl rand -hex 32)
@@ -26,30 +26,24 @@ PLEX_REDIRECT_URI=http://localhost:3000/auth/callback
# ==========================================
# Tautulli (Watch Analytics)
# Backend uses host network mode to reach this
# ==========================================
# Your Tautulli instance URL
TAUTULLI_URL=http://172.20.1.255:8181
# Get API key from: Tautulli Settings > Web Interface > API
TAUTULLI_API_KEY=""
# Optional: Secret for webhook signature verification
TAUTULLI_WEBHOOK_SECRET=""
# ==========================================
# Overseer (Content Requests)
# Backend uses host network mode to reach this
# ==========================================
# Your Overseer instance URL
OVERSEER_URL=http://172.20.1.225:5055
# Get API key from: Overseer Settings > General
OVERSEER_API_KEY=""
# ==========================================
# Solana (Devnet for testing)
# Ko-fi (Optional Credit Purchases)
# Get verification token from Ko-fi Settings > Webhooks
# ==========================================
SOLANA_RPC_URL=https://api.devnet.solana.com
SOLANA_PROGRAM_ID=CoopCredits111111111111111111111111111111111
# Generate keypair with: npm run setup:solana
SOLANA_MINT_AUTHORITY_KEYPAIR=""
SOLANA_TOKEN_DECIMALS=6
KOFI_VERIFICATION_TOKEN=""
# ==========================================
# Redis (optional caching)
@@ -59,15 +53,13 @@ REDIS_PASSWORD=""
# ==========================================
# Encryption (generate with: openssl rand -base64 32)
# Used for encrypting wallet private keys
# Used for session cookie encryption
# ==========================================
ENCRYPTION_KEY=""
# ==========================================
# Frontend Public Variables
# ==========================================
NEXT_PUBLIC_API_URL=http://localhost:3001
NEXT_PUBLIC_SOLANA_NETWORK=devnet
NEXT_PUBLIC_SOLANA_RPC_URL=https://api.devnet.solana.com
NEXT_PUBLIC_API_URL=http://localhost:3002
NEXT_PUBLIC_APP_NAME=CoopCredits
NEXT_PUBLIC_APP_URL=http://localhost:3000
+21 -18
View File
@@ -1,21 +1,24 @@
# Frontend Todo List
## Phase 1: Accessibility & Onboarding (Priority: 1)
- [x] **Landing Page**: Marketing page at `/` with "How it Works".
- [x] **Onboarding Flow**: Better guided steps for new users to set up their wallet.
- [x] **Mobile Responsiveness**: Audit and fix layout shifts on small screens.
## Completed
- [x] **Landing Page** — Barnyard-themed "Enter the Coop" page
- [x] **Login Flow** — Plex OAuth with auto-redirect
- [x] **Dashboard** — Nest Egg balance, Eggs Ordered, Market Price cards
- [x] **Watch History** — Personal watch events with credits earned
- [x] **Request History** — Content requests with status filtering
- [x] **Search Request Modal** — Overseer search with posters, episode counts, dynamic pricing
- [x] **Buy Credits Modal** — Ko-fi store links for $5/500 and $10/1000
- [x] **Activity Feed** — Recent transactions sidebar
- [x] **Leaderboard** — Rich Birds (top earners) and Lazy Birds (top watchers)
- [x] **Socket.io Integration** — Live balance updates, credit earned toasts
- [x] **Disk Space Bar** — The Silo: used/total GB with scarcity warning
- [x] **Admin Dashboard** — The Flock, Barn Rules, Donations, Egg Stats, The Feed Queue
- [x] **Mobile Responsiveness** — Barnyard cards stack on small screens
- [x] **Barnyard Theme** — Comic Sans, thick borders, earthy palette, jokey copy
## Phase 2: Engagement & Real-time (Priority: 2)
- [x] **Socket.io Integration**: Connect to backend for live watch events.
- [x] **Live Reward Toasts**: Show "You earned 10 $COOP" alerts in real-time.
- [x] **Activity Feed**: A small sidebar or section for "Global Recent Earners".
## Phase 3: Core Spend Loop (Priority: 3)
- [x] **Overseer Request UI**: Create `SearchRequestModal` component.
- [x] **Request History**: Show status of Overseer requests (Pending/Processing/Available).
- [x] **Balance Refresh**: Ensure balance updates immediately after a request.
## Phase 4: Advanced Features (Priority: 4)
- [x] **Browser Wallets**: Connect Phantom/Solflare/Backpack.
- [ ] **Referral System**: Earn bonus $COOP for inviting other Plex users. (Requires DB Migration)
- [x] **Leaderboard**: Weekly/Monthly top watchers.
## Future Ideas
- [ ] **Referral System** — Earn bonus $COOP for inviting Plex users
- [ ] **Seasonal Events** — Double credits weekends, holiday multipliers
- [ ] **Achievements** — Badges for watch milestones (100 movies, 1000 hours, etc.)
- [ ] **Notifications** — Browser push for request approvals
- [ ] **Dark Mode** — Night coop theme
+48 -57
View File
@@ -5,25 +5,22 @@
| Service | IP Address | Port | Integration Role |
|----------|----------------|------|--------------------------------|
| Plex | 172.20.1.220 | 32400| User authentication, content |
| Overseer | 172.20.1.225 | 5055 | Content requests, $COOP spend |
| Overseer | 172.20.1.225 | 5055 | Content requests, disk space |
| Tautulli | 172.20.1.255 | 8181 | Watch tracking, $COOP earn |
| Website | coop.hobokenchicken.com | 443 | User dashboard, admin panel |
## Files Created/Updated
### Configuration Files
- `.env.production` - Production environment template
- `.env` - Production environment
- `docker-compose.yml` - Docker orchestration
- `docker-compose.prod.yml` - Production Docker orchestration
- `docker/nginx/nginx.prod.conf` - Nginx reverse proxy config
### Deployment Scripts
- `deployment/setup-infrastructure.sh` - Initial infrastructure setup
- `deployment/deploy-production.sh` - Production deployment
- `deployment/health-check.sh` - Service health monitoring
### Documentation
- `docs/SETUP-INFRASTRUCTURE.md` - Step-by-step setup guide
- `docs/INFRASTRUCTURE.md` - Architecture and network documentation
- `docs/CADDY-CONFIG.md` - Reverse proxy configuration
- `docs/TROUBLESHOOTING.md` - Common issues and fixes
## Network Architecture
@@ -32,14 +29,15 @@ Internet
│ HTTPS
┌─────────────┐
Nginx │ (80/443) - SSL termination, rate limiting
Caddy │ (443) - SSL termination
└──────┬──────┘
┌───┴───┐
▼ ▼
┌──────┐ ┌──────┐
│Frontend│ │Backend
:3000 │ │:3001
│Front-│ │Back-
end │ │end
│:3000 │ │:3002 │
└──────┘ └───┬───┘
┌──────┼──────┐
@@ -61,23 +59,18 @@ Internet
## Quick Deployment Commands
```bash
# 1. Setup infrastructure
npm run setup:infra
# 1. Setup
cp .env.example .env
# Edit .env with your API keys
# 2. Edit .env with your API keys
nano .env
# 2. Deploy
docker-compose up -d --build
# 3. Setup Solana
npm run setup:solana
# 3. Initialize database (first time only)
docker exec coop-backend npx prisma db push --accept-data-loss
# 4. Deploy
npm run deploy:prod
# 5. Check health
npm run health
# 6. Watch mode monitoring
npm run health -- --watch
# 4. Check health
curl https://coop.hobokenchicken.com/health
```
## Integration Points
@@ -85,84 +78,82 @@ npm run health -- --watch
### Tautulli → CoopCredits
- **Trigger**: Watch events
- **Webhook URL**: `https://coop.hobokenchicken.com/webhooks/tautulli`
- **Action**: Mint $COOP tokens
- **Action**: Create WatchEvent + Transaction (EARN), update user balance
### Overseer → CoopCredits
### Overseer → CoopCredits
- **Trigger**: Request approval/decline
- **Webhook URL**: `https://coop.hobokenchicken.com/webhooks/overseer`
- **Action**: Burn/spend $COOP tokens
- **Action**: Update ContentRequest status (refund if declined)
### Plex → CoopCredits
- **Trigger**: User login
- **Method**: OAuth via plex.tv
- **Action**: Authenticate users
- **Action**: Authenticate users, create session
### Ko-fi → CoopCredits
- **Trigger**: Store purchase
- **Webhook URL**: `https://coop.hobokenchicken.com/webhooks/kofi`
- **Action**: Create KofiPayment, credit user if email matches
## Security Features
1. **SSL/TLS**: Let's Encrypt or custom certificates
2. **Rate Limiting**: Nginx level protection
1. **SSL/TLS**: Caddy with Let's Encrypt
2. **Rate Limiting**: 1000 req/15min per IP
3. **Firewall**: UFW rules for local network
4. **Secrets**: Encrypted in `.env` file
5. **Wallet Keys**: AES-256-GCM encrypted in database
6. **CORS**: Configured for your domain
7. **JWT**: Secure session tokens
4. **Secrets**: In `.env` file (gitignored)
5. **CORS**: Configured for your domain
6. **JWT**: Secure session tokens
7. **Ko-fi Verification**: Token check on webhook
## Monitoring
```bash
# Health check
./deployment/health-check.sh
# Watch mode (continuous)
./deployment/health-check.sh --watch
curl https://coop.hobokenchicken.com/health
# Docker logs
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
```
## Backup Strategy
```bash
# Database 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
# Environment backup
cp .env .env.backup.$(date +%Y%m%d)
# Wallet keys (secure offsite storage)
# - Solana mint authority keypair
# - Encryption key from .env
```
## Next Steps
1. **Run setup**: `npm run setup:infra`
1. **Run setup**: `cp .env.example .env` and edit
2. **Get API keys**:
- Tautulli: http://172.20.1.255:8181 → Settings → API
- Overseer: http://172.20.1.225:5055 → Settings → General
- Plex: https://plex.tv/claim
3. **Edit .env** with your keys
4. **Setup Solana**: `npm run setup:solana`
5. **Deploy**: `npm run deploy:prod`
6. **Configure webhooks** in Tautulli and Overseer
7. **Test**: `npm run health`
3. **Deploy**: `docker-compose up -d --build`
4. **Configure webhooks** in Tautulli, Overseer, and Ko-fi
5. **Set admin**: `UPDATE users SET is_admin = true WHERE ...`
6. **Test**: `curl https://coop.hobokenchicken.com/health`
## Troubleshooting
| Issue | Solution |
|-------|----------|
| Cannot reach local services | Check Docker network: `docker network ls` |
| Webhook not received | Check Nginx logs: `docker/nginx/logs/access.log` |
| Cannot reach local services | Check backend `network_mode: host` |
| Webhook not received | Check Caddy routes to port 3002 |
| Database connection failed | Verify `.env` DATABASE_URL |
| SSL error | Check certificate paths in nginx config |
| SSL error | Check Caddy certificate status |
| CORS errors | Verify CORS_ORIGINS in `.env` |
| Request stuck PENDING | Use admin **SYNC** button or check Overseer webhook |
## Support Resources
- **Setup Guide**: `docs/SETUP-INFRASTRUCTURE.md`
- **Architecture**: `docs/INFRASTRUCTURE.md`
- **Health Check**: `npm run health`
- **Logs**: `npm run docker:prod:logs`
- **Troubleshooting**: `docs/TROUBLESHOOTING.md`
- **Caddy Config**: `docs/CADDY-CONFIG.md`
+152 -49
View File
@@ -1,89 +1,192 @@
# CoopCoins: Our Family Media Rewards
# CoopCredits ($COOP) — Hoboken Chicken Media Rewards
Welcome to our private media rewards system for the Hoboken Chicken family and friends! It's powered by Solana and integrates with our Plex, Tautulli, and Overseer setup. Earn CoopCoins ($COOP) for enjoying media, and use them to request new content!
A jokey barnyard-themed rewards system for the Hoboken Chicken family and friends. Watch stuff on Plex, earn $COOP credits, request new media through Overseer. Buy extra credits via Ko-fi when the silo runs low.
## System Architecture
> **Theme:** Everything is chickens, eggs, coops, and corn. Comic Sans / Chalkboard font, thick borders, earthy palette.
## Architecture
```
┌─────────────────────────────────────────────────────────────────────────────┐
│ coop.hobokenchicken.com │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────────┐
│ │ Next.js │ │ Express │ │ PostgreSQL │ │ Solana Devnet
│ │ Frontend │◄─┤ API │◄─┤ Database │◄─┤ $COOP SPL
│ │ │ │ │ │ Token
│ └──────────────┘ └──────────────┘ └──────────────┘ └─────────────────┘
│ ▲ ▲
│ │ │
│ Plex OAuth Tautulli Webhooks
│ │ │
│ ▼ ▼
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ Plex Server │ │ Tautulli │ │ Overseer
│ │ (Content) │ │ (Analytics) │ │ (Requests) │
│ └──────────────┘ └──────────────┘ └──────────────┘
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ │ Next.js │ │ Express │ │ PostgreSQL │
│ │ Frontend │◄─┤ API │◄─┤ Database │
│ │ (3000) │ │ (3002) │ │ (5432)
│ └──────────────┘ └──────────────┘ └──────────────┘
│ ▲ ▲
│ │ │
│ Plex OAuth Tautulli Webhooks Ko-fi Webhooks
│ │ │
│ ▼ ▼
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Plex Server │ │ Tautulli │ │ Ko-fi
│ │172.20.1.220 │ │172.20.1.255 │ │ (Payments) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
│ │
│ ┌──────────────┐ │
│ │ Overseer │ (Requests & disk space for dynamic pricing) │
│ │172.20.1.225 │ │
│ └──────────────┘ │
└─────────────────────────────────────────────────────────────────────────────┘
```
## Key Features
- **Plex OAuth Login** — No passwords, just Plex auth
- **Watch-to-Earn** — Tautulli webhooks credit $COOP for watched content (30-day backfill on signup)
- **Request-to-Spend** — Request movies/shows through Overseer, pay $COOP
- **Dynamic Pricing** — Request costs rise as disk space fills (scarcity multiplier)
- **TV Episode Tiers** — Long-running shows cost more per episode count
- **Ko-fi Purchases** — Buy $COOP with real money via Ko-fi store items
- **Admin Dashboard** — Manage users, view donations, sync request statuses, adjust barn rules
- **Barnyard Theme** — "Peck for Feed", "Join the Flock", thick borders, earthy palette
## Quick Start
```bash
# 1. Clone and install dependencies
# 1. Clone
git clone <repository> coop-credits
cd coop-credits
npm install
# 2. Set up environment
# 2. Install dependencies
npm run install:all
# 3. Configure environment
cp .env.example .env
# Edit .env with your values
# 3. Create public directory
mkdir -p frontend/public
# Edit .env with your API keys (Plex, Tautulli, Overseer, Ko-fi)
# 4. Start services
docker-compose up -d --build
# 5. Initialize database (first time only)
docker-compose exec backend npx prisma db push
docker exec coop-backend npx prisma db push --accept-data-loss
# 6. Configure Caddy (see docs/CADDY-CONFIG.md)
# Services expose ports 3000 (frontend) and 3001 (backend) on localhost
```
See `docs/CADDY-CONFIG.md` for reverse proxy setup.
## Project Structure
```
coop-credits/
├── anchor-program/ # Solana Anchor program for $COOP token
├── backend/ # Express API server
├── frontend/ # Next.js dashboard
├── shared/ # Shared types and utilities
├── backend/ # Express API server (port 3002)
│ ├── src/
│ │ ├── routes/ # API routes (auth, users, wallet, overseer, admin, webhooks)
│ │ ├── services/ # Tautulli backfill, socket handlers
│ │ ├── middleware/ # Auth, rate limiting, error handling
│ │ └── utils/ # Prisma client
│ └── prisma/
│ └── schema.prisma # DB schema (User, Transaction, WatchEvent, ContentRequest, KofiPayment, etc.)
├── frontend/ # Next.js 16 dashboard (port 3000)
│ └── src/
│ ├── app/
│ │ ├── page.tsx # Landing page ("Enter the Coop")
│ │ ├── login/page.tsx # Plex OAuth login
│ │ ├── dashboard/page.tsx # User dashboard
│ │ ├── admin/page.tsx # Admin panel
│ │ └── dashboard/components/ # WatchHistory, RequestHistory, SearchRequestModal, BuyCreditsModal, etc.
│ └── lib/
│ ├── api.ts # API client
│ ├── store.ts # Zustand auth store
│ └── socket.ts # Socket.io connection
├── docs/ # Documentation
── CADDY-CONFIG.md # Reverse proxy setup
├── docker-compose.yml # Docker orchestration (no nginx)
└── .env.example # Environment template
── CADDY-CONFIG.md # Reverse proxy setup
│ ├── INFRASTRUCTURE.md # Network architecture
│ ├── SETUP-INFRASTRUCTURE.md
│ └── TROUBLESHOOTING.md
├── docker-compose.yml # Docker orchestration
└── .env.example # Environment template
```
**Note:** No internal reverse proxy. Use Caddy/Nginx/Traefik externally.
## User Flow
1. **Login**User visits coop.hobokenchicken.com, authenticates with Plex
2. **Wallet** → Auto-created Solana wallet or connect existing
3. **Watch** → Viewing on Plex → Tautulli triggers → $COOP minted
4. **Earn** → Real-time balance updates on dashboard
5. **Spend** → Request content on Overseer → $COOP deducted
6. **History**Full transaction history visible on dashboard
1. **Login**Visit coop.hobokenchicken.com, click "Join the Flock", authenticate with Plex
2. **Auto-Backfill** → First login triggers 30-day Tautulli history import (DB-only credits)
3. **Watch** → Viewing on Plex → Tautulli webhook → $COOP credited to DB balance
4. **Earn** → Real-time balance updates via Socket.io on dashboard
5. **Spend** "Peck for Feed" → Search → Request content → $COOP deducted immediately
6. **Buy More**"Buy Feed" → Ko-fi store → Credits auto-delivered via webhook
## Admin Features
- System overview and analytics
- User management and balance adjustments
- Minting rate controls
- Spending controls and promotions
- Emergency pause and recovery
Access `/admin` with an admin account:
- **The Flock** — User list with search, reward bonuses, manual backfill, promote/demote admins
- **Barn Rules** — Edit credits per minute, min watch %/minutes, movie/TV costs
- **Donations** — View all incoming Ko-fi payments with status (CREDITED / UNCLAIMED)
- **The Feed Queue** — All content requests across users, manual Overseer sync button
- **Egg Stats** — Analytics cards: flock size, total $COOP, total requests, pending count
## Environment Variables
See `backend/.env.example` and `frontend/.env.local.example` for full configuration.
See `.env.example` for full configuration. Key vars:
```env
# Database
DATABASE_URL="postgresql://coop:password@localhost:5432/coop_credits?schema=public"
# Server
PORT=3002
API_URL=https://coop.hobokenchicken.com
# JWT (generate: openssl rand -hex 32)
JWT_SECRET="..."
# Plex OAuth
PLEX_CLIENT_ID="..."
PLEX_CLIENT_SECRET="..."
PLEX_REDIRECT_URI=https://coop.hobokenchicken.com/auth/callback
# Tautulli (host network mode required)
TAUTULLI_URL=http://172.20.1.255:8181
TAUTULLI_API_KEY="..."
# Overseer (host network mode required)
OVERSEER_URL=http://172.20.1.225:5055
OVERSEER_API_KEY="..."
# Ko-fi
KOFI_VERIFICATION_TOKEN="..."
# Security
ENCRYPTION_KEY="..." # openssl rand -base64 32
```
## Dynamic Pricing
Request costs are adjusted by disk scarcity:
- **Multiplier** = `1 + (usedPercent × 2)`
- At 0% disk used → 1× base cost
- At 50% disk used → 2× base cost
- At 90% disk used → 2.8× base cost
TV shows also have episode tier multipliers on top of scarcity:
- ≤50 episodes → base
- 51-100 → 1.3×
- 101-200 → 1.6×
- 201-400 → 2.0×
- 400+ → 2.5×
## Theme
- **Primary:** Terracotta (`#C06F4A`)
- **Secondary:** Duck Egg Blue (`#D4E4E0`)
- **Accent:** Wheat (`#E8D5B5`)
- **Muted:** Feather Grey (`#C4B5AA`)
- **Font:** Comic Sans MS / Chalkboard SE (fallback system-ui)
- **Style:** Thick 4px borders, hard black box shadows, rounded-3xl corners
## Tech Stack
| Layer | Technology |
|-------|-----------|
| Frontend | Next.js 16, React 19, TypeScript, Tailwind CSS, shadcn/ui, Zustand |
| Backend | Express.js, TypeScript, Prisma ORM, Socket.io |
| Database | PostgreSQL 16 |
| Cache | Redis 7 (sessions, Socket.io adapter) |
| Auth | Plex OAuth 2.0 + JWT |
| Payments | Ko-fi webhooks |
| Deployment | Docker Compose, Caddy reverse proxy |
## License
Private — Hoboken Chicken family use only.
+38 -78
View File
@@ -1,13 +1,13 @@
# CoopCredits Setup Guide
This guide will walk you through setting up the complete CoopCredits ecosystem.
This guide walks you through setting up the complete CoopCredits ecosystem.
## Prerequisites
- Node.js 20+
- Docker & Docker Compose
- Solana CLI (for blockchain development)
- Anchor Framework (for Solana program deployment)
- Access to Plex, Tautulli, and Overseer instances
- Domain name (for production)
## Quick Start
@@ -31,48 +31,20 @@ nano .env
Required environment variables:
- `DATABASE_URL` - PostgreSQL connection string
- `JWT_SECRET` - Random string for JWT signing
- `JWT_SECRET` - Random string for JWT signing (openssl rand -hex 32)
- `PLEX_CLIENT_ID` & `PLEX_CLIENT_SECRET` - From Plex.tv
- `TAUTULLI_API_KEY` - From Tautulli settings
- `OVERSEER_API_KEY` - From Overseer settings
- `SOLANA_MINT_AUTHORITY_KEYPAIR` - Will be generated in step 3
- `ENCRYPTION_KEY` - For encrypting session data (openssl rand -base64 32)
- `KOFI_VERIFICATION_TOKEN` - From Ko-fi settings (optional)
### 3. Solana Setup
```bash
# Run the Solana setup script
npm run setup:solana
# This will:
# - Install Solana CLI if needed
# - Create a devnet keypair
# - Request airdrop (2 SOL)
# - Output the private key for your .env file
```
Copy the `SOLANA_MINT_AUTHORITY_KEYPAIR` value into your `.env` file.
### 4. Deploy Solana Program
```bash
cd anchor-program
# Build the program
anchor build
# Deploy to devnet
anchor deploy
# Note the Program ID and update .env SOLANA_PROGRAM_ID
```
### 5. Database Setup
### 3. Database Setup
```bash
# Start PostgreSQL and Redis
docker-compose up -d postgres redis
# Push schema to database (no migrations needed for fresh setup)
# Push schema to database
cd backend
npx prisma db push
@@ -80,44 +52,34 @@ npx prisma db push
npx prisma generate
```
### 6. Start Development
### 4. Start Development
```bash
# Start all services
npm run dev
# Or individually:
npm run dev:backend # API on port 3001
npm run dev:frontend # Next.js on port 3000
npm run dev:backend # API on port 3002
npm run dev:frontend # Next.js on port 3000
```
### 7. Configure Tautulli Webhook
1. Open Tautulli Settings
2. Go to Notification Agents → Add Agent → Webhook
3. Configure:
- Webhook URL: `http://your-server:3001/webhooks/tautulli`
- Webhook Method: POST
- JSON Payload: See webhook template in Admin Dashboard
4. Enable "Notify on Watched"
### 8. Production Deployment
### 5. Production Deployment
```bash
# Create public directory (required for build)
mkdir -p frontend/public
# Deploy (Caddy handles SSL termination)
# Deploy
docker-compose up -d --build
```
**Note:** This setup runs HTTP only on port 80. Place behind Caddy or another reverse proxy for SSL termination.
**Note:** This runs HTTP internally. Place behind Caddy or another reverse proxy for SSL termination. Backend runs on port 3002.
## Architecture Overview
```
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ User Browser │────▶│ Next.js (3000) │────▶│ Express (3001) │
│ User Browser │────▶│ Next.js (3000) │────▶│ Express (3002) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
┌─────────────────┐ │
@@ -126,8 +88,8 @@ docker-compose up -d --build
└─────────────────┘
┌─────────────────┐
Solana Devnet
│ ($COOP Token)
Ko-fi
│ (Purchases)
└─────────────────┘
┌───────────────────────┴───────────────────────┐
@@ -141,19 +103,20 @@ docker-compose up -d --build
## User Flow
1. **Login**: User authenticates with Plex OAuth
2. **Wallet**: Auto-created Solana wallet (or connect existing)
3. **Watch**: Viewing on Plex → Tautulli triggers webhook
4. **Earn**: Backend validates → Mints $COOP tokens
5. **Spend**: Request content on Overseer → Deducts $COOP
2. **Backfill**: First login triggers 30-day Tautulli history import
3. **Watch**: Viewing on Plex → Tautulli triggers webhook → $COOP credited to DB
4. **Earn**: Real-time balance updates on dashboard via Socket.io
5. **Spend**: Request content on Overseer → $COOP deducted from DB balance
6. **Buy**: Ko-fi purchase → Webhook → $COOP added to DB balance
## Admin Features
Access `/admin` with an admin account to:
- View system analytics
- Manage users and grant bonuses
- Configure minting rates
- Pause/resume minting
- Monitor transactions
- **The Flock** — User list with search, bonuses, backfill, promote/demote
- **Barn Rules** — Edit credits per minute, watch thresholds, request costs
- **Donations** — View Ko-fi payment history
- **The Feed Queue** — All content requests with Overseer sync button
- **Egg Stats** — Analytics cards (users, total credits, requests, pending)
## Troubleshooting
@@ -162,30 +125,26 @@ Access `/admin` with an admin account to:
# Reset database
docker-compose down -v
docker-compose up -d postgres
npx prisma migrate dev
```
### Solana Transaction Failures
```bash
# Check balance
solana balance <pubkey>
# Request airdrop
solana airdrop 2 <pubkey>
cd backend && npx prisma db push
```
### Tautulli Webhook Not Working
1. Check webhook URL is accessible
2. Verify `TAUTULLI_WEBHOOK_SECRET` matches
2. Verify `TAUTULLI_WEBHOOK_SECRET` matches (optional)
3. Check backend logs: `docker-compose logs backend`
### Request Stuck on PENDING
1. Check Overseer webhook is configured
2. Use admin dashboard **The Feed Queue****SYNC** button
3. Or use dashboard **Requests** tab → refresh button
## Security Considerations
1. **Private Keys**: Never commit `.env` files
1. **Never commit `.env` files**
2. **JWT Secret**: Use a strong random string (32+ chars)
3. **Encryption Key**: Use `openssl rand -base64 32`
4. **SSL**: Always use HTTPS in production
5. **Rate Limiting**: Nginx config includes rate limits
4. **SSL**: Always use HTTPS in production (Caddy handles this)
5. **Rate Limiting**: 1000 req/15min per IP
## Support
@@ -193,3 +152,4 @@ For issues or questions:
1. Check logs: `docker-compose logs -f`
2. Review environment variables
3. Verify all services are running: `docker-compose ps`
4. Check `docs/TROUBLESHOOTING.md`
+26 -17
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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;"
```