claude-home/paper-dynasty/dev-server-guide.md
Cal Corum be896b4c2a
All checks were successful
Reindex Knowledge Base / reindex (push) Successful in 2s
docs: add missing description frontmatter for kb-rag indexing
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 22:30:48 -05:00

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
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

# 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_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:

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
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