Dotfiles/setup/tools/migrate-to-greetd.sh

221 lines
10 KiB
Bash
Executable File

#!/bin/bash
# =============================================================================
# migrate-to-greetd.sh — switch an existing install to Plymouth + greetd/ReGreet
# =============================================================================
# Migrates a machine that currently boots lightdm / ly / GDM / SDDM / LXDM (or a
# bare greetd+tuigreet) to this repo's current default boot experience:
#
# Plymouth skull splash → greetd + ReGreet + cage (Wayland-native,
# cyberqueer-themed graphical greeter)
#
# This is the Wayland counterpart to migrate-to-lightdm.sh. ReGreet runs on
# wlroots (inside a cage kiosk), so it drives every output natively (no blank
# monitor) and hands input straight to the Wayland session with no Xorg→Wayland
# VT handover race — the reason The-Core moved off the LightDM (Xorg) greeter.
#
# What it does:
# 1. Detects the currently-configured display manager(s).
# 2. Disables every known greeter EXCEPT greetd — for the NEXT boot only. It
# does NOT stop your running session, so you stay logged in until you
# reboot yourself.
# 3. Runs the greetd-regreet module (installs greetd + greetd-regreet + cage,
# deploys the greetd/ReGreet config, the cyberqueer regreet.css skin, the
# skull fallback background + wallpaper-sync units, sets up PAM/FIDO,
# disables lightdm/ly@tty1/getty@tty1, and enables greetd.service).
# 4. Runs the plymouth module (skull splash, initramfs + GRUB cmdline) unless
# --no-plymouth is given.
#
# greetd.service is the TARGET, so it is never disabled here: a machine already
# on a bare greetd+tuigreet is simply reconfigured to run ReGreet instead.
#
# It reuses the real module scripts under optional-Modules/apps/ so there is no
# duplicated install logic — this tool only handles detection, teardown of the
# OLD display manager, and orchestration.
#
# Safe to re-run (idempotent). Reboot to complete the switch.
#
# Usage:
# migrate-to-greetd.sh [--yes] [--no-plymouth] [--dry-run] [--help]
# -y, --yes Skip the confirmation prompt (required for non-TTY runs)
# --no-plymouth Migrate the display manager only; leave Plymouth alone
# -n, --dry-run Print what would happen; change nothing
# -h, --help Show this help and exit
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SETUP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
APPS="$SETUP_DIR/modules/optional-Modules/apps"
# Shared helpers: log / skip / warn / err, and best-effort disable_service.
source "$SETUP_DIR/modules/lib/logging.sh"
# ── Argument parsing ──────────────────────────────────────────────────────────
ASSUME_YES=0
DO_PLYMOUTH=1
DRY_RUN=0
usage() {
cat <<'EOF'
migrate-to-greetd.sh — switch this machine to Plymouth + greetd/ReGreet (cyberqueer)
Disables the current display manager (lightdm / ly / GDM / SDDM / LXDM / …) for
the next boot, installs and themes the greetd + ReGreet (Wayland) greeter, and
sets up the Plymouth splash. Your running session is left untouched; reboot to
complete the switch.
Usage:
migrate-to-greetd.sh [--yes] [--no-plymouth] [--dry-run] [--help]
-y, --yes Skip the confirmation prompt (required for non-TTY runs)
--no-plymouth Migrate the display manager only; leave Plymouth alone
-n, --dry-run Print what would happen; change nothing
-h, --help Show this help and exit
EOF
}
while [[ $# -gt 0 ]]; do
case "$1" in
-y|--yes) ASSUME_YES=1 ;;
--no-plymouth) DO_PLYMOUTH=0 ;;
-n|--dry-run) DRY_RUN=1 ;;
-h|--help) usage; exit 0 ;;
*) err "Unknown argument: $1"; echo "Try --help." >&2; exit 2 ;;
esac
shift
done
# In dry-run, describe an action instead of doing it. In real mode, run it.
run() {
if (( DRY_RUN )); then
printf '[dry-run] would run: %s\n' "$*"
else
"$@"
fi
}
# ── Known display managers ────────────────────────────────────────────────────
# Every greeter/DM unit this tool knows how to turn off. greetd is the TARGET,
# so it never appears here (a bare greetd+tuigreet install is reconfigured, not
# disabled). ly is a template unit (ly@tty1) but some setups use the plain
# ly.service alias, so both are listed.
OTHER_DMS=(
"lightdm.service"
"ly@tty1.service" "ly.service"
"gdm.service" "gdm3.service"
"sddm.service"
"lxdm.service"
"xdm.service"
"slim.service"
"lemurs.service"
"emptty.service"
)
# ── 1. Detect what is configured now ──────────────────────────────────────────
log "Detecting the current display manager configuration..."
# The canonical "which DM boots" pointer is the display-manager.service symlink.
# Use plain readlink to get the intended target name even if the link is broken;
# a self-referential/absent target means no real DM is configured there.
primary_dm=""
if dm_link="$(readlink /etc/systemd/system/display-manager.service 2>/dev/null)"; then
dm_link="$(basename "$dm_link")"
[[ "$dm_link" != "display-manager.service" ]] && primary_dm="$dm_link"
fi
# Also probe every known unit directly — ly-based installs often have no
# display-manager.service symlink, they just enable ly@tty1 on tty1.
enabled_dms=()
for unit in "${OTHER_DMS[@]}"; do
state="$(systemctl is-enabled "$unit" 2>/dev/null || true)"
[[ "$state" == "enabled" || "$state" == "alias" || "$state" == "enabled-runtime" ]] \
&& enabled_dms+=("$unit")
done
# `is-enabled` on an absent unit both prints "not-found" and exits non-zero;
# capture with `|| true` (never `|| echo`, which would concatenate two lines)
# and normalise the "not installed" cases to one label.
greetd_state="$(systemctl is-enabled greetd.service 2>/dev/null || true)"
[[ -z "$greetd_state" || "$greetd_state" == "not-found" ]] && greetd_state="not-installed"
echo
echo " Current display-manager.service : ${primary_dm:-<none>}"
if (( ${#enabled_dms[@]} )); then
echo " Enabled greeter units : ${enabled_dms[*]}"
else
echo " Enabled greeter units : <none detected>"
fi
echo " greetd.service : $greetd_state"
echo " Plymouth migration : $( ((DO_PLYMOUTH)) && echo 'yes' || echo 'skipped (--no-plymouth)')"
echo
if (( ${#enabled_dms[@]} == 0 )) && [[ "$greetd_state" == "enabled" ]]; then
log "greetd already appears to be the active greeter — re-running to install/refresh ReGreet + theme."
fi
# ── 2. Confirm ────────────────────────────────────────────────────────────────
# This changes what greets you at the NEXT boot. Require an explicit yes unless
# --yes was given; on a non-interactive stdin, --yes is mandatory.
if (( ! ASSUME_YES )); then
if [[ ! -t 0 ]]; then
err "Non-interactive shell and --yes not given — refusing to change the display manager."
exit 1
fi
read -r -p "Switch this machine to Plymouth + greetd/ReGreet as described above? [y/N] " reply
case "$reply" in
y|Y|yes|YES) ;;
*) warn "Aborted — nothing changed."; exit 0 ;;
esac
fi
# ── 3. Disable the OLD display managers (next boot only) ──────────────────────
# We intentionally do NOT `systemctl stop` the running greeter: that would kill
# your current graphical session. Disabling only removes it from the next boot;
# greetd.service (enabled below by the module) takes over then.
if (( ${#enabled_dms[@]} )); then
log "Disabling old display manager(s) for the next boot: ${enabled_dms[*]}"
for unit in "${enabled_dms[@]}"; do
run disable_service "$unit"
done
else
skip "No competing display managers enabled — nothing to disable."
fi
# ── 4. Install + theme + enable greetd/ReGreet (delegated to the module) ──────
# greetd-regreet.sh installs greetd + greetd-regreet + cage, deploys the greetd
# config + ReGreet config + cyberqueer regreet.css skin + skull background,
# wires up PAM/FIDO and the wallpaper-sync units, disables lightdm/ly@tty1/
# getty@tty1, and enables greetd.service. Running it here keeps a single source
# of truth.
log "Setting up greetd + ReGreet via the greetd-regreet module..."
run bash "$APPS/greetd-regreet.sh"
# ── 5. Plymouth splash (delegated to the module) ──────────────────────────────
if (( DO_PLYMOUTH )); then
# Upgrade cleanup: the current theme is a centred skull + boot-log tail. The
# previous version scaled the skull full-screen and drew a spinning-dot
# throbber from dot.png. That file is now dead weight — strip it (and any
# other stale theme assets) BEFORE re-running the module, so it is neither
# rendered nor baked into the initramfs that plymouth.sh rebuilds.
THEME_DIR="/usr/share/plymouth/themes/m-archy"
for stale in "$THEME_DIR/dot.png"; do
if [[ -e "$stale" ]]; then
log "Removing obsolete Plymouth asset: $stale"
run sudo rm -f "$stale"
fi
done
log "Setting up the Plymouth splash via the plymouth module..."
run bash "$APPS/plymouth.sh"
else
skip "Skipping Plymouth setup (--no-plymouth)."
fi
# ── Done ──────────────────────────────────────────────────────────────────────
echo
if (( DRY_RUN )); then
log "Dry run complete — no changes were made."
else
log "Migration complete. Your current session is untouched."
log "Reboot to boot into the Plymouth splash and the greetd/ReGreet cyberqueer greeter."
fi