nicer scripts
This commit is contained in:
parent
978a439cfe
commit
7a42926fba
2 changed files with 128 additions and 75 deletions
|
|
@ -1,76 +1,92 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
UID="$(id -u)"
|
||||||
|
USER_BUS="/run/user/$UID/bus"
|
||||||
|
HM_DIR="$HOME/.config/home-manager"
|
||||||
|
SKEL_DIR="/etc/skel/.config/home-manager"
|
||||||
|
|
||||||
# Ensure basic PATH for user units
|
# Ensure basic PATH for user units
|
||||||
export PATH="/run/current-system/sw/bin:${PATH:-}"
|
export PATH="/run/current-system/sw/bin:${PATH:-}"
|
||||||
|
|
||||||
# Try to hook into the session bus if available
|
# Attach to session bus if possible
|
||||||
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] && [ -S "/run/user/$(id -u)/bus" ]; then
|
if [[ -z "${DBUS_SESSION_BUS_ADDRESS:-}" && -S "$USER_BUS" ]]; then
|
||||||
export DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$(id -u)/bus"
|
export DBUS_SESSION_BUS_ADDRESS="unix:path=$USER_BUS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Only continue in an active, unlocked user session
|
have() { command -v "$1" >/dev/null 2>&1; }
|
||||||
if command -v loginctl >/dev/null 2>&1 && [ -n "${XDG_SESSION_ID:-}" ]; then
|
|
||||||
session_class=$(loginctl show-session "${XDG_SESSION_ID}" -p Class --value 2>/dev/null || echo "")
|
# ---- Session sanity check ---------------------------------------------------
|
||||||
session_state=$(loginctl show-session "${XDG_SESSION_ID}" -p State --value 2>/dev/null || echo "")
|
|
||||||
session_locked=$(loginctl show-session "${XDG_SESSION_ID}" -p LockedHint --value 2>/dev/null || echo "yes")
|
if have loginctl && [[ -n "${XDG_SESSION_ID:-}" ]]; then
|
||||||
if [ "${session_class}" != "user" ] || [ "${session_state}" != "active" ] || [ "${session_locked}" != "no" ]; then
|
# One loginctl call instead of three
|
||||||
exit 0
|
eval "$(
|
||||||
fi
|
loginctl show-session "$XDG_SESSION_ID" \
|
||||||
|
-p Class -p State -p LockedHint \
|
||||||
|
--value 2>/dev/null |
|
||||||
|
awk '
|
||||||
|
NR==1{print "SESSION_CLASS="$0}
|
||||||
|
NR==2{print "SESSION_STATE="$0}
|
||||||
|
NR==3{print "SESSION_LOCKED="$0}
|
||||||
|
'
|
||||||
|
)"
|
||||||
|
|
||||||
|
[[ "${SESSION_CLASS:-}" == "user" ]] || exit 0
|
||||||
|
[[ "${SESSION_STATE:-}" == "active" ]] || exit 0
|
||||||
|
[[ "${SESSION_LOCKED:-yes}" == "no" ]] || exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
wait_for_notifications() {
|
# ---- Notifications ----------------------------------------------------------
|
||||||
# Wait briefly for GNOME Shell notifications to come up and the session to be unlocked.
|
|
||||||
if [ -z "${DBUS_SESSION_BUS_ADDRESS:-}" ] || ! command -v gdbus >/dev/null 2>&1; then
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Do not notify in greeter sessions.
|
notifications_ready() {
|
||||||
if [ "${XDG_SESSION_CLASS:-}" != "user" ]; then
|
[[ "${XDG_SESSION_CLASS:-user}" == "user" ]] || return 1
|
||||||
return 1
|
[[ -n "${DBUS_SESSION_BUS_ADDRESS:-}" ]] || return 1
|
||||||
fi
|
have gdbus || return 1
|
||||||
|
|
||||||
# If loginctl is available, wait until this session is unlocked and class=user (not greeter).
|
# Wait for unlock if loginctl is present
|
||||||
if command -v loginctl >/dev/null 2>&1 && [ -n "${XDG_SESSION_ID:-}" ]; then
|
if have loginctl && [[ -n "${XDG_SESSION_ID:-}" ]]; then
|
||||||
for _ in 1 2 3 4 5 6 7; do
|
for _ in {1..7}; do
|
||||||
session_class=$(loginctl show-session "${XDG_SESSION_ID}" -p Class --value 2>/dev/null || echo "")
|
[[ "$(loginctl show-session "$XDG_SESSION_ID" \
|
||||||
locked=$(loginctl show-session "${XDG_SESSION_ID}" -p LockedHint --value 2>/dev/null || echo "yes")
|
-p LockedHint --value 2>/dev/null)" == "no" ]] && break
|
||||||
if [ "${session_class}" = "user" ] && [ "${locked}" = "no" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for _ in 1 2 3 4 5 6 7; do
|
# Wait for notification service
|
||||||
if gdbus introspect --session \
|
for _ in {1..7}; do
|
||||||
|
gdbus introspect --session \
|
||||||
--dest org.freedesktop.Notifications \
|
--dest org.freedesktop.Notifications \
|
||||||
--object-path /org/freedesktop/Notifications >/dev/null 2>&1; then
|
--object-path /org/freedesktop/Notifications \
|
||||||
return 0
|
>/dev/null 2>&1 && return 0
|
||||||
fi
|
|
||||||
sleep 2
|
sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
notify() {
|
notify() {
|
||||||
local title="$1"
|
have notify-send || return 0
|
||||||
shift || true
|
notifications_ready || return 0
|
||||||
if command -v notify-send >/dev/null 2>&1 && wait_for_notifications; then
|
notify-send \
|
||||||
notify-send --app-name="Bootstrap" --urgency=critical --expire-time=0 "$title" "$@" >/dev/null 2>&1 || true
|
--app-name="Bootstrap" \
|
||||||
fi
|
--urgency=critical \
|
||||||
|
--expire-time=0 \
|
||||||
|
"$@" >/dev/null 2>&1 || true
|
||||||
}
|
}
|
||||||
|
|
||||||
notify "Reticulating Splines" "Bootstrapping. Please stay tuned."
|
notify "Reticulating Splines" "Bootstrapping. Please stay tuned."
|
||||||
trap 'notify "Bootstrap finished" "Your system is fully hydrated. It is recommended to logout and back in."' EXIT
|
trap 'notify "Bootstrap finished" "Your system is fully hydrated. It is recommended to logout and back in."' EXIT
|
||||||
|
|
||||||
mkdir -p "$HOME/.config/home-manager"
|
# ---- Home Manager bootstrap -------------------------------------------------
|
||||||
|
|
||||||
|
mkdir -p "$HM_DIR"
|
||||||
|
|
||||||
for f in flake.nix home.nix; do
|
for f in flake.nix home.nix; do
|
||||||
if [ -f "/etc/skel/.config/home-manager/$f" ] && [ ! -e "$HOME/.config/home-manager/$f" ]; then
|
src="$SKEL_DIR/$f"
|
||||||
cp "/etc/skel/.config/home-manager/$f" "$HOME/.config/home-manager/$f"
|
dst="$HM_DIR/$f"
|
||||||
chmod u+rw "$HOME/.config/home-manager/$f"
|
[[ -f "$src" && ! -e "$dst" ]] || continue
|
||||||
fi
|
install -m 600 "$src" "$dst"
|
||||||
done
|
done
|
||||||
|
|
||||||
home-manager switch --flake "$HOME/.config/home-manager#admin"
|
home-manager switch --flake "$HM_DIR#admin"
|
||||||
touch "$HOME/.config/home-manager/.hm_bootstrap_done"
|
touch "$HM_DIR/.hm_bootstrap_done"
|
||||||
|
|
|
||||||
|
|
@ -4,51 +4,84 @@ set -euo pipefail
|
||||||
# Non-interactive Btrfs installer using the flake in this repo.
|
# Non-interactive Btrfs installer using the flake in this repo.
|
||||||
# Defaults: DISK=/dev/vda TARGET_HOST=nanuqsaurus
|
# Defaults: DISK=/dev/vda TARGET_HOST=nanuqsaurus
|
||||||
|
|
||||||
DISK=${DISK:-/dev/vda}
|
DISK="${DISK:-/dev/vda}"
|
||||||
TARGET_HOST=${TARGET_HOST:-nanuqsaurus}
|
TARGET_HOST="${TARGET_HOST:-nanuqsaurus}"
|
||||||
|
|
||||||
SCRIPT_DIR=$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)
|
SCRIPT_DIR="$(cd -- "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||||
REPO_ROOT=$(cd -- "${SCRIPT_DIR}/.." && pwd)
|
REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
||||||
|
|
||||||
|
MNT=/mnt
|
||||||
|
EFI_SIZE=550M
|
||||||
|
|
||||||
|
have() { command -v "$1" >/dev/null 2>&1; }
|
||||||
|
|
||||||
|
die() {
|
||||||
|
echo "ERROR: $*" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
confirm_disk() {
|
||||||
|
echo "About to DESTROY ALL DATA on ${DISK}"
|
||||||
|
lsblk "$DISK" || die "Disk not found: $DISK"
|
||||||
|
echo "Continuing in 5 seconds… (Ctrl+C to abort)"
|
||||||
|
sleep 5
|
||||||
|
}
|
||||||
|
|
||||||
clear
|
clear
|
||||||
|
confirm_disk
|
||||||
|
|
||||||
echo "[1/7] Partitioning ${DISK}"
|
echo "[1/7] Partitioning ${DISK}"
|
||||||
printf "label: gpt\n,550M,U\n,,L\n" | sfdisk "${DISK}"
|
sfdisk "$DISK" <<EOF
|
||||||
|
label: gpt
|
||||||
|
,${EFI_SIZE},U
|
||||||
|
,,L
|
||||||
|
EOF
|
||||||
|
|
||||||
echo "[2/7] Formatting"
|
echo "[2/7] Formatting filesystems"
|
||||||
mkfs.fat -F 32 "${DISK}1"
|
mkfs.fat -F32 "${DISK}1"
|
||||||
mkfs.btrfs -f "${DISK}2"
|
mkfs.btrfs -f "${DISK}2"
|
||||||
|
|
||||||
echo "[3/7] Creating Btrfs subvolumes"
|
echo "[3/7] Creating Btrfs subvolumes"
|
||||||
mkdir -p /mnt
|
mkdir -p "$MNT"
|
||||||
mount "${DISK}2" /mnt
|
mount "${DISK}2" "$MNT"
|
||||||
btrfs subvolume create /mnt/root
|
|
||||||
btrfs subvolume create /mnt/home
|
for subvol in root home nix; do
|
||||||
btrfs subvolume create /mnt/nix
|
btrfs subvolume create "$MNT/$subvol"
|
||||||
umount /mnt
|
done
|
||||||
|
|
||||||
|
umount "$MNT"
|
||||||
|
|
||||||
echo "[4/7] Mounting subvolumes"
|
echo "[4/7] Mounting subvolumes"
|
||||||
mount -o compress=zstd,subvol=root "${DISK}2" /mnt
|
mount -o compress=zstd,subvol=root "${DISK}2" "$MNT"
|
||||||
mkdir -p /mnt/{home,nix,boot}
|
mkdir -p "$MNT"/{home,nix,boot}
|
||||||
mount -o compress=zstd,subvol=home "${DISK}2" /mnt/home
|
|
||||||
mount -o compress=zstd,subvol=nix "${DISK}2" /mnt/nix
|
mount -o compress=zstd,subvol=home "${DISK}2" "$MNT/home"
|
||||||
mount "${DISK}1" /mnt/boot
|
mount -o compress=zstd,subvol=nix "${DISK}2" "$MNT/nix"
|
||||||
|
mount "${DISK}1" "$MNT/boot"
|
||||||
|
|
||||||
echo "[5/7] Copying flake to /etc/nixos"
|
echo "[5/7] Copying flake to /etc/nixos"
|
||||||
mkdir -p /mnt/etc/nixos
|
mkdir -p "$MNT/etc/nixos"
|
||||||
if command -v rsync >/dev/null 2>&1; then
|
|
||||||
rsync -a --exclude '.git' --exclude 'result' --exclude 'node_modules' "${REPO_ROOT}/" /mnt/etc/nixos/
|
EXCLUDES=(--exclude=.git --exclude=result --exclude=node_modules)
|
||||||
|
|
||||||
|
if have rsync; then
|
||||||
|
rsync -a "${EXCLUDES[@]}" "$REPO_ROOT/" "$MNT/etc/nixos/"
|
||||||
else
|
else
|
||||||
(cd "${REPO_ROOT}" && tar -cf - --exclude=.git --exclude=result --exclude=node_modules .) | (cd /mnt/etc/nixos && tar -xf -)
|
(cd "$REPO_ROOT" && tar -cf - "${EXCLUDES[@]/#/--exclude=}" .) \
|
||||||
|
| (cd "$MNT/etc/nixos" && tar -xf -)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[6/7] Generating hardware config"
|
echo "[6/7] Generating hardware config"
|
||||||
mkdir -p /mnt/etc/nixos/hosts
|
HOSTS_DIR="$MNT/etc/nixos/hosts"
|
||||||
nixos-generate-config --root /mnt --show-hardware-config > "/mnt/etc/nixos/hosts/local-${TARGET_HOST}-hardware.nix"
|
mkdir -p "$HOSTS_DIR"
|
||||||
|
|
||||||
host_file="/mnt/etc/nixos/hosts/local-${TARGET_HOST}.nix"
|
HW_FILE="$HOSTS_DIR/local-${TARGET_HOST}-hardware.nix"
|
||||||
if [ ! -e "${host_file}" ]; then
|
HOST_FILE="$HOSTS_DIR/local-${TARGET_HOST}.nix"
|
||||||
cat > "${host_file}" <<EOF
|
|
||||||
|
nixos-generate-config --root "$MNT" --show-hardware-config > "$HW_FILE"
|
||||||
|
|
||||||
|
if [[ ! -e "$HOST_FILE" ]]; then
|
||||||
|
cat > "$HOST_FILE" <<EOF
|
||||||
{ inputs, ... }:
|
{ inputs, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
@ -67,8 +100,12 @@ if [ ! -e "${host_file}" ]; then
|
||||||
EOF
|
EOF
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[7/7] Installing ${TARGET_HOST} via flake (local-${TARGET_HOST})"
|
echo "[7/7] Installing ${TARGET_HOST} via flake"
|
||||||
nixos-install --root /mnt --flake "/mnt/etc/nixos#local-${TARGET_HOST}" --no-root-passwd |& tee /tmp/nixos-install.log
|
LOG=/tmp/nixos-install.log
|
||||||
echo "Install log saved to /tmp/nixos-install.log"
|
nixos-install \
|
||||||
|
--root "$MNT" \
|
||||||
|
--flake "$MNT/etc/nixos#local-${TARGET_HOST}" \
|
||||||
|
--no-root-passwd |& tee "$LOG"
|
||||||
|
|
||||||
|
echo "Install log saved to $LOG"
|
||||||
echo "Install complete. You can reboot now."
|
echo "Install complete. You can reboot now."
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue