From e32e5aceaf397009bce9dd6b2755fb5436990252 Mon Sep 17 00:00:00 2001 From: doomtube Date: Tue, 6 Jan 2026 05:13:49 -0500 Subject: [PATCH] Fix: Nakama chess modules, chat WebSocket protocol, and streaming SSL MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add Nakama Dockerfile to build custom image with chess modules - Update docker-compose.prod.yml to use custom Nakama image with --runtime.js_entrypoint - Fix chat WebSocket to use wss:// on HTTPS pages (was hardcoded ws://) - Add SSL configuration to nginx port 8088 for HLS/LLHLS streaming - Add Nakama build step to CI workflow 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 --- .forgejo/workflows/build.yml | 17 ++++++++++++ docker-compose.prod.yml | 4 +-- frontend/src/lib/chat/chatWebSocket.js | 4 ++- nakama/Dockerfile | 36 ++++++++++++++++++++++++++ openresty/nginx.conf | 13 +++++++--- 5 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 nakama/Dockerfile diff --git a/.forgejo/workflows/build.yml b/.forgejo/workflows/build.yml index 44c59f6..5fec035 100644 --- a/.forgejo/workflows/build.yml +++ b/.forgejo/workflows/build.yml @@ -104,3 +104,20 @@ jobs: run: | docker push ${{ env.REGISTRY }}/${{ github.repository }}/openresty:${{ github.sha }} docker push ${{ env.REGISTRY }}/${{ github.repository }}/openresty:latest + + # ========================================================================= + # Build Nakama (Game Server with Chess Modules) + # ========================================================================= + - name: Build Nakama Image + run: | + echo "=== Building Nakama ===" + docker build \ + -t ${{ env.REGISTRY }}/${{ github.repository }}/nakama:${{ github.sha }} \ + -t ${{ env.REGISTRY }}/${{ github.repository }}/nakama:latest \ + ./nakama + + - name: Push Nakama Image + if: github.event_name != 'pull_request' + run: | + docker push ${{ env.REGISTRY }}/${{ github.repository }}/nakama:${{ github.sha }} + docker push ${{ env.REGISTRY }}/${{ github.repository }}/nakama:latest diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index abdfbfc..29bb291 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -116,7 +116,7 @@ services: - backend nakama: - image: registry.heroiclabs.com/heroiclabs/nakama:3.21.1 + image: qbit.realms.pub/doomtube/beeta/nakama:latest restart: unless-stopped depends_on: postgres: @@ -134,6 +134,7 @@ services: --database.address "streamuser:$DB_PASSWORD@postgres:5432/nakama?sslmode=disable" \ --socket.server_key "$NAKAMA_SERVER_KEY" \ --session.token_expiry_sec 86400 \ + --runtime.js_entrypoint "main.js" \ --runtime.env "JWT_SECRET=$JWT_SECRET" \ --console.username admin \ --console.password "$NAKAMA_CONSOLE_PASSWORD" \ @@ -143,7 +144,6 @@ services: - NAKAMA_CONSOLE_PASSWORD=${NAKAMA_CONSOLE_PASSWORD} - NAKAMA_SERVER_KEY=${NAKAMA_SERVER_KEY} - DB_PASSWORD=${DB_PASSWORD} - # Custom modules can be baked into a custom nakama image if needed healthcheck: test: ["CMD", "curl", "-f", "http://localhost:7350/healthcheck"] interval: 10s diff --git a/frontend/src/lib/chat/chatWebSocket.js b/frontend/src/lib/chat/chatWebSocket.js index 5440a17..87b071e 100644 --- a/frontend/src/lib/chat/chatWebSocket.js +++ b/frontend/src/lib/chat/chatWebSocket.js @@ -37,7 +37,9 @@ class ChatWebSocket { // SECURITY FIX #9: Don't include token in URL query params // Token will be sent as first message after connection to avoid logging/exposure - let wsUrl = `ws://${window.location.host}/chat/ws?realmId=${encodeURIComponent(realmId)}`; + // Use wss:// for HTTPS, ws:// for HTTP (dynamic protocol detection) + const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; + let wsUrl = `${wsProtocol}//${window.location.host}/chat/ws?realmId=${encodeURIComponent(realmId)}`; // Guest connection - generate fingerprint for ban enforcement // Only guests are fingerprinted, registered users are NOT fingerprinted for privacy diff --git a/nakama/Dockerfile b/nakama/Dockerfile new file mode 100644 index 0000000..3ce4d8f --- /dev/null +++ b/nakama/Dockerfile @@ -0,0 +1,36 @@ +# ============================================================================= +# Nakama with Custom Chess Modules +# ============================================================================= +# Two-stage build: +# 1. Build TypeScript modules with Node.js +# 2. Copy compiled JS to Nakama runtime +# ============================================================================= + +# Stage 1: Build TypeScript modules +FROM node:20-alpine AS builder + +WORKDIR /app + +# Copy module files +COPY modules/package*.json ./ +RUN npm ci + +# Copy source and build +COPY modules/tsconfig.json ./ +COPY modules/src ./src + +# Build with esbuild (output to build/index.js) +RUN npm run build + +# Verify build output exists +RUN ls -la build/ && test -f build/index.js + +# Stage 2: Nakama runtime with modules +FROM registry.heroiclabs.com/heroiclabs/nakama:3.21.1 + +# Copy compiled JavaScript modules +# Nakama expects modules at /nakama/data/modules/ +COPY --from=builder /app/build/index.js /nakama/data/modules/main.js + +# Copy config file (optional - can also be passed via CLI) +COPY config.yml /nakama/data/config.yml diff --git a/openresty/nginx.conf b/openresty/nginx.conf index 63efd3d..90c4f1f 100644 --- a/openresty/nginx.conf +++ b/openresty/nginx.conf @@ -820,10 +820,17 @@ http { } } - # Separate server block for port 8088 (HLS/LLHLS) + # Separate server block for port 8088 (HLS/LLHLS) - with SSL for production server { - listen 8088; - server_name localhost; + listen 8088 ssl http2; + server_name beeta.realms.pub; + + # SSL certificates (same as main server block) + ssl_certificate /etc/letsencrypt/live/beeta.realms.pub/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/beeta.realms.pub/privkey.pem; + ssl_protocols TLSv1.2 TLSv1.3; + ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384; + ssl_prefer_server_ciphers off; # Site-wide uberban check - blocks banned fingerprints from streaming access_by_lua_block {