Feat: Automatische Timeshift Boot- und APT-Update-Snapshots sowie Retention-Limit konfiguriert
Co-authored-by: Junie <junie@jetbrains.com>
This commit is contained in:
@@ -138,7 +138,9 @@ 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.
|
||||
- `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.
|
||||
- `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`
|
||||
|
||||
@@ -109,7 +109,7 @@ sudo ./setup.sh --stages 04,05
|
||||
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.
|
||||
- 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.
|
||||
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.
|
||||
|
||||
@@ -9,6 +9,9 @@ CPU_PSTATE_AUTO=1
|
||||
|
||||
# Backup & System Snapshots (Timeshift Btrfs)
|
||||
ENABLE_TIMESHIFT_SNAPSHOTS=1
|
||||
TIMESHIFT_COUNT_BOOT=5
|
||||
TIMESHIFT_SCHEDULE_BOOT="true"
|
||||
TIMESHIFT_SNAPSHOT_ON_UPDATE="true"
|
||||
|
||||
# Bootloader & Appearance
|
||||
GRUB_THEME="vimix"
|
||||
|
||||
+158
-6
@@ -262,14 +262,159 @@ check_and_setup_btrfs_subvolumes() {
|
||||
log_success "Btrfs subvolume setup and migration completed successfully."
|
||||
}
|
||||
|
||||
# Ensure Timeshift APT hook is configured for automatic snapshots on system updates
|
||||
ensure_timeshift_apt_hook() {
|
||||
local root_prefix="${ROOT_PREFIX:-}"
|
||||
local snapshot_on_update="${TIMESHIFT_SNAPSHOT_ON_UPDATE:-true}"
|
||||
local apt_conf_file="${root_prefix}/etc/apt/apt.conf.d/80timeshift-auto-snapshot"
|
||||
local hook_script="${root_prefix}/usr/local/bin/timeshift-apt-hook"
|
||||
|
||||
# If disabled in configuration, remove hook if present
|
||||
if [[ "$snapshot_on_update" != "1" && "$snapshot_on_update" != "true" ]]; then
|
||||
if [[ -f "$apt_conf_file" || -f "$hook_script" ]]; then
|
||||
log_info "Disabling Timeshift APT update snapshot hook..."
|
||||
rm -f "$apt_conf_file" "$hook_script"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
|
||||
mkdir -p "${root_prefix}/usr/local/bin" "${root_prefix}/etc/apt/apt.conf.d"
|
||||
|
||||
# Create hook script
|
||||
log_info "Configuring Timeshift APT update hook ($hook_script)..."
|
||||
cat > "$hook_script" <<'EOF'
|
||||
#!/usr/bin/env bash
|
||||
# ==============================================================================
|
||||
# /usr/local/bin/timeshift-apt-hook - Automatic Timeshift Snapshot on APT updates
|
||||
# ==============================================================================
|
||||
set -euo pipefail
|
||||
|
||||
# Check if timeshift binary is available
|
||||
if ! command -v timeshift >/dev/null 2>&1; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if timeshift configuration exists
|
||||
if [[ ! -f /etc/timeshift/timeshift.json && ! -f /etc/timeshift.json ]]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Check if root filesystem is Btrfs
|
||||
if command -v findmnt >/dev/null 2>&1; then
|
||||
if [[ "$(findmnt -n -o FSTYPE / 2>/dev/null || true)" != "btrfs" ]]; then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# Prevent duplicate snapshots within 60 seconds (rate limiting)
|
||||
STAMP_FILE="/run/timeshift-apt-hook.stamp"
|
||||
if [[ -f "$STAMP_FILE" ]]; then
|
||||
LAST_RUN="$(stat -c %Y "$STAMP_FILE" 2>/dev/null || stat -f %m "$STAMP_FILE" 2>/dev/null || echo 0)"
|
||||
CURRENT_TIME="$(date +%s)"
|
||||
if (( CURRENT_TIME - LAST_RUN < 60 )); then
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ">> [Timeshift] Creating automatic pre-update system snapshot..."
|
||||
if timeshift --create --scripted --tags O --comments "Automatic snapshot before system update (APT)" 2>&1; then
|
||||
touch "$STAMP_FILE" 2>/dev/null || true
|
||||
echo ">> [Timeshift] Pre-update snapshot created successfully."
|
||||
else
|
||||
echo ">> [Timeshift] Warning: Automatic snapshot could not be created (continuing update)."
|
||||
fi
|
||||
|
||||
exit 0
|
||||
EOF
|
||||
chmod 755 "$hook_script"
|
||||
|
||||
# Create APT configuration hook
|
||||
cat > "$apt_conf_file" <<'EOF'
|
||||
// Automatic Timeshift snapshot before APT package operations / updates
|
||||
DPkg::Pre-Invoke { "[ -x /usr/local/bin/timeshift-apt-hook ] && /usr/local/bin/timeshift-apt-hook || true"; };
|
||||
EOF
|
||||
chmod 644 "$apt_conf_file"
|
||||
|
||||
log_success "Timeshift APT update hook configured: $apt_conf_file"
|
||||
}
|
||||
|
||||
# Ensure Timeshift systemd boot service and cron jobs are configured and enabled
|
||||
ensure_timeshift_boot_service() {
|
||||
local root_prefix="${ROOT_PREFIX:-}"
|
||||
local service_file="${root_prefix}/etc/systemd/system/timeshift-boot.service"
|
||||
local timeshift_bin
|
||||
timeshift_bin="$(command -v timeshift || echo "/usr/bin/timeshift")"
|
||||
|
||||
mkdir -p "${root_prefix}/etc/systemd/system"
|
||||
|
||||
local needs_service_update=0
|
||||
if [[ ! -f "$service_file" ]]; then
|
||||
needs_service_update=1
|
||||
fi
|
||||
|
||||
if [[ "$needs_service_update" -eq 1 ]]; then
|
||||
log_info "Creating Timeshift boot snapshot service ($service_file)..."
|
||||
cat > "$service_file" <<EOF
|
||||
[Unit]
|
||||
Description=Timeshift Boot Snapshot Service
|
||||
Documentation=man:timeshift(1)
|
||||
After=local-fs.target
|
||||
ConditionPathExists=/etc/timeshift/timeshift.json
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=${timeshift_bin} --check --scripted
|
||||
RemainAfterExit=yes
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
EOF
|
||||
chmod 644 "$service_file"
|
||||
fi
|
||||
|
||||
if [[ -z "$root_prefix" ]] && command_exists systemctl; then
|
||||
systemctl daemon-reload 2>/dev/null || true
|
||||
systemctl enable timeshift-boot.service 2>/dev/null || true
|
||||
fi
|
||||
|
||||
# Also install cron entries if cron directory exists
|
||||
if [[ -d "${root_prefix}/etc/cron.d" ]]; then
|
||||
local cron_boot="${root_prefix}/etc/cron.d/timeshift-boot"
|
||||
local cron_hourly="${root_prefix}/etc/cron.d/timeshift-hourly"
|
||||
|
||||
if [[ ! -f "$cron_boot" ]]; then
|
||||
cat > "$cron_boot" <<EOF
|
||||
SHELL=/bin/bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
MAILTO=""
|
||||
@reboot root sleep 10m && ${timeshift_bin} --create --scripted --tags B
|
||||
EOF
|
||||
chmod 644 "$cron_boot"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$cron_hourly" ]]; then
|
||||
cat > "$cron_hourly" <<EOF
|
||||
SHELL=/bin/bash
|
||||
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
|
||||
MAILTO=""
|
||||
0 * * * * root ${timeshift_bin} --check --scripted
|
||||
EOF
|
||||
chmod 644 "$cron_hourly"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
# Ensure Timeshift is configured for Btrfs mode on the root filesystem
|
||||
ensure_timeshift_btrfs_config() {
|
||||
local root_prefix="${ROOT_PREFIX:-}"
|
||||
local root_uuid
|
||||
root_uuid="$(get_root_btrfs_uuid)"
|
||||
|
||||
mkdir -p /etc/timeshift
|
||||
mkdir -p "${root_prefix}/etc/timeshift"
|
||||
|
||||
local config_file="/etc/timeshift/timeshift.json"
|
||||
local config_file="${root_prefix}/etc/timeshift/timeshift.json"
|
||||
local count_boot="${TIMESHIFT_COUNT_BOOT:-5}"
|
||||
local schedule_boot="${TIMESHIFT_SCHEDULE_BOOT:-true}"
|
||||
local needs_update=0
|
||||
|
||||
if [[ ! -f "$config_file" ]]; then
|
||||
@@ -278,6 +423,10 @@ ensure_timeshift_btrfs_config() {
|
||||
needs_update=1
|
||||
elif grep -q '"backup_device_uuid"[[:space:]]*:[[:space:]]*""' "$config_file" 2>/dev/null && [[ -n "$root_uuid" ]]; then
|
||||
needs_update=1
|
||||
elif ! grep -q "\"schedule_boot\"[[:space:]]*:[[:space:]]*\"${schedule_boot}\"" "$config_file" 2>/dev/null; then
|
||||
needs_update=1
|
||||
elif ! grep -q "\"count_boot\"[[:space:]]*:[[:space:]]*\"${count_boot}\"" "$config_file" 2>/dev/null; then
|
||||
needs_update=1
|
||||
fi
|
||||
|
||||
if [[ "$needs_update" -eq 1 ]]; then
|
||||
@@ -296,12 +445,12 @@ ensure_timeshift_btrfs_config() {
|
||||
"schedule_weekly" : "false",
|
||||
"schedule_daily" : "false",
|
||||
"schedule_hourly" : "false",
|
||||
"schedule_boot" : "false",
|
||||
"schedule_boot" : "${schedule_boot}",
|
||||
"count_monthly" : "2",
|
||||
"count_weekly" : "3",
|
||||
"count_daily" : "5",
|
||||
"count_hourly" : "6",
|
||||
"count_boot" : "5",
|
||||
"count_boot" : "${count_boot}",
|
||||
"snapshot_size" : "0",
|
||||
"snapshot_count" : "0",
|
||||
"exclude" : [
|
||||
@@ -311,10 +460,13 @@ ensure_timeshift_btrfs_config() {
|
||||
}
|
||||
EOF
|
||||
chmod 644 "$config_file"
|
||||
if [[ ! -e /etc/timeshift.json ]]; then
|
||||
ln -sf /etc/timeshift/timeshift.json /etc/timeshift.json 2>/dev/null || true
|
||||
if [[ ! -e "${root_prefix}/etc/timeshift.json" ]]; then
|
||||
ln -sf /etc/timeshift/timeshift.json "${root_prefix}/etc/timeshift.json" 2>/dev/null || true
|
||||
fi
|
||||
fi
|
||||
|
||||
ensure_timeshift_boot_service
|
||||
ensure_timeshift_apt_hook
|
||||
}
|
||||
|
||||
# Create a Btrfs snapshot using Timeshift
|
||||
|
||||
+11
-1
@@ -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
|
||||
@@ -135,7 +136,16 @@ if command_exists systemctl; then
|
||||
log_success "Ollama systemd service configured and enabled."
|
||||
fi
|
||||
|
||||
# 6. User Group Memberships
|
||||
# 6. Timeshift Boot Snapshot Service & APT Update Hook (if on Btrfs)
|
||||
log_substep "Configuring Timeshift Boot Snapshot Service and APT Update Hook..."
|
||||
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."
|
||||
elif is_root_btrfs; then
|
||||
log_info "Timeshift will be configured when installed."
|
||||
fi
|
||||
|
||||
# 7. User Group Memberships
|
||||
log_substep "Updating user group memberships for $TARGET_USER..."
|
||||
groupadd -f sudo
|
||||
groupadd -f docker
|
||||
|
||||
Reference in New Issue
Block a user