mailinabox/management/backup.py

67 lines
2.0 KiB
Python
Raw Normal View History

2014-06-03 20:21:17 +00:00
#!/usr/bin/python3
# This script performs a backup of all user data:
# 1) System services are stopped while a copy of user data is made.
# 2) An incremental backup is made using rdiff-backup into the
# directory STORAGE_ROOT/backup/rdiff-history. This directory
# will contain the latest files plus a complete history for
# all prior backups.
# 3) The stopped services are restarted.
# 4) The backup directory is compressed into a single file using tar.
# 5) That file is encrypted with a long password stored in backup/secret_key.txt.
import os, os.path, subprocess
from utils import exclusive_process, load_environment, shell
2014-06-03 20:21:17 +00:00
env = load_environment()
exclusive_process("backup")
# Ensure the backup directory exists.
backup_dir = os.path.join(env["STORAGE_ROOT"], 'backup')
rdiff_backup_dir = os.path.join(backup_dir, 'rdiff-history')
os.makedirs(backup_dir, exist_ok=True)
# Stop services.
shell('check_call', ["/usr/sbin/service", "dovecot", "stop"])
shell('check_call', ["/usr/sbin/service", "postfix", "stop"])
2014-06-03 20:21:17 +00:00
# Update the backup directory which stores increments.
try:
shell('check_call', [
"/usr/bin/rdiff-backup",
2014-06-03 20:21:17 +00:00
"--exclude", backup_dir,
env["STORAGE_ROOT"],
rdiff_backup_dir])
except subprocess.CalledProcessError:
# Trap the error so we restart services again.
2014-06-03 20:21:17 +00:00
pass
# Start services.
shell('check_call', ["/usr/sbin/service", "dovecot", "start"])
shell('check_call', ["/usr/sbin/service", "postfix", "start"])
# Tar the rdiff-backup directory into a single file.
shell('check_call', [
"/bin/tar",
"-zc",
"-f", os.path.join(backup_dir, "latest.tgz"),
"-C", rdiff_backup_dir,
"."])
# Encrypt the backup using the backup private key.
shell('check_call', [
"/usr/bin/openssl",
"enc",
"-aes-256-cbc",
"-a",
"-salt",
"-in", os.path.join(backup_dir, "latest.tgz"),
"-out", os.path.join(backup_dir, "latest.tgz.enc"),
"-pass", "file:%s" % os.path.join(backup_dir, "secret_key.txt"),
])
2014-06-03 20:21:17 +00:00
# The backup can be decrypted with:
# openssl enc -d -aes-256-cbc -a -in latest.tgz.enc -out /dev/stdout -pass file:secret_key.txt | tar -z