Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
11 KiB
| title | description | domain | type | tags | |||||
|---|---|---|---|---|---|---|---|---|---|
| Paper Dynasty Dev Server Guide | Setup guide for Paper Dynasty local development server with Docker Compose. | development | guide |
|
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
# 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
# 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.
# 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):
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
# 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)
# 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).
# 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
# 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.
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.
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)
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_TIMEOUTset (prod uses 180s)
Networking
- Dev: Joins
dev-sba-database_defaultnetwork to reachsba_postgreson the same host - Prod: Joins both
sba-database_default(for postgres) andnginx-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:
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:
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.
# 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:
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:
# 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 |