phantom-ship + vps-relay: add scuttle service + vhost

scuttle.service mirrors shelfish — fastapi/uvicorn/httpx/python-telegram-bot
plus websockets, runs uvicorn --host :: --port 8082, DB at
~/.local/share/scuttle/scuttle.db (tmpfiles rule + zt+ firewall port
added alongside shelfish's).

vps-relay gets a fourth virtualHost (scuttle.dannydannydanny.me)
reverse-proxying to phantom-ship over ZeroTier. WebSocket upgrade is
transparent under Caddy's reverse_proxy.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Danny 2026-05-03 07:26:17 +02:00
parent 4d2e40455d
commit 6d9ccf5d4e
2 changed files with 43 additions and 4 deletions

View file

@ -48,10 +48,11 @@ in
}; };
networking.firewall.trustedInterfaces = [ "enp0s31f6" ]; networking.firewall.trustedInterfaces = [ "enp0s31f6" ];
# Shelfish HTTP (8081) is reachable only over the ZeroTier mesh — the # Shelfish (:8081) and Scuttle (:8082) are reachable only over the
# vps-relay Caddy reverse-proxies into it. Same pattern as sunken-ship's # ZeroTier mesh — the vps-relay Caddy reverse-proxies into them. Same
# bbbot. Not in global allowedTCPPorts, so the WAN side stays closed. # pattern as sunken-ship's bbbot. Not in global allowedTCPPorts, so
networking.firewall.interfaces."zt+".allowedTCPPorts = [ 8081 ]; # the WAN side stays closed.
networking.firewall.interfaces."zt+".allowedTCPPorts = [ 8081 8082 ];
hardware.enableRedistributableFirmware = true; # iwlwifi (Intel 8260) + GPU + BT firmware hardware.enableRedistributableFirmware = true; # iwlwifi (Intel 8260) + GPU + BT firmware
@ -171,6 +172,7 @@ in
"d /etc/openclaw 0775 root openclaw - -" "d /etc/openclaw 0775 root openclaw - -"
"d /var/lib/openclaw/repos 0750 openclaw openclaw - -" "d /var/lib/openclaw/repos 0750 openclaw openclaw - -"
"d /home/danny/.local/share/shelfish 0755 danny users - -" "d /home/danny/.local/share/shelfish 0755 danny users - -"
"d /home/danny/.local/share/scuttle 0755 danny users - -"
]; ];
# Hara Gmail MCP server (path 1: IMAP+SMTP). Replaced by an OAuth2 # Hara Gmail MCP server (path 1: IMAP+SMTP). Replaced by an OAuth2
@ -291,6 +293,38 @@ in
}; };
}; };
# Scuttle — topdown tilt-to-move multiplayer Mini App.
# Same vps-relay-fronted ZT path as shelfish; binds to :: so the
# ZeroTier IPv6 address can reach it.
# Code rsync'd from ~/python-projects/26_scuttle/ to /home/danny/scuttle/
# DB at ~/.local/share/scuttle/scuttle.db.
systemd.services.scuttle = let
pythonEnv = pkgs.python3.withPackages (ps: with ps; [
fastapi
uvicorn
httpx
websockets
python-telegram-bot
]);
in {
description = "Scuttle FastAPI + WebSocket game server";
after = [ "network-online.target" ];
wants = [ "network-online.target" ];
wantedBy = [ "multi-user.target" ];
path = [ pythonEnv ];
environment = {
SHIPYARD_BOT_TOKEN_FILE = "/home/danny/.secrets/telegram-bot-token-shipyard";
SC_DB_PATH = "/home/danny/.local/share/scuttle/scuttle.db";
};
serviceConfig = {
WorkingDirectory = "/home/danny/scuttle";
ExecStart = "${pythonEnv}/bin/python -m uvicorn server:app --host :: --port 8082";
Restart = "on-failure";
RestartSec = 10;
User = "danny";
};
};
# Auto-rebuild service/timer + safe.directory provided by the # Auto-rebuild service/timer + safe.directory provided by the
# shared dotfiles-rebuild NixOS module (see nixos/modules/dotfiles-rebuild.nix). # shared dotfiles-rebuild NixOS module (see nixos/modules/dotfiles-rebuild.nix).
} }

View file

@ -105,6 +105,11 @@
"shelfish.dannydannydanny.me".extraConfig = '' "shelfish.dannydannydanny.me".extraConfig = ''
reverse_proxy http://[fdd5:53a2:de33:d269:6499:936c:48a:bbdc]:8081 reverse_proxy http://[fdd5:53a2:de33:d269:6499:936c:48a:bbdc]:8081
''; '';
# Scuttle — same backend, different port. WebSocket upgrade is
# transparent under reverse_proxy.
"scuttle.dannydannydanny.me".extraConfig = ''
reverse_proxy http://[fdd5:53a2:de33:d269:6499:936c:48a:bbdc]:8082
'';
}; };
}; };