From 9190f897a3abb9a171a11846fad782e0f22778de Mon Sep 17 00:00:00 2001 From: kami Date: Sat, 1 Aug 2026 01:27:11 +0400 Subject: [PATCH] Add a locked-down maven. block to the nginx template (#354) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The template's wildcard `listen 80` with no ACL was fixed in 50cc17f, but it still only covered nexus/praxis/hexis. mavweb — the one service in the set that serves an RCE surface (POST /tools defines argv internal/tool executes) — had no block at all, so anyone wiring it up wrote their own, which is how the wildcard got there the first time. Adds a maven.kvmx.ru server with the same wg+LAN bind and allow/deny, proxying 127.0.0.1:9201, with the WebSocket upgrade /ws needs, a 32m body limit for push-to-talk PCM, and a 300s read timeout because an LLM turn on the iGPU is slow. Also records in deploy/ecosystem/docker-compose.yml that the sibling `build:` paths pin nothing and ship the sibling working tree, with the command to check what is about to be deployed. The stale public DNS records (item 2) are outside the repo. Verified: nginx -t on the template inside a minimal http{} accepts it. --- deploy/ecosystem/docker-compose.yml | 12 +++++++ deploy/ecosystem/nginx.conf | 51 +++++++++++++++++++++++++++-- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/deploy/ecosystem/docker-compose.yml b/deploy/ecosystem/docker-compose.yml index a49082e..0cca3ec 100644 --- a/deploy/ecosystem/docker-compose.yml +++ b/deploy/ecosystem/docker-compose.yml @@ -8,6 +8,18 @@ # # Maven's own compose joins this same network (add `ecosystem` as an external # network there) to reach nexus:9740 / praxis:8989 / hexis:9741 directly. +# +# NO RELEASE PINNING (Vikunja #354): each `build:` below points at a sibling +# WORKING TREE, so `up --build` ships whatever is checked out there, including +# uncommitted edits. Before bringing this up, check what you are about to +# deploy: +# +# for r in nexus praxis hexis; do git -C ../../../$r status --short; \ +# git -C ../../../$r log -1 --oneline; done +# +# The host nginx that fronts these is deploy/ecosystem/nginx.conf — it binds +# the wg and LAN addresses only, with allow/deny. Keep it that way: none of +# these containers has auth of its own. name: ecosystem services: diff --git a/deploy/ecosystem/nginx.conf b/deploy/ecosystem/nginx.conf index a511b03..7e84902 100644 --- a/deploy/ecosystem/nginx.conf +++ b/deploy/ecosystem/nginx.conf @@ -1,6 +1,7 @@ -# Reverse-proxy the three sibling admin UIs. Drop into your nginx sites (or the -# nginx-panel app) and reload. Assumes the compose publishes each service on -# 127.0.0.1:. Add TLS (certbot / your existing cert block) per server. +# Reverse-proxy Maven's own web UI plus the three sibling admin UIs. Drop into +# your nginx sites (or the nginx-panel app) and reload. Assumes the compose +# publishes each service on 127.0.0.1:. Add TLS (certbot / your existing +# cert block) per server. # # NOTE: hexis. previously pointed at the MCP tool — repoint that # elsewhere first (the app now owns hexis.*). @@ -12,6 +13,50 @@ # Do NOT "fix" a failed bind by reverting to `listen 80` (all interfaces) — # that removes the only access control these containers have. +# maven. → mavweb (docker-compose.yml publishes it on 127.0.0.1:9201). +# Same bind + ACL as the siblings, and for a stronger reason: mavweb serves +# POST /tools, which defines argv that internal/tool EXECUTES, plus POST +# /routines, /api/revert and /api/chat (Vikunja #317). Without +# -webauthn-origin/-webauthn-rpid mavweb has no auth of its own, so this block +# is the auth. If you add TLS and a basic-auth/oauth2-proxy layer, keep the +# allow/deny anyway — belt and braces on an RCE surface. +# +# WebSocket upgrade matters here: /ws carries push-to-talk audio, so the +# Upgrade/Connection headers below are required, not decoration. The map keeps +# `Connection: upgrade` off plain requests; it sits in the http context, which +# is where sites-available files are included — if your nginx already defines +# $connection_upgrade, drop this block. +map $http_upgrade $connection_upgrade { + default upgrade; + '' close; +} + +server { + listen 10.42.0.1:80; + listen 192.168.1.104:80; + server_name maven.kvmx.ru; + + allow 10.42.0.0/24; + allow 192.168.1.0/24; + deny all; + + # push-to-talk uploads raw PCM; the default 1m is enough for a short + # utterance but not for a long one. + client_max_body_size 32m; + + location / { + proxy_pass http://127.0.0.1:9201; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection $connection_upgrade; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 300s; # an LLM turn can take minutes on the iGPU + } +} + server { listen 10.42.0.1:80; listen 192.168.1.104:80;