From 37a2c4985547c6100cee1cfb1741123289016b05 Mon Sep 17 00:00:00 2001 From: DragonSlayer_14 Date: Sun, 6 Sep 2026 15:19:23 +0200 Subject: [PATCH] feat(bootloader): add grub-btrfs snapshot boot support Co-authored-by: Junie --- AGENTS.md | 1 + README.md | 1 + config/packages/01-base.list | 1 + config/setup.conf | 5 +- lib/btrfs.sh | 100 +++++++++++++++++++++++++++++++++++ stages/03-bootloader.sh | 16 ++++-- stages/06-services.sh | 10 ++-- 7 files changed, 125 insertions(+), 9 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index b3d9190..2bfd70c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -141,6 +141,7 @@ Dieses Repository ist ein modulares, automatisiertes Setup- und Konfigurations-F - `ensure_timeshift_btrfs_config`: Erstellt bzw. initialisiert die Timeshift-Btrfs-Konfiguration (`/etc/timeshift/timeshift.json`, automatische Boot-Snapshots, Retention auf 5 Snapshots) für die Root-UUID. - `ensure_timeshift_boot_service`: Richtet den `timeshift-boot.service` und Cron-Einträge für automatische Boot-Snapshots ein. - `ensure_timeshift_apt_hook`: Richtet einen DPkg/APT-Hook (`/etc/apt/apt.conf.d/80timeshift-auto-snapshot` und `/usr/local/bin/timeshift-apt-hook`) für automatische Snapshots vor System-Updates ein. +- `ensure_grub_btrfs`: Installiert und konfiguriert `grub-btrfs` sowie den `grub-btrfsd`-Dienst für die automatische Generierung von Snapshot-Bootmenüeinträgen in GRUB. - `create_timeshift_snapshot "comment" [tags]`: Erstellt einen Timeshift-Btrfs-Snapshot an kritischen Setup-Meilensteinen (idempotent, steuerbar über `ENABLE_TIMESHIFT_SNAPSHOTS` in `config/setup.conf`). ### `lib/tui.sh` diff --git a/README.md b/README.md index 483fa19..d3c1b81 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,7 @@ sudo ./setup.sh --stages 04,05 - Alle Phasen können beliebig oft wiederholt werden. - Vorhandene Dotfiles (`~/.zshrc`) und Konfigurationen (`/etc/default/grub`) werden vor Änderungen automatisch mit Zeitstempel (`.backup_YYYYMMDD_HHMMSS`) gesichert. - Auf Btrfs-Systemen werden mit Timeshift automatisch Rollback-Punkte vor und nach kritischen Operationen (Dist-Upgrade, Kernel-Installation, Paketinstallation, Desktop-Setup), bei jedem System-Update (automatischer APT/DPkg-Pre-Invoke-Hook) sowie bei jedem Systemstart (`timeshift-boot.service`) erstellt, wobei standardmäßig die letzten 5 Snapshots vorgehalten werden. + - Mittels `grub-btrfs` und dem Hintergrunddienst `grub-btrfsd` werden Btrfs-Snapshots automatisch in das GRUB-Bootmenü integriert, sodass direkt beim Systemstart in beliebige Snapshots gebootet werden kann. 4. **Debian Unstable Absicherung**: - Moderne Deb822-Quellen und dedizierte Keyrings in `/etc/apt/keyrings/`. - Installation von `apt-listbugs` und `apt-listchanges` vor dem `dist-upgrade` schützt vor bekannten kritischen Paketproblemen. diff --git a/config/packages/01-base.list b/config/packages/01-base.list index de2494f..3b380bc 100644 --- a/config/packages/01-base.list +++ b/config/packages/01-base.list @@ -49,6 +49,7 @@ gparted htop hunspell hunspell-de-de-frami +inotify-tools irqbalance keepassxc lsd diff --git a/config/setup.conf b/config/setup.conf index 66465c7..9bef057 100644 --- a/config/setup.conf +++ b/config/setup.conf @@ -12,12 +12,13 @@ ENABLE_TIMESHIFT_SNAPSHOTS=1 TIMESHIFT_COUNT_BOOT=5 TIMESHIFT_SCHEDULE_BOOT="true" TIMESHIFT_SNAPSHOT_ON_UPDATE="true" +ENABLE_GRUB_BTRFS=1 # Bootloader & Appearance GRUB_THEME="vimix" PLYMOUTH_THEME="solar" -GRUB_TIMEOUT=0 -GRUB_TIMEOUT_STYLE="hidden" +GRUB_TIMEOUT=5 +GRUB_TIMEOUT_STYLE="menu" # Shell & Userland DEFAULT_SHELL="zsh" diff --git a/lib/btrfs.sh b/lib/btrfs.sh index 19223ce..32c441f 100644 --- a/lib/btrfs.sh +++ b/lib/btrfs.sh @@ -467,6 +467,106 @@ EOF ensure_timeshift_boot_service ensure_timeshift_apt_hook + ensure_grub_btrfs +} + +# Ensure grub-btrfs is installed and configured to generate GRUB snapshot boot entries +ensure_grub_btrfs() { + local root_prefix="${ROOT_PREFIX:-}" + local enable_grub_btrfs="${ENABLE_GRUB_BTRFS:-1}" + + # Check if disabled in configuration + if [[ "$enable_grub_btrfs" != "1" && "$enable_grub_btrfs" != "true" ]]; then + log_info "GRUB Btrfs snapshot booting disabled in configuration." + return 0 + fi + + # Dry-run check + if [[ "${FLAG_DRY_RUN:-0}" -eq 1 ]]; then + log_info "[DRY-RUN] Would install and configure grub-btrfs for GRUB snapshot booting." + return 0 + fi + + # Check if root is on Btrfs + if ! is_root_btrfs; then + log_info "Root filesystem is not Btrfs. Skipping grub-btrfs setup." + return 0 + fi + + log_info "Configuring GRUB Btrfs snapshot support (grub-btrfs)..." + + # Ensure required dependencies are installed + if ! command_exists inotifywait || ! command_exists git || ! command_exists make; then + log_info "Installing dependencies for grub-btrfs (inotify-tools, git, make)..." + DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true + DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends inotify-tools git make 2>/dev/null || true + fi + + local repo_dir="${root_prefix}/usr/share/debian-gaming/grub/grub-btrfs" + mkdir -p "$(dirname "$repo_dir")" + + if [[ ! -d "$repo_dir/.git" ]]; then + log_info "Cloning grub-btrfs repository..." + if ! git clone --depth 1 https://github.com/Antynea/grub-btrfs.git "$repo_dir" 2>/dev/null; then + log_warn "Failed to clone grub-btrfs repository. Snapshot boot menu may not be available." + return 0 + fi + else + log_info "grub-btrfs repository already cloned; pulling latest updates..." + (cd "$repo_dir" && git pull 2>/dev/null) || log_warn "grub-btrfs git pull skipped." + fi + + # Install grub.d script + mkdir -p "${root_prefix}/etc/grub.d" + if [[ -f "$repo_dir/41_snapshots-btrfs" ]]; then + cp -f "$repo_dir/41_snapshots-btrfs" "${root_prefix}/etc/grub.d/41_snapshots-btrfs" + chmod 755 "${root_prefix}/etc/grub.d/41_snapshots-btrfs" + fi + + # Install default config + mkdir -p "${root_prefix}/etc/default/grub-btrfs" + if [[ -f "$repo_dir/config" && ! -f "${root_prefix}/etc/default/grub-btrfs/config" ]]; then + cp -f "$repo_dir/config" "${root_prefix}/etc/default/grub-btrfs/config" + chmod 644 "${root_prefix}/etc/default/grub-btrfs/config" + fi + + # Install grub-btrfsd binary + mkdir -p "${root_prefix}/usr/bin" + if [[ -f "$repo_dir/grub-btrfsd" ]]; then + cp -f "$repo_dir/grub-btrfsd" "${root_prefix}/usr/bin/grub-btrfsd" + chmod 755 "${root_prefix}/usr/bin/grub-btrfsd" + fi + + # Install and configure systemd service for automatic snapshot tracking with Timeshift + mkdir -p "${root_prefix}/etc/systemd/system" + local service_file="${root_prefix}/etc/systemd/system/grub-btrfsd.service" + cat > "$service_file" <<'EOF' +[Unit] +Description=Regenerate grub-btrfs.cfg on snapshot changes +After=local-fs.target +ConditionPathExists=/etc/default/grub-btrfs/config + +[Service] +Type=simple +LogLevelMax=notice +Environment="PATH=/sbin:/bin:/usr/sbin:/usr/bin" +EnvironmentFile=-/etc/default/grub-btrfs/config +ExecStart=/usr/bin/grub-btrfsd --syslog --timeshift-auto +Restart=on-failure +RestartSec=5s + +[Install] +WantedBy=multi-user.target +EOF + chmod 644 "$service_file" + + if [[ -z "$root_prefix" ]] && command_exists systemctl; then + systemctl daemon-reload 2>/dev/null || true + systemctl enable grub-btrfsd.service 2>/dev/null || true + systemctl restart grub-btrfsd.service 2>/dev/null || true + fi + + log_success "grub-btrfs installed and configured successfully." } # Create a Btrfs snapshot using Timeshift diff --git a/stages/03-bootloader.sh b/stages/03-bootloader.sh index 19c6f32..8ef97af 100755 --- a/stages/03-bootloader.sh +++ b/stages/03-bootloader.sh @@ -7,6 +7,7 @@ set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" source "$SCRIPT_DIR/lib/utils.sh" +source "$SCRIPT_DIR/lib/btrfs.sh" if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then # shellcheck source=/dev/null @@ -20,8 +21,8 @@ log_step "Running Stage 03: Bootloader & Splash Screen Configuration" require_root GRUB_CFG="/etc/default/grub" -GRUB_TIMEOUT="${GRUB_TIMEOUT:-0}" -GRUB_TIMEOUT_STYLE="${GRUB_TIMEOUT_STYLE:-hidden}" +GRUB_TIMEOUT="${GRUB_TIMEOUT:-5}" +GRUB_TIMEOUT_STYLE="${GRUB_TIMEOUT_STYLE:-menu}" GRUB_CMDLINE_LINUX_DEFAULT_BASE="quiet splash apparmor=1 usbcore.autosuspend=-1 vt.global_cursor_default=0 loglevel=3 rd.luks.options=discard plymouth.ignore-serial-consoles threadirqs" GRUB_CMDLINE_LINUX="rcutree.rcu_idle_gp_delay=1" GRUB_THEME_DIR="/usr/share/debian-gaming/grub/grub2-themes" @@ -100,7 +101,16 @@ else (cd "$GRUB_THEME_DIR" && git pull 2>/dev/null && ./install.sh -b -t "${GRUB_THEME:-vimix}" 2>/dev/null) || log_warn "Vimix theme update skipped." fi -# 5. Update GRUB & Initramfs +# 5. Configure GRUB Btrfs Snapshot Booting (grub-btrfs) +log_substep "Configuring GRUB Btrfs snapshot booting support..." +if is_root_btrfs; then + ensure_grub_btrfs + log_success "GRUB Btrfs snapshot booting configured." +else + log_info "Root filesystem is not Btrfs. Skipping grub-btrfs setup." +fi + +# 6. Update GRUB & Initramfs log_substep "Running update-grub and update-initramfs..." if command_exists update-grub; then update-grub diff --git a/stages/06-services.sh b/stages/06-services.sh index 5c322e3..afda760 100755 --- a/stages/06-services.sh +++ b/stages/06-services.sh @@ -136,13 +136,15 @@ if command_exists systemctl; then log_success "Ollama systemd service configured and enabled." fi -# 6. Timeshift Boot Snapshot Service & APT Update Hook (if on Btrfs) -log_substep "Configuring Timeshift Boot Snapshot Service and APT Update Hook..." +# 6. Timeshift Boot Snapshot Service, APT Update Hook & GRUB Btrfs Daemon (if on Btrfs) +log_substep "Configuring Timeshift Boot Snapshot Service, APT Update Hook and GRUB Btrfs Snapshot Daemon..." if command_exists timeshift && is_root_btrfs; then ensure_timeshift_btrfs_config - log_success "Timeshift Boot Snapshot Service and APT Update Hook configured and enabled." + ensure_grub_btrfs + log_success "Timeshift and GRUB Btrfs snapshot services configured and enabled." elif is_root_btrfs; then - log_info "Timeshift will be configured when installed." + ensure_grub_btrfs + log_info "Timeshift will be configured when installed; grub-btrfs configured." fi # 7. User Group Memberships