feat: add CoopCredits Solana media rewards ecosystem
Add complete token system with Plex/Tautulli/Overseer integration: - Anchor program for SPL token mint/burn/transfer - Express backend with OAuth, webhooks, Solana integration - Next.js frontend with dashboard, admin panel, wallet management - Docker deployment for 172.20.1.0/24 infrastructure - Production configs with SSL, Nginx, health monitoring Tautulli webhooks auto-mint on watch events. Overseer integration burns for content requests.
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
# CoopCredits Infrastructure Documentation
|
||||
|
||||
## Network Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ External Access │
|
||||
│ coop.hobokenchicken.com │
|
||||
└─────────────────────────────────┬───────────────────────────────────────┘
|
||||
│ HTTPS (443)
|
||||
▼
|
||||
┌─────────────────────────────────────────────────────────────────────────┐
|
||||
│ CoopCredits Server │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │ Nginx │ │ Frontend │ │ Backend │ │ PostgreSQL │ │
|
||||
│ │ (80/443) │──│ (Next.js) │──│ (Express) │──│ (5432) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────┬───────┘ └──────────────┘ │
|
||||
│ │ │
|
||||
│ ┌──────────────┐ ┌──────────────┐ │ ┌──────────────┐ │
|
||||
│ │ Certbot │ │ Redis │◀────────┘ │ Anchor CLI │ │
|
||||
│ │ (SSL) │ │ (6379) │ │ (Optional) │ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
└──────────────────────────────────┬──────────────────────────────────────┘
|
||||
│
|
||||
│ 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 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Service Details
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
### 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
|
||||
|
||||
## Communication Flow
|
||||
|
||||
### 1. User Authentication
|
||||
```
|
||||
User → Nginx → Frontend → Backend → Plex OAuth (172.20.1.220:32400)
|
||||
↓
|
||||
User authenticated, JWT issued
|
||||
```
|
||||
|
||||
### 2. Watch Event Processing
|
||||
```
|
||||
Plex → Tautulli → Webhook → Nginx → Backend → Solana Devnet
|
||||
↓
|
||||
Database updated
|
||||
↓
|
||||
WebSocket → User notified
|
||||
```
|
||||
|
||||
### 3. Content Request
|
||||
```
|
||||
User → Nginx → Frontend → Backend → Overseer API (172.20.1.225:5055)
|
||||
↓
|
||||
Request created, $COOP reserved
|
||||
↓
|
||||
Webhook on approval → Burn $COOP
|
||||
```
|
||||
|
||||
## 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
|
||||
|
||||
### 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
|
||||
|
||||
### Data Security
|
||||
1. **Wallet Keys**: Encrypted with AES-256-GCM in database
|
||||
2. **Database**: Not exposed externally
|
||||
3. **Redis**: Password protected, localhost only
|
||||
|
||||
## Firewall Configuration
|
||||
|
||||
```bash
|
||||
# Web traffic
|
||||
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
|
||||
sudo ufw deny 3001/tcp # Backend
|
||||
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
|
||||
- Isolated from external network
|
||||
- Used for: frontend ↔ backend ↔ database
|
||||
|
||||
### External Network (coop-external)
|
||||
- Allows containers to reach local services
|
||||
- Subnet: 172.20.2.0/24
|
||||
- Used for: backend → Tautulli/Overseer/Plex
|
||||
|
||||
## SSL/TLS Setup
|
||||
|
||||
### Let's Encrypt (Recommended)
|
||||
```bash
|
||||
# Initial certificate
|
||||
docker-compose -f docker-compose.prod.yml run --rm certbot certonly \
|
||||
--webroot -w /var/www/certbot \
|
||||
-d coop.hobokenchicken.com \
|
||||
--agree-tos --no-eff-email
|
||||
|
||||
# Auto-renewal (configured in docker-compose)
|
||||
```
|
||||
|
||||
### Self-Signed (Testing only)
|
||||
```bash
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout docker/nginx/ssl/key.pem \
|
||||
-out docker/nginx/ssl/cert.pem \
|
||||
-subj '/CN=coop.hobokenchicken.com'
|
||||
```
|
||||
|
||||
## Monitoring and Logging
|
||||
|
||||
### Log Locations
|
||||
- Nginx: `docker/nginx/logs/`
|
||||
- Backend: Docker logs (`docker-compose logs backend`)
|
||||
- Frontend: Docker logs (`docker-compose logs frontend`)
|
||||
- Database: Inside container (`/var/log/postgresql/`)
|
||||
|
||||
### Health Checks
|
||||
```bash
|
||||
# Backend health
|
||||
curl https://coop.hobokenchicken.com/health
|
||||
|
||||
# Database connection
|
||||
docker-compose exec postgres pg_isready -U coop
|
||||
|
||||
# Service status
|
||||
docker-compose 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
|
||||
```
|
||||
|
||||
### 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
|
||||
@@ -0,0 +1,372 @@
|
||||
# CoopCredits Setup for 172.20.1.0/24 Infrastructure
|
||||
|
||||
This guide covers setting up CoopCredits with your existing Plex/Tautulli/Overseer infrastructure.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- Server running Docker and Docker Compose
|
||||
- Access to 172.20.1.0/24 network
|
||||
- API keys from Tautulli and Overseer
|
||||
- Domain name (coop.hobokenchicken.com) pointing to your server
|
||||
|
||||
## Network Overview
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ CoopCredits Server │
|
||||
│ (Your Server IP) │
|
||||
│ :443 │
|
||||
└─────────────────────────────────┬───────────────────────────────┘
|
||||
│ HTTPS
|
||||
┌─────────────────────────┼──────────────────────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ Plex │ │ Tautulli │ │ Overseer │
|
||||
│172.20.1.220 │ │172.20.1.255 │ │172.20.1.225 │
|
||||
│ :32400 │ │ :8181 │ │ :5055 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Quick Start
|
||||
|
||||
### 1. Clone Repository
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
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
|
||||
- Check SSL certificate status
|
||||
- Output configuration instructions
|
||||
|
||||
### 3. Configure Environment
|
||||
|
||||
Edit the generated `.env` file:
|
||||
|
||||
```bash
|
||||
nano .env
|
||||
```
|
||||
|
||||
Add your API keys:
|
||||
|
||||
```env
|
||||
# Get from Tautulli: Settings > Web Interface > API
|
||||
TAUTULLI_API_KEY=your-tautulli-api-key
|
||||
|
||||
# Get from Overseer: Settings > General > API Key
|
||||
OVERSEER_API_KEY=your-overseer-api-key
|
||||
|
||||
# Get from https://plex.tv/claim or Plex settings
|
||||
PLEX_CLIENT_ID=your-plex-client-id
|
||||
PLEX_CLIENT_SECRET=your-plex-client-secret
|
||||
```
|
||||
|
||||
### 4. Setup Solana
|
||||
|
||||
```bash
|
||||
npm run setup:solana
|
||||
```
|
||||
|
||||
This will:
|
||||
- Install Solana CLI
|
||||
- Create a devnet wallet
|
||||
- Request airdrop
|
||||
- Output the private key for your `.env` file
|
||||
|
||||
Copy the `SOLANA_MINT_AUTHORITY_KEYPAIR` into your `.env` file.
|
||||
|
||||
### 5. Deploy Solana Program
|
||||
|
||||
```bash
|
||||
cd anchor-program
|
||||
anchor build
|
||||
anchor deploy
|
||||
```
|
||||
|
||||
Update `SOLANA_PROGRAM_ID` in `.env` with the deployed program ID.
|
||||
|
||||
### 6. Setup SSL Certificates
|
||||
|
||||
#### Option A: Let's Encrypt (Recommended)
|
||||
|
||||
```bash
|
||||
# Obtain certificate
|
||||
docker-compose -f docker-compose.prod.yml run --rm certbot certonly \
|
||||
--webroot -w /var/www/certbot \
|
||||
-d coop.hobokenchicken.com \
|
||||
--agree-tos --no-eff-email
|
||||
|
||||
# Update nginx config to use Let's Encrypt paths
|
||||
# Edit docker/nginx/nginx.prod.conf:
|
||||
# ssl_certificate /etc/letsencrypt/live/coop.hobokenchicken.com/fullchain.pem;
|
||||
# ssl_certificate_key /etc/letsencrypt/live/coop.hobokenchicken.com/privkey.pem;
|
||||
```
|
||||
|
||||
#### Option B: Existing Certificates
|
||||
|
||||
```bash
|
||||
cp /path/to/your/cert.pem docker/nginx/ssl/cert.pem
|
||||
cp /path/to/your/key.pem docker/nginx/ssl/key.pem
|
||||
```
|
||||
|
||||
#### Option C: Self-Signed (Testing only)
|
||||
|
||||
```bash
|
||||
openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
|
||||
-keyout docker/nginx/ssl/key.pem \
|
||||
-out docker/nginx/ssl/cert.pem \
|
||||
-subj '/CN=coop.hobokenchicken.com'
|
||||
```
|
||||
|
||||
### 7. Deploy
|
||||
|
||||
```bash
|
||||
./deployment/deploy-production.sh
|
||||
```
|
||||
|
||||
### 8. Configure Tautulli Webhook
|
||||
|
||||
1. Open Tautulli: http://172.20.1.255:8181
|
||||
2. Go to **Settings > Notification Agents**
|
||||
3. Click **Add a new notification agent > Webhook**
|
||||
|
||||
**Configuration:**
|
||||
- Webhook URL: `https://coop.hobokenchicken.com/webhooks/tautulli`
|
||||
- Webhook Method: `POST`
|
||||
- Content Type: `application/json`
|
||||
|
||||
**JSON Payload:**
|
||||
```json
|
||||
{
|
||||
"action": "watched",
|
||||
"user_id": "{user_id}",
|
||||
"username": "{username}",
|
||||
"rating_key": "{rating_key}",
|
||||
"session_key": "{session_key}",
|
||||
"media_type": "{media_type}",
|
||||
"title": "{title}",
|
||||
"grandparent_title": "{grandparent_title}",
|
||||
"started": "{started}",
|
||||
"stopped": "{stopped}",
|
||||
"percent_complete": "{percent_complete}",
|
||||
"is_new": "{is_new}"
|
||||
}
|
||||
```
|
||||
|
||||
**Triggers:** Enable **Watched**
|
||||
|
||||
### 9. Configure Overseer Webhook
|
||||
|
||||
1. Open Overseer: http://172.20.1.225:5055
|
||||
2. Go to **Settings > Notifications**
|
||||
3. Enable **Webhook**
|
||||
|
||||
**Configuration:**
|
||||
- Webhook URL: `https://coop.hobokenchicken.com/webhooks/overseer`
|
||||
- Authorization Header: `Bearer your-webhook-secret-from-env`
|
||||
|
||||
**JSON Payload:**
|
||||
```json
|
||||
{
|
||||
"request_id": "{{request.id}}",
|
||||
"status": "{{request.status}}",
|
||||
"media_type": "{{media.media_type}}",
|
||||
"title": "{{media.title}}"
|
||||
}
|
||||
```
|
||||
|
||||
**Events:** Enable **Request Approved** and **Request Declined**
|
||||
|
||||
## Verification
|
||||
|
||||
### Test Connectivity
|
||||
|
||||
```bash
|
||||
./deployment/health-check.sh
|
||||
```
|
||||
|
||||
### Watch Mode
|
||||
|
||||
```bash
|
||||
./deployment/health-check.sh --watch
|
||||
```
|
||||
|
||||
### Manual Tests
|
||||
|
||||
**Test Tautulli webhook:**
|
||||
```bash
|
||||
curl -X POST https://coop.hobokenchicken.com/webhooks/tautulli \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"action": "watched",
|
||||
"user_id": "12345",
|
||||
"username": "testuser",
|
||||
"rating_key": "1234",
|
||||
"session_key": "abc123",
|
||||
"media_type": "movie",
|
||||
"title": "Test Movie",
|
||||
"started": "'$(date +%s)'",
|
||||
"stopped": "'$(($(date +%s) + 3600))'",
|
||||
"percent_complete": "90"
|
||||
}'
|
||||
```
|
||||
|
||||
**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
|
||||
```
|
||||
|
||||
### SSL certificate issues
|
||||
|
||||
1. Check certificate:
|
||||
```bash
|
||||
openssl s_client -connect coop.hobokenchicken.com:443 -servername coop.hobokenchicken.com
|
||||
```
|
||||
|
||||
2. Verify certificate paths in nginx config
|
||||
|
||||
3. Check certificate expiry:
|
||||
```bash
|
||||
openssl x509 -in docker/nginx/ssl/cert.pem -noout -dates
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
### Update Application
|
||||
|
||||
```bash
|
||||
cd /opt/coop-credits
|
||||
git pull
|
||||
./deployment/deploy-production.sh
|
||||
```
|
||||
|
||||
### 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
|
||||
```
|
||||
|
||||
### View Logs
|
||||
|
||||
```bash
|
||||
# All services
|
||||
docker-compose -f docker-compose.prod.yml logs -f
|
||||
|
||||
# Specific service
|
||||
docker-compose -f docker-compose.prod.yml logs -f backend
|
||||
```
|
||||
|
||||
### Restart Services
|
||||
|
||||
```bash
|
||||
docker-compose -f docker-compose.prod.yml restart backend
|
||||
```
|
||||
|
||||
## Security Checklist
|
||||
|
||||
- [ ] Changed all default passwords in `.env`
|
||||
- [ ] SSL certificates installed and valid
|
||||
- [ ] 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
|
||||
|
||||
## 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`
|
||||
Reference in New Issue
Block a user