Skip to main content

max / makenotwork

2.7 KB · 64 lines History Blame Raw
1 #!/usr/bin/env bash
2 # Rebuild and restart sandod itself to a target commit.
3 #
4 # Runs as ROOT, invoked by the oneshot unit `sando-update@<sha>.service` (the
5 # sha is the instance name, passed here as $1). sandod cannot do this itself:
6 # it runs User=sando with NoNewPrivileges + ProtectSystem=strict, so it can
7 # neither write /usr/local/bin/sandod nor restart its own service. sandod only
8 # *triggers* this unit (authorized for the sando user by a scoped polkit rule);
9 # the actual privileged work lives here.
10 #
11 # Build runs as the unprivileged build user (the sando user already carries a
12 # rustup toolchain at /srv/sando/.cargo/bin); only the install + restart run as
13 # root. The build uses a dedicated checkout, never the operator's dev tree.
14 #
15 # Config via environment (defaults shown), set in the unit or /etc/sando/sando.env:
16 # SANDO_SELF_UPDATE_DIR /srv/sando/self-update build checkout parent (build-user-owned)
17 # SANDO_UPSTREAM_URL git@ssh.makenot.work:max/makenotwork.git
18 # SANDO_BUILD_USER sando
19 # SANDO_BIN /usr/local/bin/sandod install destination
20 set -euo pipefail
21
22 SHA="${1:-}"
23 if [[ ! "$SHA" =~ ^[0-9a-f]{7,40}$ ]]; then
24 echo "sando-self-update: refusing non-hex sha: '$SHA'" >&2
25 exit 2
26 fi
27
28 SELF_DIR="${SANDO_SELF_UPDATE_DIR:-/srv/sando/self-update}"
29 UPSTREAM_URL="${SANDO_UPSTREAM_URL:-git@ssh.makenot.work:max/makenotwork.git}"
30 BUILD_USER="${SANDO_BUILD_USER:-sando}"
31 BIN="${SANDO_BIN:-/usr/local/bin/sandod}"
32 REPO_DIR="$SELF_DIR/MNW"
33 BUILD_HOME="$(getent passwd "$BUILD_USER" | cut -d: -f6)"
34
35 echo "sando-self-update: building sandod @ $SHA as $BUILD_USER"
36
37 # Fetch + checkout + build, all as the unprivileged build user. The clone is
38 # created once; thereafter we just fetch the new sha. Detached checkout so the
39 # dedicated tree never carries a branch to drift.
40 install -d -o "$BUILD_USER" -g "$BUILD_USER" "$SELF_DIR"
41 runuser -u "$BUILD_USER" -- env \
42 HOME="$BUILD_HOME" \
43 PATH="$BUILD_HOME/.cargo/bin:/usr/local/bin:/usr/bin:/bin" \
44 bash -euo pipefail -c "
45 if [[ ! -d '$REPO_DIR/.git' ]]; then
46 git clone '$UPSTREAM_URL' '$REPO_DIR'
47 fi
48 cd '$REPO_DIR'
49 git fetch --prune origin
50 git checkout --detach '$SHA'
51 cd sando/daemon
52 cargo build --release --locked
53 "
54
55 NEW_BIN="$REPO_DIR/sando/daemon/target/release/sandod"
56 [[ -x "$NEW_BIN" ]] || { echo "sando-self-update: build produced no binary at $NEW_BIN" >&2; exit 3; }
57
58 # Install + restart as root. install is atomic (writes a temp then renames), so
59 # a concurrent exec of $BIN never sees a half-written file.
60 echo "sando-self-update: installing $NEW_BIN -> $BIN and restarting sandod"
61 install -m 0755 "$NEW_BIN" "$BIN"
62 systemctl restart sandod
63 echo "sando-self-update: done ($SHA live)"
64