# SPDX-FileCopyrightText: 2026 Wouter Gritter # SPDX-License-Identifier: GPL-3.0-or-later # Self-hosted WiiLink WFC server for LAN Mario Kart Wii play. # # cp .env.example .env # then edit the secrets # docker compose up -d --build # # Prerequisite: the client payloads must already be built, since the server # serves them to every client at boot. From the repo root: # ./local/build-client.sh # which produces dist/payload/ (mounted below). services: postgres: image: postgres:16 container_name: wwfc-postgres restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - pgdata:/var/lib/postgresql/data # Imported once, on first boot into an empty data directory. # 00 creates the 'wiilink' role that upstream's dump assigns ownership to. - ./00-owner-role.sh:/docker-entrypoint-initdb.d/00-owner-role.sh:ro - ./schema.sql:/docker-entrypoint-initdb.d/10-schema.sql:ro # Published on loopback only: the wwfc container reaches it via the host # network namespace, and nothing else on the LAN has any business here. ports: - "127.0.0.1:5432:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 5s timeout: 5s retries: 12 start_period: 10s wwfc: build: context: . dockerfile: Dockerfile image: mkwii-wwfc:local container_name: wwfc restart: unless-stopped init: true depends_on: postgres: condition: service_healthy # REQUIRED - do not switch this to a bridge network with published ports. # # The server records the source address it observes for each client and # hands that address to the other players so they can open the peer-to-peer # race connection directly. Behind Docker's bridge NAT every client would be # observed as the bridge gateway, sessions would collide on a single # address, and NAT negotiation would hand out an unroutable one. Host # networking keeps the real LAN source addresses intact. network_mode: host environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} WWFC_DB_ADDRESS: 127.0.0.1 WWFC_BIND_ADDRESS: ${WWFC_BIND_ADDRESS:-0.0.0.0} WWFC_SERVER_NAME: ${WWFC_SERVER_NAME:-wfc} WWFC_LOG_LEVEL: ${WWFC_LOG_LEVEL:-4} WWFC_LOG_OUTPUT: ${WWFC_LOG_OUTPUT:-StdOutAndFile} WWFC_API_SECRET: ${WWFC_API_SECRET} volumes: # Built client artifacts. Read-only: the server only ever reads these, # and it holds the payload signing key, which should not be writable. - ../dist/payload:/app/payload:ro - ./logs:/app/logs volumes: pgdata: