# Deployment Guide ## Prerequisites ### Required - **Java 8+** (tested on Java 8, 11, 21) - Download: https://www.oracle.com/java/technologies/downloads/ - Verify: `java -version` - **Maven 3.6+** (for building) - Download: https://maven.apache.org/download.cgi - Verify: `mvn -version` - **Node.js 18+** (for web client only) - Download: https://nodejs.org/ - Verify: `node --version` and `npm --version` ### Optional - **Git** — for cloning repository - **Docker + Docker Compose** — for containerized deployment (recommended for quick start) - **nginx/Apache** — for reverse proxy (if needed) --- ## Quick Start (Docker Compose) **Fastest way to get started — single command:** ```bash docker compose up --build ``` **Then:** - Open `http://localhost:8080` in your browser - Server API: `http://localhost:1024` (TCP), `http://localhost:1025` (WebSocket) **Stop:** ```bash docker compose down ``` **What's running:** - **caro-server** — Java server on `1024` (TCP) + `1025` (WebSocket/HTTP) - **caro-web-client** — Nginx serving web UI on host port `8080` **Storage:** In-memory only; games not persisted. Restart to clear all rooms. **Logs:** ```bash docker compose logs -f caro-server docker compose logs -f caro-web-client ``` **Prerequisites:** Docker + Docker Compose --- ## Local Development Setup ### 1. Clone Repository ```bash git clone https://github.com/tiennm99/caro.git cd caro ``` ### 2. Build Java Modules **Build all modules (server + CLI client):** ```bash mvn clean package -DskipTests ``` **Output:** - `landlords-server/target/landlords-server-1.4.0.jar` (15-20 MB) - `landlords-client/target/landlords-client-1.4.0.jar` (10-15 MB) - `landlords-common/target/landlords-common-1.4.0.jar` (shared lib) **With tests (recommended):** ```bash mvn clean package ``` Takes ~30-60 seconds. Tests must pass before continuing. ### 3. Run Server ```bash java -jar landlords-server/target/landlords-server-1.4.0.jar -p 1024 ``` **Output:** ``` [INFO] Server listening on port 1024 (TCP) [INFO] WebSocket server listening on port 1025 [INFO] Static file handler enabled ``` **What's running:** - **TCP port 1024** — CLI clients connect here (Protobuf protocol) - **WebSocket port 1025** — Web clients connect here (JSON protocol) - **HTTP port 1025** — Static file serving (same port as WebSocket) ### 4. Play in Browser (Built-in UI) Open `http://localhost:1025/` in your browser. This is a basic static HTML UI served directly by the server. To play: 1. Enter your nickname 2. Choose PVP or PVE (with difficulty) 3. Create or join a room 4. Wait for opponent or start AI game ### 5. Play with Phaser Web Client (Recommended) **In a new terminal:** ```bash cd web-client npm install npm run dev ``` **Output:** ``` VITE v6.3.1 ready in 234 ms ➜ Local: http://localhost:5173/ ➜ press h to show help ``` Open `http://localhost:5173/` in your browser. This is the full-featured Phaser 3 client with: - Professional board rendering - Stone animations - Move history panel - Sound effects - Better responsive design ### 6. Play from CLI (Terminal) **In another terminal:** ```bash java -jar landlords-client/target/landlords-client-1.4.0.jar -h 127.0.0.1 -p 1024 ``` **Usage:** 1. Enter your nickname 2. Choose game mode (create PVP/PVE, join room, spectate) 3. Make moves as `row,col` (e.g., `7,7` for center) 4. Type `exit` or `e` to quit --- ## Production Deployment ### Option A: Standalone JAR (Recommended) **Simplest deployment — single command:** ```bash java -jar landlords-server-1.4.0.jar -p 1024 ``` **For production:** - Run in background: `nohup java -jar ... &` - Or use systemd service (see below) - Or container (Docker) **System Requirements:** - 512 MB RAM (minimum) - 1 GB RAM (recommended) - 100 MB disk space - Java 8+ **Port Configuration:** - Server listens on `-p {port}` (TCP) - WebSocket/HTTP automatically use `{port} + 1` **Example:** - `-p 1024` → TCP:1024, WS/HTTP:1025 - `-p 8080` → TCP:8080, WS/HTTP:8081 ### Option B: Docker Container **Dockerfile example:** ```dockerfile FROM openjdk:8-jre-slim WORKDIR /app COPY landlords-server/target/landlords-server-1.4.0.jar . EXPOSE 1024 1025 CMD ["java", "-jar", "landlords-server-1.4.0.jar", "-p", "1024"] ``` **Build:** ```bash docker build -t caro-server:1.4.0 . ``` **Run:** ```bash docker run -d --name caro-server \ -p 1024:1024/tcp \ -p 1025:1025/tcp \ caro-server:1.4.0 ``` ### Option C: Linux Systemd Service **Create service file `/etc/systemd/system/caro-server.service`:** ```ini [Unit] Description=Caro Gomoku Server After=network.target [Service] Type=simple User=gameserver WorkingDirectory=/opt/caro ExecStart=/usr/bin/java -jar /opt/caro/landlords-server-1.4.0.jar -p 1024 Restart=on-failure RestartSec=10 StandardOutput=journal StandardError=journal [Install] WantedBy=multi-user.target ``` **Enable and start:** ```bash sudo systemctl daemon-reload sudo systemctl enable caro-server sudo systemctl start caro-server ``` **Monitor:** ```bash sudo systemctl status caro-server sudo journalctl -u caro-server -f ``` --- ## Web Client Deployment ### Option A: GitHub Pages (Automatic) Push to `master` branch. GitHub Actions automatically: 1. Build web client (`npm run build`) 2. Deploy to `https://tiennm99.github.io/caro/` **Configuration:** `.github/workflows/deploy-pages.yml` **URL:** `https://.github.io/caro/` **Connect to custom server:** - Web client connects to server on `window.location.hostname` - For different server, modify `connection-service.js` endpoint ### Option B: Static Hosting (Netlify, Vercel, AWS S3) **Build:** ```bash cd web-client npm install npm run build ``` **Output:** `web-client/dist/` directory (ready to deploy) **Deploy to Netlify:** ```bash npm install -g netlify-cli netlify deploy --prod --dir web-client/dist ``` **Deploy to Vercel:** ```bash npm install -g vercel vercel --prod ``` **Deploy to AWS S3:** ```bash aws s3 sync web-client/dist/ s3://my-bucket/caro/ --delete ``` ### Option C: Nginx Reverse Proxy **Serve web client + proxy API:** ```nginx server { listen 80; server_name caro.example.com; # Static files (web client) location / { root /var/www/caro; try_files $uri /index.html; } # WebSocket proxy to server location /ratel { proxy_pass ws://localhost:1025; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_set_header Host $host; } } ``` **Deploy:** ```bash # Build web client cd web-client npm run build # Copy to nginx root sudo cp -r dist/* /var/www/caro/ # Restart nginx sudo systemctl restart nginx ``` --- ## Configuration & Options ### Server Options **Usage:** ```bash java -jar landlords-server-1.4.0.jar [OPTIONS] ``` **Available options:** ``` -p, -port TCP port (default: 1024) WebSocket will use port + 1 (e.g., 1025) ``` **Examples:** ```bash java -jar landlords-server-1.4.0.jar -p 1024 # TCP:1024, WS:1025 java -jar landlords-server-1.4.0.jar -p 8080 # TCP:8080, WS:8081 java -jar landlords-server-1.4.0.jar # TCP:1024, WS:1025 (default) ``` ### CLI Client Options **Usage:** ```bash java -jar landlords-client-1.4.0.jar -h -p [OPTIONS] ``` **Required:** ``` -h, -host Server hostname/IP (required) -p, -port Server TCP port (required) ``` **Optional:** ``` -ptl, -protocol Protocol: "pb" (Protobuf/TCP) or "ws" (WebSocket) Default: "pb" (Protobuf) -lang Language: "en", "en_US" Default: "en" ``` **Examples:** ```bash # Connect to localhost via TCP (default) java -jar landlords-client-1.4.0.jar -h 127.0.0.1 -p 1024 # Connect to remote server via WebSocket java -jar landlords-client-1.4.0.jar -h example.com -p 1024 -ptl ws # With language java -jar landlords-client-1.4.0.jar -h localhost -p 1024 -lang en_US ``` ### Web Client Configuration **Connection endpoint:** Defined in `connection-service.js` ```javascript // Default: connect to server on same host:1025/ratel const wsUrl = `ws://${window.location.hostname}:1025/ratel`; ``` **To connect to different server:** Edit `web-client/src/services/connection-service.js`: ```javascript // Change this line: const wsUrl = `ws://${window.location.hostname}:1025/ratel`; // To: const wsUrl = 'ws://your-server.com:1025/ratel'; ``` Then rebuild: ```bash npm run build ``` --- ## Running Tests ### Java Unit Tests **Run all tests:** ```bash mvn clean test ``` **Expected output:** ``` ------------------------------------------------------- T E S T S ------------------------------------------------------- Running org.nico.ratel.landlords.helper.tests.GomokuHelperTest Tests run: 20, Failures: 0, Errors: 0, Skipped: 0 Running org.nico.ratel.landlords.robot.tests.GomokuAITest Tests run: 17, Failures: 0, Errors: 0, Skipped: 0 Results: 37 tests passed ``` **Run specific test:** ```bash mvn test -Dtest=GomokuHelperTest ``` **Run with coverage (requires plugin):** ```bash mvn clean test jacoco:report # Report: target/site/jacoco/index.html ``` ### Web Client Tests Currently no automated tests for web client (UI testing requires Selenium/Cypress). **Manual testing:** 1. Start server: `java -jar landlords-server-1.4.0.jar` 2. Start web client: `npm run dev` in web-client/ 3. Open browser: `http://localhost:5173` 4. Test flows: Create game, make moves, check AI, spectate, etc. --- ## Monitoring & Maintenance ### Server Health Check **Check if server is running:** ```bash # Check port 1024 (TCP) netstat -an | grep 1024 # Or using lsof lsof -i :1024 ``` **Test WebSocket connection:** ```bash # Using curl (if server supports HTTP health endpoint) curl -i http://localhost:1025/ # Or open browser console and test: // In browser console: ws = new WebSocket('ws://localhost:1025/ratel') ws.onopen = () => console.log('Connected') ws.onerror = (e) => console.log('Error:', e) ``` ### Logs **Server logs:** - Standard output (if running in foreground) - If using systemd: `journalctl -u caro-server -f` - If using Docker: `docker logs -f caro-server` **Key log patterns:** ``` [INFO] Client connected: [INFO] Room created: [INFO] Game move: at , [ERROR] Invalid move: ``` ### Performance Monitoring **Memory usage:** ```bash # While server is running top -p $(pgrep -f landlords-server) ``` **Check concurrent connections:** ```bash # Linux netstat -an | grep -c ESTABLISHED # macOS netstat -an | grep -c ESTABLISHED # Or with lsof lsof -i -P -n | grep java | wc -l ``` ### Cleanup & Maintenance **Clear inactive rooms (automatic):** - Server auto-cleans finished rooms after 1 hour - No manual action needed **Restart server:** ```bash # Kill current process kill $(pgrep -f landlords-server) # Or force kill kill -9 $(pgrep -f landlords-server) # Start again java -jar landlords-server-1.4.0.jar -p 1024 ``` --- ## Troubleshooting ### Port Already in Use **Error:** `Address already in use` **Solution:** ```bash # Find process using port 1024 lsof -i :1024 # Kill it kill -9 # Or use different port java -jar landlords-server-1.4.0.jar -p 9090 ``` ### Connection Refused **Error:** `Connection refused: connect` (client can't reach server) **Solutions:** 1. **Check server is running:** ```bash ps aux | grep landlords-server ``` 2. **Check firewall:** ```bash # Allow port sudo ufw allow 1024/tcp sudo ufw allow 1025/tcp ``` 3. **Check hostname/IP:** ```bash # From client machine, test connectivity nc -zv localhost 1024 nc -zv server-ip 1024 ``` 4. **Check port mapping (if Docker):** ```bash docker ps -a docker port caro-server ``` ### WebSocket Connection Fails **Error:** `Failed to connect to WebSocket` **Solutions:** 1. **Check WebSocket port (TCP + 1):** ```bash # If TCP is 1024, WebSocket should be 1025 lsof -i :1025 ``` 2. **Check CORS (if web client on different domain):** - Server doesn't require CORS (native WebSocket) - Ensure client connects to correct hostname 3. **Test WebSocket directly:** ```bash # Using websocat tool websocat ws://localhost:1025/ratel # Should show connection ``` ### High Memory Usage **If server uses > 1 GB RAM:** 1. **Check concurrent players:** ```bash netstat -an | grep ESTABLISHED | wc -l ``` 2. **Increase JVM heap:** ```bash java -Xmx2g -jar landlords-server-1.4.0.jar -p 1024 ``` 3. **Check for room leaks** (finished rooms not cleaned): - Restart server to clear memory - Or check RoomClearTask configuration ### Slow Performance **If moves are delayed (> 500ms):** 1. **Check CPU usage:** ```bash top -p $(pgrep -f landlords-server) ``` 2. **Check network latency:** ```bash ping server-ip ``` 3. **Check board size** (AI might be slow): - Hard difficulty AI takes ~1 second - This is normal, not a bug 4. **Reduce AI difficulty** (if PVE): - Easy: instant - Medium: < 100ms - Hard: ~1 second ### Client Can't Join Room **Error:** `Room is full` or `Room does not exist` **Solutions:** 1. **Room full:** Max 2 players + spectators. Create new room. 2. **Room doesn't exist:** Room was deleted (auto-cleanup). List rooms again. 3. **Connection lost:** Try reconnecting. Web client auto-reconnects. --- ## Deployment Checklist Before going live: - [ ] Java 8+ installed - [ ] Build successful: `mvn clean package` (all tests pass) - [ ] Server starts without errors: `java -jar landlords-server-1.4.0.jar -p 1024` - [ ] TCP port 1024 and WebSocket port 1025 open (firewall) - [ ] Web client built: `npm run build` - [ ] Web client connects to correct server endpoint - [ ] Tested: Create game, make moves, join room, spectate - [ ] Tested: CLI client connection - [ ] Monitored: Server memory and CPU under load - [ ] Logged: Set up log aggregation if needed - [ ] Backup: Keep copy of JAR and config - [ ] Health check: Set up monitoring/alerting --- ## Updating & Patching ### Update Server 1. **Back up current JAR:** ```bash cp landlords-server-1.4.0.jar landlords-server-1.4.0.jar.backup ``` 2. **Download new version:** ```bash git pull origin master mvn clean package -DskipTests ``` 3. **Stop current server:** ```bash kill $(pgrep -f landlords-server) ``` 4. **Start new version:** ```bash java -jar landlords-server/target/landlords-server-1.4.0.jar -p 1024 ``` 5. **Verify:** ```bash # Test connection java -jar landlords-client-1.4.0.jar -h localhost -p 1024 ``` ### Update Web Client 1. **Rebuild:** ```bash cd web-client git pull origin master npm install npm run build ``` 2. **Deploy new `dist/` to hosting:** ```bash # If using GitHub Pages: just push git push origin master # If manual: copy dist/ to server scp -r dist/* user@server:/var/www/caro/ ``` ### Zero-Downtime Update **For critical updates without disconnecting players:** 1. Keep old server running on separate port: `-p 9090` 2. Start new server on original port: `-p 1024` 3. Gradually migrate clients (or wait for natural disconnect) 4. Stop old server --- ## Performance Tuning ### JVM Tuning **For production servers with 4+ GB RAM:** ```bash java -Xmx4g \ -Xms2g \ -XX:+UseG1GC \ -XX:MaxGCPauseMillis=200 \ -jar landlords-server-1.4.0.jar -p 1024 ``` **Flags:** - `-Xmx4g` — Max heap size (4 GB) - `-Xms2g` — Initial heap size (2 GB) - `-XX:+UseG1GC` — Use G1 garbage collector (better for large heaps) - `-XX:MaxGCPauseMillis=200` — Limit pause time ### Network Tuning **Linux socket tuning (for high concurrency):** ```bash # Increase max file descriptors ulimit -n 65536 # Increase TCP backlog sysctl -w net.core.somaxconn=65535 sysctl -w net.ipv4.tcp_max_syn_backlog=65535 ``` ### Load Balancing **If more than 50+ concurrent players, consider load balancing:** ```nginx upstream caro_servers { server localhost:1024; server localhost:1025; } server { listen 1024; proxy_pass caro_servers; } ``` --- ## Rollback Plan **If new version has issues:** 1. **Stop new server:** ```bash kill $(pgrep -f landlords-server) ``` 2. **Restore backup JAR:** ```bash cp landlords-server-1.4.0.jar.backup landlords-server-1.4.0.jar ``` 3. **Start old version:** ```bash java -jar landlords-server-1.4.0.jar -p 1024 ``` 4. **Notify players:** - Existing games end - Players reconnect to stable version --- ## References - **Caro Repository:** https://github.com/tiennm99/caro - **Java Downloads:** https://www.oracle.com/java/technologies/downloads/ - **Maven Guide:** https://maven.apache.org/ - **Node.js Downloads:** https://nodejs.org/ - **Phaser 3 Docs:** https://photonstorm.github.io/phaser3-docs/ - **Vite Docs:** https://vitejs.dev/ - **Netty Guide:** https://netty.io/wiki/