From 00307cda9c3efeb07069c233b4de42d8839dcc50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Di=C3=B3genes=20Castro?= Date: Fri, 17 Jul 2026 01:48:36 +0000 Subject: [PATCH] feat: add COLLIE_SKIP_SERVE env var to bypass tailscale serve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds COLLIE_SKIP_SERVE=1 support to collie-ctl.sh so the bridge can run behind a reverse proxy (Caddy, Nginx, etc.) without triggering tailscale serve. The bridge stays on 127.0.0.1 only — your proxy handles TLS, auth, and public access. - cmd_serve/cmd_unserve: early return when COLLIE_SKIP_SERVE=1 - print_status_banner: shows 'proxy' instead of 'tailnet' when skipped - cmd_status: skips tailscale serve status check when skipped - .env.example: documents the new variable - Version bumped to 0.12.0 (minor — new feature) --- .env.example | 4 ++++ CHANGELOG.md | 5 +++++ herdr-plugin.toml | 2 +- package.json | 2 +- scripts/collie-ctl.sh | 20 ++++++++++++++++++-- web/package.json | 2 +- 6 files changed, 30 insertions(+), 5 deletions(-) diff --git a/.env.example b/.env.example index 21e1158..332ddfa 100644 --- a/.env.example +++ b/.env.example @@ -12,6 +12,10 @@ COLLIE_HOST=127.0.0.1 # (plain HTTP on :$COLLIE_PORT — for Headscale / `.internal` domains without HTTPS certs; then set # COLLIE_PUBLIC_HOSTS below, and note PWA install + Web Push need a secure context). # COLLIE_SERVE_MODE=https +# Skip tailscale serve entirely (set to 1 when using a reverse proxy like Caddy/Nginx). +# The bridge stays on 127.0.0.1 only — your proxy handles TLS, auth, and public access. +# With this enabled, set COLLIE_ALLOWED_ORIGINS and COLLIE_PUBLIC_HOSTS to match your proxy's hostname. +# COLLIE_SKIP_SERVE=1 # --- Herdr connection --- # Usually injected by the systemd unit; override only if your socket is elsewhere. diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fa6532..deb55aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,11 @@ All notable changes to Collie are recorded here. The format follows `version` in `herdr-plugin.toml`, `package.json`, and `web/package.json` (enforced by `scripts/check-version.sh`). See [`CLAUDE.md`](./CLAUDE.md) → *Versioning* for the bump policy. +## [0.12.0] - 2026-07-17 + +### Added +- `COLLIE_SKIP_SERVE=1` env var to disable tailscale serve entirely — bridge stays on loopback only, ideal for deployments behind a reverse proxy (Caddy, Nginx, etc.) + ## [0.11.0] - 2026-07-15 ### Added diff --git a/herdr-plugin.toml b/herdr-plugin.toml index 9749c5c..0662448 100644 --- a/herdr-plugin.toml +++ b/herdr-plugin.toml @@ -1,6 +1,6 @@ id = "herdr.collie" name = "Collie" -version = "0.11.0" +version = "0.12.0" min_herdr_version = "0.7.0" description = "Mobile web UI to monitor and reply to your agent herd, served over Tailscale" platforms = ["linux", "macos"] diff --git a/package.json b/package.json index 9b297f2..f5db2fd 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "collie", - "version": "0.11.0", + "version": "0.12.0", "private": true, "license": "MIT", "description": "Collie — a mobile web UI to monitor and reply to your Herdr agent herd over Tailscale", diff --git a/scripts/collie-ctl.sh b/scripts/collie-ctl.sh index 88763a3..754f14d 100755 --- a/scripts/collie-ctl.sh +++ b/scripts/collie-ctl.sh @@ -149,7 +149,11 @@ print_status_banner() { fi echo " service ${svc}" echo " local http://127.0.0.1:${PORT}" - echo " tailnet $(bridge_url)" + if [ "${COLLIE_SKIP_SERVE:-}" = "1" ]; then + echo " proxy (COLLIE_SKIP_SERVE=1 — use your reverse proxy)" + else + echo " tailnet $(bridge_url)" + fi echo } @@ -270,6 +274,10 @@ cmd_apply_update() { } cmd_serve() { + if [ "${COLLIE_SKIP_SERVE:-}" = "1" ]; then + echo "tailscale serve skipped (COLLIE_SKIP_SERVE=1) — bridge is on 127.0.0.1:${PORT} only" + return + fi command -v tailscale >/dev/null || { echo "note: tailscale not found; bridge is on 127.0.0.1:${PORT} only"; return; } local out="${CONFIG_DIR}/serve.out" if [ "$SERVE_MODE" = "http" ]; then @@ -293,6 +301,10 @@ cmd_serve() { # https:443 by default, or http:$PORT in http mode. Best-effort (|| true) so teardown is idempotent # when the mapping is already gone. cmd_unserve() { + if [ "${COLLIE_SKIP_SERVE:-}" = "1" ]; then + echo "tailscale serve skipped (COLLIE_SKIP_SERVE=1) — nothing to unserve" + return + fi command -v tailscale >/dev/null || { echo "note: tailscale not found; no serve mapping to remove"; return; } if [ "$SERVE_MODE" = "http" ]; then tailscale serve --http="$PORT" off >/dev/null 2>&1 || true @@ -305,7 +317,11 @@ cmd_unserve() { cmd_status() { print_status_banner - echo " serve config:"; tailscale serve status 2>/dev/null | sed 's/^/ /' || true + if [ "${COLLIE_SKIP_SERVE:-}" = "1" ]; then + echo " serve config: skipped (COLLIE_SKIP_SERVE=1)" + else + echo " serve config:"; tailscale serve status 2>/dev/null | sed 's/^/ /' || true + fi } cmd_logs() { diff --git a/web/package.json b/web/package.json index 624b1a4..4922674 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "collie-web", - "version": "0.11.0", + "version": "0.12.0", "private": true, "license": "MIT", "type": "module",