Symbolbild, welches ein stilisierte WordPress-Logo zeigt

WordPress Backup über Skript

Hintergrund: BackWPup wurde kaputt gemacht

Viele Jahre lang habe ich für meine regelmäßigen WordPress-Backups das Plugin BackWPup genutzt. Ursprünglich wurde es von Syde entwickelt und bereitgestellt und hat stets zuverlässig funktioniert. Eine Pro-Version war nicht erforderlich, solange man seine Backups nicht in irgendeine fragwürdige Cloud-Lösung hochladen wollte.

Irgendwann wurde das Plugin jedoch an ein anderes Unternehmen übergeben. Mit der Version 5 führte dieses nicht nur umfassende Änderungen an der Benutzeroberfläche ein, sondern verschlechterte damit auch die bisher gewohnte Benutzerfreundlichkeit erheblich. Zudem wurde sowohl die Dokumentation als auch die neue Oberfläche darauf ausgelegt, Nutzer stärker zu kostenpflichtigen Upgrades zu drängen.

Sieht man sich die Kommentare im wp.org Forum an, wird man erkennen, dass auch viele andere diese Meinung teilen.

Screenshot aus dem Forum bei wp.org zum Plugin.
Man sieht sehr viele Beiträge mit einer 1 von 5 Rezession des Plugins, die sich über die version beklagen.
Screenshot: Beitrage im WordPress Directory Forum zum NackWPUP-Plugin

Ein neues Backup muss her!

Ein Backup zu machen ist keine Rocket Science. Und wenn man sich die gängigen Plugins anschaut, dann muss man auch feststellen, dass sie im wesentlichen nur Wrapper sind, um ein Skript via WP-Cron auszuführen. Dieses Skript tut zwei Dinge: Ein Dump der Datenbank (und dieses zippen) und eine ZIP-Datei des WordPress-Verzeichnisses anlegen. Danach wird das Ganze entweder in einem gesonderten Verzeichnis abgelegt oder bei den Pro-Versionen auch noch auf einem externen Dienstleister.

Im Wesentlichen sind das 3 Befehle auf der Console (ohne Argumente):

  • mysqldump
  • tar
  • scp

Dieser Wrapper wird dann über WP-CRON regelmäßig ausgeführt.

Klar könnte man sich stattdessen auch ein anderes Plugin suchen, aber nach der Erfahrung mit dem obigen Plugin (und auch den gerade bei anderen Plugins feststellbaren Trend, einfachste Pippifax-Funktionen zu kommerzialisien und das Dashboard mit Werbe-Empfehlungen vollzuklatschen) möchte ich lieber eine seriösere Lösung unter meiner eigenen Kontrolle.

Backup via Shell-Skript

Ich hab daher folgendes Bash-Skript in meinem Server erstellt:

#!/bin/bash

# Variablen setzen
BACKUP_DIR="MEINSERVERVERZEICHNIS/webdomains/wordpress-backup"
SOURCE_DIR="MEINSERVERVERZEICHNIS/webdomains/MEINWORDPRESSDOMAINVERZEICHNIS"
DB_NAME="db10480177-blog"
DB_BACKUP_FILE="$BACKUP_DIR/db_backup_$(date +%Y%m%d%H%M%S).sql.gz"
FILE_BACKUP_FILE="$BACKUP_DIR/files_backup_$(date +%Y%m%d%H%M%S).tar.gz"
MY_CNF_PATH="MEINSERVERVERZEICHNIS/webdomains/scripts/.wp.cnf"
EXCLUDE_FILE="MEINSERVERVERZEICHNIS/webdomains/scripts/wordpress-backup-exclude-dirs.txt"
TIMESTAMP=$(date +"%Y-%m-%d %H:%M:%S")

# Sicherstellen, dass das Backup-Verzeichnis existiert
mkdir -p "$BACKUP_DIR"

echo "[$TIMESTAMP] Backup gestartet..."

# Datenbank-Backup mit mysqldump und Komprimierung
echo "Sicherung der Datenbank: $DB_NAME"
mysqldump --defaults-extra-file="$MY_CNF_PATH" --no-tablespaces "$DB_NAME" | gzip > "$DB_BACKUP_FILE"

if [ $? -eq 0 ]; then
    echo "Datenbank-Backup erfolgreich: $DB_BACKUP_FILE"
else
    echo "Fehler beim Sichern der Datenbank!"
    exit 1
fi

# Datei-Backup (WordPress-Verzeichnis) mit direkter Komprimierung
echo "Sicherung der WordPress-Dateien..."
tar -czf "$FILE_BACKUP_FILE" --exclude-from="$EXCLUDE_FILE" -C "$SOURCE_DIR" .

if [ $? -eq 0 ]; then
    echo "Datei-Backup erfolgreich: $FILE_BACKUP_FILE"
else
    echo "Fehler beim Sichern der Dateien!"
    exit 1
fi

# Alte Backups (älter als 7 Tage) bereinigen
echo "Lösche alte Backups (älter als 7 Tage)..."
find "$BACKUP_DIR" -type f -name "*.tar.gz" -mtime +7 -exec rm {} \;
find "$BACKUP_DIR" -type f -name "*.sql.gz" -mtime +7 -exec rm {} \;

echo "Backup abgeschlossen: $(date +"%Y-%m-%d %H:%M:%S")"

exit 0

Hinweis: Die im Skript angegebenen Bezeichnis MEINSERVERVERZEICHNIS und MEINWORDPRESSDOMAINVERZEICHNIS sind Platzhalter für den absoluten Verzeichnisnahmen auf meinem Server und dem Verzeichnis, indem sich die WordPress-Installation befindet. Diese Angaben muss man für seine eigene Installation anpassen.

Zusätzlich verwende ich im Bashskript zwei Dateien mit Konfigurationsangaben:

Konfigurationsdatei wordpress-backup-exclude-dirs.txt

In dieser Datei befindet sich eine Liste von Dateien und Verzeichnisse, die beim Erstellen des Dateibackups ignoriert werden sollen. Die Datei könnte bspw. so aussehen:

.well-known
wp-content/log
wp-content/cache
security.txt
wp-content/uploads/backup
wp-content/uploads/cache
*.log
*.tmp

Konfigurationsdatei .wp.cnf

[client]
user=datenbankusername
password=datenbankuserpassword
host=datenbankhostname

In dieser Datei befinden sich die vertraulichen Angaben zur Verbindung zu der Datenbank, die WordPress verwendet.
(An dieser Stelle war ich zugegebenermaßen etwas faul. Ich hätte stattdessen auch einfach die wp-config.php auslesen können, in der die Daten ja auch enthalten sind. Aber ich wollte es unabhängig machen.)

Was macht jetzt das obige Shell-Skript?

Das Skript erstellt zunächst das Backup-Verzeichnis, falls es noch nicht existert.

Anschließend führt das Skript mit mysqldump ein Backup der verwendeten WordPress-Datenbank durch. Die dafür notwendigen Login-Daten werden aus der Datei .wp.cnf ausgelesen. Um Rechteprobleme bei manchen Providern zu vermeiden, wird die Option --no-tablespaces verwendet. Der Datenbank-Dump wird mit gzip komprimiert und mit einem aktuellen Zeitstempel im Dateinamen im Backup-Verzeichnis gespeichert.

Nachdem die Datenbank gesichert wurde, folgt die Sicherung des Dateisystems. Dazu wird das WordPress-Verzeichnis mit tar -czf archiviert und komprimiert. Über das Argument --exclude-from="$EXCLUDE_FILE" werden unnötige Dateien und Verzeichnisse vom Backup ausgeschlossen. Auch diese Datei erhält einen Zeitstempel im Dateinamen und wird ins Backup-Verzeichnis verschoben.

Zum Abschluss löscht das Skript alle Backups, die älter als 7 Tage sind. Falls diese Frist zu kurz ist und Backups länger aufbewahrt werden sollen, kann die Angabe -mtime +7 entsprechend angepasst werden.

Crontab

Damit das Skript regelmäßig (zum Beispiel nächtlich) ausgeführt wird, muss am Ende noch ein Crontab-Eintrag gemacht werden.

Wenn man einen (linuxbasierten) virtuellen Server mit den entsprechenden Berechtigungen hat, kann hierfür das crontab -e Kommando nutzen. Viele dürften jedoch auch bei der Administratonsoberfläche ihres Providers eine ensprechende Funktion vorfinden.

Bei Nutzung eines Webserver-Angebots bei Hosteurope sieht das Beispielsweise so aus:

Screenshot der Crontab-Einstellung bei Webserver Basic von Hosteurope
Screenshot: Crontab-Einstellung eines Jobs in der KIS-Oberfläche von Hosteuope

Je nach Provider sieht das unterschiedlich aus. Das Prinzip ist immer dasselbe: Das Skript wird in der crontab des Servers eingetragen und automatisch zu vorgegebenen Zeiten gestartet.

Zusätzliche Eigensicherung

Das Skript legt die Dateien nur in dem Ordner auf dem selben Server ab, wo auch die WordPress-Installation läuft. In dem Fall, dass der Server abraucht, hat man dabei leider noch nicht viel gewonnen. Denn dann sind auch diese Dateien unerreichbar. Zwar wird jeder gute Provider die Dateien alle ebenfalls nochmal sichern, aber hier ist man wieder abhängig von Dritten.

Hat man einen eigenen, getrennten Server, kann man nun noch zusätzlich auf diesen ein Skript ähnlich dem obigen ablegen, welcher die Dateien regelmässig über scp kopiert. Natürlich kann man das auch manuell machen.
Dies kann dann so aussehen:

scp MEINUSERNAME@MEINHOSTNAME:~/webdomains/wordpress-backup/*.gz .

Lange Rede, kurzer Sinn:
Mit den obigen Skript erspare ich mir ein neues Plugin und hab alles selbst in der Hand. Und wie man sieht, ist das alles kein Hexenwerk. Zusammen mit der üblicherweise zusätzlichen Sicherung des Providers, kann ich so meine WordPress-Installation selbstständig sichern und hab für den Fall der Fälle eine zweite Sicherheit.