Bind to all interfaces by default and add one-command uninstall script #12
Loading…
Reference in a new issue
No description provided.
Delete branch "feature/11_bind_default_and_uninstall"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #11
Что сделано
Пункт 2 — доступ с Windows-машины (
BIND=0.0.0.0)deploy/install.sh: дефолтBINDизменён на0.0.0.0; токенAUTH_TOKENдля сетевого режима генерируется автоматически при первой установке (защита от «голого» сетевого доступа уже есть в конфиге сервиса).http://<IP-машины>:8787(IP определяется автоматически) плюс локальный127.0.0.1; предупреждение про сетевой доступ заменено на честное «вход защищён AUTH_TOKEN, в интернет порт не пробрасывать»./etc/default/pi-web-monitor, а не из переменных текущего запуска.Пункт 3 — удаление
deploy/uninstall.sh(«одна команда», по аналогии с установкой): останавливает и удаляет systemd-юнит, удаляет код/opt/watcherenish(только если это клон именно watcherenish — проверка поorigin) и конфиг/etc/default/pi-web-monitor. Node.js/git/curl и данные~/.piне трогает. Идемпотентен.uninstall.shтой же ветки).Пункт 1 («зачем TUI на Linux-машине») — правок не требует, объяснение в комментарии к issue: полноценного терминального интерфейса на машине нет и не было — это headless веб-сервис; «объёмный» интерфейс видит только браузер клиента, сама машина остаётся поставщиком данных.
По ходу ревью
0e4f5bb— CORS открыт по умолчанию (по решению заказчика):ALLOWED_ORIGINSне задан → агент отвечаетAccess-Control-Allow-Originлюбому origin на/api/*(токен остаётся обязателен); задан → белый список.6946ef2— все скрипты и README переведены наhttps://forgejo.lamanshe.ru.6d692f1+eeb5e70— установщик больше не молчит про ветку: код ставится изmain(даже если сам скрипт взят из ветки PR — раньше это путало), а ветку можно передать первым аргументом илиBRANCH=…; явная ветка проверяетсяgit ls-remote, в сводке — напоминание вернуться наmainпосле проверки PR.Как проверить
Тесты
npm test— 33/33 зелёные.uninstall.shпрогнан в песочнице (фейковыеINSTALL_DIR/ENV_FILE/SERVICE_NAME): клон watcherenish и конфиг удаляются, чужой git-репозиторий не трогается, повторный запуск чистый, без root скрипт отказывается работать.install.shпрогнан в песочнице на 4 сценария: ветка аргументом (клон в origin/ветку PR), ветка черезBRANCH=…, без аргументов (ставитmain+ подсказка), несуществующая ветка (внятная ошибка до каких-либо изменений)."Агент доступен, но браузер заблокировал запрос (CORS). Добавьте адрес этого хаба в ALLOWED_ORIGINS на агенте." - ошибка при подключении агента.
Разобрался: это не сбой, а штатная защита агента. По умолчанию агент работает в same-origin режиме (CORS opt-in, сделано в #5): он не отдаёт CORS-заголовки никому, поэтому браузер на странице хаба блокирует кросс-доменный запрос к
http://<агент>:8787/api/health. Сообщение «Добавьте адрес этого хаба в ALLOWED_ORIGINS на агенте» — ровно об этом.Что сделать на машине агента:
/etc/default/pi-web-monitorустановить: Origin указывается точно в том виде, в каком он в адресной строке браузера: схема + host + порт, без завершающего слэша. Несколько hub-ов — через запятую.sudo systemctl restart pi-web-monitor.Удобно: адрес хаба именно в этом формате печатается в итоговой сводке установки хаба (
http://<IP>:8787) — можно скопировать оттуда.По безопасности:
ALLOWED_ORIGINSлишь разрешает браузеру указанного origin читать ответы агента; bearer-токен обязателен для всех/api/*как и раньше. Порт агента наружу в интернет по-прежнему открывать не стоит.Если после этого ошибка осталась, проверьте:
curl -s -D - -o /dev/null -H "Origin: http://<IP-хаба>:8787" http://127.0.0.1:8787/api/health— в ответе должен появитьсяAccess-Control-Allow-Origin.Если хотите, могу добавить в
install.shагента опциональный вопрос «адрес хаба для CORS» (сразу пропишетALLOWED_ORIGINSв конфиг) — скажите, внесу в эту же ветку.А можно ли разрешить всем? У нас ведь есть AUTH токен - я думаю этого достаточно.
Сделал в коммите
0e4f5bb(веткаfeature/11_bind_default_and_uninstall, тот же PR).По безопасности: да, токена достаточно. Все
/api/*и так требуют Bearer-токен, поэтому открытый CORS не позволяет сторонним сайтам читать данные — без токена они получают 401. CORS управляет лишь тем, ч какой origin браузер разрешит JS читать ответы.1. Можно ли это сделать сразу на машине? Ничего настраивать не нужно: теперь это поведение по умолчанию. Достаточно обновить код и перезапустить сервис:
Установщик сам подтянет ветку (
git reset --hard origin/…), отрестартитpi-web-monitor, конфиг в/etc/default/pi-web-monitorне перетрёт. После обновления подключение агента из хаба заработает без правки конфига.2. Поведение по умолчанию:
ALLOWED_ORIGINSне задан (дефолт) → CORS открыт: агент отвечаетAccess-Control-Allow-Origin: <Origin>любому origin на/api/*.ALLOWED_ORIGINSзадан → работает как белый список: только перечисленные origin (старое поведение, для строгих окружений).Обновил: сервер (
src/server.js), README (переменная + раздел «Безопасность»), подсказку об ошибке в UI хаба и комментарий в шаблоне конфига установщика.npm test— 33/33 зелёные (включая новые тесты на allow-all и на то, что явный список продолжает отсекать чужие origin).Я попробовал без удаления - не заработало. Решил переустановить - вот такие ошибки:
root@developer-agent:
# curl -fsSL http://10.10.1.7:3000/forgejo-admin/watcherenish/raw/branch/main/deploy/uninstall.sh | sudo bash# curl -fsSL http://forgejo.lamanshe.ru/forgejo-admin/watcherenish/raw/branch/main/deploy/uninstall.sh | sudo bashcurl: (22) The requested URL returned error: 404
root@developer-agent:
curl: (22) The requested URL returned error: 404
root@developer-agent:
# curl -fsSL https://forgejo.lamanshe.ru/forgejo-admin/watcherenish/raw/branch/main/deploy/uninstall.sh | sudo bash# ping forgejo.lamanshe.rucurl: (22) The requested URL returned error: 404
root@developer-agent:
P.S. я настроил домен на forgejo.lamanshe.ru, теперь это будет https://forgejo.lamanshe.ru вместо http://10.10.1.7:3000
Разобрался по пунктам:
1. Почему 404.
uninstall.sh— новый файл из этого PR, он есть только в веткеfeature/11_bind_default_and_uninstall; вmainон попадёт после мержа. Команды из README (и из моего прошлого комментария) сbranch/mainдля uninstall сработают только после того, как PR уйдёт в main. Сейчас удалять нужно из ветки PR:(проверил: по обоим адресам — и по IP, и по домену — этот URL отдаёт 200; 404 был именно из-за ветки
main, домен ни при чём).2. Новый домен — принято, перевёл всё на
https://forgejo.lamanshe.ru(коммит6946ef2в этой же ветке): дефолтныйREPO_URLвdeploy/install.shиdeploy/uninstall.sh, команды установки/удаления иgit cloneв README. Старый адресhttp://10.10.1.7:3000при этом продолжает работать, существующие установки не ломаются.3. «Попробовал без удаления — не заработало». Скорее всего дело в конфиге: если ранее по моей инструкции в
/etc/default/pi-web-monitorвыставлялсяALLOWED_ORIGINS=<адрес хаба>— этот белый список теперь блокирует новый origin хаба (https://forgejo.lamanshe.ru…). С нового дефолта (CORS открыт всем, токен остаётся обязательным) достаточно убрать строкуALLOWED_ORIGINSиз конфига (или обновить в ней адрес хаба) и перезапустить сервис. Порядок обновления без удаления:Если после этого подключение всё равно не проходит — пришлите вывод последней команды и содержимое
/etc/default/pi-web-monitor(токен можно затереть), посмотрю.Сводку в теле PR обновил под новый домен.
════════════════════════════════════════════════════════════
УСТАНОВКА ВЫПОЛНЕНА УСПЕШНО
Сервис: pi-web-monitor (systemd, включён автозапуск)
Код: /opt/watcherenish (ветка main)
Адрес: http://10.10.1.21:8787 (из локальной сети)
Локально: http://127.0.0.1:8787
Внимание: BIND=0.0.0.0 — UI доступен по сети, вход защищён AUTH_TOKEN;
пробрасывать порт в интернет не рекомендуется
Конфиг: /etc/default/pi-web-monitor (правки сохраняются при повторных установках)
AUTH_TOKEN: см. /etc/default/pi-web-monitor (не менялся)
Проверка: systemctl status pi-web-monitor
Удаление: curl -fsSL https://forgejo.lamanshe.ru/forgejo-admin/watcherenish/raw/branch/main/deploy/uninstall.sh | sudo bash
════════════════════════════════════════════════════════════
root@developer-agent:
/projects/forgejo/developer# systemctl restart pi-web-monitor/projects/forgejo/developer# curl -s -D - -o /dev/null -H "Origin: https://forgejo.lamanshe.ru" http://127.0.0.1:8787/api/healthroot@developer-agent:
HTTP/1.1 401 Unauthorized
Content-Type: application/json; charset=utf-8
Content-Length: 24
Cache-Control: no-store
Date: Sat, 26 Sep 2026 13:38:12 GMT
Connection: keep-alive
Keep-Alive: timeout=5
root@developer-agent:~/projects/forgejo/developer# cat /etc/default/pi-web-monitor
watcherenish / pi-web-monitor — configuration
Created by deploy/install.sh on 2026-09-26 17:14:45 +05.
This file is NOT overwritten on reinstall: manual edits persist.
PORT=8787
BIND=0.0.0.0
Bearer token for /api/*; generated automatically on first install
AUTH_TOKEN=***
SESSIONS_DIR=/root/.pi/agent/sessions
GATE_LOG=/var/log/pi-agent/gate.log
ACTIVE_SESSION_TTL_MIN=15
Optional overrides:
#ALLOWED_ORIGINS=http://192.168.0.204:8787
#GATE_LINE_REGEX=
root@developer-agent:~/projects/forgejo/developer#
Разобрался — код на машине обновился, но не до той ревизии.
Что произошло. В сводке видно:
Код: /opt/watcherenish (ветка main). Установщик по умолчанию ставит веткуmain, а правка «CORS открыт по умолчанию» (коммит0e4f5bb) есть только в ветке PRfeature/11_bind_default_and_uninstall— вmainона попадёт после мержа. Поэтому агент работает ещё на старом CORS-режиме (opt-in), где пустойALLOWED_ORIGINS= заголовки не выдаются, отсюда и 401 безAccess-Control-Allow-Origin.Кстати, сам факт
401— это нормально: без Bearer-токена/api/*всегда отвечает 401. Для проверки CORS нужен запрос с заголовком Origin и токеном — тогда в ответе появитсяAccess-Control-Allow-Origin:Как исправить сейчас — до мержа ставим код из ветки PR:
ALLOWED_ORIGINSу вас закомментирован — ничего в конфиге менять не нужно, после установки кода из ветки PR CORS будет открыт всем (токен останется обязателен). Подключение агента из хаба заработает без правок конфига. После мержа этого PR в main достаточно будет один раз переустановить из main — вернётесь на обычную ветку.Чтобы такая ситуация больше не путала, добавил в коммите
6d692f1предупреждение в сводку установки: если код ставится не изmain, установщик явно печатает жёлтую плашку «временная установка для проверки PR, после мержа переустановите из main».npm test— 33/33 зелёные.Если после установки из ветки PR подключение всё равно не пройдёт — пришлите вывод curl-команды выше, посмотрю дальше.
Не работает, я прям код скопировал из ветки в install.sh файл, чтобы точно взять его с твоей ветки, но все равно. Вот вывод:
root@developer-agent:/tmp# INSTALL_USER=root ./install.sh
[install] 1/7 Проверка окружения
[install] ✓ окружение: Linux + systemd, пользователь root, каталог /opt/watcherenish
[install] 2/7 Проверка Node.js (нужен >= 20)
[install] ✓ Node.js v24.21.0 уже установлен
[install] 3/7 Код: /opt/watcherenish (ветка main)
[install] ✓ код обновлён до origin/main (
6b9103b)[install] 4/7 Тесты (npm test)
✔ GET /api/summary: counters on fixtures dir (58.376211ms)
✔ GET /api/sessions: list sorted by mtime desc, search works (58.426287ms)
✔ GET /api/sessions/🆔 entries with previews (21.841421ms)
✔ GET /api/sessions/:id/messages: transcript for rendering (17.846806ms)
✔ GET /api/logs/gate: graceful when file missing (14.366368ms)
✔ GET /api/logs/gate: returns tail lines (19.504995ms)
✔ AUTH_TOKEN: api requires Bearer, 401 without/with-wrong token (28.10716ms)
✔ AUTH_TOKEN: static UI served without token, so user can enter it (7.013048ms)
✔ GET /api/health: 401 without/wrong token, 200 with correct token (8.343679ms)
✔ GET /api/health: works without AUTH_TOKEN, reports missing sessions dir as degraded (4.622355ms)
✔ CORS: allowed origin gets ACAO on GET, disallowed does not (5.060894ms)
✔ CORS: preflight OPTIONS answered with allow methods/headers for allowed origin (5.950541ms)
✔ CORS: without ALLOWED_ORIGINS no CORS headers even with Origin (same-origin mode) (3.438603ms)
✔ loadConfig: defaults without env (1.886643ms)
✔ loadConfig: reads all env keys (1.496785ms)
✔ loadConfig: BIND 0.0.0.0 without AUTH_TOKEN throws (0.652883ms)
✔ loadConfig: BIND 0.0.0.0 with AUTH_TOKEN is allowed (0.285444ms)
✔ loadConfig: ACTIVE_SESSION_TTL_MIN must be a positive number (0.407179ms)
✔ loadConfig: allowedOrigins defaults to empty list (same-origin mode) (1.829163ms)
✔ loadConfig: ALLOWED_ORIGINS is parsed into trimmed origin list (0.421218ms)
✔ tailFile: returns last N lines of a log (8.575904ms)
✔ tailFile: missing file -> error, no throw (3.480369ms)
✔ tailFile: no trailing newline handled (4.18277ms)
✔ parseSessionFile: normal session — header, entry count, tree links (16.906662ms)
✔ parseSessionFile: broken JSON line is skipped with warning, rest parses (6.465627ms)
✔ aggregateSession: counts messages, tool calls, errors (4.349413ms)
✔ aggregateSession: sums usage across assistant messages (normal) (3.402425ms)
✔ aggregateSession: includes standalone usage and compaction usage (3.005234ms)
✔ aggregateSession: tool duration via toolCallId link (2.137795ms)
✔ aggregateSession: start/end from first/last entry timestamps (3.492102ms)
✔ aggregateSession: models list from model_change entries (4.409686ms)
✔ listSessionFiles: finds .jsonl recursively under sessions dir (1.762114ms)
✔ parseSessionFile: missing file returns null session, warning, no throw (3.047767ms)
ℹ tests 33
ℹ suites 0
ℹ pass 33
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 734.358304
[install] ✓ тесты пройдены
[install] 5/7 Конфигурация: /etc/default/pi-web-monitor
[install] ✓ конфиг уже существует — не перетираю (ручные правки сохранены)
[install] 6/7 systemd-юнит: /etc/systemd/system/pi-web-monitor.service
[install] ✓ юнит установлен, сервис перезапущен
[install] 7/7 Проверка живости (GET /api/health)
[install] ✓ сервис отвечает: http://127.0.0.1:8787/api/health
════════════════════════════════════════════════════════════
УСТАНОВКА ВЫПОЛНЕНА УСПЕШНО
Сервис: pi-web-monitor (systemd, включён автозапуск)
Код: /opt/watcherenish (ветка main)
Адрес: http://10.10.1.21:8787 (из локальной сети)
Локально: http://127.0.0.1:8787
Внимание: BIND=0.0.0.0 — UI доступен по сети, вход защищён AUTH_TOKEN;
пробрасывать порт в интернет не рекомендуется
Конфиг: /etc/default/pi-web-monitor (правки сохраняются при повторных установках)
AUTH_TOKEN: см. /etc/default/pi-web-monitor (не менялся)
Проверка: systemctl status pi-web-monitor
Удаление: curl -fsSL https://forgejo.lamanshe.ru/forgejo-admin/watcherenish/raw/branch/main/deploy/uninstall.sh | sudo bash
════════════════════════════════════════════════════════════
root@developer-agent:/tmp# curl -s -D - -o /dev/null
-H "Origin: https://forgejo.lamanshe.ru"
-H "Authorization: Bearer $(grep '^AUTH_TOKEN=' /etc/default/pi-web-monitor | cut -d= -f2)"
http://127.0.0.1:8787/api/health
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 98
Cache-Control: no-store
Date: Sat, 26 Sep 2026 14:50:14 GMT
Connection: keep-alive
Keep-Alive: timeout=5
root@developer-agent:/tmp#
Разобрался — моя прошлая инструкция была ошибочной, прошу прощения за потерянное время: установщик из ветки PR на самом деле всегда ставит код из
main(BRANCHжёстко по умолчаниюmain). Это видно и в вашем логе: «Код: /opt/watcherenish (ветка main)», «код обновлён до origin/main (6b9103b)». Ручное копированиеinstall.shне помогало именно поэтому — ветку кода скрипт из своей ветки не наследует. Ваш curl-вывод при этом корректный:200 OKбез заголовкаAccess-Control-Allow-Origin— ровно то, что отдаёт старый код изmain(CORS opt-in). Т.е. проблема не в вашей машине, а в установщике.Исправил в коммите
eeb5e70(эта же ветка/PR):bashили черезBRANCH=…:Теперь не нужно копировать файл вручную: один curl с
bash -s <ветка>ставит код ровно из PR-ветки. Явно заданная ветка проверяется черезgit ls-remoteещё до каких-либо изменений — с опечаткой установка падает сразу с внятной ошибкой.main, но теперь скрипт об этом явно пишет и печатает подсказку, как поставить другую ветку — больше никакой неявной «магии веток».Проверено в песочнице (с заглушкой systemd): ветка аргументом ✓, ветка через env ✓, без аргументов — main + подсказка ✓, несуществующая ветка — внятная ошибка ✓.
npm test— 33/33 зелёные.Проверка на вашей машине:
После этого подключение агента из хаба должно заработать. Конфиг (
/etc/default/pi-web-monitor) перетирать не нужно —ALLOWED_ORIGINSу вас закомментирован, открытый CORS включится сам. После мержа PR достаточно один раз переустановить изmainбез аргументов.