All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 2s
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
321 lines
11 KiB
Markdown
321 lines
11 KiB
Markdown
---
|
|
title: Paper Dynasty Dev Server Guide
|
|
description: Setup guide for Paper Dynasty local development server with Docker Compose.
|
|
domain: development
|
|
type: guide
|
|
tags:
|
|
- paper-dynasty
|
|
- docker
|
|
- deployment
|
|
- postgresql
|
|
- ssh
|
|
---
|
|
|
|
# Paper Dynasty Dev Server Guide
|
|
|
|
Comprehensive reference for accessing, deploying, and troubleshooting the Paper Dynasty dev (and prod) API servers.
|
|
|
|
## Server Architecture
|
|
|
|
```
|
|
┌─────────────────────────────────────────────┐
|
|
│ akamai (172.237.147.99) │
|
|
pd.manticorum.com │ pd_api (:8002) → manticorum67/paper- │
|
|
(Cloudflare CDN) │ dynasty-database:latest │
|
|
│ Postgres: pd_master (sba_postgres) │
|
|
│ Nginx Proxy Manager → reverse proxy │
|
|
└─────────────────────────────────────────────┘
|
|
|
|
┌─────────────────────────────────────────────┐
|
|
│ pd-database / sba-db (10.10.0.42) │
|
|
pddev.manticorum │ dev_pd_database (:813) → manticorum67/ │
|
|
.com (local) │ paper-dynasty-database:dev │
|
|
│ Postgres: paperdynasty_dev (sba_postgres) │
|
|
│ Also runs: sba_db_api, sba_adminer, │
|
|
│ sba_postgres, sba_redis │
|
|
└─────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Quick Reference
|
|
|
|
| Environment | URL | Server | SSH Alias | Container | Image Tag | Port | DB Name |
|
|
|-------------|-----|--------|-----------|-----------|-----------|------|---------|
|
|
| **Production** | `pd.manticorum.com/api` | akamai (172.237.147.99) | `akamai` | `pd_api` | `:latest` | 8002 | `pd_master` |
|
|
| **Dev** | `pddev.manticorum.com/api` | pd-database (10.10.0.42) | `pd-database` | `dev_pd_database` | `:dev` | 813 | `paperdynasty_dev` |
|
|
|
|
**API Token** (both envs): `Tp3aO3jhYve5NJF1IqOmJTmk`
|
|
|
|
## SSH Access
|
|
|
|
```bash
|
|
# Dev server (all these aliases work)
|
|
ssh pd-database # or: sba-db, strat-database, pd-db, strat-db, sba-database
|
|
# → 10.10.0.42, user: cal
|
|
|
|
# Prod server
|
|
ssh akamai # or: akamai-nano
|
|
# → 172.237.147.99, user: root
|
|
```
|
|
|
|
## Dev Server Operations
|
|
|
|
### Container Management
|
|
|
|
```bash
|
|
# Check status
|
|
ssh pd-database "docker ps --filter name=dev_pd_database --format '{{.Names}}\t{{.Image}}\t{{.Status}}'"
|
|
|
|
# View logs (stdout/stderr)
|
|
ssh pd-database "docker logs dev_pd_database --tail 100"
|
|
ssh pd-database "docker logs dev_pd_database -f --tail 50" # follow
|
|
|
|
# View application logs (file-based, by date)
|
|
ssh pd-database "cat /home/cal/container-data/dev-pd-database/logs/database/$(date +%Y-%-m-%-d).log"
|
|
```
|
|
|
|
### Deploy New Dev Image
|
|
|
|
The CI pipeline pushes `manticorum67/paper-dynasty-database:dev` on PR builds to main.
|
|
|
|
```bash
|
|
# Standard deploy (compose file already uses :dev tag)
|
|
ssh pd-database "cd /home/cal/container-data/dev-pd-database && docker compose pull && docker compose up -d"
|
|
```
|
|
|
|
**If the container name conflicts** (orphaned from previous non-compose run):
|
|
```bash
|
|
ssh pd-database "docker stop dev_pd_database && docker rm dev_pd_database && cd /home/cal/container-data/dev-pd-database && docker compose up -d"
|
|
```
|
|
|
|
### Health Check
|
|
|
|
```bash
|
|
# Quick status code check
|
|
curl -sL -o /dev/null -w "%{http_code}" "https://pddev.manticorum.com/api/v2/players/?limit=1" \
|
|
-H "Authorization: Bearer Tp3aO3jhYve5NJF1IqOmJTmk"
|
|
|
|
# Time a card render (fresh, no cache)
|
|
curl -sL -o /dev/null -w "HTTP %{http_code} | Total: %{time_total}s | TTFB: %{time_starttransfer}s\n" \
|
|
"https://pddev.manticorum.com/api/v2/players/12726/battingcard?d=$(date +%Y-%m-%d-%s)"
|
|
|
|
# Test HTML card render
|
|
# Append &html=true for HTML output (useful for debugging card layout)
|
|
curl -sL "https://pddev.manticorum.com/api/v2/players/12726/battingcard?d=$(date +%Y-%m-%d)&html=true"
|
|
```
|
|
|
|
### File System Layout
|
|
|
|
```
|
|
/home/cal/container-data/dev-pd-database/
|
|
├── docker-compose.yml # Compose config
|
|
├── storage/ # Mounted → /usr/src/app/storage
|
|
│ ├── templates/ # HTML card templates (style.html, player_card.html)
|
|
│ ├── cards/ # Cached rendered card PNGs
|
|
│ │ └── cardset-{id}/
|
|
│ │ ├── batting/ # {player_id}-{date}-v{variant}.png
|
|
│ │ └── pitching/
|
|
│ ├── static/ # Static assets
|
|
│ ├── card_creation.db # Legacy SQLite (unused in PostgreSQL mode)
|
|
│ └── *.csv # Scouting report data
|
|
└── logs/
|
|
└── database/
|
|
└── {YYYY}-{M}-{D}.log # Application logs (date format: no zero-padding)
|
|
```
|
|
|
|
### Clear Card Cache (Force Re-render)
|
|
|
|
```bash
|
|
# Clear specific player
|
|
ssh pd-database "rm -f /home/cal/container-data/dev-pd-database/storage/cards/cardset-27/batting/12726-*.png"
|
|
|
|
# Clear all cached cards for a cardset
|
|
ssh pd-database "rm -rf /home/cal/container-data/dev-pd-database/storage/cards/cardset-27/"
|
|
|
|
# Alternative: use cache-busting query param (changes the ?d= value)
|
|
curl -sL "https://pddev.manticorum.com/api/v2/players/12726/battingcard?d=2026-3-13-$(date +%s)"
|
|
```
|
|
|
|
### Database Access
|
|
|
|
Dev uses `paperdynasty_dev` on the shared `sba_postgres` container (same server, port 5432).
|
|
|
|
```bash
|
|
# Direct psql
|
|
ssh pd-database "docker exec -it sba_postgres psql -U sba_admin -d paperdynasty_dev"
|
|
|
|
# Adminer web UI
|
|
# http://10.10.0.42:8080
|
|
# Server: sba_postgres | User: sba_admin | Password: your_production_password | DB: paperdynasty_dev
|
|
|
|
# Quick query
|
|
ssh pd-database "docker exec sba_postgres psql -U sba_admin -d paperdynasty_dev -c 'SELECT count(*) FROM player WHERE cardset_id = 27'"
|
|
```
|
|
|
|
## Production Server Operations
|
|
|
|
### Container Management
|
|
|
|
```bash
|
|
# Check status
|
|
ssh akamai "docker ps --filter name=pd_api --format '{{.Names}}\t{{.Image}}\t{{.Status}}'"
|
|
|
|
# View logs
|
|
ssh akamai "docker logs pd_api --tail 100"
|
|
```
|
|
|
|
### Deploy to Production
|
|
|
|
Production uses `:latest` tag. After merging to main, CI pushes both `:latest` and a CalVer tag.
|
|
|
|
```bash
|
|
ssh akamai "cd /root/container-data/paper-dynasty && docker compose pull && docker compose up -d"
|
|
```
|
|
|
|
### File System Layout (Prod)
|
|
|
|
```
|
|
/root/container-data/paper-dynasty/
|
|
├── docker-compose.yml
|
|
├── storage/ # Card cache, templates, scouting data
|
|
│ └── cards/cardset-{id}/...
|
|
└── logs/
|
|
└── database/
|
|
```
|
|
|
|
### Database Access (Prod)
|
|
|
|
Production uses `pd_master` database with `pd_admin` user on the shared `sba_postgres` on akamai.
|
|
|
|
```bash
|
|
ssh akamai "docker exec -it sba_postgres psql -U pd_admin -d pd_master"
|
|
```
|
|
|
|
## Docker Image Tags
|
|
|
|
| Tag | Source | When Pushed | Use |
|
|
|-----|--------|-------------|-----|
|
|
| `:latest` | `main` branch merge | On merge to main | Production |
|
|
| `:dev` | PR to `main` | On PR creation/update | Dev testing |
|
|
| `:YYYY.MM.BUILD` | `main` branch merge | On merge to main | Versioned releases |
|
|
| `:rc-SHA` | `next-release` push | On push to next-release | Release candidates |
|
|
|
|
CI pipeline: `.gitea/workflows/build.yml` in `paper-dynasty-database` repo.
|
|
|
|
## Docker Compose Config (Dev)
|
|
|
|
```yaml
|
|
services:
|
|
database:
|
|
image: manticorum67/paper-dynasty-database:dev
|
|
restart: unless-stopped
|
|
container_name: dev_pd_database
|
|
volumes:
|
|
- ./storage:/usr/src/app/storage
|
|
- ./logs:/usr/src/app/logs
|
|
ports:
|
|
- 813:80
|
|
environment:
|
|
- TESTING=True
|
|
- LOG_LEVEL=INFO
|
|
- API_TOKEN=Tp3aO3jhYve5NJF1IqOmJTmk
|
|
- TZ=America/Chicago
|
|
- WORKERS_PER_CORE=1.0
|
|
- PRIVATE_IN_SCHEMA=TRUE
|
|
- DATABASE_TYPE=postgresql
|
|
- POSTGRES_DB=paperdynasty_dev
|
|
- POSTGRES_USER=sba_admin
|
|
- POSTGRES_PASSWORD=your_production_password
|
|
- POSTGRES_HOST=sba_postgres
|
|
- POSTGRES_PORT=5432
|
|
networks:
|
|
default:
|
|
external:
|
|
name: dev-sba-database_default
|
|
```
|
|
|
|
**Key differences from prod:**
|
|
- `TESTING=True` (enables private endpoints in schema)
|
|
- `PRIVATE_IN_SCHEMA=TRUE` (shows all endpoints in Swagger)
|
|
- `WORKERS_PER_CORE=1.0` (fewer workers than prod's 1.5)
|
|
- No healthcheck configured (prod has one)
|
|
- No `WORKER_TIMEOUT` set (prod uses 180s)
|
|
|
|
## Networking
|
|
|
|
- **Dev**: Joins `dev-sba-database_default` network to reach `sba_postgres` on the same host
|
|
- **Prod**: Joins both `sba-database_default` (for postgres) and `nginx-proxy-manager_npm_network` (for reverse proxy) on akamai
|
|
- **DNS**: `pd.manticorum.com` → Cloudflare → akamai:8002; `pddev.manticorum.com` → local DNS → 10.10.0.42:813
|
|
|
|
## Troubleshooting
|
|
|
|
### Container won't start (name conflict)
|
|
|
|
```
|
|
Error: container name "/dev_pd_database" is already in use
|
|
```
|
|
|
|
The old container was started outside compose tracking. Remove it manually:
|
|
```bash
|
|
ssh pd-database "docker stop dev_pd_database; docker rm dev_pd_database"
|
|
ssh pd-database "cd /home/cal/container-data/dev-pd-database && docker compose up -d"
|
|
```
|
|
|
|
### Card renders return 502
|
|
|
|
Usually means Chromium crashed inside the container. Check logs and restart:
|
|
```bash
|
|
ssh pd-database "docker logs dev_pd_database --tail 20"
|
|
ssh pd-database "cd /home/cal/container-data/dev-pd-database && docker compose restart"
|
|
```
|
|
|
|
With the persistent browser (Phase 0), `get_browser()` auto-reconnects on the next request. If it persists, the container may need more memory (Chromium needs ~100MB per page).
|
|
|
|
### Application logs missing for today
|
|
|
|
Log files use non-zero-padded date format: `2026-3-13.log` not `2026-03-13.log`.
|
|
|
|
```bash
|
|
# Correct
|
|
ssh pd-database "cat /home/cal/container-data/dev-pd-database/logs/database/$(date +%Y-%-m-%-d).log"
|
|
```
|
|
|
|
### Database connection errors
|
|
|
|
Verify the postgres container is running and the network is correct:
|
|
```bash
|
|
ssh pd-database "docker ps --filter name=sba_postgres"
|
|
ssh pd-database "docker exec dev_pd_database ping -c1 sba_postgres"
|
|
```
|
|
|
|
### Stale card images (old render showing)
|
|
|
|
Cards are cached as PNG files on disk. Either delete the file or use a new `?d=` cache-buster value:
|
|
```bash
|
|
# Option 1: Delete cached file
|
|
ssh pd-database "rm /home/cal/container-data/dev-pd-database/storage/cards/cardset-27/batting/12726-*.png"
|
|
|
|
# Option 2: Use different date param (generates new file, old one remains)
|
|
curl "https://pddev.manticorum.com/api/v2/players/12726/battingcard?d=2026-3-13-$(date +%s)"
|
|
```
|
|
|
|
## Server Hardware
|
|
|
|
| Spec | pd-database (dev) | akamai (prod) |
|
|
|------|-------------------|---------------|
|
|
| Hostname | databases-bots | akamai |
|
|
| IP | 10.10.0.42 (homelab) | 172.237.147.99 (Linode) |
|
|
| OS | Ubuntu 22.04 (6.8 kernel) | — |
|
|
| RAM | 16 GB | — |
|
|
| Disk | 503 GB (24% used) | — |
|
|
| Docker | 24.0.6 / Compose 2.21 | — |
|
|
|
|
## Related Compose Stacks on pd-database
|
|
|
|
| Stack | Path | Purpose |
|
|
|-------|------|---------|
|
|
| `dev-pd-database` | `/home/cal/container-data/dev-pd-database/` | PD dev API |
|
|
| `pd-database` | `/home/cal/container-data/pd-database/` | PD legacy (stopped) |
|
|
| `dev-sba-database` | `/home/cal/container-data/dev-sba-database/` | Major Domo dev API |
|
|
| `sba-database` | `/home/cal/container-data/sba-database/` | Major Domo prod API |
|
|
| `postgres-database` | `/home/cal/container-data/postgres-database/` | Shared PostgreSQL + Adminer |
|