Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 21 additions & 13 deletions deploy/crawler-remote/install.sh
Original file line number Diff line number Diff line change
@@ -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
#
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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 <<EOF
$WRITE "$UNIT_DIR/pitbot-pages@.service" >/dev/null <<EOF
[Unit]
Description=pitbot page worker %i (fetch only; dev2 Redis via tunnel)
After=network-online.target
Expand All @@ -62,12 +70,12 @@ Environment=CRAWL_INDEX_PATH=:memory:
Environment=CRAWL_HEALTH_PORT=0

[Install]
WantedBy=multi-user.target
WantedBy=$TARGET
EOF

if [ $INDEX = 1 ]; then
# The publish role: drains the outbox into the index and the archive, serves the API.
sudo tee /etc/systemd/system/pitbot-index.service >/dev/null <<EOF
$WRITE "$UNIT_DIR/pitbot-index.service" >/dev/null <<EOF
[Unit]
Description=pitbot index (publish role: search index, page archive, API on 127.0.0.1:8807)
After=network-online.target
Expand All @@ -82,21 +90,21 @@ Environment=CRAWL_HEALTH_PORT=8807
MemoryMax=8G

[Install]
WantedBy=multi-user.target
WantedBy=$TARGET
EOF
fi

sudo systemctl daemon-reload
$SCTL daemon-reload
# Exactly WORKERS page workers: start 1..N, stop any above N.
for i in $(seq 1 "$WORKERS"); do sudo systemctl enable --now "pitbot-pages@$i" >/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}'
6 changes: 4 additions & 2 deletions deploy/crawler-remote/poll.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Loading