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:
@@ -150,9 +150,52 @@ load_answers() {
|
||||
# file — the point of asking for a single step is to run that step.
|
||||
ONLY_STEP="${ONLY_STEP:-}"
|
||||
|
||||
# ── Steps that do not exist on macOS ──
|
||||
#
|
||||
# A Mac running Officer is a DEV MACHINE, never a server. That is not a
|
||||
# simplification to revisit: nobody puts a laptop behind a public hostname and
|
||||
# hands it a tailnet exit node, and the sections below are all about being a
|
||||
# server that is on all the time.
|
||||
#
|
||||
# Most would fail rather than misbehave — there is 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 its address
|
||||
# on a network it moves between every day.
|
||||
#
|
||||
# Keyed on the step title, so the sections themselves stay Linux code with no
|
||||
# `if macos` branches threaded through them. The reason is printed, because a
|
||||
# silent skip and a missing step look identical.
|
||||
declare -A MACOS_SKIP=(
|
||||
["User account"]="accounts are System Settings' business on a Mac, not a script's"
|
||||
["Disk space"]="ballast and swap tuning are server concerns"
|
||||
["Locale"]="macOS manages locale itself"
|
||||
["Timezone"]="macOS manages the timezone itself"
|
||||
["Swap"]="macOS sizes its own swap dynamically"
|
||||
["Emergency disk ballast"]="a server trick for a machine nobody is sitting at"
|
||||
["earlyoom"]="Linux OOM killer tuning; macOS has its own memory pressure handling"
|
||||
["inotify watch limit"]="Linux inotify; macOS watches files through FSEvents"
|
||||
["Sleep and suspend"]="a laptop SHOULD sleep — this stops a server from doing it"
|
||||
["Boot hang"]="a systemd boot ordering fix"
|
||||
["SSH access"]="hardening a door a dev machine should not be opening"
|
||||
["DNS"]="systemd-resolved"
|
||||
["Network address"]="netplan, and a laptop moves between networks by design"
|
||||
["fail2ban"]="brute-force protection for an exposed SSH port"
|
||||
["Unattended upgrades"]="apt; macOS updates through Software Update"
|
||||
["Firewall"]="ufw; macOS has its own application firewall"
|
||||
["Shell"]="zsh is already the default, and tmux is a choice you make yourself"
|
||||
)
|
||||
|
||||
step() {
|
||||
CURRENT_STEP="$1"
|
||||
|
||||
if [[ "${OS:-}" == "macos" && -n "${MACOS_SKIP[$1]:-}" ]]; then
|
||||
echo ""
|
||||
echo -e "${BOLD}── $1 ──${NC}"
|
||||
echo -e " ${GREEN}SKIP${NC}: not on macOS — ${MACOS_SKIP[$1]}"
|
||||
SKIP_STEP=true
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$ONLY_STEP" ]]; then
|
||||
if [[ "${1,,}" == "${ONLY_STEP,,}" ]]; then
|
||||
SKIP_STEP=false
|
||||
@@ -585,6 +628,15 @@ default_iface() {
|
||||
# firewall open on one. Every branch downstream is about what this machine is
|
||||
# exposed to, so it is worth one deliberate keystroke rather than an Enter.
|
||||
ask_machine_role() {
|
||||
# Not a question on a Mac. Officer on macOS is a dev helper on a machine
|
||||
# somebody sits at — there is no homelab or VPS answer that would make sense,
|
||||
# and every section that branches on the role branches toward "server".
|
||||
if [[ "${OS:-}" == "macos" && -z "$MACHINE_ROLE" ]]; then
|
||||
MACHINE_ROLE="dev"
|
||||
info "macOS — treated as a dev machine. The server-only sections are skipped."
|
||||
return
|
||||
fi
|
||||
|
||||
if [[ -n "$MACHINE_ROLE" ]]; then
|
||||
case "$MACHINE_ROLE" in
|
||||
homelab | vps | dev) return ;;
|
||||
|
||||
Reference in New Issue
Block a user