diff --git a/root/.ssh/config b/root/.ssh/config new file mode 100644 index 0000000..317083d --- /dev/null +++ b/root/.ssh/config @@ -0,0 +1,5 @@ +Host gitea-internal + HostName 127.0.0.1 + User git + Port 2222 + IdentityFile /root/.ssh/id_ed25519 diff --git a/root/backup-config/backup-config.sh b/root/backup-config/backup-config.sh new file mode 100755 index 0000000..4cb4c1f --- /dev/null +++ b/root/backup-config/backup-config.sh @@ -0,0 +1,267 @@ +#!/usr/bin/env bash +set -Eeuo pipefail + +######################################## +# Einstellungen +######################################## + +SOURCE_LIST="/root/backup-config/sources.txt" +BACKUP_ROOT="/root/backup-config/backup" +LOGFILE="/var/log/backup-config.log" + +# Git +USE_GIT="yes" +GIT_BRANCH="DockerDMZ_Configfiles" + +# Verzeichnisse, die automatisch nach Config-Dateien durchsucht werden +AUTO_SCAN_DIRS=( + "/root/docker" +) + +# Dateitypen, die automatisch erkannt werden +AUTO_FILE_TYPES=( + "*.sh" + "*.yml" + "*.yaml" + "*.env" + "*.conf" + "*.cnf" + "*.ini" + "*.json" + "*.toml" + "*.service" + "Dockerfile" + "docker-compose.yml" + "compose.yml" +) + +# Pfade, die beim automatischen Scan ausgeschlossen werden +EXCLUDES=( + "*/data/pages/*" + "*/data/media/*" + "*/data/cache/*" + "*/data/tmp/*" + "*/logs/*" + "*/log/*" + "*/db/*" + "*/database/*" + "*/mysql/*" + "*/mariadb/*" + "*/postgres/*" + "*/redis/*" + "*/.git/*" +) + +######################################## +# Logging +######################################## + +log() { + printf '%s %s\n' "$(date '+%F %T')" "$1" | tee -a "$LOGFILE" +} + +######################################## +# Hilfsfunktionen +######################################## + +is_excluded() { + local path="$1" + local ex + + for ex in "${EXCLUDES[@]}"; do + if [[ "$path" == $ex ]]; then + return 0 + fi + done + + return 1 +} + +copy_path() { + local src="$1" + local rel + local dst + + if is_excluded "$src"; then + log "SKIP (exclude): $src" + return 0 + fi + + if [[ -f "$src" ]]; then + rel="${src#/}" + dst="$BACKUP_ROOT/$rel" + + mkdir -p "$(dirname "$dst")" + cp -a "$src" "$dst" + log "OK (FILE): $src -> $dst" + return 0 + fi + + if [[ -d "$src" ]]; then + rel="${src#/}" + dst="$BACKUP_ROOT/$rel" + + mkdir -p "$(dirname "$dst")" + cp -a "$src" "$dst" + log "OK (DIR): $src -> $dst" + return 0 + fi + + log "WARN: Pfad nicht gefunden: $src" + return 1 +} + +######################################## +# Automatischer Scan +######################################## + +auto_scan() { + local dir + local file + local find_expr=() + + log "INFO: Starte automatischen Scan" + + # find-Ausdruck für Dateitypen bauen + for pattern in "${AUTO_FILE_TYPES[@]}"; do + find_expr+=( -name "$pattern" -o ) + done + unset 'find_expr[${#find_expr[@]}-1]' + + for dir in "${AUTO_SCAN_DIRS[@]}"; do + if [[ ! -d "$dir" ]]; then + log "WARN: Auto-Scan-Verzeichnis fehlt: $dir" + continue + fi + + while IFS= read -r file; do + if is_excluded "$file"; then + log "SKIP (exclude): $file" + continue + fi + copy_path "$file" || true + done < <( + find "$dir" -type f \( "${find_expr[@]}" \) 2>/dev/null | sort -u + ) + done +} + +######################################## +# Git +######################################## + +git_prepare_repo() { + if [[ "$USE_GIT" != "yes" ]]; then + return 0 + fi + + if ! command -v git >/dev/null 2>&1; then + log "ERROR: Git ist nicht installiert" + return 1 + fi + + mkdir -p "$BACKUP_ROOT" + + if [[ ! -d "$BACKUP_ROOT/.git" ]]; then + log "INFO: Git-Repository wird initialisiert" + git -C "$BACKUP_ROOT" init + fi + + # Benutzerinfo prüfen + if ! git -C "$BACKUP_ROOT" config user.name >/dev/null; then + log "WARN: Git user.name ist im Repository nicht gesetzt" + fi + + if ! git -C "$BACKUP_ROOT" config user.email >/dev/null; then + log "WARN: Git user.email ist im Repository nicht gesetzt" + fi +} + +git_checkout_branch() { + local branch="$1" + + if [[ "$USE_GIT" != "yes" ]]; then + return 0 + fi + + if [[ -z "$branch" ]]; then + return 0 + fi + + if git -C "$BACKUP_ROOT" show-ref --verify --quiet "refs/heads/$branch"; then + git -C "$BACKUP_ROOT" checkout "$branch" >/dev/null 2>&1 + log "INFO: Git-Branch aktiviert: $branch" + return 0 + fi + + # Wenn noch gar kein Commit existiert, zuerst initialen Commit anlegen + if ! git -C "$BACKUP_ROOT" rev-parse --verify HEAD >/dev/null 2>&1; then + git -C "$BACKUP_ROOT" add -A + if ! git -C "$BACKUP_ROOT" diff --cached --quiet; then + git -C "$BACKUP_ROOT" commit -m "Initial backup import" + log "INFO: Initialer Commit erstellt" + fi + fi + + git -C "$BACKUP_ROOT" checkout -b "$branch" >/dev/null 2>&1 + log "INFO: Git-Branch erstellt und aktiviert: $branch" +} + +git_commit_changes() { + local changed_files + local commit_msg + + if [[ "$USE_GIT" != "yes" ]]; then + return 0 + fi + + git -C "$BACKUP_ROOT" add -A + + if git -C "$BACKUP_ROOT" diff --cached --quiet; then + log "INFO: Keine Änderungen für Git" + return 0 + fi + + changed_files="$(git -C "$BACKUP_ROOT" diff --cached --name-only | sed 's#^# - #' || true)" + + commit_msg=$( + cat <&2 + exit 1 + fi + + mkdir -p "$BACKUP_DIR" + + log "INFO: Starte Backup" + "$BACKUP_SCRIPT" + log "INFO: Backup beendet" + + cd "$BACKUP_DIR" + + if ! command -v git >/dev/null 2>&1; then + log "ERROR: Git ist nicht installiert" + exit 1 + fi + + if [[ ! -d .git ]]; then + log "INFO: Git-Repository wird initialisiert" + git init + fi + + # Branch aktivieren oder anlegen + if git show-ref --verify --quiet "refs/heads/$BRANCH"; then + git checkout "$BRANCH" >/dev/null 2>&1 + log "INFO: Git-Branch aktiviert: $BRANCH" + else + if git rev-parse --verify HEAD >/dev/null 2>&1; then + git checkout -b "$BRANCH" >/dev/null 2>&1 + else + git checkout --orphan "$BRANCH" >/dev/null 2>&1 + fi + log "INFO: Git-Branch erstellt: $BRANCH" + fi + + git add -A + + if git diff --cached --quiet; then + log "INFO: Keine neuen Dateiinhalte für Commit" + else + git commit -m "Config-Backup $(hostname) $(date '+%F %T')" + log "INFO: Commit erstellt" + fi + + if ! git remote get-url origin >/dev/null 2>&1; then + log "WARN: Kein Remote 'origin' konfiguriert, Push übersprungen" + exit 0 + fi + + # Remote-Infos aktualisieren + git fetch origin "$BRANCH" >/dev/null 2>&1 || true + + # Falls der Remote-Branch noch nicht existiert + if ! git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then + git push -u origin "$BRANCH" + log "INFO: Initialer Push des Branches erfolgreich" + exit 0 + fi + + # Prüfen, ob lokale Commits noch nicht gepusht wurden + AHEAD_COUNT="$(git rev-list --count "origin/$BRANCH..$BRANCH" 2>/dev/null || echo 0)" + + if [[ "$AHEAD_COUNT" -gt 0 ]]; then + git push origin "$BRANCH" + log "INFO: Push erfolgreich ($AHEAD_COUNT lokale Commits übertragen)" + else + log "INFO: Kein Push nötig, Remote ist aktuell" + fi +} + +main diff --git a/root/backup-config/sources.txt b/root/backup-config/sources.txt new file mode 100644 index 0000000..be14142 --- /dev/null +++ b/root/backup-config/sources.txt @@ -0,0 +1,44 @@ +#systembasis +/etc/network/interfaces +/etc/hosts +/etc/fstab +/etc/samba/smb.conf +/etc/systemd/system +/root/backup-config/backup-config.sh +/root/backup-config/run-backup-and-push.sh +/root/backup-config/sources.txt +/root/.ssh/config +/root/dokuwiki_backup/backup_rsit.sh +/root/dokuwiki_backup/backup_wiki.sh + + +#traefik +/root/docker/traefik/data/traefik.yml +/root/docker/traefik/start.sh +/root/docker/traefik/data/dynamic/middlewares.yml +/root/docker/traefik/data/traefik.yml +/root/docker/traefik/data/dynamic + +#dokuwiki +/root/docker/dokuwiki/docker-compose.yml +/root/docker/dokuwiki/start.sh +/root/docker/dokuwiki/data/conf + +#Webroxy +/root/docker/Webproxy/start.sh +/root/docker/Webproxy/docker-compose.yml +/root/docker/Webproxy/certbot.sh +/root/docker/Webproxy/Data/nginx/ + +#nextcloud +/root/docker/nextcloud/start.sh +/root/docker/nextcloud/docker-compose.yml +/root/docker/nextcloud/Dockerfile +/root/docker/nextcloud/data/nginx/nginx.conf +/root/docker/nextcloud/.env +/srv/nextcloud-data-local/nextcloud/config/config.php + +#Gitea +/root/docker/gitea/data/gitea/conf/app.ini +/root/docker/gitea/docker-compose.yml +/root/docker/gitea/start.sh diff --git a/root/dokuwiki_backup/backup_rsit.sh b/root/dokuwiki_backup/backup_rsit.sh new file mode 100755 index 0000000..4690624 --- /dev/null +++ b/root/dokuwiki_backup/backup_rsit.sh @@ -0,0 +1,47 @@ +#!/bin/bash +set -euo pipefail + +# ===== Konfiguration ===== +SOURCE="/root/docker/dokuwiki/data" # Root von DokuWiki (enthält data/) +BACKUPDIR="/root/dokuwiki_backup" +REMOTE_USER="backupuser" +REMOTE_HOST="backupserver" +REMOTE_PATH="/remote/backup/path" +RETENTION_DAYS=14 + +DATE=$(date +%F) +ARCHIVE="dokuwiki-rsit-$DATE.tar.gz" +HASHFILE="$ARCHIVE.sha256" + +# Nur diese Teilpfade sichern (relativ zu $SOURCE) +INCLUDE_PATHS=( + "data/meta/rsit" + "data/media/rsit" + "data/pages/rsit" +) + +# ===== Vorbereitung ===== +mkdir -p "$BACKUPDIR" + +# ===== Prüfen, ob alle Pfade existieren (sonst hart abbrechen) ===== +for p in "${INCLUDE_PATHS[@]}"; do + if [[ ! -d "$SOURCE/$p" ]]; then + echo "FEHLER: Verzeichnis fehlt: $SOURCE/$p" >&2 + exit 1 + fi +done + +# ===== Archiv erstellen (Struktur bleibt erhalten) ===== +tar -czf "$BACKUPDIR/$ARCHIVE" -C "$SOURCE" "${INCLUDE_PATHS[@]}" + +# ===== Hash erzeugen ===== +cd "$BACKUPDIR" +sha256sum "$ARCHIVE" > "$HASHFILE" + +# ===== Upload ===== +#rsync -avz "$ARCHIVE" "$HASHFILE" \ +# "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" + +# ===== Alte Backups lokal löschen ===== +find "$BACKUPDIR" -type f -mtime +"$RETENTION_DAYS" -name "dokuwiki-rsit-*.tar.gz" -delete +find "$BACKUPDIR" -type f -mtime +"$RETENTION_DAYS" -name "dokuwiki-rsit-*.sha256" -delete diff --git a/root/dokuwiki_backup/backup_wiki.sh b/root/dokuwiki_backup/backup_wiki.sh new file mode 100755 index 0000000..28fc0af --- /dev/null +++ b/root/dokuwiki_backup/backup_wiki.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -euo pipefail + +# ===== Konfiguration ===== +SOURCE="/root/docker/dokuwiki" +BACKUPDIR="/root/dokuwiki_backup" +REMOTE_USER="backupuser" +REMOTE_HOST="backupserver" +REMOTE_PATH="/remote/backup/path" +RETENTION_DAYS=14 + +DATE=$(date +%F) +ARCHIVE="dokuwiki-$DATE.tar.gz" +HASHFILE="$ARCHIVE.sha256" + +# ===== Vorbereitung ===== +mkdir -p "$BACKUPDIR" + +# ===== Archiv erstellen ===== +tar -czf "$BACKUPDIR/$ARCHIVE" \ + -C "$SOURCE" data + +# ===== Hash erzeugen ===== +cd "$BACKUPDIR" +sha256sum "$ARCHIVE" > "$HASHFILE" + +# ===== Upload ===== +# rsync -avz "$ARCHIVE" "$HASHFILE" \ +# "${REMOTE_USER}@${REMOTE_HOST}:${REMOTE_PATH}/" + +# ===== Alte Backups lokal löschen ===== +find "$BACKUPDIR" -type f -mtime +"$RETENTION_DAYS" -name "dokuwiki-*.tar.gz" -delete +find "$BACKUPDIR" -type f -mtime +"$RETENTION_DAYS" -name "dokuwiki-*.sha256" -delete