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>
This commit is contained in:
+1
-1
@@ -25,7 +25,7 @@
|
|||||||
"format": "{ git diff --name-only HEAD -- 'src/**/*.ts' 'src/**/*.tsx'; git ls-files --others --exclude-standard -- 'src/**/*.ts' 'src/**/*.tsx'; } | xargs -r prettier --write",
|
"format": "{ git diff --name-only HEAD -- 'src/**/*.ts' 'src/**/*.tsx'; git ls-files --others --exclude-standard -- 'src/**/*.ts' 'src/**/*.tsx'; } | xargs -r prettier --write",
|
||||||
"format:all": "prettier --write \"src/**/*.{ts,tsx}\"",
|
"format:all": "prettier --write \"src/**/*.{ts,tsx}\"",
|
||||||
"format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
|
"format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
|
||||||
"setup": "bash scripts/setup/officer-setup.sh"
|
"setup": "bash scripts/install.sh"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@anthropic-ai/claude-agent-sdk": "^0.2.41",
|
"@anthropic-ai/claude-agent-sdk": "^0.2.41",
|
||||||
|
|||||||
Executable
+103
@@ -0,0 +1,103 @@
|
|||||||
|
#!/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}"
|
||||||
@@ -66,7 +66,17 @@ echo -e "${BOLD}╔════════════════════
|
|||||||
echo -e "${BOLD}║ Officer Setup ║${NC}"
|
echo -e "${BOLD}║ Officer Setup ║${NC}"
|
||||||
echo -e "${BOLD}╚══════════════════════════════════════════════════╝${NC}"
|
echo -e "${BOLD}╚══════════════════════════════════════════════════╝${NC}"
|
||||||
|
|
||||||
if [[ "$EUID" -ne 0 ]]; then
|
# root on Linux, NOT root on macOS — the same split machine-setup makes, for the
|
||||||
|
# same reason. On Linux this creates directories owned by another account and
|
||||||
|
# drops privileges with `sudo -u`. On macOS the account running the script IS the
|
||||||
|
# owner, so there is nothing to chown and nothing to drop to — and Homebrew, which
|
||||||
|
# machine-setup ran just before this, refuses to run as root at all.
|
||||||
|
OFFICER_OS="$(uname -s)"
|
||||||
|
if [[ "$OFFICER_OS" == "Darwin" ]]; then
|
||||||
|
if [[ "$EUID" -eq 0 ]]; then
|
||||||
|
fail "Do not run this with sudo on macOS — run it as yourself."
|
||||||
|
fi
|
||||||
|
elif [[ "$EUID" -ne 0 ]]; then
|
||||||
fail "Please run as root: sudo ./officer-setup.sh"
|
fail "Please run as root: sudo ./officer-setup.sh"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user