17 KiB
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 --versionandnpm --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:
docker compose up --build
Then:
- Open
http://localhost:8080in your browser - Server API:
http://localhost:1024(TCP),http://localhost:1025(WebSocket)
Stop:
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:
docker compose logs -f caro-server
docker compose logs -f caro-web-client
Prerequisites: Docker + Docker Compose
Local Development Setup
1. Clone Repository
git clone https://github.com/tiennm99/caro.git
cd caro
2. Build Java Modules
Build all modules (server + CLI client):
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):
mvn clean package
Takes ~30-60 seconds. Tests must pass before continuing.
3. Run Server
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:
- Enter your nickname
- Choose PVP or PVE (with difficulty)
- Create or join a room
- Wait for opponent or start AI game
5. Play with Phaser Web Client (Recommended)
In a new terminal:
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:
java -jar landlords-client/target/landlords-client-1.4.0.jar -h 127.0.0.1 -p 1024
Usage:
- Enter your nickname
- Choose game mode (create PVP/PVE, join room, spectate)
- Make moves as
row,col(e.g.,7,7for center) - Type
exitoreto quit
Production Deployment
Option A: Standalone JAR (Recommended)
Simplest deployment — single command:
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:
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:
docker build -t caro-server:1.4.0 .
Run:
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:
[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:
sudo systemctl daemon-reload
sudo systemctl enable caro-server
sudo systemctl start caro-server
Monitor:
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:
- Build web client (
npm run build) - Deploy to
https://tiennm99.github.io/caro/
Configuration: .github/workflows/deploy-pages.yml
URL: https://<username>.github.io/caro/
Connect to custom server:
- Web client connects to server on
window.location.hostname - For different server, modify
connection-service.jsendpoint
Option B: Static Hosting (Netlify, Vercel, AWS S3)
Build:
cd web-client
npm install
npm run build
Output: web-client/dist/ directory (ready to deploy)
Deploy to Netlify:
npm install -g netlify-cli
netlify deploy --prod --dir web-client/dist
Deploy to Vercel:
npm install -g vercel
vercel --prod
Deploy to AWS S3:
aws s3 sync web-client/dist/ s3://my-bucket/caro/ --delete
Option C: Nginx Reverse Proxy
Serve web client + proxy API:
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:
# 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:
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:
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:
java -jar landlords-client-1.4.0.jar -h <host> -p <port> [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:
# 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
// 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:
// Change this line:
const wsUrl = `ws://${window.location.hostname}:1025/ratel`;
// To:
const wsUrl = 'ws://your-server.com:1025/ratel';
Then rebuild:
npm run build
Running Tests
Java Unit Tests
Run all tests:
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:
mvn test -Dtest=GomokuHelperTest
Run with coverage (requires plugin):
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:
- Start server:
java -jar landlords-server-1.4.0.jar - Start web client:
npm run devin web-client/ - Open browser:
http://localhost:5173 - Test flows: Create game, make moves, check AI, spectate, etc.
Monitoring & Maintenance
Server Health Check
Check if server is running:
# Check port 1024 (TCP)
netstat -an | grep 1024
# Or using lsof
lsof -i :1024
Test WebSocket connection:
# 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: <ip>
[INFO] Room created: <room-id>
[INFO] Game move: <player> at <row>,<col>
[ERROR] Invalid move: <reason>
Performance Monitoring
Memory usage:
# While server is running
top -p $(pgrep -f landlords-server)
Check concurrent connections:
# 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:
# 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:
# Find process using port 1024
lsof -i :1024
# Kill it
kill -9 <PID>
# 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:
-
Check server is running:
ps aux | grep landlords-server -
Check firewall:
# Allow port sudo ufw allow 1024/tcp sudo ufw allow 1025/tcp -
Check hostname/IP:
# From client machine, test connectivity nc -zv localhost 1024 nc -zv server-ip 1024 -
Check port mapping (if Docker):
docker ps -a docker port caro-server
WebSocket Connection Fails
Error: Failed to connect to WebSocket
Solutions:
-
Check WebSocket port (TCP + 1):
# If TCP is 1024, WebSocket should be 1025 lsof -i :1025 -
Check CORS (if web client on different domain):
- Server doesn't require CORS (native WebSocket)
- Ensure client connects to correct hostname
-
Test WebSocket directly:
# Using websocat tool websocat ws://localhost:1025/ratel # Should show connection
High Memory Usage
If server uses > 1 GB RAM:
-
Check concurrent players:
netstat -an | grep ESTABLISHED | wc -l -
Increase JVM heap:
java -Xmx2g -jar landlords-server-1.4.0.jar -p 1024 -
Check for room leaks (finished rooms not cleaned):
- Restart server to clear memory
- Or check RoomClearTask configuration
Slow Performance
If moves are delayed (> 500ms):
-
Check CPU usage:
top -p $(pgrep -f landlords-server) -
Check network latency:
ping server-ip -
Check board size (AI might be slow):
- Hard difficulty AI takes ~1 second
- This is normal, not a bug
-
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:
- Room full: Max 2 players + spectators. Create new room.
- Room doesn't exist: Room was deleted (auto-cleanup). List rooms again.
- 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
-
Back up current JAR:
cp landlords-server-1.4.0.jar landlords-server-1.4.0.jar.backup -
Download new version:
git pull origin master mvn clean package -DskipTests -
Stop current server:
kill $(pgrep -f landlords-server) -
Start new version:
java -jar landlords-server/target/landlords-server-1.4.0.jar -p 1024 -
Verify:
# Test connection java -jar landlords-client-1.4.0.jar -h localhost -p 1024
Update Web Client
-
Rebuild:
cd web-client git pull origin master npm install npm run build -
Deploy new
dist/to hosting:# 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:
- Keep old server running on separate port:
-p 9090 - Start new server on original port:
-p 1024 - Gradually migrate clients (or wait for natural disconnect)
- Stop old server
Performance Tuning
JVM Tuning
For production servers with 4+ GB RAM:
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):
# 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:
upstream caro_servers {
server localhost:1024;
server localhost:1025;
}
server {
listen 1024;
proxy_pass caro_servers;
}
Rollback Plan
If new version has issues:
-
Stop new server:
kill $(pgrep -f landlords-server) -
Restore backup JAR:
cp landlords-server-1.4.0.jar.backup landlords-server-1.4.0.jar -
Start old version:
java -jar landlords-server-1.4.0.jar -p 1024 -
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/