golfgame/INSTALL.md
adlee-was-taken 9fc6b83bba v3.0.0: V3 features, server refactoring, and documentation overhaul
- Extract WebSocket handlers from main.py into handlers.py
- Add V3 feature docs (dealer rotation, dealing animation, round end reveal,
  column pair celebration, final turn urgency, opponent thinking, score tallying,
  card hover/selection, knock early drama, column pair indicator, swap animation
  improvements, draw source distinction, card value tooltips, active rules context,
  discard pile history, realistic card sounds)
- Add V3 refactoring docs (ai.py, main.py/game.py, misc improvements)
- Add installation guide with Docker, systemd, and nginx setup
- Add helper scripts (install.sh, dev-server.sh, docker-build.sh)
- Add animation flow diagrams documentation
- Add test files for handlers, rooms, and V3 features
- Add e2e test specs for V3 features
- Update README with complete project structure and current tech stack
- Update CLAUDE.md with full architecture tree and server layer descriptions
- Update .env.example to reflect PostgreSQL (remove SQLite references)
- Update .gitignore to exclude virtualenv files, .claude/, and .db files
- Remove tracked virtualenv files (bin/, lib64, pyvenv.cfg)
- Remove obsolete game_log.py (SQLite) and games.db

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-14 10:03:45 -05:00

574 lines
12 KiB
Markdown

# Golf Game Installation Guide
Complete guide for installing and running the Golf card game server.
## Table of Contents
- [Quick Start](#quick-start)
- [Requirements](#requirements)
- [Development Setup](#development-setup)
- [Production Installation](#production-installation)
- [Docker Deployment](#docker-deployment)
- [Configuration Reference](#configuration-reference)
- [Troubleshooting](#troubleshooting)
---
## Quick Start
The fastest way to get started is using the interactive installer:
```bash
./scripts/install.sh
```
This provides a menu with options for:
- Development setup (Docker services + virtualenv + dependencies)
- Production installation to /opt/golfgame
- Systemd service configuration
- Status checks
---
## Requirements
### For Development
- **Python 3.11+** (3.12, 3.13, 3.14 also work)
- **Docker** and **Docker Compose** (for PostgreSQL and Redis)
- **Git**
### For Production
- **Python 3.11+**
- **PostgreSQL 16+**
- **Redis 7+**
- **systemd** (for service management)
- **nginx** (recommended, for reverse proxy)
---
## Development Setup
### Option A: Using the Installer (Recommended)
```bash
./scripts/install.sh
# Select option 1: Development Setup
```
This will:
1. Start PostgreSQL and Redis in Docker containers
2. Create a Python virtual environment
3. Install all dependencies
4. Generate a `.env` file configured for local development
### Option B: Manual Setup
#### 1. Start Docker Services
```bash
docker-compose -f docker-compose.dev.yml up -d
```
This starts:
- **PostgreSQL** on `localhost:5432` (user: `golf`, password: `devpassword`, database: `golf`)
- **Redis** on `localhost:6379`
Verify services are running:
```bash
docker-compose -f docker-compose.dev.yml ps
```
#### 2. Create Python Virtual Environment
```bash
# Create venv in project root
python3 -m venv .
# Activate it
source bin/activate
# Upgrade pip
pip install --upgrade pip
# Install dependencies (including dev tools)
pip install -e ".[dev]"
```
#### 3. Configure Environment
```bash
cp .env.example .env
```
Edit `.env` for development:
```bash
HOST=0.0.0.0
PORT=8000
DEBUG=true
LOG_LEVEL=DEBUG
ENVIRONMENT=development
DATABASE_URL=postgresql://golf:devpassword@localhost:5432/golf
POSTGRES_URL=postgresql://golf:devpassword@localhost:5432/golf
```
#### 4. Run the Development Server
```bash
cd server
../bin/uvicorn main:app --reload --host 0.0.0.0 --port 8000
```
Or use the helper script:
```bash
./scripts/dev-server.sh
```
The server will be available at http://localhost:8000
#### 5. Verify Installation
```bash
# Health check
curl http://localhost:8000/health
# Should return: {"status":"ok","timestamp":"..."}
```
### Stopping Development Services
```bash
# Stop the server: Ctrl+C
# Stop Docker containers
docker-compose -f docker-compose.dev.yml down
# Stop and remove volumes (clean slate)
docker-compose -f docker-compose.dev.yml down -v
```
---
## Production Installation
### Option A: Using the Installer (Recommended)
```bash
sudo ./scripts/install.sh
# Select option 2: Production Install to /opt/golfgame
```
### Option B: Manual Installation
#### 1. Install System Dependencies
```bash
# Debian/Ubuntu
sudo apt update
sudo apt install -y python3 python3-venv python3-pip postgresql redis-server nginx
# Start and enable services
sudo systemctl enable --now postgresql redis-server nginx
```
#### 2. Create PostgreSQL Database
```bash
sudo -u postgres psql << EOF
CREATE USER golf WITH PASSWORD 'your_secure_password';
CREATE DATABASE golf OWNER golf;
GRANT ALL PRIVILEGES ON DATABASE golf TO golf;
EOF
```
#### 3. Create Installation Directory
```bash
sudo mkdir -p /opt/golfgame
sudo chown $USER:$USER /opt/golfgame
```
#### 4. Clone and Install Application
```bash
cd /opt/golfgame
git clone https://github.com/alee/golfgame.git .
# Create virtual environment
python3 -m venv .
source bin/activate
# Install application
pip install --upgrade pip
pip install .
```
#### 5. Configure Production Environment
Create `/opt/golfgame/.env`:
```bash
# Generate a secret key
SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
cat > /opt/golfgame/.env << EOF
HOST=0.0.0.0
PORT=8000
DEBUG=false
LOG_LEVEL=INFO
ENVIRONMENT=production
DATABASE_URL=postgresql://golf:your_secure_password@localhost:5432/golf
POSTGRES_URL=postgresql://golf:your_secure_password@localhost:5432/golf
SECRET_KEY=$SECRET_KEY
MAX_PLAYERS_PER_ROOM=6
ROOM_TIMEOUT_MINUTES=60
# Optional: Error tracking with Sentry
# SENTRY_DSN=https://your-sentry-dsn
# Optional: Email via Resend
# RESEND_API_KEY=your-api-key
EOF
# Secure the file
chmod 600 /opt/golfgame/.env
```
#### 6. Set Ownership
```bash
sudo chown -R www-data:www-data /opt/golfgame
```
#### 7. Create Systemd Service
Create `/etc/systemd/system/golfgame.service`:
```ini
[Unit]
Description=Golf Card Game Server
Documentation=https://github.com/alee/golfgame
After=network.target postgresql.service redis.service
Wants=postgresql.service redis.service
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/golfgame/server
Environment="PATH=/opt/golfgame/bin:/usr/local/bin:/usr/bin:/bin"
EnvironmentFile=/opt/golfgame/.env
ExecStart=/opt/golfgame/bin/uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4
ExecReload=/bin/kill -HUP $MAINPID
Restart=always
RestartSec=5
StandardOutput=journal
StandardError=journal
# Security hardening
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/opt/golfgame
[Install]
WantedBy=multi-user.target
```
#### 8. Enable and Start Service
```bash
sudo systemctl daemon-reload
sudo systemctl enable golfgame
sudo systemctl start golfgame
# Check status
sudo systemctl status golfgame
# View logs
journalctl -u golfgame -f
```
#### 9. Configure Nginx Reverse Proxy
Create `/etc/nginx/sites-available/golfgame`:
```nginx
upstream golfgame {
server 127.0.0.1:8000;
keepalive 64;
}
server {
listen 80;
server_name your-domain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL configuration (use certbot for Let's Encrypt)
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
location / {
proxy_pass http://golfgame;
proxy_http_version 1.1;
# WebSocket support
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Standard proxy headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts for WebSocket
proxy_read_timeout 86400;
proxy_send_timeout 86400;
}
}
```
Enable the site:
```bash
sudo ln -s /etc/nginx/sites-available/golfgame /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
```
#### 10. SSL Certificate (Let's Encrypt)
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.com
```
---
## Docker Deployment
### Build the Docker Image
```bash
./scripts/docker-build.sh
# Or manually:
docker build -t golfgame:latest .
```
### Development with Docker
```bash
# Start dev services only (PostgreSQL + Redis)
docker-compose -f docker-compose.dev.yml up -d
```
### Production with Docker Compose
```bash
# Set required environment variables
export DB_PASSWORD="your-secure-database-password"
export SECRET_KEY=$(python3 -c "import secrets; print(secrets.token_hex(32))")
export ACME_EMAIL="your-email@example.com"
export DOMAIN="your-domain.com"
# Optional
export RESEND_API_KEY="your-resend-key"
export SENTRY_DSN="your-sentry-dsn"
# Start all services
docker-compose -f docker-compose.prod.yml up -d
# View logs
docker-compose -f docker-compose.prod.yml logs -f app
# Scale app instances
docker-compose -f docker-compose.prod.yml up -d --scale app=3
```
The production compose file includes:
- **app**: The Golf game server (scalable)
- **postgres**: PostgreSQL database
- **redis**: Redis for sessions
- **traefik**: Reverse proxy with automatic HTTPS
---
## Configuration Reference
### Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `HOST` | `0.0.0.0` | Server bind address |
| `PORT` | `8000` | Server port |
| `DEBUG` | `false` | Enable debug mode |
| `LOG_LEVEL` | `INFO` | Logging level (DEBUG, INFO, WARNING, ERROR) |
| `ENVIRONMENT` | `production` | Environment name |
| `DATABASE_URL` | - | PostgreSQL URL (event sourcing, game logs, stats) |
| `POSTGRES_URL` | - | PostgreSQL URL for auth/stats (can be same as DATABASE_URL) |
| `SECRET_KEY` | - | Secret key for JWT tokens |
| `MAX_PLAYERS_PER_ROOM` | `6` | Maximum players per game room |
| `ROOM_TIMEOUT_MINUTES` | `60` | Inactive room cleanup timeout |
| `ROOM_CODE_LENGTH` | `4` | Length of room codes |
| `DEFAULT_ROUNDS` | `9` | Default holes per game |
| `SENTRY_DSN` | - | Sentry error tracking DSN |
| `RESEND_API_KEY` | - | Resend API key for emails |
| `RATE_LIMIT_ENABLED` | `false` | Enable rate limiting |
### File Locations
| Path | Description |
|------|-------------|
| `/opt/golfgame/` | Production installation root |
| `/opt/golfgame/.env` | Production environment config |
| `/opt/golfgame/server/` | Server application code |
| `/opt/golfgame/client/` | Static web client |
| `/opt/golfgame/bin/` | Python virtualenv binaries |
| `/etc/systemd/system/golfgame.service` | Systemd service file |
| `/etc/nginx/sites-available/golfgame` | Nginx site config |
---
## Troubleshooting
### Check Service Status
```bash
# Systemd service
sudo systemctl status golfgame
journalctl -u golfgame -n 100
# Docker containers
docker-compose -f docker-compose.dev.yml ps
docker-compose -f docker-compose.dev.yml logs
# Using the installer
./scripts/install.sh
# Select option 6: Show Status
```
### Health Check
```bash
curl http://localhost:8000/health
# Expected: {"status":"ok","timestamp":"..."}
```
### Common Issues
#### "No module named 'config'"
The server must be started from the `server/` directory:
```bash
cd /opt/golfgame/server
../bin/uvicorn main:app --host 0.0.0.0 --port 8000
```
#### "Connection refused" on PostgreSQL
1. Check PostgreSQL is running:
```bash
sudo systemctl status postgresql
# Or for Docker:
docker ps | grep postgres
```
2. Verify connection settings in `.env`
3. Test connection:
```bash
psql -h localhost -U golf -d golf
```
#### "POSTGRES_URL not configured" warning
Add `POSTGRES_URL` to your `.env` file. This is required for authentication and stats features.
#### Broken virtualenv symlinks
If Python was upgraded, the virtualenv symlinks may break. Recreate it:
```bash
rm -rf bin lib lib64 pyvenv.cfg include share
python3 -m venv .
source bin/activate
pip install -e ".[dev]" # or just: pip install .
```
#### Permission denied on /opt/golfgame
```bash
sudo chown -R www-data:www-data /opt/golfgame
sudo chmod 600 /opt/golfgame/.env
```
### Updating
#### Development
```bash
git pull
source bin/activate
pip install -e ".[dev]"
# Server auto-reloads with --reload flag
```
#### Production
```bash
cd /opt/golfgame
sudo systemctl stop golfgame
sudo -u www-data git pull
sudo -u www-data ./bin/pip install .
sudo systemctl start golfgame
```
#### Docker
```bash
docker-compose -f docker-compose.prod.yml down
git pull
docker-compose -f docker-compose.prod.yml build
docker-compose -f docker-compose.prod.yml up -d
```
---
## Scripts Reference
| Script | Description |
|--------|-------------|
| `scripts/install.sh` | Interactive installer menu |
| `scripts/dev-server.sh` | Start development server |
| `scripts/docker-build.sh` | Build production Docker image |
---
## Support
- GitHub Issues: https://github.com/alee/golfgame/issues
- Documentation: See `README.md` for game rules and API docs