Skip to content

Instantly share code, notes, and snippets.

@rallisf1
Last active December 28, 2023 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rallisf1/db2869c921d765c3ea227bfad9834982 to your computer and use it in GitHub Desktop.
Save rallisf1/db2869c921d765c3ea227bfad9834982 to your computer and use it in GitHub Desktop.
mailcow-borgmatic-restore
version: '2.1'
services:
borgmatic-mailcow:
image: ghcr.io/borgmatic-collective/borgmatic
hostname: mailcow
restart: always
dns: ${IPV4_NETWORK:-172.22.1}.254
volumes:
- vmail-vol-1:/mnt/source/vmail:ro
- crypt-vol-1:/mnt/source/crypt:ro
- redis-vol-1:/mnt/source/redis:ro
- rspamd-vol-1:/mnt/source/rspamd:ro
- postfix-vol-1:/mnt/source/postfix:ro
- mysql-socket-vol-1:/var/run/mysqld/
- borg-config-vol-1:/root/.config/borg
- borg-cache-vol-1:/root/.cache/borg
- ./data/conf/borgmatic/etc:/etc/borgmatic.d:Z
- ./data/conf/borgmatic/ssh:/root/.ssh:Z
- ./data/conf/borgmatic/mount:/RestoreMount
- ./data/conf/borgmatic/recover:/Restore
environment:
- TZ=${TZ}
- BORG_PASSPHRASE=YOUR_SUPER_STRONG_PASS
devices:
- /dev/fuse
cap_add:
- SYS_ADMIN
security_opt:
- apparmor:unconfined
- label:disable
networks:
mailcow-network:
aliases:
- borgmatic
volumes:
borg-cache-vol-1:
borg-config-vol-1:
#!/bin/bash
# Configuration
MOUNT_PATH="/RestoreMount"
DOMAIN=""
USER=""
RECOVERY_PATH="/Restore"
ARCHIVE_PREFIX="mailcow-" # change this to match your archive naming scheme
# Function to show usage
usage() {
echo "Usage: $0 -d <domain> -u <user>"
exit 1
}
# Parse named arguments
while getopts "d:u:" opt; do
case $opt in
d)
DOMAIN=$OPTARG
echo "Domain: $OPTARG" >&2
;;
u)
USER=$OPTARG
echo "User: $OPTARG" >&2
;;
?)
echo "Invalid option: -$OPTARG" >&2
usage
;;
esac
done
# Check if DOMAIN is set
if [ -z "$DOMAIN" ]; then
echo "Error: Domain is required."
usage
fi
# Mount the repository
echo "Mounting repository..."
borgmatic mount --mount-point "$MOUNT_PATH"
# Iterate through each archive
for archive in $(ls "$MOUNT_PATH" | grep "$ARCHIVE_PREFIX"); do
echo "Processing archive: $archive"
[ -z "$USER" ] && ARCHIVE_VMAIL_PATH="$MOUNT_PATH/$archive/mnt/source/vmail/$DOMAIN" || ARCHIVE_VMAIL_PATH="$MOUNT_PATH/$archive/mnt/source/vmail/$DOMAIN/$USER/Maildir"
[ -z "$USER" ] && LIVE_VMAIL_PATH="/mnt/source/vmail/$DOMAIN" || LIVE_VMAIL_PATH="/mnt/source/vmail/$DOMAIN/$USER/Maildir"
[ -z "$USER" ] && RECOVERY_PATH="/Restore/$DOMAIN" || RECOVERY_PATH="/Restore/$DOMAIN/$USER/Maildir"
if [ -d "$ARCHIVE_VMAIL_PATH" ]; then
# Use diff to find deleted files and copy them
diff -r --brief "$ARCHIVE_VMAIL_PATH" "$LIVE_VMAIL_PATH" | grep "Only in $ARCHIVE_VMAIL_PATH" | while read line; do
file=$(echo "$line" | cut -d ' ' -f 4-)
echo "Recovering: $file"
mkdir -p "$RECOVERY_PATH/$(dirname $file)"
cp -p "$ARCHIVE_VMAIL_PATH/$file" "$RECOVERY_PATH/$file"
done
else
echo "Directory not found in archive: $ARCHIVE_VMAIL_PATH"
fi
done
# Unmount the repository
echo "Unmounting repository..."
borgmatic umount --mount-point "$MOUNT_PATH"
echo "Recovery process completed."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment