From 2551fb833cb6a4a9beb8bbaa5482155075490a26 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 20 Aug 2026 10:41:04 -0400 Subject: [PATCH 1/4] add lila preview site stack --- stacks/lila-preview/compose.yml | 223 ++++++++++++++++++ stacks/lila-preview/conf/Caddyfile | 51 ++++ stacks/lila-preview/conf/lila.conf | 47 ++++ stacks/lila-preview/conf/picfit.json | 13 + .../scripts/update-asset-volume.sh | 14 ++ 5 files changed, 348 insertions(+) create mode 100644 stacks/lila-preview/compose.yml create mode 100644 stacks/lila-preview/conf/Caddyfile create mode 100644 stacks/lila-preview/conf/lila.conf create mode 100644 stacks/lila-preview/conf/picfit.json create mode 100755 stacks/lila-preview/scripts/update-asset-volume.sh diff --git a/stacks/lila-preview/compose.yml b/stacks/lila-preview/compose.yml new file mode 100644 index 00000000..b8734968 --- /dev/null +++ b/stacks/lila-preview/compose.yml @@ -0,0 +1,223 @@ +services: + + caddy: + image: caddy:2 + environment: + - LILA_DOMAIN=preview.${SUBDOMAIN:-test}.lichess.app + - LILA_URL=https://preview.${SUBDOMAIN:-test}.lichess.app + volumes: + - ./conf/Caddyfile:/etc/caddy/Caddyfile + networks: + - frontend + - lila + labels: + - traefik.enable=true + - traefik.docker.network=frontend + - traefik.http.services.lila-preview-${SUBDOMAIN:-test}.loadbalancer.server.port=80 + - traefik.http.routers.lila-preview-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.lichess.app`) + - traefik.http.routers.lila-preview-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-preview-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-preview-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.lichess.app`) && (PathPrefix(`/player`) || PathPrefix(`/forum`) || PathPrefix(`/team`) || PathPrefix(`/blog`) || PathPrefix(`/games`) || PathPrefix(`/class`) || PathPrefix(`/tournament/leaderboard`) || PathPrefix(`/training`) || PathPrefix(`/streak`) || PathPrefix(`/storm`) || PathPrefix(`/racer`) || PathPrefix(`/insights`) || PathPrefix(`/opening`) || PathPrefix(`/analysis/pgn`)) + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.middlewares=authentik@file + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.priority=100 + - traefik.http.routers.lila-preview-protected-${SUBDOMAIN:-test}.service=lila-preview-${SUBDOMAIN:-test} + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.lichess.app`) && PathPrefix(`/outpost.goauthentik.io`) + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.priority=200 + - traefik.http.routers.lila-preview-outpost-${SUBDOMAIN:-test}.service=authentik-server@file + + lila: + image: ghcr.io/lichess-org/lila-server:${LILA_SERVER_TAG:-latest} + environment: + - LILA_DOMAIN=preview.${SUBDOMAIN:-test}.lichess.app + - LILA_URL=https://preview.${SUBDOMAIN:-test}.lichess.app + - LILA_SITE_NAME=${LILA_SITE_NAME:-lichess preview} + - LILA_EXPLORER_ENDPOINT=https://preview.${SUBDOMAIN:-test}.explorer.lichess.app + volumes: + - ./conf/lila.conf:/lila/conf/application.conf + - lila-assets-data:/lila/public:ro + secrets: + - lila_preview_firebase_service_account + networks: + - lila + + lila_assets: + image: ghcr.io/lichess-org/lila-assets:${LILA_ASSETS_TAG:-latest} + volumes: + - lila-assets-data:/assets:rw + - ./scripts/update-asset-volume.sh:/docker-entrypoint.d/50-update-assets.sh:ro + networks: + - lila + + lila_ws: + image: ghcr.io/lichess-org/lila-ws:${LILA_WS_TAG:-latest} + environment: + - CONFIG_FORCE_csrf.origin=https://preview.${SUBDOMAIN:-test}.lichess.app + - CONFIG_FORCE_mongo_uri=mongodb://mongodb:27017/lichess?appName=lila-ws + - CONFIG_FORCE_redis.uri=redis://redis + networks: + - lila + + mongodb: + image: mongo:8.2-noble + networks: + - lila + + redis: + image: redis:8 + networks: + - lila + + openingexplorer: + image: ghcr.io/lichess-org/lila-openingexplorer:latest + restart: unless-stopped + environment: + - LILA_URL=https://preview.${SUBDOMAIN:-test}.lichess.app + - EXPLORER_BEARER=lip_openingexplorer-${USER_SEED_PASSWORD:-password} + volumes: + - openingexplorer-data:/app/_db + networks: + - frontend + - lila + labels: + - traefik.enable=true + - traefik.docker.network=frontend + - traefik.http.services.lila-explorer-${SUBDOMAIN:-test}.loadbalancer.server.port=9002 + - traefik.http.routers.lila-explorer-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.explorer.lichess.app`) + - traefik.http.routers.lila-explorer-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-explorer-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-explorer-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-explorer-${SUBDOMAIN:-test}.middlewares=explorer-cors-${SUBDOMAIN:-test} + - traefik.http.middlewares.explorer-cors-${SUBDOMAIN:-test}.headers.accessControlAllowOriginList=https://preview.${SUBDOMAIN:-test}.lichess.app + - traefik.http.middlewares.explorer-cors-${SUBDOMAIN:-test}.headers.accessControlAllowCredentials=true + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.explorer.lichess.app`) && PathPrefix(`/import`) + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.priority=200 + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.middlewares=block-import-${SUBDOMAIN:-test} + - traefik.http.routers.lila-explorer-blocked-${SUBDOMAIN:-test}.service=lila-explorer-${SUBDOMAIN:-test} + - traefik.http.middlewares.block-import-${SUBDOMAIN:-test}.ipallowlist.sourcerange=192.0.2.1/32 + + lila_fishnet: + image: ghcr.io/lichess-org/lila-fishnet:latest + environment: + - REDIS_HOST=redis + # - HTTP_API_LOGGER=true + networks: + - lila + + fishnet_play: + image: niklasf/fishnet:master + environment: + - ENDPOINT=http://lila_fishnet:9665/fishnet + - MAX_BACKOFF=5 + - STATS_FILE=/stats.json + networks: + - lila + + fishnet_analysis: + image: niklasf/fishnet:master + environment: + - ENDPOINT=http://lila:9663/fishnet + - MAX_BACKOFF=5 + - STATS_FILE=/stats.json + networks: + - lila + + lila_gif: + image: ghcr.io/lichess-org/lila-gif:latest + entrypoint: /usr/local/bin/lila-gif --bind 0.0.0.0:6175 + networks: + - lila + + lila_push: + image: ghcr.io/lichess-org/lila-push:latest + entrypoint: /usr/local/bin/lila-push --vapid /app/private.pem --vapid-subject mailto:contact@lichess.org --bind 0.0.0.0:9054 + environment: + - PUSH_LOG=debug + volumes: + - /data/lila-preview/lila-push/private.pem:/app/private.pem:ro + networks: + - lila + + lila_db_seed: + image: ghcr.io/lichess-org/lila-db-seed:latest + environment: + - USER_SEED_PASSWORD=${USER_SEED_PASSWORD:-password} + networks: + - lila + deploy: + restart_policy: + condition: none + + picfit: + image: thoas/picfit:0.16.1 + environment: + - PICFIT_CONFIG_PATH=/mnt/config.json + volumes: + - ./conf/picfit.json:/mnt/config.json + networks: + - lila + + mailpit: + image: axllent/mailpit:latest + environment: + - MP_WEBROOT=mailpit + - MP_MAX_AGE=1h + networks: + - frontend + - lila + labels: + - traefik.enable=true + - traefik.docker.network=frontend + - traefik.http.services.lila-mailpit-${SUBDOMAIN:-test}.loadbalancer.server.port=8025 + - traefik.http.routers.lila-mailpit-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.lichess.app`) && PathPrefix(`/mailpit`) + - traefik.http.routers.lila-mailpit-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-mailpit-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-mailpit-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-mailpit-${SUBDOMAIN:-test}.priority=100 + + mongo_express: + image: mongo-express:1-20-alpine3.19 + environment: + - ME_CONFIG_BASICAUTH=false + - ME_CONFIG_MONGODB_SERVER=mongodb + - ME_CONFIG_SITE_BASEURL=/mongodb + depends_on: + - mongodb + networks: + - frontend + - lila + labels: + - traefik.enable=true + - traefik.docker.network=frontend + - traefik.http.services.lila-mongo-express-${SUBDOMAIN:-test}.loadbalancer.server.port=8081 + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.rule=Host(`preview.${SUBDOMAIN:-test}.lichess.app`) && PathPrefix(`/mongodb`) + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.entrypoints=websecure + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.tls=true + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.tls.certresolver=myresolver + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.middlewares=authentik@file + - traefik.http.routers.lila-mongo-express-${SUBDOMAIN:-test}.priority=100 + +volumes: + lila-assets-data: + openingexplorer-data: + external: true + +secrets: + lila_preview_firebase_service_account: + external: true + +networks: + frontend: + external: true + lila: + driver: overlay + # driver: bridge diff --git a/stacks/lila-preview/conf/Caddyfile b/stacks/lila-preview/conf/Caddyfile new file mode 100644 index 00000000..e583c5b6 --- /dev/null +++ b/stacks/lila-preview/conf/Caddyfile @@ -0,0 +1,51 @@ +:80 + +log + +@trailing_slash { + path_regexp reTrailingSlash ^/(.+)/$ +} +redir @trailing_slash /{re.reTrailingSlash.1} permanent + +handle_path /oops/* { + rewrite * /public/oops{path} + reverse_proxy lila_assets:80 +} + +# for /oops/font.html +handle_path /font/* { + rewrite * /public/font{path} + reverse_proxy lila_assets:80 +} + +handle_path /display* { + rewrite * /display + reverse_proxy picfit:3001 +} + +handle_path /.well-known/* { + rewrite * /lichess-org/lichess-org.github.io/refs/heads/preview/.well-known{uri} + reverse_proxy https://raw.githubusercontent.com { + header_up Host raw.githubusercontent.com + } + header Content-Type application/json +} + +@websockets { + header Connection *Upgrade* + header Upgrade websocket +} + +reverse_proxy @websockets lila_ws:9664 { + header_up Origin {$LILA_URL} +} + +reverse_proxy lila:9663 { + header_up Host {$LILA_DOMAIN} + header_up Origin {$LILA_URL} + + # allow CORS for requests from web client on lichess.org/api + header_down Access-Control-Allow-Origin "*" + + header_down Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0" +} diff --git a/stacks/lila-preview/conf/lila.conf b/stacks/lila-preview/conf/lila.conf new file mode 100644 index 00000000..2ef97e58 --- /dev/null +++ b/stacks/lila-preview/conf/lila.conf @@ -0,0 +1,47 @@ +include "base" +include "version" + +user.password.bpass.secret = "9qEYN0ThHer1KWLNekA76Q==" + +net.site.name = ${?LILA_SITE_NAME} +net.domain = ${?LILA_DOMAIN} +net.socket.domains = [ ${?LILA_DOMAIN} ] +net.asset.base_url = ${?LILA_URL} +net.base_url = ${?LILA_URL} +net.email = "contact@example.com" +net.stage.banner = true +net.ratelimit = false + +mongodb.uri = "mongodb://mongodb?appName=lila" +redis.uri = "redis://redis" + +explorer.internal_endpoint = "http://openingexplorer:9002" +explorer.endpoint = ${?LILA_EXPLORER_ENDPOINT} + +game.gifUrl = "http://lila_gif:6175" + +search.enabled = false +search.endpoint = "http://lila_search_app:9673" + +memo.picfit.endpointGet = ${?LILA_URL} +memo.picfit.endpointPost = "http://picfit:3001" + +push.web.url = "http://lila_push:9054" +push.web.vapid_public_key = "BKLo08qJgT9tmfl1dgFpvh5l-Dd17cpuqJ_ZWP-_mcfPjPns89Zjg3W49rrQR_AQJYzn4arFPiSb4_k0HM7NACA" +push.firebase.mobile.url = "https://fcm.googleapis.com/v1/projects/lichess-preview/messages:send" +push.firebase.mobile.jsonPath = "/run/secrets/lila_preview_firebase_service_account" + +mailer.primary.mock = false +mailer.primary.tls = false +mailer.primary.host = "mailpit" +mailer.primary.port = 1025 +mailer.primary.sender = "lichess.org " +security.email_confirm.enabled = true + +plan.stripe.keys.public = "pk_test_123" +plan.stripe.keys.secret = "sk_test_123" +plan.payPal.keys.public = "sb" + +zulip.domain = ${?ZULIP_DOMAIN} +zulip.user = ${?ZULIP_USER} +zulip.pass = ${?ZULIP_PASS} diff --git a/stacks/lila-preview/conf/picfit.json b/stacks/lila-preview/conf/picfit.json new file mode 100644 index 00000000..018021f5 --- /dev/null +++ b/stacks/lila-preview/conf/picfit.json @@ -0,0 +1,13 @@ +{ + "debug": true, + "port": 3001, + "options": { + "enable_upload": true + }, + "storage": { + "src": { + "type": "fs", + "location": "/uploads/" + } + } +} diff --git a/stacks/lila-preview/scripts/update-asset-volume.sh b/stacks/lila-preview/scripts/update-asset-volume.sh new file mode 100755 index 00000000..d6ca3379 --- /dev/null +++ b/stacks/lila-preview/scripts/update-asset-volume.sh @@ -0,0 +1,14 @@ +#!/bin/sh -e + +echo "⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️⚪️" + +echo "Updating assets volume with latest from lila-assets image..." +echo "This is how the static files are updated on the lila-server container." +echo "This script is necessary because lila reads the manifest from disk and needs the files." + +rm -rf /assets/* +cp -r /usr/share/nginx/html/public/* /assets/ + +echo "Done!" + +echo "🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢🟢" From fbe2158821f00805cf95668fe8d5650247286918 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 20 Aug 2026 10:47:21 -0400 Subject: [PATCH 2/4] tweaks --- stacks/lila-preview/compose.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/stacks/lila-preview/compose.yml b/stacks/lila-preview/compose.yml index b8734968..27eedd41 100644 --- a/stacks/lila-preview/compose.yml +++ b/stacks/lila-preview/compose.yml @@ -76,7 +76,6 @@ services: openingexplorer: image: ghcr.io/lichess-org/lila-openingexplorer:latest - restart: unless-stopped environment: - LILA_URL=https://preview.${SUBDOMAIN:-test}.lichess.app - EXPLORER_BEARER=lip_openingexplorer-${USER_SEED_PASSWORD:-password} @@ -114,7 +113,7 @@ services: - lila fishnet_play: - image: niklasf/fishnet:master + image: niklasf/fishnet:latest environment: - ENDPOINT=http://lila_fishnet:9665/fishnet - MAX_BACKOFF=5 @@ -123,7 +122,7 @@ services: - lila fishnet_analysis: - image: niklasf/fishnet:master + image: niklasf/fishnet:latest environment: - ENDPOINT=http://lila:9663/fishnet - MAX_BACKOFF=5 From dc5ebc8437e8ce83d0b40f7732c2d1e29e5d243f Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 20 Aug 2026 10:49:33 -0400 Subject: [PATCH 3/4] cleanup networks --- stacks/lila-preview/compose.yml | 40 +++++++-------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/stacks/lila-preview/compose.yml b/stacks/lila-preview/compose.yml index 27eedd41..017bb15f 100644 --- a/stacks/lila-preview/compose.yml +++ b/stacks/lila-preview/compose.yml @@ -9,7 +9,7 @@ services: - ./conf/Caddyfile:/etc/caddy/Caddyfile networks: - frontend - - lila + - default labels: - traefik.enable=true - traefik.docker.network=frontend @@ -44,16 +44,12 @@ services: - lila-assets-data:/lila/public:ro secrets: - lila_preview_firebase_service_account - networks: - - lila lila_assets: image: ghcr.io/lichess-org/lila-assets:${LILA_ASSETS_TAG:-latest} volumes: - lila-assets-data:/assets:rw - ./scripts/update-asset-volume.sh:/docker-entrypoint.d/50-update-assets.sh:ro - networks: - - lila lila_ws: image: ghcr.io/lichess-org/lila-ws:${LILA_WS_TAG:-latest} @@ -61,18 +57,12 @@ services: - CONFIG_FORCE_csrf.origin=https://preview.${SUBDOMAIN:-test}.lichess.app - CONFIG_FORCE_mongo_uri=mongodb://mongodb:27017/lichess?appName=lila-ws - CONFIG_FORCE_redis.uri=redis://redis - networks: - - lila mongodb: image: mongo:8.2-noble - networks: - - lila redis: image: redis:8 - networks: - - lila openingexplorer: image: ghcr.io/lichess-org/lila-openingexplorer:latest @@ -83,7 +73,7 @@ services: - openingexplorer-data:/app/_db networks: - frontend - - lila + - default labels: - traefik.enable=true - traefik.docker.network=frontend @@ -109,8 +99,6 @@ services: environment: - REDIS_HOST=redis # - HTTP_API_LOGGER=true - networks: - - lila fishnet_play: image: niklasf/fishnet:latest @@ -118,8 +106,6 @@ services: - ENDPOINT=http://lila_fishnet:9665/fishnet - MAX_BACKOFF=5 - STATS_FILE=/stats.json - networks: - - lila fishnet_analysis: image: niklasf/fishnet:latest @@ -127,15 +113,11 @@ services: - ENDPOINT=http://lila:9663/fishnet - MAX_BACKOFF=5 - STATS_FILE=/stats.json - networks: - - lila - + lila_gif: image: ghcr.io/lichess-org/lila-gif:latest entrypoint: /usr/local/bin/lila-gif --bind 0.0.0.0:6175 - networks: - - lila - + lila_push: image: ghcr.io/lichess-org/lila-push:latest entrypoint: /usr/local/bin/lila-push --vapid /app/private.pem --vapid-subject mailto:contact@lichess.org --bind 0.0.0.0:9054 @@ -143,27 +125,21 @@ services: - PUSH_LOG=debug volumes: - /data/lila-preview/lila-push/private.pem:/app/private.pem:ro - networks: - - lila lila_db_seed: image: ghcr.io/lichess-org/lila-db-seed:latest environment: - USER_SEED_PASSWORD=${USER_SEED_PASSWORD:-password} - networks: - - lila deploy: restart_policy: condition: none - + picfit: image: thoas/picfit:0.16.1 environment: - PICFIT_CONFIG_PATH=/mnt/config.json volumes: - ./conf/picfit.json:/mnt/config.json - networks: - - lila mailpit: image: axllent/mailpit:latest @@ -172,7 +148,7 @@ services: - MP_MAX_AGE=1h networks: - frontend - - lila + - default labels: - traefik.enable=true - traefik.docker.network=frontend @@ -193,7 +169,7 @@ services: - mongodb networks: - frontend - - lila + - default labels: - traefik.enable=true - traefik.docker.network=frontend @@ -217,6 +193,6 @@ secrets: networks: frontend: external: true - lila: + default: driver: overlay # driver: bridge From 0a15d0cd3f41088406b056fffa584f1f603577c5 Mon Sep 17 00:00:00 2001 From: Trevor Fitzgerald Date: Thu, 20 Aug 2026 11:25:04 -0400 Subject: [PATCH 4/4] yaml anchor for public networks --- stacks/lila-preview/compose.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/stacks/lila-preview/compose.yml b/stacks/lila-preview/compose.yml index 017bb15f..a5cdba3c 100644 --- a/stacks/lila-preview/compose.yml +++ b/stacks/lila-preview/compose.yml @@ -1,3 +1,7 @@ +x-public-networks: &public-networks + - frontend + - default + services: caddy: @@ -7,9 +11,7 @@ services: - LILA_URL=https://preview.${SUBDOMAIN:-test}.lichess.app volumes: - ./conf/Caddyfile:/etc/caddy/Caddyfile - networks: - - frontend - - default + networks: *public-networks labels: - traefik.enable=true - traefik.docker.network=frontend @@ -71,9 +73,7 @@ services: - EXPLORER_BEARER=lip_openingexplorer-${USER_SEED_PASSWORD:-password} volumes: - openingexplorer-data:/app/_db - networks: - - frontend - - default + networks: *public-networks labels: - traefik.enable=true - traefik.docker.network=frontend @@ -146,9 +146,7 @@ services: environment: - MP_WEBROOT=mailpit - MP_MAX_AGE=1h - networks: - - frontend - - default + networks: *public-networks labels: - traefik.enable=true - traefik.docker.network=frontend @@ -167,9 +165,7 @@ services: - ME_CONFIG_SITE_BASEURL=/mongodb depends_on: - mongodb - networks: - - frontend - - default + networks: *public-networks labels: - traefik.enable=true - traefik.docker.network=frontend