Skip to content

Commit e17ce31

Browse files
authored
deploy: centralize shell path constants in shared helper (#113)
1 parent 699b80f commit e17ce31

14 files changed

Lines changed: 172 additions & 105 deletions

AGENTS.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ bin/ security & operations scripts
3131
setup-arch.sh Arch Linux droplet: prereqs + setup + tests
3232
lib/ shared shell helpers sourced by CLI/release scripts
3333
shell-common.sh strict mode + shared logging/error/root-check helpers
34+
paths-common.sh shared path constants (bb_init_paths, bb_refresh_release_paths)
3435
release-common.sh shared update/rollback helpers
3536
deploy-common.sh deploy/runtime helper functions
3637
doctor-common.sh doctor status/check formatting helpers
@@ -181,7 +182,7 @@ Add new test files to `vitest.config.mjs` (and shell wrappers under `test/` as n
181182
- Security functions must be pure, testable modules (no side effects, no env vars at module scope).
182183
- All security code must have tests before merging.
183184
- Run `bin/security-audit.sh --deep` after any security-relevant changes.
184-
- Keep shell CLIs thin: move reusable logic to `bin/lib/*.sh`, and source shared helpers (`shell-common.sh`, `release-common.sh`, `deploy-common.sh`, `doctor-common.sh`) instead of duplicating logging/error/root-check patterns.
185+
- Keep shell CLIs thin: move reusable logic to `bin/lib/*.sh`, and source shared helpers (`shell-common.sh`, `paths-common.sh`, `release-common.sh`, `deploy-common.sh`, `doctor-common.sh`) instead of duplicating logging/error/root-check patterns.
185186
- For shell scripts, standardize on `bb_enable_strict_mode` and shared helper functions (`bb_log`, `bb_die`, etc.) rather than ad-hoc wrappers.
186187
- Protected files (`tool-guard.ts`, `security.mjs`, their tests) are deployed read-only. The agent cannot modify them at runtime.
187188
- New integrations get their own subdirectory (e.g. `discord-bridge/`).

bin/deploy.sh

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,21 @@
1515

1616
# Auto-detect source repo from this script's location
1717
BAUDBOT_SRC="${BAUDBOT_SRC:-$(cd "$(dirname "$0")/.." && pwd)}"
18-
BAUDBOT_HOME="${BAUDBOT_HOME:-/home/baudbot_agent}"
19-
AGENT_USER="baudbot_agent"
2018
DRY_RUN=0
2119
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
2220

2321
# shellcheck source=bin/lib/shell-common.sh
2422
source "$SCRIPT_DIR/lib/shell-common.sh"
23+
# shellcheck source=bin/lib/paths-common.sh
24+
source "$SCRIPT_DIR/lib/paths-common.sh"
2525
# shellcheck source=bin/lib/json-common.sh
2626
source "$SCRIPT_DIR/lib/json-common.sh"
2727
# shellcheck source=bin/lib/deploy-common.sh
2828
source "$SCRIPT_DIR/lib/deploy-common.sh"
2929
bb_enable_strict_mode
30+
bb_init_paths
31+
32+
AGENT_USER="${AGENT_USER:-$BAUDBOT_AGENT_USER}"
3033

3134
# Helper: run a command as baudbot_agent
3235
as_agent() {

bin/doctor.sh

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,12 @@
77
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
88
# shellcheck source=bin/lib/shell-common.sh
99
source "$SCRIPT_DIR/lib/shell-common.sh"
10+
# shellcheck source=bin/lib/paths-common.sh
11+
source "$SCRIPT_DIR/lib/paths-common.sh"
1012
# shellcheck source=bin/lib/doctor-common.sh
1113
source "$SCRIPT_DIR/lib/doctor-common.sh"
1214
bb_enable_strict_mode
15+
bb_init_paths
1316

1417
for arg in "$@"; do
1518
case "$arg" in
@@ -20,7 +23,6 @@ for arg in "$@"; do
2023
esac
2124
done
2225

23-
BAUDBOT_HOME="/home/baudbot_agent"
2426
doctor_init_counters
2527
IS_ROOT=0
2628
if [ "$(id -u)" -eq 0 ]; then
@@ -42,10 +44,10 @@ fi
4244
# ── User ─────────────────────────────────────────────────────────────────────
4345

4446
echo "User:"
45-
if id baudbot_agent &>/dev/null; then
46-
pass "baudbot_agent user exists"
47+
if id "$BAUDBOT_AGENT_USER" &>/dev/null; then
48+
pass "$BAUDBOT_AGENT_USER user exists"
4749
else
48-
fail "baudbot_agent user does not exist (run: baudbot setup)"
50+
fail "$BAUDBOT_AGENT_USER user does not exist (run: baudbot setup)"
4951
fi
5052

5153
# ── Dependencies ─────────────────────────────────────────────────────────────
@@ -90,10 +92,10 @@ else
9092
fi
9193

9294
if command -v gh &>/dev/null; then
93-
if sudo -u baudbot_agent gh auth status &>/dev/null; then
95+
if sudo -u "$BAUDBOT_AGENT_USER" gh auth status &>/dev/null; then
9496
pass "gh cli authenticated"
9597
else
96-
warn "gh cli installed but not authenticated (run: sudo -u baudbot_agent gh auth login)"
98+
warn "gh cli installed but not authenticated (run: sudo -u $BAUDBOT_AGENT_USER gh auth login)"
9799
fi
98100
else
99101
fail "gh cli not found"
@@ -136,10 +138,10 @@ if [ -f "$ENV_FILE" ]; then
136138
else
137139
fail ".env has $PERMS permissions (should be 600)"
138140
fi
139-
if [ "$OWNER" = "baudbot_agent" ]; then
140-
pass ".env owned by baudbot_agent"
141+
if [ "$OWNER" = "$BAUDBOT_AGENT_USER" ]; then
142+
pass ".env owned by $BAUDBOT_AGENT_USER"
141143
else
142-
fail ".env owned by $OWNER (should be baudbot_agent)"
144+
fail ".env owned by $OWNER (should be $BAUDBOT_AGENT_USER)"
143145
fi
144146

145147
# LLM key validation: require at least one valid key, and flag malformed configured keys.
@@ -369,7 +371,7 @@ if bb_has_systemd; then
369371
fi
370372
else
371373
# No systemd — check for pi process
372-
if pgrep -u baudbot_agent -f "pi --session-control" &>/dev/null; then
374+
if pgrep -u "$BAUDBOT_AGENT_USER" -f "pi --session-control" &>/dev/null; then
373375
pass "agent is running (direct mode)"
374376
else
375377
warn "agent is not running"

bin/lib/paths-common.sh

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#!/bin/bash
2+
# Shared path constants for baudbot shell scripts.
3+
4+
# shellcheck disable=SC2120 # Optional args are used by callers in other scripts.
5+
bb_refresh_release_paths() {
6+
local release_root="${BAUDBOT_RELEASE_ROOT:-/opt/baudbot}"
7+
local force="0"
8+
9+
if [ "$#" -ge 1 ]; then
10+
release_root="$1"
11+
fi
12+
if [ "$#" -ge 2 ]; then
13+
force="$2"
14+
fi
15+
16+
BAUDBOT_RELEASE_ROOT="$release_root"
17+
18+
if [ "$force" = "1" ]; then
19+
BAUDBOT_RELEASES_DIR="$BAUDBOT_RELEASE_ROOT/releases"
20+
BAUDBOT_CURRENT_LINK="$BAUDBOT_RELEASE_ROOT/current"
21+
BAUDBOT_PREVIOUS_LINK="$BAUDBOT_RELEASE_ROOT/previous"
22+
BAUDBOT_SOURCE_URL_FILE="$BAUDBOT_RELEASE_ROOT/source.url"
23+
BAUDBOT_SOURCE_BRANCH_FILE="$BAUDBOT_RELEASE_ROOT/source.branch"
24+
else
25+
: "${BAUDBOT_RELEASES_DIR:=$BAUDBOT_RELEASE_ROOT/releases}"
26+
: "${BAUDBOT_CURRENT_LINK:=$BAUDBOT_RELEASE_ROOT/current}"
27+
: "${BAUDBOT_PREVIOUS_LINK:=$BAUDBOT_RELEASE_ROOT/previous}"
28+
: "${BAUDBOT_SOURCE_URL_FILE:=$BAUDBOT_RELEASE_ROOT/source.url}"
29+
: "${BAUDBOT_SOURCE_BRANCH_FILE:=$BAUDBOT_RELEASE_ROOT/source.branch}"
30+
fi
31+
}
32+
33+
bb_init_paths() {
34+
: "${BAUDBOT_AGENT_USER:=baudbot_agent}"
35+
36+
if [ -n "${BAUDBOT_HOME:-}" ] && [ -z "${BAUDBOT_AGENT_HOME:-}" ]; then
37+
BAUDBOT_AGENT_HOME="$BAUDBOT_HOME"
38+
fi
39+
40+
if [ -z "${BAUDBOT_AGENT_HOME:-}" ]; then
41+
BAUDBOT_AGENT_HOME="$(bb_resolve_user_home "$BAUDBOT_AGENT_USER" 2>/dev/null || true)"
42+
fi
43+
: "${BAUDBOT_AGENT_HOME:=/home/$BAUDBOT_AGENT_USER}"
44+
45+
if [ -z "${BAUDBOT_HOME:-}" ]; then
46+
BAUDBOT_HOME="$BAUDBOT_AGENT_HOME"
47+
fi
48+
49+
: "${BAUDBOT_RUNTIME_DIR:=$BAUDBOT_AGENT_HOME/runtime}"
50+
: "${BAUDBOT_PI_DIR:=$BAUDBOT_AGENT_HOME/.pi}"
51+
: "${BAUDBOT_AGENT_DIR:=$BAUDBOT_PI_DIR/agent}"
52+
: "${BAUDBOT_AGENT_EXT_DIR:=$BAUDBOT_AGENT_DIR/extensions}"
53+
: "${BAUDBOT_AGENT_SKILLS_DIR:=$BAUDBOT_AGENT_DIR/skills}"
54+
: "${BAUDBOT_AGENT_SETTINGS_FILE:=$BAUDBOT_AGENT_DIR/settings.json}"
55+
: "${BAUDBOT_VERSION_FILE:=$BAUDBOT_AGENT_DIR/baudbot-version.json}"
56+
: "${BAUDBOT_MANIFEST_FILE:=$BAUDBOT_AGENT_DIR/baudbot-manifest.json}"
57+
: "${BAUDBOT_ENV_FILE:=$BAUDBOT_AGENT_HOME/.config/.env}"
58+
59+
bb_refresh_release_paths
60+
61+
export BAUDBOT_AGENT_USER BAUDBOT_AGENT_HOME BAUDBOT_HOME
62+
export BAUDBOT_RUNTIME_DIR BAUDBOT_PI_DIR BAUDBOT_AGENT_DIR
63+
export BAUDBOT_AGENT_EXT_DIR BAUDBOT_AGENT_SKILLS_DIR BAUDBOT_AGENT_SETTINGS_FILE
64+
export BAUDBOT_VERSION_FILE BAUDBOT_MANIFEST_FILE BAUDBOT_ENV_FILE
65+
export BAUDBOT_RELEASE_ROOT BAUDBOT_RELEASES_DIR BAUDBOT_CURRENT_LINK BAUDBOT_PREVIOUS_LINK
66+
export BAUDBOT_SOURCE_URL_FILE BAUDBOT_SOURCE_BRANCH_FILE
67+
}

bin/rollback-release.sh

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,11 @@
88
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
99
# shellcheck source=bin/lib/shell-common.sh
1010
source "$SCRIPT_DIR/lib/shell-common.sh"
11+
# shellcheck source=bin/lib/paths-common.sh
12+
source "$SCRIPT_DIR/lib/paths-common.sh"
1113
bb_enable_strict_mode
1214

13-
BAUDBOT_RELEASE_ROOT="${BAUDBOT_RELEASE_ROOT:-/opt/baudbot}"
14-
BAUDBOT_RELEASES_DIR="${BAUDBOT_RELEASES_DIR:-$BAUDBOT_RELEASE_ROOT/releases}"
15-
BAUDBOT_CURRENT_LINK="${BAUDBOT_CURRENT_LINK:-$BAUDBOT_RELEASE_ROOT/current}"
16-
BAUDBOT_PREVIOUS_LINK="${BAUDBOT_PREVIOUS_LINK:-$BAUDBOT_RELEASE_ROOT/previous}"
15+
bb_init_paths
1716

1817
BAUDBOT_ROLLBACK_DEPLOY_CMD="${BAUDBOT_ROLLBACK_DEPLOY_CMD:-}"
1918
BAUDBOT_ROLLBACK_RESTART_CMD="${BAUDBOT_ROLLBACK_RESTART_CMD:-}"
@@ -24,9 +23,6 @@ BAUDBOT_ROLLBACK_SKIP_VERSION_CHECK="${BAUDBOT_ROLLBACK_SKIP_VERSION_CHECK:-0}"
2423
BAUDBOT_ROLLBACK_SKIP_CLI_LINK="${BAUDBOT_ROLLBACK_SKIP_CLI_LINK:-0}"
2524
BAUDBOT_ROLLBACK_ALLOW_NON_ROOT="${BAUDBOT_ROLLBACK_ALLOW_NON_ROOT:-0}"
2625

27-
BAUDBOT_AGENT_USER="${BAUDBOT_AGENT_USER:-baudbot_agent}"
28-
BAUDBOT_AGENT_HOME="${BAUDBOT_AGENT_HOME:-/home/baudbot_agent}"
29-
3026
log() { bb_log "$1"; }
3127
die() { bb_die "$1"; }
3228

@@ -50,10 +46,7 @@ while [ "$#" -gt 0 ]; do
5046
case "$1" in
5147
--release-root)
5248
[ "$#" -ge 2 ] || die "--release-root requires a value"
53-
BAUDBOT_RELEASE_ROOT="$2"
54-
BAUDBOT_RELEASES_DIR="$BAUDBOT_RELEASE_ROOT/releases"
55-
BAUDBOT_CURRENT_LINK="$BAUDBOT_RELEASE_ROOT/current"
56-
BAUDBOT_PREVIOUS_LINK="$BAUDBOT_RELEASE_ROOT/previous"
49+
bb_refresh_release_paths "$2" 1
5750
shift 2
5851
;;
5952
--skip-restart)

bin/scan-extensions.test.mjs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,7 @@ describe("scan-extensions: new rules", () => {
316316
await writeFile(join(dir, "bad.js"), `
317317
const mod = require(userInput);
318318
`);
319-
const { output, exitCode } = runScanner(dir);
319+
const { output } = runScanner(dir);
320320
// info severity = exit 0, but should appear in output
321321
assert.ok(output.includes("dynamic") || output.includes("Dynamic") || output.includes("require"), output);
322322
});

bin/security-audit.sh

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
1313
# shellcheck source=bin/lib/shell-common.sh
1414
source "$SCRIPT_DIR/lib/shell-common.sh"
15+
# shellcheck source=bin/lib/paths-common.sh
16+
source "$SCRIPT_DIR/lib/paths-common.sh"
1517
bb_enable_strict_mode
18+
bb_init_paths
1619

17-
BAUDBOT_HOME="${BAUDBOT_HOME:-/home/baudbot_agent}"
1820
# Source repo — auto-detect from this script's location, or use env override
1921
BAUDBOT_SRC="${BAUDBOT_SRC:-$(cd "$SCRIPT_DIR/.." && pwd)}"
2022

@@ -97,12 +99,12 @@ echo ""
9799
# ── Docker group ─────────────────────────────────────────────────────────────
98100

99101
echo "Docker Access"
100-
if id baudbot_agent 2>/dev/null | grep -q '(docker)'; then
101-
finding "CRITICAL" "baudbot_agent is in docker group" \
102+
if id "$BAUDBOT_AGENT_USER" 2>/dev/null | grep -q '(docker)'; then
103+
finding "CRITICAL" "$BAUDBOT_AGENT_USER is in docker group" \
102104
"Can bypass baudbot-docker wrapper via /usr/bin/docker directly"
103-
fix_skip "Remove from docker group" "Requires root: sudo gpasswd -d baudbot_agent docker"
105+
fix_skip "Remove from docker group" "Requires root: sudo gpasswd -d $BAUDBOT_AGENT_USER docker"
104106
else
105-
ok "baudbot_agent not in docker group"
107+
ok "$BAUDBOT_AGENT_USER not in docker group"
106108
fi
107109

108110
if [ -f /usr/local/bin/baudbot-docker ]; then
@@ -191,7 +193,7 @@ echo "Source Isolation & Integrity"
191193
# Source repo lives outside agent's home — agent should not be able to read it
192194
if [ -r "$BAUDBOT_SRC/setup.sh" ] 2>/dev/null; then
193195
# If we're running as admin, this is expected — check agent can't
194-
agent_can_read=$(sudo -u baudbot_agent test -r "$BAUDBOT_SRC/setup.sh" 2>/dev/null && echo "yes" || echo "no")
196+
agent_can_read=$(sudo -u "$BAUDBOT_AGENT_USER" test -r "$BAUDBOT_SRC/setup.sh" 2>/dev/null && echo "yes" || echo "no")
195197
if [ "$agent_can_read" = "yes" ]; then
196198
finding "WARN" "Agent can read source repo at $BAUDBOT_SRC" \
197199
"Ensure admin home is 700: chmod 700 $(dirname "$BAUDBOT_SRC")"
@@ -566,10 +568,10 @@ echo ""
566568
echo "Extension & Skill Safety"
567569

568570
# Check pi extensions for suspicious patterns (deployed copies only)
569-
AGENT_USER="${BAUDBOT_AGENT_USER:-baudbot_agent}"
571+
AGENT_USER="$BAUDBOT_AGENT_USER"
570572
suspicious_extension_patterns="(eval\s*\(|new\s+Function\s*\(|child_process|execSync|execFile|spawn\s*\(|writeFileSync.*\/etc|writeFileSync.*\/home\/(?!${AGENT_USER}))"
571573
ext_dirs=(
572-
"$BAUDBOT_HOME/.pi/agent/extensions"
574+
"$BAUDBOT_AGENT_EXT_DIR"
573575
)
574576
ext_findings=0
575577
for ext_dir in "${ext_dirs[@]}"; do
@@ -588,7 +590,7 @@ fi
588590

589591
# Check skills for dangerous tool instructions (deployed copies only)
590592
skill_dirs=(
591-
"$BAUDBOT_HOME/.pi/agent/skills"
593+
"$BAUDBOT_AGENT_SKILLS_DIR"
592594
)
593595
skill_findings=0
594596
for skill_dir in "${skill_dirs[@]}"; do

bin/setup-firewall.sh

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,25 @@
1616
# - Bind to ports (no inbound listeners/backdoors)
1717
# - Do DNS tunneling over non-53 UDP
1818

19-
set -euo pipefail
19+
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
20+
# shellcheck source=bin/lib/shell-common.sh
21+
source "$SCRIPT_DIR/lib/shell-common.sh"
22+
# shellcheck source=bin/lib/paths-common.sh
23+
source "$SCRIPT_DIR/lib/paths-common.sh"
24+
bb_enable_strict_mode
25+
bb_init_paths
2026

21-
if [ "$(id -u)" -ne 0 ]; then
22-
echo "❌ Must run as root (sudo $0)"
23-
exit 1
24-
fi
27+
bb_require_root "setup-firewall"
2528

26-
UID_BAUDBOT=$(id -u baudbot_agent 2>/dev/null)
29+
UID_BAUDBOT=$(id -u "$BAUDBOT_AGENT_USER" 2>/dev/null)
2730
if [ -z "$UID_BAUDBOT" ]; then
28-
echo "baudbot_agent user not found"
31+
echo "$BAUDBOT_AGENT_USER user not found"
2932
exit 1
3033
fi
3134

3235
CHAIN="BAUDBOT_OUTPUT"
3336

34-
echo "🔒 Setting up firewall rules for baudbot_agent (uid $UID_BAUDBOT)..."
37+
echo "🔒 Setting up firewall rules for $BAUDBOT_AGENT_USER (uid $UID_BAUDBOT)..."
3538

3639
# Clean up any existing rules first
3740
iptables -w -D OUTPUT -m owner --uid-owner "$UID_BAUDBOT" -j "$CHAIN" 2>/dev/null || true

0 commit comments

Comments
 (0)