diff --git a/deploy/crawler-remote/install.sh b/deploy/crawler-remote/install.sh index 487ebab..6735bc8 100755 --- a/deploy/crawler-remote/install.sh +++ b/deploy/crawler-remote/install.sh @@ -1,7 +1,8 @@ #!/usr/bin/env bash # pitbot on a second box, natively (no Docker): N fetch-only page workers and, with # --index, the publish role (local search index + page archive + the API pit.world reads). -# Idempotent: re-run to change the worker count. Needs sudo for the systemd units. +# Idempotent: re-run to change the worker count. System units need sudo; --user writes +# systemd user units instead (no sudo; needs `loginctl enable-linger`, e.g. dev3). # # bash install.sh --workers 8 --index # @@ -14,11 +15,12 @@ # 127.0.0.1:5601) and anything else secret; this script never writes secrets. set -euo pipefail -WORKERS=4; INDEX=0 +WORKERS=4; INDEX=0; MODE=system while [ $# -gt 0 ]; do case "$1" in --workers) WORKERS=$2; shift 2 ;; --index) INDEX=1; shift ;; + --user) MODE=user; shift ;; *) echo "unknown option $1" >&2; exit 1 ;; esac done @@ -35,7 +37,13 @@ chmod 600 "$ROOT/crawler.env" (cd "$APP" && git fetch -q origin main && git reset -q --hard origin/main && "$BUN" install --frozen-lockfile >/dev/null) USER_NAME=$(id -un) -COMMON="User=$USER_NAME +if [ $MODE = user ]; then + SCTL="systemctl --user"; UNIT_DIR=$HOME/.config/systemd/user; WRITE="tee"; USER_LINE=""; TARGET=default.target + mkdir -p "$UNIT_DIR" +else + SCTL="sudo systemctl"; UNIT_DIR=/etc/systemd/system; WRITE="sudo tee"; USER_LINE="User=$USER_NAME"; TARGET=multi-user.target +fi +COMMON="$USER_LINE WorkingDirectory=$APP EnvironmentFile=$ROOT/crawler.env Environment=CRAWL_REDIS_URL=redis://127.0.0.1:6396 @@ -49,7 +57,7 @@ MemoryMax=1500M Nice=5" # Fetch-only workers: no index, no health port, 64 pages at once each. -sudo tee /etc/systemd/system/pitbot-pages@.service >/dev/null </dev/null </dev/null </dev/null </dev/null 2>&1; done -for unit in $(systemctl list-units --plain --no-legend 'pitbot-pages@*' | awk '{print $1}'); do +for i in $(seq 1 "$WORKERS"); do $SCTL enable --now "pitbot-pages@$i" >/dev/null 2>&1; done +for unit in $($SCTL list-units --plain --no-legend 'pitbot-pages@*' | awk '{print $1}'); do n=${unit#pitbot-pages@}; n=${n%.service} - if [ "$n" -gt "$WORKERS" ]; then sudo systemctl disable --now "$unit" >/dev/null 2>&1; fi + if [ "$n" -gt "$WORKERS" ]; then $SCTL disable --now "$unit" >/dev/null 2>&1; fi done -if [ $INDEX = 1 ]; then sudo systemctl enable --now pitbot-index >/dev/null 2>&1; fi +if [ $INDEX = 1 ]; then $SCTL enable --now pitbot-index >/dev/null 2>&1; fi # Deploy on merge and ship sealed archive hours, from the user's crontab. POLL="*/5 * * * * bash $APP/deploy/crawler-remote/poll.sh >> $ROOT/poll.log 2>&1 # pitbot remote deploy-on-merge" SHIP="7 * * * * flock -n /tmp/pitbot-ship.lock bash $APP/deploy/crawler-remote/ship-archive.sh >> $ROOT/ship.log 2>&1 # pitbot archive -> seed1" { crontab -l 2>/dev/null | grep -v -e 'pitbot remote deploy-on-merge' -e 'pitbot archive -> seed1'; echo "$POLL"; if [ $INDEX = 1 ]; then echo "$SHIP"; fi; } | crontab - -systemctl list-units --plain --no-legend 'pitbot-*' | awk '{print $1, $3, $4}' +$SCTL list-units --plain --no-legend 'pitbot-*' | awk '{print $1, $3, $4}' diff --git a/deploy/crawler-remote/poll.sh b/deploy/crawler-remote/poll.sh index f1f29c2..ce40e54 100755 --- a/deploy/crawler-remote/poll.sh +++ b/deploy/crawler-remote/poll.sh @@ -12,8 +12,10 @@ if [ "$want" = "$have" ] && [ "${1:-}" != "--force" ]; then exit 0; fi echo "$(date -u +%FT%TZ) deploying ${want:0:12} (was ${have:0:12})" git reset -q --hard "$want" bun install --frozen-lockfile >/dev/null -for unit in $(systemctl list-units --plain --no-legend 'pitbot-*' | awk '{print $1}'); do sudo systemctl restart "$unit"; done +# install.sh --user boxes (no sudo) run user units; the rest run system units. +if systemctl --user list-units --plain --no-legend 'pitbot-*' 2>/dev/null | grep -q pitbot; then SCTL="systemctl --user"; else SCTL="sudo systemctl"; fi +for unit in $($SCTL list-units --plain --no-legend 'pitbot-*' | awk '{print $1}'); do $SCTL restart "$unit"; done sleep 10 -failed=$(systemctl list-units --plain --no-legend --state=failed 'pitbot-*' | awk '{print $1}') +failed=$($SCTL list-units --plain --no-legend --state=failed 'pitbot-*' | awk '{print $1}') if [ -n "$failed" ]; then echo "$(date -u +%FT%TZ) ${want:0:12} FAILED: $failed" >&2; exit 1; fi echo "$(date -u +%FT%TZ) ${want:0:12} running"