Files
platform/scripts/install.sh
T
pastilhasandClaude Opus 5 3cca07187e scripts/install.sh — one command for both halves
`bun setup` runs it. Machine setup first, then officer setup, stopping if the
first does not finish rather than running the second against a machine that is
not ready.

They stay two scripts because they answer two different questions and are worth
running apart — a machine you already trust needs only the second, one you are
rebuilding needs only the first. --machine-only and --officer-only say so
directly, and both halves remain runnable by path.

Privileges are checked here, before anything is done, because the two systems
want opposite things: Linux needs root for apt, systemd, useradd, netplan and ufw
and for creating directories owned by the service account; macOS must NOT be
root, since Homebrew refuses to run as one. Each script already enforces its own
rule, so this is only about failing early instead of halfway.

officer-setup.sh gained the same OS-aware check. It required root unconditionally,
which on macOS would have failed immediately after machine-setup — which must run
as the user — and for no reason: there the account running it IS the owner, so
there is nothing to chown and nothing to drop privileges to.

Arguments are parsed before privileges, so --help works without sudo and an
unknown option is rejected before anybody is asked for a password. It did not,
first time round.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-13 02:49:44 +00:00

104 lines
3.6 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# Officer — install
# =============================================================================
#
# One command, blank machine to running platform. It runs the two halves in
# order and does nothing else itself:
#
# setup/machine-setup/machine-setup.sh a usable machine — packages, tailnet,
# runtimes, docker, shell
# setup/officer-setup.sh the platform on top of it — repo,
# dependencies, postgres, .env, secret
# store, schema, build, pm2
#
# They stay two scripts because they answer two different questions and are worth
# running separately: a machine you already trust needs only the second, and a
# machine you are rebuilding needs only the first. This is the wrapper for the
# case where you want both, which is most first runs.
#
# Both are re-runnable. Each remembers the steps it finished and skips them, so
# stopping halfway and coming back costs nothing.
#
# ── Privileges ──
#
# Linux needs root: apt, systemd units, useradd, netplan, ufw, and creating
# directories owned by the service account. macOS must NOT be root: Homebrew
# refuses to run as one, and there is nothing to chown because the account
# running this IS the owner. Both scripts enforce that themselves; this checks
# first so the failure arrives before anything has been done.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MACHINE="$SCRIPT_DIR/setup/machine-setup/machine-setup.sh"
OFFICER="$SCRIPT_DIR/setup/officer-setup.sh"
BOLD='\033[1m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
say() { echo -e "$*"; }
die() {
echo -e "${YELLOW}error:${NC} $*" >&2
exit 1
}
[[ -r "$MACHINE" ]] || die "missing $MACHINE"
[[ -r "$OFFICER" ]] || die "missing $OFFICER"
# Which halves to run. Both by default.
RUN_MACHINE=true
RUN_OFFICER=true
for arg in "$@"; do
case "$arg" in
--machine-only) RUN_OFFICER=false ;;
--officer-only) RUN_MACHINE=false ;;
-h | --help)
say "usage: install.sh [--machine-only | --officer-only]"
say ""
say " no flags both halves, machine first"
say " --machine-only stop after the machine is provisioned"
say " --officer-only the platform only, on a machine you already trust"
exit 0
;;
*) die "unknown option: $arg" ;;
esac
done
KERNEL="$(uname -s)"
case "$KERNEL" in
Darwin)
[[ "$EUID" -eq 0 ]] && die "do not run this with sudo on macOS — Homebrew refuses to run as root. Run it as yourself."
;;
Linux)
[[ "$EUID" -ne 0 ]] && die "please run as root: sudo ./scripts/install.sh"
;;
*) die "unsupported system: $KERNEL. Officer installs on Linux and macOS." ;;
esac
say ""
say "${BOLD}Officer install${NC}"
say " system: $KERNEL"
$RUN_MACHINE && say " 1/2 machine setup"
$RUN_OFFICER && say " $($RUN_MACHINE && echo 2/2 || echo 1/1) officer setup"
say ""
say " Either half can be run on its own later:"
say " scripts/setup/machine-setup/machine-setup.sh"
say " scripts/setup/officer-setup.sh"
say ""
# Not `set -e`'s job: a half that exits non-zero should say which half, and stop
# before the next one starts on a machine that is not ready for it.
if $RUN_MACHINE; then
bash "$MACHINE" || die "machine setup did not finish — fix what it reported, then run this again"
fi
if $RUN_OFFICER; then
bash "$OFFICER" || die "officer setup did not finish — fix what it reported, then run this again"
fi
say ""
say "${GREEN}Done.${NC}"