Feat: Automatische Timeshift Btrfs-Snapshots an kritischen Meilensteinen integriert

Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
2026-09-06 14:53:37 +02:00
co-authored by Junie
parent 5889acd1e3
commit d0f88a3608
10 changed files with 159 additions and 2 deletions
+2
View File
@@ -138,6 +138,8 @@ Dieses Repository ist ein modulares, automatisiertes Setup- und Konfigurations-F
- `is_root_subvolume_configured`: Prüft, ob Root bereits in einem Subvolume (`@`) läuft.
- `update_btrfs_fstab "fstab_file" "root_id"`: Aktualisiert Mount-Optionen in `/etc/fstab` für `@` und `@home`.
- `check_and_setup_btrfs_subvolumes`: Erkennt flache Btrfs-Root-Volumes und migriert `/` und `/home` transparent in Subvolumes `@` und `@home`.
- `ensure_timeshift_btrfs_config`: Erstellt bzw. initialisiert die Timeshift-Btrfs-Konfiguration (`/etc/timeshift/timeshift.json`) für die Root-UUID.
- `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`
- `tui_show_stage_selection`: Zeigt ein `whiptail` Checklist-Menü zur interaktiven Auswahl der auszuführenden Phasen.
+3 -2
View File
@@ -62,7 +62,7 @@ sudo ./setup.sh --stages 04,05
├── lib/ # Wiederverwendbare Hilfsbibliotheken
│ ├── utils.sh # Logging, Error-Traps (set -euo pipefail), Root/User-Erkennung & Abfrage
│ ├── apt.sh # APT-Keyring-Management (/etc/apt/keyrings/), Deb822, Pinning
│ ├── btrfs.sh # Btrfs Root- & Subvolume-Erkennung, Migration (@, @home)
│ ├── btrfs.sh # Btrfs Root- & Subvolume-Erkennung, Migration (@, @home), Timeshift-Snapshots
│ └── tui.sh # Whiptail-Menüs und Dialoge
├── config/ # Konfigurationsdateien & Paketlisten
│ ├── setup.conf # Globale Variablen (Kernel, GRUB-Theme, Plymouth)
@@ -106,9 +106,10 @@ sudo ./setup.sh --stages 04,05
2. **Keine gefährlichen Login-Hooks**:
- Vollständige Beseitigung unkontrollierter Live-Downloads (`curl | sh`) beim Login.
- Standardkonforme Bereitstellung über `/etc/skel` für neue und bestehende Benutzer.
3. **Idempotenz & Backups**:
3. **Idempotenz, Backups & Timeshift Btrfs-Snapshots**:
- 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) erstellt.
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.
+3
View File
@@ -7,6 +7,9 @@
XANMOD_BRANCH="main"
CPU_PSTATE_AUTO=1
# Backup & System Snapshots (Timeshift Btrfs)
ENABLE_TIMESHIFT_SNAPSHOTS=1
# Bootloader & Appearance
GRUB_THEME="vimix"
PLYMOUTH_THEME="solar"
+104
View File
@@ -261,3 +261,107 @@ check_and_setup_btrfs_subvolumes() {
log_success "Btrfs subvolume setup and migration completed successfully."
}
# Ensure Timeshift is configured for Btrfs mode on the root filesystem
ensure_timeshift_btrfs_config() {
local root_uuid
root_uuid="$(get_root_btrfs_uuid)"
mkdir -p /etc/timeshift
local config_file="/etc/timeshift/timeshift.json"
local needs_update=0
if [[ ! -f "$config_file" ]]; then
needs_update=1
elif grep -q '"btrfs_mode"[[:space:]]*:[[:space:]]*"false"' "$config_file" 2>/dev/null; then
needs_update=1
elif grep -q '"backup_device_uuid"[[:space:]]*:[[:space:]]*""' "$config_file" 2>/dev/null && [[ -n "$root_uuid" ]]; then
needs_update=1
fi
if [[ "$needs_update" -eq 1 ]]; then
log_info "Initializing Timeshift Btrfs configuration ($config_file)..."
backup_file_or_dir "$config_file"
cat > "$config_file" <<EOF
{
"backup_device_uuid" : "${root_uuid}",
"parent_device_uuid" : "",
"do_first_run" : "false",
"btrfs_mode" : "true",
"include_btrfs_home_for_backup" : "false",
"include_btrfs_home_for_restore" : "false",
"stop_cron_emails" : "true",
"schedule_monthly" : "false",
"schedule_weekly" : "false",
"schedule_daily" : "false",
"schedule_hourly" : "false",
"schedule_boot" : "false",
"count_monthly" : "2",
"count_weekly" : "3",
"count_daily" : "5",
"count_hourly" : "6",
"count_boot" : "5",
"snapshot_size" : "0",
"snapshot_count" : "0",
"exclude" : [
],
"exclude-apps" : [
]
}
EOF
chmod 644 "$config_file"
if [[ ! -e /etc/timeshift.json ]]; then
ln -sf /etc/timeshift/timeshift.json /etc/timeshift.json 2>/dev/null || true
fi
fi
}
# Create a Btrfs snapshot using Timeshift
create_timeshift_snapshot() {
local comment="${1:-Setup Snapshot}"
local tags="${2:-O}"
# Check if disabled via configuration
if [[ "${ENABLE_TIMESHIFT_SNAPSHOTS:-1}" != "1" && "${ENABLE_TIMESHIFT_SNAPSHOTS:-1}" != "true" ]]; then
log_info "Timeshift snapshots disabled in configuration. Skipping: '$comment'"
return 0
fi
# Dry-run check
if [[ "${FLAG_DRY_RUN:-0}" -eq 1 ]]; then
log_info "[DRY-RUN] Would create Timeshift Btrfs snapshot: '$comment' (Tag: $tags)"
return 0
fi
# Check if root is on Btrfs
if ! is_root_btrfs; then
log_info "Root filesystem is not Btrfs. Skipping Timeshift snapshot: '$comment'"
return 0
fi
# Ensure timeshift is installed
if ! command_exists timeshift; then
log_info "Timeshift not found. Attempting to install timeshift..."
DEBIAN_FRONTEND=noninteractive apt-get update -y >/dev/null 2>&1 || true
if ! DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends timeshift 2>/dev/null; then
log_warn "Timeshift is not available and could not be installed. Skipping snapshot: '$comment'"
return 0
fi
fi
# Ensure Timeshift configuration for Btrfs
ensure_timeshift_btrfs_config
log_substep "Creating Timeshift Btrfs snapshot: '$comment' (Tag: $tags)..."
local root_dev
root_dev="$(get_root_btrfs_device)"
if timeshift --create --scripted --comments "$comment" --tags "$tags" 2>/dev/null || \
([[ -n "$root_dev" ]] && timeshift --create --scripted --snapshot-device "$root_dev" --btrfs --comments "$comment" --tags "$tags" 2>/dev/null); then
log_success "Timeshift Btrfs snapshot created: '$comment'"
else
log_warn "Timeshift snapshot could not be created for '$comment' (non-fatal)."
fi
}
+7
View File
@@ -59,6 +59,7 @@ EOF
FLAG_ALL=0
FLAG_STAGES=""
FLAG_DRY_RUN=0
export FLAG_DRY_RUN
CLI_USER=""
# Parse CLI arguments
@@ -184,6 +185,9 @@ if [[ "$FLAG_DRY_RUN" -eq 1 ]]; then
log_warn "DRY-RUN MODE: No changes will be made to the system."
fi
# Create pre-setup baseline Timeshift snapshot if on Btrfs
create_timeshift_snapshot "Pre-Setup Baseline: Before executing stages (${SELECTED_STAGES[*]})" "B"
# Execute Selected Stages
for stage in "${SELECTED_STAGES[@]}"; do
# Skip 00 if it was manually added since it already ran
@@ -208,4 +212,7 @@ for stage in "${SELECTED_STAGES[@]}"; do
fi
done
# Create final completion Timeshift snapshot if on Btrfs
create_timeshift_snapshot "Post-Setup Final: All stages completed successfully (${SELECTED_STAGES[*]})" "O"
log_step "All selected setup stages completed successfully!"
+8
View File
@@ -9,6 +9,11 @@ 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
source "$SCRIPT_DIR/config/setup.conf"
fi
setup_err_trap
log_step "Running Stage 00: Pre-flight System Checks..."
@@ -72,4 +77,7 @@ fi
log_substep "Checking Btrfs root volume & subvolume layout..."
check_and_setup_btrfs_subvolumes
# 7. Create Timeshift Btrfs Snapshot after preflight & subvolume setup
create_timeshift_snapshot "Stage 00: Pre-flight checks & Btrfs baseline" "B"
log_success "Stage 00: Pre-flight checks passed successfully."
+8
View File
@@ -8,6 +8,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/apt.sh"
source "$SCRIPT_DIR/lib/btrfs.sh"
if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then
# shellcheck source=/dev/null
source "$SCRIPT_DIR/config/setup.conf"
fi
setup_err_trap
@@ -70,6 +76,8 @@ DEBIAN_FRONTEND=noninteractive apt-get install -y apt-listbugs apt-listchanges
# 7. Perform Full Dist-Upgrade
log_substep "Performing full distribution upgrade to Debian Sid..."
create_timeshift_snapshot "Stage 01: Pre-dist-upgrade to Debian Sid" "B"
apt_dist_upgrade
create_timeshift_snapshot "Stage 01: Post-dist-upgrade to Debian Sid" "O"
log_success "Stage 01: Debian Unstable migration and upgrade completed successfully!"
+4
View File
@@ -8,6 +8,7 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/apt.sh"
source "$SCRIPT_DIR/lib/btrfs.sh"
if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then
# shellcheck source=/dev/null
@@ -33,6 +34,7 @@ apt_update
# 2. Determine XanMod Kernel Package
log_substep "Detecting CPU microarchitecture level and XanMod branch..."
create_timeshift_snapshot "Stage 02: Pre-XanMod kernel installation" "B"
BRANCH="${XANMOD_BRANCH:-main}"
log_info "Configured XanMod branch: $BRANCH"
@@ -118,4 +120,6 @@ if compgen -G "$SCRIPT_DIR/data/etc/environment.d/*.conf" > /dev/null; then
done
fi
create_timeshift_snapshot "Stage 02: Post-kernel and hardware tuning" "O"
log_success "Stage 02: Kernel and Hardware Tuning completed successfully!"
+10
View File
@@ -8,6 +8,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/apt.sh"
source "$SCRIPT_DIR/lib/btrfs.sh"
if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then
# shellcheck source=/dev/null
source "$SCRIPT_DIR/config/setup.conf"
fi
setup_err_trap
@@ -22,6 +28,8 @@ if [[ ! -d "$PACKAGES_DIR" ]]; then
exit 1
fi
create_timeshift_snapshot "Stage 04: Pre-thematic package installation" "B"
# List of APT package lists to process (excluding flatpaks which are handled in stage 08)
APT_LISTS=(
"01-base.list"
@@ -47,4 +55,6 @@ for list_name in "${APT_LISTS[@]}"; do
fi
done
create_timeshift_snapshot "Stage 04: Post-thematic package installation" "O"
log_success "Stage 04: Thematic package installation completed successfully!"
+10
View File
@@ -8,6 +8,12 @@ set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
# shellcheck source=lib/utils.sh
source "$SCRIPT_DIR/lib/utils.sh"
source "$SCRIPT_DIR/lib/btrfs.sh"
if [[ -f "$SCRIPT_DIR/config/setup.conf" ]]; then
# shellcheck source=/dev/null
source "$SCRIPT_DIR/config/setup.conf"
fi
setup_err_trap
@@ -22,6 +28,7 @@ log_info "Configuring Hyprland Desktop for target user: $TARGET_USER ($TARGET_HO
# 1. Execute LinuxBeginnings Debian-Hyprland installer
log_substep "Downloading and executing LinuxBeginnings Debian-Hyprland installer..."
create_timeshift_snapshot "Stage 10: Pre-Hyprland desktop installation" "B"
if command_exists curl; then
log_info "Running Debian-Hyprland installer as target user '$TARGET_USER'..."
if run_as_target_user bash -c 'sh <(curl -L https://raw.githubusercontent.com/LinuxBeginnings/Debian-Hyprland/main/auto-install.sh)'; then
@@ -68,4 +75,7 @@ log_success "Rudimentary Hyprland configuration deployed:"
log_info " - SUPER+ENTER: Kitty Terminal"
log_info " - SUPER+Q: Close Active Window"
log_info " - Login Prompt: Asks user after login to choose Dotfiles setup & installs JetBrains Junie CLI + AwesomeJunieSkills"
create_timeshift_snapshot "Stage 10: Post-Hyprland desktop setup" "O"
log_success "Stage 10: Hyprland Desktop installation & configuration completed successfully!"