180 lines
6.3 KiB
Python
180 lines
6.3 KiB
Python
|
|
# Backup & recovery commands for encrypted remote backups
|
||
|
|
# Each function returns a bash command string that app.py executes via ssh_run()
|
||
|
|
|
||
|
|
|
||
|
|
def backup_now_cmd(paths="/etc /var/www /opt/seteclabs /root", dest="/var/backups/setec",
|
||
|
|
encrypt_pass="", remote_host="", remote_path=""):
|
||
|
|
"""Return bash cmd to create an encrypted compressed backup."""
|
||
|
|
ts = "$(date +%Y%m%d_%H%M%S)"
|
||
|
|
archive = f"{dest}/setec-backup-{ts}.tar.gz"
|
||
|
|
|
||
|
|
cmd = (
|
||
|
|
f"echo '=== Creating Backup ===' && "
|
||
|
|
f"mkdir -p {dest} && "
|
||
|
|
f"tar czf {archive} {paths} 2>&1 && "
|
||
|
|
f"SIZE=$(du -h {archive} | cut -f1) && "
|
||
|
|
f"echo \"Archive created: {archive} ($SIZE)\" "
|
||
|
|
)
|
||
|
|
|
||
|
|
if encrypt_pass:
|
||
|
|
enc_archive = f"{archive}.enc"
|
||
|
|
cmd += (
|
||
|
|
f"&& echo 'Encrypting...' && "
|
||
|
|
f"openssl enc -aes-256-cbc -salt -pbkdf2 -in {archive} "
|
||
|
|
f"-out {enc_archive} -pass pass:'{encrypt_pass}' 2>&1 && "
|
||
|
|
f"rm -f {archive} && "
|
||
|
|
f"echo 'Encrypted: {enc_archive}' "
|
||
|
|
)
|
||
|
|
archive = enc_archive
|
||
|
|
|
||
|
|
if remote_host and remote_path:
|
||
|
|
cmd += (
|
||
|
|
f"&& echo 'Transferring to remote...' && "
|
||
|
|
f"scp -o StrictHostKeyChecking=no '{archive}' "
|
||
|
|
f"'{remote_host}:{remote_path}/' 2>&1 && "
|
||
|
|
f"echo 'Transferred to {remote_host}:{remote_path}' "
|
||
|
|
)
|
||
|
|
|
||
|
|
cmd += "&& echo '' && echo 'Backup complete'"
|
||
|
|
return cmd
|
||
|
|
|
||
|
|
|
||
|
|
def backup_list_cmd(dest="/var/backups/setec"):
|
||
|
|
"""Return bash cmd to list existing backups."""
|
||
|
|
return (
|
||
|
|
f"echo '=== Backup Archive List ===' && "
|
||
|
|
f"if [ -d {dest} ]; then "
|
||
|
|
f" ls -lhS {dest}/setec-backup-* 2>/dev/null | head -30 || echo 'No backups found'; "
|
||
|
|
f" echo '' && "
|
||
|
|
f" echo '--- Disk Usage ---' && "
|
||
|
|
f" du -sh {dest} 2>/dev/null; "
|
||
|
|
f"else "
|
||
|
|
f" echo 'Backup directory {dest} does not exist'; "
|
||
|
|
f"fi"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def backup_restore_cmd(archive, dest="/", encrypt_pass=""):
|
||
|
|
"""Return bash cmd to restore from a backup archive."""
|
||
|
|
if encrypt_pass:
|
||
|
|
return (
|
||
|
|
f"echo '=== Restoring from Encrypted Backup ===' && "
|
||
|
|
f"DECRYPTED=$(mktemp /tmp/setec-restore-XXXXXX.tar.gz) && "
|
||
|
|
f"openssl enc -aes-256-cbc -d -salt -pbkdf2 -in '{archive}' "
|
||
|
|
f"-out \"$DECRYPTED\" -pass pass:'{encrypt_pass}' 2>&1 && "
|
||
|
|
f"echo 'Decrypted successfully' && "
|
||
|
|
f"tar xzf \"$DECRYPTED\" -C {dest} 2>&1 && "
|
||
|
|
f"rm -f \"$DECRYPTED\" && "
|
||
|
|
f"echo 'Restore complete from {archive}'"
|
||
|
|
)
|
||
|
|
return (
|
||
|
|
f"echo '=== Restoring from Backup ===' && "
|
||
|
|
f"tar xzf '{archive}' -C {dest} 2>&1 && "
|
||
|
|
f"echo 'Restore complete from {archive}'"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def backup_delete_cmd(archive):
|
||
|
|
"""Return bash cmd to delete a backup archive."""
|
||
|
|
return (
|
||
|
|
f"echo '=== Deleting Backup ===' && "
|
||
|
|
f"rm -f '{archive}' 2>&1 && "
|
||
|
|
f"echo 'Deleted: {archive}'"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def backup_schedule_cmd(paths="/etc /var/www /opt/seteclabs /root", dest="/var/backups/setec",
|
||
|
|
encrypt_pass="", schedule="daily", keep=7):
|
||
|
|
"""Return bash cmd to set up scheduled backups via cron."""
|
||
|
|
if schedule == "hourly":
|
||
|
|
cron_time = "0 * * * *"
|
||
|
|
elif schedule == "daily":
|
||
|
|
cron_time = "0 2 * * *"
|
||
|
|
elif schedule == "weekly":
|
||
|
|
cron_time = "0 2 * * 0"
|
||
|
|
else:
|
||
|
|
cron_time = "0 2 * * *"
|
||
|
|
|
||
|
|
encrypt_section = ""
|
||
|
|
if encrypt_pass:
|
||
|
|
encrypt_section = (
|
||
|
|
f"openssl enc -aes-256-cbc -salt -pbkdf2 -in \\\"$ARCHIVE\\\" "
|
||
|
|
f"-out \\\"$ARCHIVE.enc\\\" -pass pass:'{encrypt_pass}' && "
|
||
|
|
f"rm -f \\\"$ARCHIVE\\\" && "
|
||
|
|
f"ARCHIVE=\\\"$ARCHIVE.enc\\\" && "
|
||
|
|
)
|
||
|
|
|
||
|
|
script = (
|
||
|
|
"#!/bin/bash\\n"
|
||
|
|
"# Setec Labs Automated Backup\\n"
|
||
|
|
f"DEST={dest}\\n"
|
||
|
|
"TS=$(date +%Y%m%d_%H%M%S)\\n"
|
||
|
|
"ARCHIVE=$DEST/setec-backup-$TS.tar.gz\\n"
|
||
|
|
f"KEEP={keep}\\n"
|
||
|
|
"\\n"
|
||
|
|
"mkdir -p $DEST\\n"
|
||
|
|
f"tar czf \\\"$ARCHIVE\\\" {paths} 2>/dev/null\\n"
|
||
|
|
f"{encrypt_section}"
|
||
|
|
"echo \\\"$(date): Backup created: $ARCHIVE\\\" >> /var/log/setec-backup.log\\n"
|
||
|
|
"\\n"
|
||
|
|
"# Cleanup old backups\\n"
|
||
|
|
"ls -1t $DEST/setec-backup-* 2>/dev/null | tail -n +$((KEEP+1)) | xargs rm -f 2>/dev/null\\n"
|
||
|
|
)
|
||
|
|
|
||
|
|
return (
|
||
|
|
"echo '=== Setting Up Scheduled Backups ===' && "
|
||
|
|
f"mkdir -p {dest} && "
|
||
|
|
f"echo -e '{script}' > /usr/local/bin/setec-backup.sh && "
|
||
|
|
"chmod +x /usr/local/bin/setec-backup.sh && "
|
||
|
|
"touch /var/log/setec-backup.log && "
|
||
|
|
"(crontab -l 2>/dev/null | grep -v 'setec-backup.sh'; "
|
||
|
|
f"echo '{cron_time} /usr/local/bin/setec-backup.sh') | crontab - && "
|
||
|
|
f"echo 'Backup schedule: {schedule}' && "
|
||
|
|
f"echo 'Paths: {paths}' && "
|
||
|
|
f"echo 'Destination: {dest}' && "
|
||
|
|
f"echo 'Retention: {keep} backups' && "
|
||
|
|
f"echo 'Encryption: {'yes' if encrypt_pass else 'no'}'"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def backup_schedule_status_cmd():
|
||
|
|
"""Return bash cmd to check backup schedule status."""
|
||
|
|
return (
|
||
|
|
"echo '=== Backup Schedule Status ===' && "
|
||
|
|
"echo '' && "
|
||
|
|
"echo '--- Script ---' && "
|
||
|
|
"if [ -f /usr/local/bin/setec-backup.sh ]; then "
|
||
|
|
" echo 'Script: INSTALLED'; "
|
||
|
|
" ls -la /usr/local/bin/setec-backup.sh; "
|
||
|
|
"else "
|
||
|
|
" echo 'Script: NOT INSTALLED'; "
|
||
|
|
"fi && "
|
||
|
|
"echo '' && "
|
||
|
|
"echo '--- Cron Job ---' && "
|
||
|
|
"if crontab -l 2>/dev/null | grep -q 'setec-backup.sh'; then "
|
||
|
|
" echo 'Cron: ACTIVE'; "
|
||
|
|
" crontab -l 2>/dev/null | grep 'setec-backup.sh'; "
|
||
|
|
"else "
|
||
|
|
" echo 'Cron: NOT FOUND'; "
|
||
|
|
"fi && "
|
||
|
|
"echo '' && "
|
||
|
|
"echo '--- Recent Backup Log (last 10) ---' && "
|
||
|
|
"if [ -f /var/log/setec-backup.log ]; then "
|
||
|
|
" tail -10 /var/log/setec-backup.log; "
|
||
|
|
"else "
|
||
|
|
" echo 'No backup log found'; "
|
||
|
|
"fi"
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
def backup_schedule_remove_cmd():
|
||
|
|
"""Return bash cmd to remove scheduled backups."""
|
||
|
|
return (
|
||
|
|
"echo '=== Removing Scheduled Backups ===' && "
|
||
|
|
"(crontab -l 2>/dev/null | grep -v 'setec-backup.sh') | crontab - && "
|
||
|
|
"rm -f /usr/local/bin/setec-backup.sh && "
|
||
|
|
"echo 'Backup script removed' && "
|
||
|
|
"echo 'Cron job removed' && "
|
||
|
|
"echo 'Existing backups preserved'"
|
||
|
|
)
|