Files
command-center/scripts/install.sh

120 lines
4.4 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# install.sh — idempotent fleet package installer for the ~/.omp repo deployment.
#
# Model: packages/*.pkgs declare DESIRED state per host. This script computes
# (desired − installed) and installs only that delta via pacman/yay. It NEVER
# removes anything. Re-running after a fresh install, or casually months later,
# is safe by construction.
#
# Modes:
# install.sh check (default): print the plan for this host, write nothing
# install.sh --apply install the delta + run host-gated enablement actions
#
# Host selection: --host <name> overrides $(hostname); an unknown host gets the
# common manifest only — wrong-host runs are a no-op, not a hazard.
#
# Sudo: set FRANK_SUDO_PW in the environment for non-interactive runs;
# otherwise sudo prompts normally. The value is never stored in this repo.
set -euo pipefail
REPO="$(git -C "$(dirname "$(realpath "$0")")" rev-parse --show-toplevel 2>/dev/null || true)"
REPO="${INSTALL_REPO:-$REPO}"
[ -n "$REPO" ] && [ -d "$REPO/packages" ] || { echo "install.sh: no packages/ under ${REPO:-<repo>}" >&2; exit 1; }
MODE="check"
HOST="$(hostname)"
while [[ $# -gt 0 ]]; do
case "$1" in
--apply) MODE="apply"; shift ;;
--host) HOST="$2"; shift 2 ;;
*) echo "usage: install.sh [--apply] [--host <name>]" >&2; exit 2 ;;
esac
done
SUDO() {
if [[ -n "${FRANK_SUDO_PW:-}" ]]; then printf '%s' "$FRANK_SUDO_PW" | sudo -S -p '' "$@"
else sudo "$@"; fi
}
read_manifest() { # $1 = manifest path; emits package names, strips comments/blanks
sed 's/#.*//' "$1" | tr -d '\r' | awk '{if ($1) print $1}'
}
# ---- desired-minus-installed delta ------------------------------------------
PKGS=()
for m in common.pkgs "$HOST.pkgs"; do
[[ -f "$REPO/packages/$m" ]] || continue
mapfile -t _pkgs < <(read_manifest "$REPO/packages/$m")
PKGS+=("${_pkgs[@]}")
done
# AUR phase only when the helper exists or can be bootstrapped from a repo pkg
AUR_PKGS=()
if [[ -f "$REPO/packages/aur.pkgs" ]]; then
mapfile -t AUR_PKGS < <(read_manifest "$REPO/packages/aur.pkgs")
fi
# Membership via direct DB query per package — deterministic, no set-diff plumbing.
DELTAC=()
for p in "${PKGS[@]}"; do
pacman -Qq --quiet -- "$p" >/dev/null || DELTAC+=("$p")
done
echo "install.sh [$MODE] host=$HOST"
if [[ ${#DELTAC[@]} -eq 0 ]]; then
echo "repo pkgs: delta empty — nothing to install"
else
echo "repo pkgs to install: ${DELTAC[*]}"
fi
for p in "${AUR_PKGS[@]}"; do
pacman -Qq --quiet -- "$p" >/dev/null || echo "aur pkg pending: $p"
done
[[ "$MODE" == "check" ]] && exit 0
# ---- apply ------------------------------------------------------------------
if [[ ${#DELTAC[@]} -gt 0 ]]; then
SUDO pacman -S --needed --noconfirm -- "${DELTAC[@]}"
fi
# Helper bootstrap: yay itself ships in the cachyos repo (no chicken-and-egg).
if [[ ${#AUR_PKGS[@]} -gt 0 ]] && ! pacman -Qq yay >/dev/null 2>&1; then
SUDO pacman -S --needed --noconfirm -- yay
fi
# AUR builds must NOT run as root (makepkg refuses); yay escalates only for
# the final package install via its internal sudo — prime the timestamp cache.
if [[ ${#AUR_PKGS[@]} -gt 0 ]]; then
if [[ -n "${FRANK_SUDO_PW:-}" ]]; then printf '%s' "$FRANK_SUDO_PW" | sudo -S -p '' true; fi
for p in "${AUR_PKGS[@]}"; do
printf '%s\n' "${INSTALLED[@]}" | grep -qx -- "$p" || {
YAYFLAGS="--answerclean None --answerdiff None" yay -S --needed --noconfirm --aur -- "$p"
}
done
fi
# ---- host-gated enablement ---------------------------------------------------
case "$HOST" in
dankware)
# nvidia sleep fix: package hooks already ship /usr/lib/modprobe.d/nvidia-sleep.conf
# (UseKernelSuspendNotifiers=1 + TemporaryFilePath); enable the units idempotently.
SUDO systemctl enable --now nvidia-suspend nvidia-resume 2>/dev/null || true
;;
blankpad)
# Cezanne iGPU: amdgpu is in-kernel, amd-ucode carried by kernel pkg; no module options.
:
;;
esac
# sshd + firewall — same posture on both hosts (decision 2026-09: ssh open in default zone)
if command -v sshd >/dev/null 2>&1 || pacman -Qq openssh >/dev/null 2>&1; then
SUDO systemctl enable --now sshd
fi
if command -v firewall-cmd >/dev/null 2>&1 && firewall-cmd --state >/dev/null 2>&1; then
if ! firewall-cmd --query-service ssh >/dev/null 2>&1; then
SUDO firewall-cmd --permanent --zone=public --add-service=ssh
SUDO firewall-cmd --reload
fi
fi
echo "install.sh [$MODE] host=$HOST done"