move host setup into scripts/setup/

scripts/ was holding two unrelated kinds of thing: install-this-machine, and run-this-occasionally. The
eight installers now live in scripts/setup/; what stays at the top level is the build steps (gen-index,
prebuild, build/) and the two maintenance scripts (reindex-music, rebuild-soulseek-tree).

The move is not just a rename. Three of these derive the repo root from their own location:

  setup.sh:51            PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
  setup_mac_light.sh:51  same
  cleanup-desktop.sh:134 ENV_FILE="$(dirname "$0")/../.env"

Left alone, all three would now resolve to scripts/ — and nothing downstream complains. PROJECT_DIR is
where .env is written, where `bun install`, `gen:index` and `db:push` run, and what pm2 is pointed at, so
a fresh install would have quietly provisioned scripts/ and reported success. cleanup-desktop.sh fails
the other way: it would find no .env, print "No .env — skipping", and leave the real VNC_PASSWORD in the
real file. All three are now `../..` with a comment saying why the level matters.

provision-user-dirs.ts imports data-path.ts relatively; that one tsgo caught.

Also disambiguated `setup.sh` where it had become two files. app-store/templates/<name>/setup.sh is a
per-sidecar installer with its own contract, and preflight.ts + docs/sidecar-app-store.md discussed both
in the same paragraph. The host one is now spelled with its full path at those sites.

Verified: bash -n on all six shell scripts, tsgo clean, os-user tests pass, both derivations resolve to
the repo root, starship.toml still resolves from os-user-shell.ts, and provision-user-dirs.ts runs under
DRY_RUN.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-12 04:02:19 +00:00
co-authored by Claude Opus 5
parent 37adc65a12
commit 9c353f5f0d
18 changed files with 48 additions and 35 deletions
@@ -26,7 +26,7 @@ set -euo pipefail
# their profile in it. Opt in rather than surprise someone.
#
# Usage:
# bash scripts/cleanup-desktop.sh [--purge-brave]
# bash scripts/setup/cleanup-desktop.sh [--purge-brave]
#
# Reboot afterwards: the GDM and GRUB changes are both boot-time.
@@ -131,7 +131,9 @@ fi
# --- Step 7: .env ---
echo "[7/7] Cleaning .env..."
ENV_FILE="$(cd "$(dirname "$0")/.." && pwd)/.env"
# ../.. — this lives in scripts/setup/. A wrong level here is quiet in the other direction: the sed
# below simply finds no file, reports "No .env" and leaves the real VNC_PASSWORD in place.
ENV_FILE="$(cd "$(dirname "$0")/../.." && pwd)/.env"
if [ -f "$ENV_FILE" ]; then
sed -i '/^VNC_PASSWORD=/d; /^VNC_PORT=/d' "$ENV_FILE"
echo " Removed VNC entries."
@@ -1,7 +1,7 @@
// Create the per-user root under DATA_PATH for the given accounts.
//
// bun scripts/provision-user-dirs.ts a@b.com c@d.com
// DRY_RUN=1 bun scripts/provision-user-dirs.ts a@b.com
// bun scripts/setup/provision-user-dirs.ts a@b.com c@d.com
// DRY_RUN=1 bun scripts/setup/provision-user-dirs.ts a@b.com
//
// Takes emails as arguments rather than reading the user table: the directory layout does not depend
// on the database, and keeping the DB out means this runs with nothing else up. At invite time the
@@ -19,13 +19,13 @@ import { join } from 'node:path';
// The list and DATA_PATH itself come from the platform rather than being restated here. The owner's
// create-account handler provisions the same skeleton, and a script that drifted from it would produce
// accounts that differ by how they were made. Importing data-path.ts pulls in no database and no server.
import { DATA_PATH, USER_DIRS } from '../src/servers/data-path';
import { DATA_PATH, USER_DIRS } from '../../src/servers/data-path';
const DRY_RUN = process.env.DRY_RUN === '1';
const emails = process.argv.slice(2).filter(Boolean);
if (!emails.length) {
console.error('Usage: bun scripts/provision-user-dirs.ts <email> [email...]');
console.error('Usage: bun scripts/setup/provision-user-dirs.ts <email> [email...]');
process.exit(2);
}
@@ -7,7 +7,7 @@ set -euo pipefail
# capture an Xorg server, NOT a Wayland compositor — so we install the full GNOME desktop but force GDM
# onto the Xorg session (WaylandEnable=false). Auto-login is enabled so a user session owns :0 for the
# mirror to attach to. Switching the display manager takes effect on the next reboot.
# Usage: ./scripts/setup-desktop.sh
# Usage: ./scripts/setup/setup-desktop.sh
echo "=== Officer Remote Desktop Setup (Ubuntu GNOME on Xorg) ==="
echo ""
@@ -4,8 +4,8 @@
# Outputs parseable key=value lines to stdout; all prompts go to stderr.
#
# Usage:
# bash scripts/setup-dockers.sh
# eval "$(bash scripts/setup-dockers.sh)"
# bash scripts/setup/setup-dockers.sh
# eval "$(bash scripts/setup/setup-dockers.sh)"
#
# Environment overrides:
# SETUP_DOCKER_SERVICES="1 2 3" — pre-select services (or "all"/"none")
+7 -4
View File
@@ -3,8 +3,8 @@
# Run once on a fresh Ubuntu/Debian host before launching the server.
#
# Usage:
# bash scripts/setup.sh # full server install
# OFFICER_PROFILE=light bash scripts/setup.sh # light install
# bash scripts/setup/setup.sh # full server install
# OFFICER_PROFILE=light bash scripts/setup/setup.sh # light install
#
# PROFILES
# full Everything: the self-hosted estate, the remote desktop, the music/audio stack, the shell
@@ -48,7 +48,10 @@ is_light() { [ "$OFFICER_PROFILE" = "light" ]; }
if is_light; then ECOSYSTEM_FILE="ecosystem.light.config.cjs"; else ECOSYSTEM_FILE="ecosystem.config.cjs"; fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# ../.. — this lives in scripts/setup/, so the repo root is two levels up, not one. Nothing here fails
# loudly if that is wrong: PROJECT_DIR is where .env is written, where `bun install` and `db:push` run and
# where pm2 is pointed, so an off-by-one level silently sets up scripts/ instead of the repo.
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
# Resolve the real user's home even when running under sudo
if [[ -n "${SUDO_USER:-}" ]]; then
@@ -540,7 +543,7 @@ if [ ! -f "$STARSHIP_DEST" ]; then
elif cmp -s "$SCRIPT_DIR/starship.toml" "$STARSHIP_DEST"; then
skip "starship config"
else
warn "starship config kept — yours differs (cp scripts/starship.toml ~/.config/ to take this one)"
warn "starship config kept — yours differs (cp scripts/setup/starship.toml ~/.config/ to take this one)"
fi
@@ -1,14 +1,14 @@
#!/bin/bash
# Officer — macOS laptop setup.
#
# The barebones counterpart to scripts/setup.sh (which targets an Ubuntu/Debian server and is left
# The barebones counterpart to scripts/setup/setup.sh (which targets an Ubuntu/Debian server and is left
# alone). This installs only what a laptop workflow needs: the file browser, Claude/opencode chat,
# and a terminal. No Go/Rust/cliamp/PulseAudio, no neovim, no shell dotfile stack, no VNC desktop,
# no sudoers grant, no power-management changes.
#
# EVERY STEP IS OPTIONAL. Each one prompts before doing anything, and can be preset non-interactively:
#
# SETUP_POSTGRES=0 SETUP_OPENCODE=0 bash scripts/setup_mac_light.sh
# SETUP_POSTGRES=0 SETUP_OPENCODE=0 bash scripts/setup/setup_mac_light.sh
#
# SETUP_PACKAGES brew node@22 / bun / ffmpeg SETUP_CLAUDE claude code CLI
# SETUP_POSTGRES brew postgresql@18 + createdb SETUP_OPENCODE opencode CLI
@@ -22,7 +22,7 @@
# This script never calls sudo itself — everything lands under the Homebrew prefix or $HOME. Note
# that Homebrew's own installer does ask for an administrator password on a fresh Mac.
#
# Usage: bash scripts/setup_mac_light.sh
# Usage: bash scripts/setup/setup_mac_light.sh
set -euo pipefail
@@ -48,7 +48,10 @@ FAILURES=()
note_failure() { FAILURES+=("$1"); fail "$1"; }
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
# ../.. — this lives in scripts/setup/. See the note in setup.sh: PROJECT_DIR is where .env is written
# and where bun install, gen:index, db:push and pm2 are pointed, and none of them fails loudly on the
# wrong directory.
PROJECT_DIR="$(cd "$SCRIPT_DIR/../.." && pwd)"
PG_FORMULA="postgresql@18"
PG_DATABASE="officer_dev"
@@ -103,7 +106,7 @@ echo "════════════════════════
step "Preflight"
if [ "$(uname -s)" != "Darwin" ]; then
fail "This script is macOS-only. On Linux use scripts/setup.sh."
fail "This script is macOS-only. On Linux use scripts/setup/setup.sh."
exit 1
fi
@@ -532,5 +535,5 @@ echo " • Not run on macOS: VNC desktop, email sync, music indexer, cliamp aud
echo " that front a container or an external service — vault, slskd, headscale, transmission,"
echo " invoiceshelf, memos, photos, caldav, notify, wallet. See ecosystem.mac.light.config.cjs."
echo " • Pin a specific Claude CLI with CLAUDE_BIN=/path/to/claude in .env if you need to"
echo " • Re-run any single step with e.g. SETUP_OPENCODE=1 bash scripts/setup_mac_light.sh"
echo " • Re-run any single step with e.g. SETUP_OPENCODE=1 bash scripts/setup/setup_mac_light.sh"
echo ""