Single-script builder (nosignal.sh) that turns a stock Arch Linux ISO into a fully-offline installer for a themed Hyprland + caelestia (Quickshell) desktop: matching SDDM greeter, Btrfs/Limine bootable snapshots, chwd-style GPU detection, and a curated "os updates" layer (keybind cheatsheet, settings panels, system polish, on-box management skill). See README.md. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
72 lines
3.3 KiB
Bash
Executable file
72 lines
3.3 KiB
Bash
Executable file
#!/bin/sh
|
|
# patch-lock-pam.sh — make the Caelestia lock screen use a faillock-free PAM
|
|
# service. Two parts, both idempotent:
|
|
#
|
|
# 1. DELIVER the faillock-free `caelestia` service into the directory the lock
|
|
# actually reads — Quickshell.shellDir + "/assets/pam.d" — i.e.
|
|
# /etc/xdg/quickshell/caelestia/assets/pam.d/caelestia. (Placing it in
|
|
# /etc/pam.d/caelestia, which PamContext never reads, makes the lock
|
|
# fall through to assets/pam.d/passwd — still faillock'd — and reject even
|
|
# the correct password.)
|
|
# 2. REPOINT the lock's PamContext at it: config: "passwd" -> "caelestia".
|
|
#
|
|
# Runs as root (via the installer, or the pacman hook after every caelestia-shell
|
|
# upgrade, which restores the shell tree under /etc/xdg — so BOTH the asset file
|
|
# and the repoint must be re-applied here each time, or an upgrade drops them).
|
|
#
|
|
# Symptom (before this fix): the lock screen rejects the CORRECT password; only a
|
|
# reboot escapes. The stock lock authenticates via PamContext { config: "passwd",
|
|
# configDirectory: shellDir + "/assets/pam.d" } -> assets/pam.d/passwd, which
|
|
# calls pam_faillock; a few failed unlocks trip a temporary account lock that
|
|
# then refuses every attempt (right password included) until /run/faillock clears.
|
|
#
|
|
# TARGET (Pam.qml) is overridable for testing the change against a copy; the
|
|
# asset destination is derived from it (shellDir = TARGET/../../..).
|
|
set -eu
|
|
|
|
HERE=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
|
|
SRC_PAM="$HERE/etc-pam.d-caelestia" # the faillock-free service we ship
|
|
|
|
TARGET=${TARGET:-/etc/xdg/quickshell/caelestia/modules/lock/Pam.qml}
|
|
|
|
[ -f "$TARGET" ] || { echo "caelestia-shell lock not found at $TARGET — nothing to patch"; exit 0; }
|
|
|
|
# shellDir = the caelestia shell root = three levels up from modules/lock/Pam.qml.
|
|
SHELLDIR=$(CDPATH= cd -- "$(dirname -- "$TARGET")/../.." && pwd)
|
|
ASSETS_PAMD="$SHELLDIR/assets/pam.d"
|
|
|
|
# --- 1. deliver the faillock-free service where the lock reads it -------------
|
|
if [ -f "$SRC_PAM" ]; then
|
|
install -d -m 0755 "$ASSETS_PAMD"
|
|
install -m 0644 "$SRC_PAM" "$ASSETS_PAMD/caelestia"
|
|
echo ":: installed $ASSETS_PAMD/caelestia (faillock-free lock auth)"
|
|
else
|
|
echo "WARNING: source PAM service $SRC_PAM missing — cannot deliver the lock service." >&2
|
|
fi
|
|
|
|
# --- 2. repoint the lock's PamContext at it ----------------------------------
|
|
# Already pointed at our service?
|
|
if grep -q 'config:[[:space:]]*"caelestia"' "$TARGET"; then
|
|
echo ":: Pam.qml already points at the caelestia lock service"
|
|
exit 0
|
|
fi
|
|
|
|
# Only act if the stock "passwd" service is referenced.
|
|
if ! grep -q 'config:[[:space:]]*"passwd"' "$TARGET"; then
|
|
echo "WARNING: Pam.qml does not reference config: \"passwd\" — upstream shape changed." >&2
|
|
echo " Leaving it untouched; review the lock PamContext for the new" >&2
|
|
echo " service name and update the regex in $(basename "$0")." >&2
|
|
exit 0
|
|
fi
|
|
|
|
cp -n "$TARGET" "$TARGET.pre-nosignal" 2>/dev/null || true
|
|
|
|
# Repoint only the PAM service name; keep everything else as-is.
|
|
sed -i 's/config:\([[:space:]]*\)"passwd"/config:\1"caelestia"/g' "$TARGET"
|
|
|
|
if grep -q 'config:[[:space:]]*"caelestia"' "$TARGET"; then
|
|
echo ":: patched $TARGET (lock now uses the faillock-free caelestia PAM service)"
|
|
else
|
|
echo "WARNING: patch did not apply — Pam.qml left untouched." >&2
|
|
exit 0
|
|
fi
|