#!/usr/bin/env bash # InternetPressure.io probe agent installer (idempotent). # # sudo deploy/install.sh [ingest_url] # # - picks dist/ip-probe-- (or $IP_PROBE_BINARY) and installs it to /usr/local/bin/ip-probe # - writes /etc/internetpressure/probe.yaml (0600) — existing file is kept unless probe_id/key/url differ # - creates /var/lib/internetpressure (0700, owned by the service user) # - macOS: installs the LaunchDaemon (UserName = $IP_PROBE_USER, default: the invoking user) and bootstraps it # - Linux: creates the ip-probe system user, sets net.ipv4.ping_group_range, installs + enables the unit # Re-running upgrades the binary and restarts the service. set -euo pipefail PROBE_ID="${1:-}" KEY="${2:-}" INGEST_URL="${3:-https://www.internetpressure.io/ingest/v1}" if [[ -z "$PROBE_ID" || -z "$KEY" ]]; then echo "usage: sudo $0 [ingest_url]" >&2 exit 2 fi if [[ ! "$PROBE_ID" =~ ^[a-z0-9][a-z0-9-]{1,63}$ ]]; then echo "probe_id must be lowercase letters/digits/dashes" >&2; exit 2 fi if [[ ! "$KEY" =~ ^[0-9a-fA-F]{64}$ ]]; then echo "key must be 64 hex characters" >&2; exit 2 fi if [[ "$(id -u)" -ne 0 ]]; then echo "run as root (sudo)" >&2; exit 1 fi HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" OS="$(uname -s | tr '[:upper:]' '[:lower:]')" ARCH="$(uname -m)" case "$ARCH" in arm64|aarch64) ARCH=arm64 ;; x86_64|amd64) ARCH=amd64 ;; esac BIN_SRC="${IP_PROBE_BINARY:-$HERE/dist/ip-probe-$OS-$ARCH}" if [[ ! -x "$BIN_SRC" ]]; then echo "binary not found: $BIN_SRC (run 'make build' first or set IP_PROBE_BINARY)" >&2; exit 1 fi BIN_DST=/usr/local/bin/ip-probe CONF_DIR=/etc/internetpressure CONF="$CONF_DIR/probe.yaml" DATA_DIR=/var/lib/internetpressure LOG=/var/log/internetpressure-probe.log if [[ "$OS" == "darwin" ]]; then SVC_USER="${IP_PROBE_USER:-${SUDO_USER:-root}}" SVC_GROUP="$(id -gn "$SVC_USER")" else SVC_USER="${IP_PROBE_USER:-ip-probe}" if ! id "$SVC_USER" >/dev/null 2>&1; then useradd --system --home-dir "$DATA_DIR" --shell /usr/sbin/nologin --user-group "$SVC_USER" 2>/dev/null \ || adduser --system --home "$DATA_DIR" --no-create-home --group "$SVC_USER" echo "created system user $SVC_USER" fi SVC_GROUP="$(id -gn "$SVC_USER")" fi # --- binary --------------------------------------------------------------------------------------------------- NEW_VERSION="$("$BIN_SRC" --version | awk '{print $2}')" OLD_VERSION="$([[ -x "$BIN_DST" ]] && "$BIN_DST" --version 2>/dev/null | awk '{print $2}' || echo none)" install -d -m 0755 /usr/local/bin install -m 0755 "$BIN_SRC" "$BIN_DST.new" mv -f "$BIN_DST.new" "$BIN_DST" echo "binary: $OLD_VERSION → $NEW_VERSION at $BIN_DST" # --- config --------------------------------------------------------------------------------------------------- install -d -m 0755 "$CONF_DIR" TMP_CONF="$(mktemp)" cat > "$TMP_CONF" </dev/null 2>&1; then echo "config: unchanged ($CONF)" rm -f "$TMP_CONF" else install -m 0600 -o "$SVC_USER" -g "$SVC_GROUP" "$TMP_CONF" "$CONF" rm -f "$TMP_CONF" echo "config: written $CONF" fi "$BIN_DST" check-config --config "$CONF" >/dev/null # --- data dir + log -------------------------------------------------------------------------------------------- install -d -m 0700 -o "$SVC_USER" -g "$SVC_GROUP" "$DATA_DIR" touch "$LOG"; chown "$SVC_USER:$SVC_GROUP" "$LOG"; chmod 0640 "$LOG" # --- service -------------------------------------------------------------------------------------------------- if [[ "$OS" == "darwin" ]]; then PLIST=/Library/LaunchDaemons/io.internetpressure.probe.plist sed "s/__USER__/$SVC_USER/" "$HERE/deploy/launchd/io.internetpressure.probe.plist" > "$PLIST.new" chown root:wheel "$PLIST.new"; chmod 0644 "$PLIST.new" if launchctl print system/io.internetpressure.probe >/dev/null 2>&1; then launchctl bootout system/io.internetpressure.probe || true sleep 1 fi mv -f "$PLIST.new" "$PLIST" launchctl bootstrap system "$PLIST" launchctl kickstart -k system/io.internetpressure.probe echo "service: launchd io.internetpressure.probe running as $SVC_USER" echo "logs: tail -f $LOG" else if [[ ! -x /usr/bin/traceroute && ! -x /usr/sbin/traceroute ]]; then echo "warning: traceroute not installed (apt install traceroute) — traceroute checks disabled" >&2 fi install -d -m 0755 /etc/sysctl.d echo 'net.ipv4.ping_group_range = 0 2147483647' > /etc/sysctl.d/60-ip-probe.conf sysctl -q -p /etc/sysctl.d/60-ip-probe.conf || sysctl -q -w net.ipv4.ping_group_range="0 2147483647" || true install -m 0644 "$HERE/deploy/systemd/ip-probe.service" /etc/systemd/system/ip-probe.service if [[ "$SVC_USER" != "ip-probe" ]]; then sed -i "s/^User=.*/User=$SVC_USER/; s/^Group=.*/Group=$SVC_GROUP/" /etc/systemd/system/ip-probe.service fi systemctl daemon-reload systemctl enable --now ip-probe.service systemctl restart ip-probe.service echo "service: systemd ip-probe.service running as $SVC_USER" echo "logs: journalctl -u ip-probe -f" fi sleep 2 if curl -fsS http://127.0.0.1:9381/healthz >/dev/null 2>&1; then echo "health: $(curl -fsS http://127.0.0.1:9381/healthz)" else echo "health: endpoint not answering yet (check the logs)" fi