Collector milestone 6: packaging — install.sh, systemd unit, docs

systemd/agent-watcher.service: --user unit with on-failure restart,
ProtectSystem=strict, ProtectHome=read-write, NoNewPrivileges=yes,
PrivateTmp=yes. JSON logs to journald. Survives reboot via
'loginctl enable-linger'.

examples/collector.yaml: working starter config for both sources with
inline comments, per-route examples, and the spec §3.1.2 schema for
drop files.

install.sh: idempotent installer following the agent-ping pattern.
Builds the binary, installs it + the unit, drops the example config if
absent, reloads systemd, enables, and (unless --no-start) starts the
service. Adds drop-folder lifecycle artifacts (*.tmp, .dead-letter/)
to workspace .stignore so they don't replicate during processing.
Skips Syncthing-related steps gracefully when ~/Nyx/workspace is not
present.

INSTALL.md: prerequisites, install, configure, verify (drop-file +
webhook end-to-end probes), survive-logout, uninstall, troubleshooting
table.

README.md: rewritten to reflect actual status — v0 working with 43
tests, packaging ready, Layer 2 in progress on Bob's side.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
bob-boat 2026-05-06 16:26:16 -04:00
parent e7d4ea036a
commit 4ff8c3f78d
5 changed files with 324 additions and 6 deletions

114
install.sh Executable file
View file

@ -0,0 +1,114 @@
#!/usr/bin/env bash
# install.sh — set up the agent-watcher Collector on this machine.
#
# Usage:
# ./install.sh # build + install + enable + start
# ./install.sh --no-start # everything but `systemctl start`
#
# What it does:
# 1. Builds the agent-watcher binary (requires Go 1.22+).
# 2. Installs to ~/.local/bin/agent-watcher.
# 3. Drops the systemd --user unit into ~/.config/systemd/user/.
# 4. Drops a starter ~/.config/agent-watcher/collector.yaml if missing
# (copies examples/collector.yaml; you edit it before first start).
# 5. Reloads systemd, enables, and (unless --no-start) starts the unit.
# 6. Adds drop-folder lifecycle patterns to the workspace .stignore so
# drop files do not Syncthing-replicate during local processing.
#
# Per CLAUDE.md rule #2, this is intended to be run by a human. The
# Collector itself, like agent-ping, never invokes this script.
#
# Layer 2 (MCP Watcher) has its own install path — different language,
# different runtime, different unit. See its README when it lands.
set -euo pipefail
NO_START=0
for arg in "$@"; do
case "$arg" in
--no-start) NO_START=1 ;;
*) echo "unknown arg: $arg" >&2; exit 2 ;;
esac
done
REPO_DIR="$(cd "$(dirname "$0")" && pwd)"
BIN_DIR="$HOME/.local/bin"
CONF_DIR="$HOME/.config/agent-watcher"
UNIT_DIR="$HOME/.config/systemd/user"
WORKSPACE="$HOME/Nyx/workspace"
STIGNORE="$WORKSPACE/.stignore"
echo "agent-watcher install"
echo "repo: $REPO_DIR"
echo
# 1. Check Go
echo "[1/6] checking Go toolchain"
if ! command -v go >/dev/null 2>&1; then
echo " ERROR: 'go' not found. Install Go 1.22+ first." >&2
echo " e.g. sudo apt install golang-go" >&2
exit 1
fi
GO_VERSION=$(go version | awk '{print $3}')
echo " $GO_VERSION"
# 2. Build
echo "[2/6] building agent-watcher binary"
mkdir -p "$BIN_DIR"
( cd "$REPO_DIR" && go build -o "$BIN_DIR/agent-watcher" ./cmd/agent-watcher )
echo " installed: $BIN_DIR/agent-watcher"
# 3. systemd unit
echo "[3/6] installing systemd --user unit"
mkdir -p "$UNIT_DIR"
install -m 0644 "$REPO_DIR/systemd/agent-watcher.service" "$UNIT_DIR/agent-watcher.service"
echo " installed: $UNIT_DIR/agent-watcher.service"
# 4. Config skeleton
echo "[4/6] config skeleton"
mkdir -p "$CONF_DIR"
if [ -f "$CONF_DIR/collector.yaml" ]; then
echo " $CONF_DIR/collector.yaml exists — leaving as-is"
else
install -m 0644 "$REPO_DIR/examples/collector.yaml" "$CONF_DIR/collector.yaml"
echo " installed example: $CONF_DIR/collector.yaml — EDIT BEFORE START"
fi
# 5. .stignore — drop folder is replicated, but lifecycle artifacts shouldn't be
echo "[5/6] .stignore (drop-folder lifecycle artifacts are local-only)"
if [ -d "$WORKSPACE" ]; then
touch "$STIGNORE"
for pattern in "incoming/.dead-letter/" "incoming/*.json.tmp"; do
if ! grep -qxF "$pattern" "$STIGNORE"; then
echo "$pattern" >> "$STIGNORE"
echo " added: $pattern"
fi
done
else
echo " $WORKSPACE not present — skipping (Syncthing not set up here)"
fi
# 6. systemd reload + enable + (optionally) start
echo "[6/6] systemd reload + enable"
systemctl --user daemon-reload
systemctl --user enable agent-watcher.service >/dev/null
echo " enabled at user login (loginctl enable-linger required to run when logged out)"
if [ "$NO_START" -eq 0 ]; then
echo " starting…"
systemctl --user restart agent-watcher.service
sleep 1
systemctl --user status agent-watcher.service --no-pager -n 5 || true
else
echo " --no-start: not starting; run 'systemctl --user start agent-watcher' when ready"
fi
echo
echo "installation complete."
echo
echo "next steps:"
echo " 1. EDIT $CONF_DIR/collector.yaml to suit this host."
echo " 2. systemctl --user restart agent-watcher (after edits)."
echo " 3. journalctl --user -u agent-watcher -f (watch logs)."
echo " 4. curl http://127.0.0.1:18790/health (sanity check)."
echo " 5. To survive logout: loginctl enable-linger \$USER"