From 1610c0a7a0ceb865c43e612a48ea7da53e632e66 Mon Sep 17 00:00:00 2001 From: Hans-Christian Payer Date: Wed, 29 Apr 2026 08:29:30 +0200 Subject: [PATCH] Systemsicherung at und ppa s erweitert --- README-system-sicherung.md | 233 +++++++++++++++++++ netzwerk-sicherung.sh => system-sicherung.sh | 41 +++- 2 files changed, 268 insertions(+), 6 deletions(-) create mode 100644 README-system-sicherung.md rename netzwerk-sicherung.sh => system-sicherung.sh (61%) diff --git a/README-system-sicherung.md b/README-system-sicherung.md new file mode 100644 index 0000000..22a9ef4 --- /dev/null +++ b/README-system-sicherung.md @@ -0,0 +1,233 @@ +# README – Sicherung von WireGuard-, NetworkManager- und APT-Konfiguration + +Dieses Skript sichert Konfigurationen aus `/etc/wireguard`, `/etc/NetworkManager/system-connections` sowie die APT-Quellen und Schlüsseldateien in zeitgestempelten Snapshots mit `rsync` und `--link-dest`.[cite:118][cite:131][cite:141] Dadurch entsteht eine nachvollziehbare Historie, während unveränderte Dateien zwischen den Snapshots per Hardlink wiederverwendet werden.[cite:34][cite:92] + +## Zweck + +Das Skript ist für die Sicherung sensibler System- und Netzwerk-Konfigurationen gedacht, insbesondere von WireGuard-Tunneln, persistenten NetworkManager-Profilen sowie der Paketquellen-Konfiguration inklusive zusätzlicher Repositories und PPAs.[cite:131][cite:130][cite:135] Auch die zugehörigen Keyring-Dateien werden mitgesichert, damit Paketquellen bei einer Wiederherstellung wieder korrekt verifiziert werden können.[cite:141][cite:147] + +## Gesicherte Quellen + +| Quelle | Inhalt | +|---|---| +| `/etc/wireguard` | WireGuard-Konfigurationen wie `wg0.conf` mit Interface-, Peer- und Schlüsseldaten.[cite:131][cite:129] | +| `/etc/NetworkManager/system-connections` | NetworkManager-Profile im Keyfile-Format, die WLAN-, VPN-, Ethernet- oder andere Verbindungsdaten enthalten können.[cite:118][cite:130] | +| `/etc/apt/sources.list` | Zentrale APT-Quellenliste des Systems.[cite:135][cite:138] | +| `/etc/apt/sources.list.d` | Zusätzliche Repository-Definitionen, darunter auch PPA-Einträge und weitere Drittquellen.[cite:135][cite:140] | +| `/etc/apt/trusted.gpg.d` | Klassische APT-Schlüsselablage für vertrauenswürdige Repository-Schlüssel.[cite:141][cite:144] | +| `/etc/apt/keyrings` | Moderne Ablage für Keyrings, die über `signed-by=` in Quellen eingebunden werden.[cite:141][cite:147] | + +Hinweis: Unter neueren Ubuntu-Versionen wird die Schlüsselverwaltung zunehmend über Keyring-Dateien und `signed-by=` abgewickelt; `apt-key` gilt als veraltet.[cite:147][cite:141] Deshalb ist die Sicherung von `/etc/apt/keyrings` besonders wichtig.[cite:147] + +## Sicherheitsaspekte + +Die Dateien in `/etc/NetworkManager/system-connections` müssen restriktive Rechte haben; zu offene Berechtigungen können dazu führen, dass NetworkManager sie ignoriert.[cite:120][cite:122] Auch WireGuard-Konfigurationen und einige APT-Schlüsseldateien enthalten sicherheitsrelevante Informationen und sollten nur mit Root-Rechten gelesen und gesichert werden.[cite:123][cite:141] + +Deshalb gilt für dieses Skript: + +- Es muss mit `sudo` oder als `root` ausgeführt werden, da die Quelldateien Root-Rechte erfordern.[cite:123][cite:120] +- Das Backup-Ziel sollte auf einem vertrauenswürdigen Datenträger liegen und gegen unbefugten Zugriff geschützt sein.[cite:123][cite:141] +- Ein Linux-Dateisystem wie ext4, XFS oder btrfs ist für `--link-dest` sinnvoll, weil Hardlinks benötigt werden.[cite:34][cite:91] + +## Beispielskript + +```bash +#!/usr/bin/env bash +set -Eeuo pipefail + +DEST_BASE="/run/media/hans/usbsicherung/system-config-backup" +HOST="$(hostname -s)" +STAMP="$(date +%F_%H-%M-%S)" +TARGET_DIR="${DEST_BASE}/${HOST}/${STAMP}" +LATEST_LINK="${DEST_BASE}/${HOST}/latest" +LOG_DIR="${DEST_BASE}/${HOST}/logs" +LOG_FILE="${LOG_DIR}/netzwerk-backup-${STAMP}.log" +KEEP=20 + +WG_SRC="/etc/wireguard" +NM_SRC="/etc/NetworkManager/system-connections" +APT_SOURCES_LIST="/etc/apt/sources.list" +APT_SOURCES_D="/etc/apt/sources.list.d" +APT_TRUSTED_D="/etc/apt/trusted.gpg.d" +APT_KEYRINGS="/etc/apt/keyrings" + +log() { + local msg="[$(date +%F\ %T)] $*" + echo "${msg}" + mkdir -p "${LOG_DIR}" + echo "${msg}" >> "${LOG_FILE}" +} + +fail() { + log "FEHLER: $*" + exit 1 +} + +if [[ ${EUID} -ne 0 ]]; then + fail "Dieses Skript muss mit sudo oder als root ausgeführt werden, da /etc/wireguard, NetworkManager-Profile und APT-Konfigurationen Root-Rechte benötigen." +fi + +if [[ ! -d "${DEST_BASE}" ]]; then + fail "Zielbasis ${DEST_BASE} existiert nicht oder ist nicht gemountet." +fi + +if [[ ! -w "${DEST_BASE}" ]]; then + fail "Zielbasis ${DEST_BASE} ist nicht beschreibbar." +fi + +mkdir -p "${TARGET_DIR}" "${LOG_DIR}" + +RSYNC_OPTS=( + -aHAX + --numeric-ids + --delete + --info=stats2,progress2 + --human-readable + --partial +) + +if [[ -L "${LATEST_LINK}" ]] && [[ -d "$(readlink -f "${LATEST_LINK}")" ]]; then + RSYNC_OPTS+=(--link-dest="$(readlink -f "${LATEST_LINK}")") + log "Verwende link-dest: $(readlink -f "${LATEST_LINK}")" +else + log "Kein vorheriger Snapshot gefunden – es wird ein vollständiger Lauf erstellt." +fi + +backup_tree() { + local src="$1" + local name="$2" + + if [[ -d "${src}" ]]; then + log "Sichere Verzeichnis ${src} -> ${TARGET_DIR}/${name}/" + rsync "${RSYNC_OPTS[@]}" "${src}/" "${TARGET_DIR}/${name}/" | tee -a "${LOG_FILE}" + else + log "Quelle (Verzeichnis) ${src} existiert nicht – wird übersprungen." + fi +} + +backup_file() { + local src="$1" + local name="$2" + + if [[ -f "${src}" ]]; then + log "Sichere Datei ${src} -> ${TARGET_DIR}/${name}" + mkdir -p "$(dirname "${TARGET_DIR}/${name}")" + rsync "${RSYNC_OPTS[@]}" "${src}" "${TARGET_DIR}/${name}" | tee -a "${LOG_FILE}" + else + log "Quelle (Datei) ${src} existiert nicht – wird übersprungen." + fi +} + +backup_tree "${WG_SRC}" "wireguard" +backup_tree "${NM_SRC}" "networkmanager-system-connections" +backup_file "${APT_SOURCES_LIST}" "apt/sources.list" +backup_tree "${APT_SOURCES_D}" "apt/sources.list.d" +backup_tree "${APT_TRUSTED_D}" "apt/trusted.gpg.d" +backup_tree "${APT_KEYRINGS}" "apt/keyrings" + +ln -sfn "${TARGET_DIR}" "${LATEST_LINK}" +log "latest-Link zeigt jetzt auf ${TARGET_DIR}" + +cd "${DEST_BASE}/${HOST}" +SNAPS=(20*/) + +if (( ${#SNAPS[@]} > KEEP )); then + log "Rotationslauf: ${#SNAPS[@]} Snapshots vorhanden, KEEP=${KEEP}." + ls -1dt 20*/ | tail -n +$((KEEP + 1)) | while read -r old; do + log "Lösche alten Snapshot: ${old}" + rm -rf -- "${old}" + done +else + log "Keine Rotation nötig. Snapshots vorhanden: ${#SNAPS[@]}" +fi + +log "Netzwerk-, WireGuard- und APT-Konfigurationsbackup abgeschlossen." +``` + +## Verwendung + +Zuerst die Syntax prüfen: + +```bash +bash -n netzwerk-sicherung.sh +``` + +Dann das Skript mit Root-Rechten ausführen: + +```bash +sudo bash netzwerk-sicherung.sh +``` + +Da die Quellen sensible Systemdaten enthalten, ist ein Aufruf ohne `sudo` nicht ausreichend.[cite:123][cite:141] + +## Zielstruktur + +Pro Lauf wird ein neuer Snapshot angelegt.[cite:34][cite:92] + +```text +/run/media/hans/usbsicherung/system-config-backup/ +└── / + ├── 2026-04-29_08-20-00/ + │ ├── wireguard/ + │ ├── networkmanager-system-connections/ + │ └── apt/ + │ ├── sources.list + │ ├── sources.list.d/ + │ ├── trusted.gpg.d/ + │ └── keyrings/ + ├── latest -> /run/media/hans/usbsicherung/system-config-backup//2026-04-29_08-20-00 + └── logs/ +``` + +## Wiederherstellung + +Für einen Test-Restore sollte nie direkt produktiv nach `/etc` zurückgeschrieben werden, sondern zunächst in ein Testverzeichnis.[cite:105][cite:107] Ein Beispiel für WireGuard: + +```bash +mkdir -p /tmp/restore-system-config +SNAP="/run/media/hans/usbsicherung/system-config-backup/$(hostname -s)/2026-04-29_08-20-00" +rsync -aHAX "${SNAP}/wireguard/" /tmp/restore-system-config/wireguard/ +``` + +Für NetworkManager: + +```bash +rsync -aHAX "${SNAP}/networkmanager-system-connections/" /tmp/restore-system-config/networkmanager-system-connections/ +``` + +Für APT-Quellen und Schlüssel: + +```bash +rsync -aHAX "${SNAP}/apt/" /tmp/restore-system-config/apt/ +``` + +Danach sollten Dateirechte, Inhalte und Konfigurationsvollständigkeit geprüft werden.[cite:105][cite:110] Beim produktiven Restore nach `/etc/NetworkManager/system-connections` müssen restriktive Rechte wie `600` erhalten bleiben, da NetworkManager Dateien mit zu offenen Rechten ignorieren kann.[cite:120][cite:122] + +## Produktiver Restore von APT + +Wenn APT-Dateien produktiv zurückgespielt werden, sollten `sources.list`, `sources.list.d`, `trusted.gpg.d` und `keyrings` bewusst und vollständig restauriert werden.[cite:135][cite:141] Danach ist ein `apt update` sinnvoll, um zu prüfen, ob alle Quellen erreichbar sind und die Signaturen korrekt verifiziert werden.[cite:144][cite:147] + +Beispiel: + +```bash +sudo rsync -aHAX /tmp/restore-system-config/apt/sources.list /etc/apt/sources.list +sudo rsync -aHAX /tmp/restore-system-config/apt/sources.list.d/ /etc/apt/sources.list.d/ +sudo rsync -aHAX /tmp/restore-system-config/apt/trusted.gpg.d/ /etc/apt/trusted.gpg.d/ +sudo rsync -aHAX /tmp/restore-system-config/apt/keyrings/ /etc/apt/keyrings/ +sudo apt update +``` + +## Nach einem Restore + +Wenn NetworkManager-Profile produktiv zurückkopiert wurden, kann ein erneutes Laden oder ein Neustart des Dienstes nötig sein.[cite:120][cite:122] + +Beispiel: + +```bash +sudo chmod 600 /etc/NetworkManager/system-connections/* +sudo systemctl restart NetworkManager +``` + +## Mögliche Erweiterungen + +Sinnvoll wären zusätzlich ein `--dry-run`-Schalter, optionales Backup weiterer Dateien wie `/etc/NetworkManager/NetworkManager.conf`, `/etc/apt/preferences.d` oder `/etc/resolv.conf`, sowie eine Automatisierung per `systemd`-Timer.[cite:124][cite:125] diff --git a/netzwerk-sicherung.sh b/system-sicherung.sh similarity index 61% rename from netzwerk-sicherung.sh rename to system-sicherung.sh index 75fdfbc..f779cf8 100644 --- a/netzwerk-sicherung.sh +++ b/system-sicherung.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash set -Eeuo pipefail -DEST_BASE="/run/media/hans/usbsicherung/system-config-backup" +DEST_BASE="/run/media/hans/usbsicherung/jacboy_sicherung/system_sicherung" HOST="$(hostname -s)" STAMP="$(date +%F_%H-%M-%S)" TARGET_DIR="${DEST_BASE}/${HOST}/${STAMP}" @@ -10,11 +10,16 @@ LOG_DIR="${DEST_BASE}/${HOST}/logs" LOG_FILE="${LOG_DIR}/netzwerk-backup-${STAMP}.log" KEEP=20 +# Quellen WG_SRC="/etc/wireguard" NM_SRC="/etc/NetworkManager/system-connections" +APT_SOURCES_LIST="/etc/apt/sources.list" +APT_SOURCES_D="/etc/apt/sources.list.d" +APT_TRUSTED_D="/etc/apt/trusted.gpg.d" +APT_KEYRINGS="/etc/apt/keyrings" log() { - local msg="[$(date +%F\ %T)] $*" + local msg="[$(date +%F\\ %T)] $*" echo "${msg}" mkdir -p "${LOG_DIR}" echo "${msg}" >> "${LOG_FILE}" @@ -25,10 +30,12 @@ fail() { exit 1 } +# Root nötig, weil /etc/* und ggf. restriktive Rechte if [[ ${EUID} -ne 0 ]]; then - fail "Dieses Skript muss mit sudo oder als root ausgeführt werden, da /etc/wireguard und /etc/NetworkManager/system-connections Root-Rechte benötigen." + fail "Dieses Skript muss mit sudo oder als root ausgeführt werden." fi +# Ziel prüfen if [[ ! -d "${DEST_BASE}" ]]; then fail "Zielbasis ${DEST_BASE} existiert nicht oder ist nicht gemountet." fi @@ -60,19 +67,41 @@ backup_tree() { local name="$2" if [[ -d "${src}" ]]; then - log "Sichere ${src} -> ${TARGET_DIR}/${name}/" + log "Sichere Verzeichnis ${src} -> ${TARGET_DIR}/${name}/" rsync "${RSYNC_OPTS[@]}" "${src}/" "${TARGET_DIR}/${name}/" | tee -a "${LOG_FILE}" else - log "Quelle ${src} existiert nicht – wird übersprungen." + log "Quelle (Verzeichnis) ${src} existiert nicht – wird übersprungen." fi } +backup_file() { + local src="$1" + local name="$2" + + if [[ -f "${src}" ]]; then + log "Sichere Datei ${src} -> ${TARGET_DIR}/${name}" + mkdir -p "$(dirname "${TARGET_DIR}/${name}")" + rsync "${RSYNC_OPTS[@]}" "${src}" "${TARGET_DIR}/${name}" | tee -a "${LOG_FILE}" + else + log "Quelle (Datei) ${src} existiert nicht – wird übersprungen." + fi +} + +# WireGuard & NetworkManager backup_tree "${WG_SRC}" "wireguard" backup_tree "${NM_SRC}" "networkmanager-system-connections" +# APT: sources und Keys +backup_file "${APT_SOURCES_LIST}" "apt/sources.list" +backup_tree "${APT_SOURCES_D}" "apt/sources.list.d" +backup_tree "${APT_TRUSTED_D}" "apt/trusted.gpg.d" +backup_tree "${APT_KEYRINGS}" "apt/keyrings" + +# latest-Link aktualisieren ln -sfn "${TARGET_DIR}" "${LATEST_LINK}" log "latest-Link zeigt jetzt auf ${TARGET_DIR}" +# Rotation cd "${DEST_BASE}/${HOST}" SNAPS=(20*/) @@ -86,4 +115,4 @@ else log "Keine Rotation nötig. Snapshots vorhanden: ${#SNAPS[@]}" fi -log "Netzwerk-Konfigurationsbackup abgeschlossen." \ No newline at end of file +log "Netzwerk- und APT-Konfigurationsbackup abgeschlossen." \ No newline at end of file