macOS is a dev machine, and machine-setup now treats it as one

Officer on a Mac is a dev helper on a laptop somebody sits at. It is never the
homelab or VPS case, so the role is not asked for there — it is `dev`, and every
section that exists to make a machine a good server is skipped.

Seventeen of twenty-six sections skip, listed once in MACOS_SKIP in lib/base.sh
with a reason each, rather than an `if macos` threaded through each section. Most
would simply fail — no systemd, no ufw, no netplan, no useradd, no
/etc/ssh/sshd_config.d — but a few would SUCCEED and be wrong, which is worse:
stopping a laptop from sleeping, or freezing the address of a machine that moves
between networks daily.

Nine run: System update, Core utils, Tailscale, Command-line tools, Git, Docker,
Neovim, JavaScript runtimes, Agent CLIs.

The blocker was root. Linux needs it for nearly everything; Homebrew REFUSES to
run as root and says so, so the whole script under sudo would have failed at the
first brew install having already taken a password. It is now required on Linux
and refused on macOS, which works precisely because the macOS path skips
everything that needed it.

Docker is checked, not installed. Docker Desktop is a GUI app that wants opening,
permissions and a running window — not a shell script's business — and colima and
lima both cost an evening the first time something does not resolve. So the step
reports whether the daemon answers and points at the download otherwise. The
group-vs-rootless choice below it is Linux only: Desktop runs containers in a VM
owned by whoever is logged in, so there is no group to join.

Added the Xcode command line tools as a macOS-only step, before anything that
builds. node-pty ships no prebuilt binary on any platform and always falls
through to node-gyp, so `bun install` cannot finish without a compiler — and it
fails deep in a dependency tree naming neither Xcode nor node-pty. `xcode-select
--install` opens a dialogue and returns immediately, so the step says to come
back rather than pretending to have waited.

Tailscale takes the cask, not install.sh — that script is a Linux package-manager
wrapper. The cask ships a usable CLI; the Mac App Store build is sandboxed and
does not.

Not run on a Mac. There isn't one here, so this is read from the code and from
what each tool documents, not observed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-13 02:29:56 +00:00
co-authored by Claude Opus 5
parent 7280d13b93
commit b075f1f882
7 changed files with 316 additions and 16 deletions
+79 -4
View File
@@ -50,6 +50,8 @@ source "$SCRIPT_DIR/officer-setup/lib/postgres.sh"
source "$SCRIPT_DIR/officer-setup/lib/env.sh"
# shellcheck source=officer-setup/lib/secrets.sh
source "$SCRIPT_DIR/officer-setup/lib/secrets.sh"
# shellcheck source=officer-setup/lib/build.sh
source "$SCRIPT_DIR/officer-setup/lib/build.sh"
trap 'echo ""; echo -e "${RED}╔══════════════════════════════════════════════════╗${NC}"; echo -e "${RED}║ OFFICER SETUP FAILED${NC}"; echo -e "${RED}║ Step: ${CURRENT_STEP:-unknown}${NC}"; echo -e "${RED}║ Line: $LINENO${NC}"; echo -e "${RED}║ Command: $BASH_COMMAND${NC}"; echo -e "${RED}╚══════════════════════════════════════════════════╝${NC}"' ERR
@@ -554,13 +556,86 @@ if ! skip; then
step_ok
fi
# =============================================================================
# 8. Schema
# =============================================================================
step "Schema"
if ! skip; then
echo ""
info "Database schema"
echo " ${SCHEMA_TABLES:-?} tables, applied with 'bun db:push' — drizzle-kit"
echo " diffs the schema code against Postgres and alters it directly. There"
echo " are no migration files and no migration table; the code is the source"
echo " of truth."
echo ""
echo " Only the CORE tables. Every plugin's tables are commented out in"
echo " src/databases/officer_db/src/schema.ts and get created when the"
echo " plugin is installed."
echo ""
if confirm "Push it?"; then
if OUT="$(push_schema)"; then
ok "schema applied"
SUMMARY+=("Schema: ${SCHEMA_TABLES:-?} tables pushed")
else
warn "db:push failed"
echo "$OUT" | tail -12 | sed 's/^/ /'
SUMMARY+=("Schema: FAILED — see the output above")
fi
else
warn "skipped by request — the platform will not start without it"
SUMMARY+=("Schema: SKIPPED by request")
fi
step_ok
fi
# =============================================================================
# 9. Build
# =============================================================================
step "Build"
if ! skip; then
echo ""
info "index.gen.html"
echo " 'bun gen:index' substitutes your public URL into index.html and"
echo " writes index.gen.html, which is the file the server imports. It is"
echo " gitignored, so a fresh clone never has one and the server has no page"
echo " to serve until this runs."
echo ""
echo " URL: ${ENV_PUBLIC_URL:-<not set — run the Environment section first>}"
echo ""
echo " To change it later: bun gen:index https://your.new.url"
echo ""
if [[ -z "${ENV_PUBLIC_URL:-}" ]]; then
ENV_PUBLIC_URL="$(env_get PUBLIC_URL)"
fi
if [[ -z "$ENV_PUBLIC_URL" ]]; then
warn "PUBLIC_URL is not in $(env_file) — run the Environment section, then this one"
SUMMARY+=("Build: SKIPPED — no PUBLIC_URL")
elif confirm "Generate it?"; then
if OUT="$(gen_index)"; then
ok "$(gen_index_output)"
SUMMARY+=("Build: index.gen.html for ${ENV_PUBLIC_URL}")
else
warn "gen:index failed"
echo "$OUT" | tail -8 | sed 's/^/ /'
SUMMARY+=("Build: FAILED — see the output above")
fi
else
warn "skipped by request — the server has no page to serve without it"
SUMMARY+=("Build: SKIPPED by request")
fi
step_ok
fi
# =============================================================================
# NOT BUILT YET
# =============================================================================
# 6 Schema db:push
# 7 Build gen:index
# 8 Services pm2 startOrRestart · save · startup
# 9 Verify are the processes actually up
# 10 Services pm2 startOrRestart · save · startup
# 11 Verify are the processes actually up
echo ""
echo -e "${BOLD} Pre-flight complete.${NC} The remaining sections are not built yet."