Gregor Horvath, Ing.

Industrieberatung

Softwareentwicklung

Backupserver mit rotierenden außer Haus Festplatten

1 Über diese Dokumentation

Diese Dokumentation enthält die Besonderheiten meiner Backup Einrichtung, die nicht in freier Dokumentation enthalten ist. (Man Pages etc.).

Einerseits da ich eine lange Betriebszeit der Lösung anstrebe und in 10 Jahren noch wissen will was ich wie und warum so eingerichtet habe und andererseits hege ich die Hoffnung, dass andere aus den Informationen nutzen ziehen können und ich damit den Einsatz freier Software und folglich die Erlangung informationeller Selbstbestimmung und digitaler Freiheit unserer Gesellschaft unterstütze.

Das Ziel ist kein How To und keine Schritt für Schrittanleitung, sondern eine Ergänzung zu im Netz und freier Softwaredokumentation vorhandenen Informationen. Verweise auf diese werden ggf. gegeben.

Bei Fragen, Hinweisen, Fehlern oder kommerziellen Beratungs/Installations/Anpassungsbedarf bitte melden.

Diese Dokumentation ist lizenziert unter CC BY-SA 4.0. Der Quellcode unter GNU General Public License v3 or later.

2 Zielsetzung

Für die Sicherung aller unserer Geräte und um im Notfall eine idente, freie Austauschhardware für meinen Web/Emailserver zu haben habe ich einen Backupserver mit derselben Olimex A20 Hardware (freie Konstruktion) eingerichtet. Dieser kleine, sehr stromsparende ARM basierte SoC Server sichert automatisch laufend diverse Server und Laptops, PC's und Handys über das Netzwerk (Wlan, Lan, Internet) auf 2 externe verschlüsselte USB Festplatten. Eine davon ist immer extern physikalisch getrennt verwahrt, während auf die andere laufend vom Server gesichert wird. Wöchentlich werden die Platten getauscht. Auf den zu sichernden Geräten sollte einzig rsync und ssh mit passwortlosem Login notwendig sein. Das Backup sollte zentral vom Server ausgelöst, gesteuert und überwacht werden. Das erleichtert die Administration.

3 Hardware

3.1 Olimex A20-OlinuXino-MICRO wie Webserver, mit folgenden Unterschieden:

  • blaues Gehäuse statt schwarz (zwecks Unterscheidbarkeit)
  • kleinere 250mA Batterie, die 1400mAh des Webservers sind für eine USV überdimensioniert.
  • T2 Prozessor statt dem A20. T hat einen größeren Temperaturbereich (Industrieausführung), ansonsten ident. T hat es zum Zeitpunkt als ich den Webserver kaufte noch nicht gegeben.

3.2 2 x 2,5'' externe USB Platten 4T Seagate BUP SL

Die externen Festplatten werden am oberen USB Port 1, der 1000 mA liefert, angeschlossen. Der untere Port 2 liefert nur 523mA und ist daher zu schwach.

UAS funktioniert mit dem Linux Kernel nicht zuverlässig und mußte deaktiviert werden:

$ cat /etc/modprobe.d/blacklist_uas.conf
options usb-storage quirks=0bc2:ab28:u

Die Platten sind mit dm-crypt/luks verschlüsselt und mit ext4 Dateisystem formatiert. Zwecks Unterscheidbarkeit haben sie unterschiedliche Gehäusefarben.

3.3 1 x vorhandene interne SATA HDD 320 GB Samsung HM329JI

wird für andere Zwecke benutzt

4 Software

4.1 Betriebssystem

Installiert wurde wie auf dem Webserver Standard Debian Stretch, allerdings mit unverschlüsselter Root Partition auf der SD/MMC1 microSD Karte und dem von Olimex mit deren Image mitgelieferten u-boot. Von dem größeren SD/MMC2 SD Karten Schacht ist leider kein Betriebssystemstart möglich. (von Olimex dokumentiert)

Diverse Absicherungen des Servers wurden konfiguriert / installiert.

Um ein versehentliches Schreiben auf das nicht eingehängte Mount-Verzeichnis der externen Platte und damit ein Vollschreiben der Root Partition zu vermeiden, wurde das Verzeichnis mit chattr schreibgeschützt.

Zur Erhöhung der Sicherheit und um Strom zu sparen werden die externen USB Platten vor dem Backup eingeschaltet und nach dem Backup wieder komplett abgeschaltet:

$ cat /usr/local/bin/mount-exthdd
#!/bin/bash
# exit 2
source getbkpdev
source lockwait

timeout=30 # seconds to wait for the device appearing
lockfile=/var/lock/mount-exthdd.lock
lockwait $lockfile 10 60

trap "rm -f ${lockfile}; exit" INT TERM EXIT
echo $$ >${lockfile}

if mount | grep "/dev/mapper/exthdd_crypt" > /dev/null; then
    exit 0;
fi

if ! get_dev >/dev/null ; then
    # probably before powered off usb device, reload kernel module to turn it on again
    rmmod ehci_platform
    modprobe ehci_platform

    # wait for the device to appear
    i=0
    until get_dev > /dev/null ; do
        sleep 10
        let "i++"
        if [ $i -eq $timeout ]; then
            echo "timout searching for the device waited times: $i"
            exit 1
        fi
        # echo "waiting... nr $i"
    done
fi

if ! get_dev > /dev/null; then
    echo "unable to find backup device" 1>&2
    exit 1
fi

cryptsetup luksOpen $(get_dev) exthdd_crypt --key-file=xxxx

if [ $? ]; then
  mount /dev/mapper/exthdd_crypt /mnt/exthdd
fi
$ cat /usr/local/bin/lockwait

function dbg {
    # logger -id "$srcname.lockwait" -p syslog.debug "$1"
    # echo $1
    }

function lockwait () {
    lockfile=$1
    sleeptime=$2
    timeout=$3
    scrname=$(echo $0 | awk -F "/" '{print $NF}')

    if [ -f $lockfile ]; then
        PID=$(cat $lockfile)
        dbg "lockfile $lockfile : andere PID=$PID eigene=$$"
        if [ $PID -ne $$ ]; then
            if kill -0 $PID; then
                t="waiting for '$lockfile' pid: $PID"
                logger -id $scrname -p syslog.info "$t"
                dbg "$t"
                i=0
                while ps -p $PID >/dev/null 2>&1
                do
                    dbg "sleep $sleeptime nr $i"
                    sleep $sleeptime
                    let "i++"
                    if [ $i -eq $timeout ]; then
                        t="timeout waiting for '$lockfile' pid: $PID"
                        logger -id $scrname -p syslog.err $t
                        dbg "$t"
                        exit 1
                    fi
                done
                dbg "$PID nicht mehr da"
            fi
        fi
    else
        dbg "lockfile $lockfile nicht vorhanden"
    fi
}
$ cat /usr/local/bin/getbkpdev
#!/bin/bash

dev_schwarz=/dev/disk/by-uuid/xxxxxxx-xxxx-xxx-xxxx-xxxxxx
dev_silber=/dev/disk/by-uuid/xxxxxxx-xxxx-xxx-xxxx-xxxxxx

get_dev () {
    if test -b $dev_schwarz; then
        echo $dev_schwarz
        return 0
    elif test -b $dev_silber; then
        echo $dev_silber
        return 0
    else
        return 1
    fi
}
$ cat /usr/local/bin/umount-exthdd
#!/bin/bash

source getbkpdev
timeout=10 # seconds to wait for the device powering off

umount /mnt/exthdd && cryptsetup luksClose /dev/mapper/exthdd_crypt

if [ $? -eq 0 ] && get_dev > /dev/null; then
  i=0
  until udisksctl power-off -b $(get_dev) || [ $i -eq $timeout ]; do
    sleep 1
    i=$(( i++ ))
  done
fi

4.2 Backup Software

Für die inkrementelle Sicherung täglich, wöchentlich, monatlich wird rsnapshot verwendet. BorgBackup wird nicht verwendet weil es nicht in Dateien, sondern in ein eigenes Container Format sichert. Allerdings ist für mich die Einfachheit, Solidität und direkter, langlebiger, zukunftssicherer Dateizugriff eine zentrales Kriterium eines Backups. Die Deduplizierung auf Byteebene die BorgBackup im Gegensatz zu rsnapshot bietet, ist bei unseren Daten nicht entscheidend relevant. Darüberhinaus bin ich der Meinung, dass die Deduplizierung eine separate Aufgabe des Dateisystems oder einer dedizierten Schicht zwischen Dateisystem und Anwendung ist. Leider sind die Programme dazu (btrfs, zfs etc.) für GNU/Linux nicht vorhanden bzw. noch nicht ausgereift.

Für rdiff-backup gilt Ähnliches (zumindest für die Inkrements), darüber hinaus scheint es derzeit nicht wirklich aktiv gepflegt/genutzt zu werden. rsnapshot ist im Aufbau recht einfach und setzt über Jahrzehnte bewährte, simple Unix Hausmittel wie Hardlinks, cp, rsync, mv, touch etc. ein.

Für die Auslösung, Steuerung und Überwachung der Sicherung werden cron, anacron und selbst erstellte Bash Skripte verwendet. Systemd wird abseits des Debian Standards nicht verwendet, da die Architektur nicht der Unix Philosophie entspricht.

Server die dauernd eingeschaltet sind und Endgeräte die nur sporadisch im Netz verfügbar sind benötigen eine separate Konfiguration:

4.2.1 Nicht andauernd eingeschaltete Geräte

Über cron wird regelmäßig geprüft ob das Gerät im Netz ist und nicht im Batteriebetrieb läuft (ansonsten leert das Backup die Batterie) und ob dieses an diesem Tag noch nicht gesichert wurde:

$ cat /etc/cron.d/backup_check_hosts
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
MAILTO=root

# m h dom mon dow user  command
*/2 * * * *       root    /usr/local/bin/backup_check_hosts
$ cat /usr/local/bin/backup_check_hosts
#!/bin/bash

hosts="host1 host2 host3"
lockfile=/var/run/rsnapshot.pid
debug=0

dbg () {
    if [ ! $debug == "0" ]; then
       echo $1
    fi
}

if [ -f $lockfile ]; then
    if kill -0 $(cat $lockfile); then
        dbg "rsnapshot already running. $lockfile: PID $(cat $lockfile)"
        exit 0
    fi
fi

for host in $hosts; do
    if nc -z -w 1 $host 22 &> /dev/null; then
        if [ $debug == "0" ]; then
            ssh $host /usr/bin/on_ac_power 2> /dev/null
        else
            ssh $host /usr/bin/on_ac_power
        fi
        if [ $? -ne 1 ]; then
            dbg "run anacron for $host"
            anacron -q -s -d -n -t /etc/anacrontab-bkp $host.*
        else
            dbg "$host not on ac power"
        fi
    fi
done

Anacron wird verwendet um die Intervalle der Sicherungen zu steuern. Für die Steuerung der Debian Standard /etc/cron.* jobs wurde cron statt anacron konfiguriert, da ja der Backupserver selbst kein anacron benötigt, da er immer läuft. Im Debian-Standard wird dafür anacron verwendet sobald es installiert ist.

$ cat /etc/anacrontab-bkp
# /etc/anacrontab: configuration file for anacron

# See anacron(8) and anacrontab(5) for details.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
HOME=/root
LOGNAME=root

# days          delay   job             command
1               10      host1.daily   backup host1 daily
7               5       host1.weekly  backup host1 weekly
@monthly        0       host1.monthly backup host1 monthly

1               10      host3.daily    backup host3 daily
7               5       host3.weekly   backup host3 weekly
@monthly        0       host3.monthly  backup host3 monthly

1               10      host2.daily       backup host2 daily
7               5       host2.weekly      backup host2 weekly
@monthly        0       host2.monthly     backup host2 monthly
$ cat /usr/local/bin/backup
#!/bin/bash

source lockwait

lockfile=/var/run/rsnapshot.pid

lockwait $lockfile 300 40

/usr/local/bin/mount-exthdd && /usr/bin/rsnapshot -c /etc/rsnapshot-$1.conf $2
/usr/local/bin/umount-exthdd

Da die Endgeräte üblicherweise tagsüber gesichert werden, wird um den sonstigen Netzwerkverkehr nicht zu beeinträchtigen für rsync ein Bandbreitenlimit abhängig von der typischen Netzwerkverbindung des Gerätes (WLAN, LAN, WAN) gesetzt. Beispiel einer rechnerspezifischen rsnapshot Konfiguration:

$ cat /etc/rsnapshot-host1.conf
include_conf    /etc/rsnapshot.conf
snapshot_root   /mnt/exthdd/rsnapshot/host1
exclude         /media
exclude         /mnt
backup          host1:/       ./      +rsync_long_args=--bwlimit=4166K

4.2.2 Server

Das Backup der Server wird über eine typische, übliche rsnapshot Konfiguation mit cron gesteuert.

$ cat /etc/cron.d/rsnapshot
# This is a sample cron file for rsnapshot.
# The values used correspond to the examples in /etc/rsnapshot.conf.
# There you can also set the backup points and many other things.
#
# To activate this cron file you have to uncomment the lines below.
# Feel free to adapt it to your needs.

SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

#m  h dom mon dow       user    command
# 0 */4         * * *           root    /usr/bin/rsnapshot alpha
30 2    * * *           root    /usr/local/bin/backup server daily
0  2    * * 1           root    /usr/local/bin/backup server weekly
30 1    1 * *           root    /usr/local/bin/backup server monthly

4.2.3 Überwachung

Um zu überpüfen ob und welche Dateien tatsächlich gesichert wurden, ruft ein separater Cron Job find auf um die Dateien zu finden, deren Änderungszeit jünger als 24 h ist. Das Ergebnis wird täglich gemailt:

$ cat /etc/cron.d/mailbackupdateien
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin

#m  h dom mon dow       user    command
0 5 * * *       root    /usr/local/bin/mount-exthdd && find /mnt/exthdd/rsnapshot -path '*/daily.0/*' -mtime -1 | /usr/bin/mail -s "Backup Dateien exthdd - 1 Tag alt" xxx@xxx.com; /usr/local/bin/umount-exthdd

# EOF

Autor: Gregor Horvath

Created: 2019-02-27 Mit 09:38

Validate