scripts/setup is the initial install, nothing else
Two of the eight did not belong. cleanup-desktop.sh is the teardown — the inverse of an install, not part of one. provision-user-dirs.ts runs per account at invite time, on a machine that is already set up. Both are back at the top level, with their `../` derivations and usage strings put back. What is left is what a fresh machine runs once: the two installers (setup.sh, setup_mac_light.sh), the two things setup.sh calls (setup-dockers.sh, setup-desktop.sh), and the two files they deploy — starship.toml, copied to ~/.config, and officer-set-display.sh, which setup-desktop.sh installs to ~/.local/bin as a login-time mode setter. The last one is not a setup script and does not read like one; it is here because it is install payload, same as the toml, and setup-desktop.sh loads it by `$(dirname $0)`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,149 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Officer Remote Desktop teardown — the inverse of setup-desktop.sh.
|
||||
#
|
||||
# WHAT THIS DOES AND DOES NOT REMOVE, and why the distinction matters:
|
||||
#
|
||||
# Officer used to install a desktop of its OWN — XFCE on a TigerVNC Xvnc server — so tearing the
|
||||
# remote desktop down meant deleting a desktop environment nobody else was using. That is no longer
|
||||
# the model. Officer now MIRRORS the machine's existing physical session with x11vnc, which means
|
||||
# ubuntu-desktop, gdm3 and dbus-x11 are the machine's own desktop, not Officer's. Removing them here
|
||||
# would take the user's graphical session with it.
|
||||
#
|
||||
# So this script removes Officer's *configuration of* the desktop and the mirroring pieces, and
|
||||
# leaves the desktop itself alone:
|
||||
#
|
||||
# removed x11vnc, ~/.vnc, the GDM auto-login + forced-Xorg keys, the forced EDID and its kernel
|
||||
# command line, the login-time mode setter, the legacy officer-vnc systemd unit, and the
|
||||
# VNC entries in .env
|
||||
# kept ubuntu-desktop, gdm3, dbus-x11 — the machine's desktop
|
||||
# legacy XFCE and TigerVNC are purged if present, since a host set up by an older version of
|
||||
# setup-desktop.sh still carries them and they are exactly what this is undoing
|
||||
#
|
||||
# Brave is only removed with --purge-brave. setup-desktop.sh installs it, so removing it is the
|
||||
# symmetric thing to do, but by the time anyone runs this it is usually just the user's browser with
|
||||
# their profile in it. Opt in rather than surprise someone.
|
||||
#
|
||||
# Usage:
|
||||
# bash scripts/setup/cleanup-desktop.sh [--purge-brave]
|
||||
#
|
||||
# Reboot afterwards: the GDM and GRUB changes are both boot-time.
|
||||
|
||||
PURGE_BRAVE=false
|
||||
for arg in "$@"; do
|
||||
case "$arg" in
|
||||
--purge-brave) PURGE_BRAVE=true ;;
|
||||
*) echo "unknown option: $arg" >&2; exit 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
echo "=== Officer Remote Desktop teardown ==="
|
||||
echo ""
|
||||
|
||||
# --- Step 1: stop the mirror and remove x11vnc ---
|
||||
echo "[1/7] Stopping the screen mirror..."
|
||||
# The VNC sidecar spawns x11vnc; kill the server itself rather than the sidecar, which PM2 owns.
|
||||
pkill -x x11vnc 2>/dev/null || true
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get remove -y --purge x11vnc >/dev/null 2>&1 || true
|
||||
rm -rf ~/.vnc
|
||||
echo " x11vnc removed, ~/.vnc deleted."
|
||||
|
||||
# --- Step 2: revert the GDM session configuration ---
|
||||
# setup-desktop.sh forces Xorg (x11vnc cannot capture Wayland) and enables auto-login (so a user
|
||||
# session owns the display for the mirror to attach to). Both are Officer's doing, so both go back.
|
||||
echo "[2/7] Reverting GDM auto-login and the forced Xorg session..."
|
||||
GDM_CONF=/etc/gdm3/custom.conf
|
||||
if [ -f "$GDM_CONF" ]; then
|
||||
sudo cp "$GDM_CONF" "$GDM_CONF.bak-$(date +%Y%m%d%H%M%S)"
|
||||
# Auto-login off, and drop the username line entirely rather than leave a dangling account name.
|
||||
sudo sed -i 's|^[[:space:]]*AutomaticLoginEnable=.*|AutomaticLoginEnable=false|' "$GDM_CONF"
|
||||
sudo sed -i '/^[[:space:]]*AutomaticLogin=/d' "$GDM_CONF"
|
||||
# Comment the Xorg forcing so the distro default (Wayland on Ubuntu) applies again.
|
||||
sudo sed -i 's|^[[:space:]]*WaylandEnable=false.*|#WaylandEnable=false|' "$GDM_CONF"
|
||||
echo " Auto-login disabled; Wayland restored to the distro default."
|
||||
echo " ! The next boot will use Wayland. Nothing can mirror it — that is the point of this script,"
|
||||
echo " but if you want the screen back later, re-run setup-desktop.sh."
|
||||
else
|
||||
echo " No $GDM_CONF — skipping."
|
||||
fi
|
||||
|
||||
# --- Step 3: drop the forced EDID from the kernel command line ---
|
||||
echo "[3/7] Removing the headless display forcing..."
|
||||
if grep -q "drm.edid_firmware=" /etc/default/grub 2>/dev/null; then
|
||||
sudo cp /etc/default/grub "/etc/default/grub.bak-$(date +%Y%m%d%H%M%S)"
|
||||
# Strip both parameters, then collapse the double space they leave behind.
|
||||
sudo sed -i -E 's/[[:space:]]*drm\.edid_firmware=[^" ]*//g; s/[[:space:]]*video=[^" ]*//g' /etc/default/grub
|
||||
sudo sed -i -E 's/GRUB_CMDLINE_LINUX_DEFAULT="[[:space:]]+/GRUB_CMDLINE_LINUX_DEFAULT="/; s/[[:space:]]+"$/"/' /etc/default/grub
|
||||
sudo update-grub >/dev/null 2>&1
|
||||
echo " Kernel command line cleaned and GRUB regenerated (takes effect on reboot)."
|
||||
else
|
||||
echo " No forced EDID in GRUB — skipping."
|
||||
fi
|
||||
sudo rm -f /lib/firmware/edid/officer-screen.bin /lib/firmware/edid/officer-connector
|
||||
# Only remove the directory if Officer's files were the only thing in it.
|
||||
sudo rmdir /lib/firmware/edid 2>/dev/null || true
|
||||
|
||||
# --- Step 4: remove the login-time mode setter ---
|
||||
echo "[4/7] Removing the display mode setter..."
|
||||
rm -f ~/.local/bin/officer-set-display.sh ~/.config/autostart/officer-set-display.desktop
|
||||
echo " Done."
|
||||
|
||||
# --- Step 5: legacy XFCE / TigerVNC residue ---
|
||||
# Only relevant on a host set up by the pre-mirror version of setup-desktop.sh. Harmless elsewhere.
|
||||
echo "[5/7] Removing legacy XFCE / TigerVNC residue..."
|
||||
# Anchored and spelled out on purpose. The tempting shortening to '^libxf' also matches libxfixes,
|
||||
# libxft and libxfont — core X11 libraries GNOME needs — so each xfce-family prefix is named instead.
|
||||
XFCE_PKGS=$(dpkg-query -W -f='${Package}\n' 2>/dev/null | grep -E '^(xfce|xfdesktop|xfwm|xfconf|thunar|libxfce|libxfconf|libgarcon|libexo|exo-utils|tumbler|elementary-xfce)' || true)
|
||||
if [ -n "$XFCE_PKGS" ]; then
|
||||
# shellcheck disable=SC2086
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get remove -y --purge $XFCE_PKGS >/dev/null 2>&1 || true
|
||||
echo " Purged $(echo "$XFCE_PKGS" | wc -l) XFCE package(s)."
|
||||
else
|
||||
echo " No XFCE packages."
|
||||
fi
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get remove -y --purge \
|
||||
tigervnc-standalone-server tigervnc-common tigervnc-tools >/dev/null 2>&1 || true
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get autoremove -y --purge >/dev/null 2>&1 || true
|
||||
rm -rf ~/.config/xfce4 ~/.cache/xfce4 ~/.local/share/xfce4 ~/.config/Thunar ~/.cache/sessions ~/.dmrc.bak-xfce
|
||||
# The pre-mirror setup ran x11vnc/Xvnc from a systemd unit rather than the sidecar.
|
||||
if systemctl list-unit-files officer-vnc.service &>/dev/null; then
|
||||
sudo systemctl stop officer-vnc 2>/dev/null || true
|
||||
sudo systemctl disable officer-vnc 2>/dev/null || true
|
||||
sudo rm -f /etc/systemd/system/officer-vnc.service
|
||||
sudo systemctl daemon-reload
|
||||
echo " Removed the legacy officer-vnc systemd unit."
|
||||
fi
|
||||
|
||||
# --- Step 6: Brave (opt-in) ---
|
||||
echo "[6/7] Browser..."
|
||||
if [ "$PURGE_BRAVE" = true ]; then
|
||||
sudo DEBIAN_FRONTEND=noninteractive apt-get remove -y --purge brave-browser >/dev/null 2>&1 || true
|
||||
sudo rm -f /usr/share/keyrings/brave-browser-archive-keyring.gpg \
|
||||
/etc/apt/sources.list.d/brave-browser-release.list \
|
||||
/usr/bin/brave-browser-stable
|
||||
sudo rm -rf /etc/brave
|
||||
rm -rf ~/.config/BraveSoftware
|
||||
echo " Brave removed, including its profile."
|
||||
else
|
||||
echo " Brave kept (pass --purge-brave to remove it and its profile)."
|
||||
fi
|
||||
|
||||
# --- Step 7: .env ---
|
||||
echo "[7/7] Cleaning .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."
|
||||
else
|
||||
echo " No .env — skipping."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Teardown complete. ubuntu-desktop, gdm3 and dbus-x11 were left in place — they are this"
|
||||
echo "machine's desktop, not Officer's. The app code is untouched: the VNC sidecar keeps running under"
|
||||
echo "PM2, but with x11vnc gone it can no longer start a mirror, so opening /desktop will fail to"
|
||||
echo "connect rather than take the app down with it."
|
||||
echo "REBOOT to drop auto-login and the forced EDID."
|
||||
@@ -1,57 +0,0 @@
|
||||
// Create the per-user root under DATA_PATH for the given accounts.
|
||||
//
|
||||
// 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
|
||||
// caller already knows the email.
|
||||
//
|
||||
// This is the directory skeleton ONLY. It is deliberately not a revival of the old provision.ts, which
|
||||
// also seeded shell rc files and wrote a generated CLAUDE.md + settings.json describing the user's
|
||||
// Docker container. That architecture is gone. What survives from it is the useful part: a user has a
|
||||
// root, and a home inside it.
|
||||
//
|
||||
// Idempotent — an existing directory is left exactly as it is, so re-running is safe.
|
||||
|
||||
import { mkdirSync, existsSync } from 'node:fs';
|
||||
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';
|
||||
|
||||
const DRY_RUN = process.env.DRY_RUN === '1';
|
||||
const emails = process.argv.slice(2).filter(Boolean);
|
||||
|
||||
if (!emails.length) {
|
||||
console.error('Usage: bun scripts/setup/provision-user-dirs.ts <email> [email...]');
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
// A stray argument would create a junk directory next to real user roots, and it would look like a
|
||||
// user. Cheap to refuse.
|
||||
const invalid = emails.filter((e) => !/^[^\s@/]+@[^\s@/]+\.[^\s@/]+$/.test(e));
|
||||
if (invalid.length) {
|
||||
console.error(`Not valid email addresses: ${invalid.join(', ')}`);
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
console.log(`DATA_PATH = ${DATA_PATH}`);
|
||||
console.log(`${DRY_RUN ? 'Would provision' : 'Provisioning'} ${emails.length} user root(s)\n`);
|
||||
|
||||
for (const email of emails) {
|
||||
const root = join(DATA_PATH, email);
|
||||
console.log(`${email}${existsSync(root) ? '' : ' [new root]'}`);
|
||||
|
||||
for (const dir of USER_DIRS) {
|
||||
const path = join(root, dir);
|
||||
if (existsSync(path)) {
|
||||
console.log(` · ${dir} (exists)`);
|
||||
continue;
|
||||
}
|
||||
if (!DRY_RUN) mkdirSync(path, { recursive: true });
|
||||
console.log(` ${DRY_RUN ? '+' : '✓'} ${dir}`);
|
||||
}
|
||||
console.log('');
|
||||
}
|
||||
Reference in New Issue
Block a user