Sanitized mirror from private repository - 2026-03-29 13:33:25 UTC
This commit is contained in:
260
ansible/automation/playbooks/synology_backup_orchestrator.yml
Normal file
260
ansible/automation/playbooks/synology_backup_orchestrator.yml
Normal file
@@ -0,0 +1,260 @@
|
||||
---
|
||||
# Synology Backup Orchestrator
|
||||
# Coordinates backups across Atlantis/Calypso with integrity verification
|
||||
# Run with: ansible-playbook -i hosts.ini playbooks/synology_backup_orchestrator.yml --limit synology
|
||||
|
||||
- name: Synology Backup Orchestration
|
||||
hosts: synology
|
||||
gather_facts: yes
|
||||
vars:
|
||||
backup_retention_days: 30
|
||||
critical_containers:
|
||||
- "postgres"
|
||||
- "mariadb"
|
||||
- "gitea"
|
||||
- "immich-server"
|
||||
- "paperlessngx"
|
||||
- "authentik-server"
|
||||
- "vaultwarden"
|
||||
|
||||
backup_paths:
|
||||
atlantis:
|
||||
- "/volume1/docker"
|
||||
- "/volume1/media"
|
||||
- "/volume1/backups"
|
||||
- "/volume1/documents"
|
||||
calypso:
|
||||
- "/volume1/docker"
|
||||
- "/volume1/backups"
|
||||
- "/volume1/development"
|
||||
|
||||
tasks:
|
||||
- name: Check Synology system status
|
||||
shell: |
|
||||
echo "=== System Info ==="
|
||||
uname -a
|
||||
echo "=== Disk Usage ==="
|
||||
df -h
|
||||
echo "=== Memory Usage ==="
|
||||
free -h
|
||||
echo "=== Load Average ==="
|
||||
uptime
|
||||
register: system_status
|
||||
|
||||
- name: Display system status
|
||||
debug:
|
||||
msg: "{{ system_status.stdout_lines }}"
|
||||
|
||||
- name: Check Docker service status
|
||||
shell: systemctl is-active docker
|
||||
register: docker_status
|
||||
failed_when: false
|
||||
|
||||
- name: Get running containers
|
||||
shell: docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Image}}"
|
||||
register: running_containers
|
||||
become: yes
|
||||
|
||||
- name: Identify critical containers
|
||||
shell: docker ps --filter "name={{ item }}" --format "{{.Names}}"
|
||||
register: critical_container_check
|
||||
loop: "{{ critical_containers }}"
|
||||
become: yes
|
||||
|
||||
- name: Create backup directory structure
|
||||
file:
|
||||
path: "/volume1/backups/{{ item }}"
|
||||
state: directory
|
||||
mode: '0755'
|
||||
loop:
|
||||
- "containers"
|
||||
- "databases"
|
||||
- "configs"
|
||||
- "logs"
|
||||
become: yes
|
||||
|
||||
- name: Stop non-critical containers for backup
|
||||
shell: |
|
||||
# Get list of running containers excluding critical ones
|
||||
critical_pattern="{{ critical_containers | join('|') }}"
|
||||
docker ps --format "{{.Names}}" | grep -vE "($critical_pattern)" > /tmp/non_critical_containers.txt || true
|
||||
|
||||
# Stop non-critical containers
|
||||
if [ -s /tmp/non_critical_containers.txt ]; then
|
||||
echo "Stopping non-critical containers for backup..."
|
||||
cat /tmp/non_critical_containers.txt | xargs -r docker stop
|
||||
echo "Stopped containers:"
|
||||
cat /tmp/non_critical_containers.txt
|
||||
else
|
||||
echo "No non-critical containers to stop"
|
||||
fi
|
||||
register: stopped_containers
|
||||
when: stop_containers_for_backup | default(false) | bool
|
||||
become: yes
|
||||
|
||||
- name: Backup Docker volumes
|
||||
shell: |
|
||||
backup_date=$(date +%Y%m%d_%H%M%S)
|
||||
backup_file="/volume1/backups/containers/docker_volumes_${backup_date}.tar.gz"
|
||||
|
||||
echo "Creating Docker volumes backup: $backup_file"
|
||||
tar -czf "$backup_file" -C /volume1/docker . 2>/dev/null || true
|
||||
|
||||
if [ -f "$backup_file" ]; then
|
||||
size=$(du -h "$backup_file" | cut -f1)
|
||||
echo "Backup created successfully: $backup_file ($size)"
|
||||
else
|
||||
echo "Backup failed"
|
||||
exit 1
|
||||
fi
|
||||
register: volume_backup
|
||||
become: yes
|
||||
|
||||
- name: Backup database containers
|
||||
shell: |
|
||||
backup_date=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
# Backup PostgreSQL databases
|
||||
for container in $(docker ps --filter "ancestor=postgres" --format "{{.Names}}"); do
|
||||
echo "Backing up PostgreSQL container: $container"
|
||||
docker exec "$container" pg_dumpall -U postgres > "/volume1/backups/databases/${container}_${backup_date}.sql" 2>/dev/null || true
|
||||
done
|
||||
|
||||
# Backup MariaDB databases
|
||||
for container in $(docker ps --filter "ancestor=mariadb" --format "{{.Names}}"); do
|
||||
echo "Backing up MariaDB container: $container"
|
||||
docker exec "$container" mysqldump --all-databases -u root > "/volume1/backups/databases/${container}_${backup_date}.sql" 2>/dev/null || true
|
||||
done
|
||||
|
||||
echo "Database backups completed"
|
||||
register: database_backup
|
||||
become: yes
|
||||
|
||||
- name: Backup container configurations
|
||||
shell: |
|
||||
backup_date=$(date +%Y%m%d_%H%M%S)
|
||||
config_backup="/volume1/backups/configs/container_configs_${backup_date}.tar.gz"
|
||||
|
||||
# Find all docker-compose files and configs
|
||||
find /volume1/docker -name "docker-compose.yml" -o -name "*.env" -o -name "config" -type d | \
|
||||
tar -czf "$config_backup" -T - 2>/dev/null || true
|
||||
|
||||
if [ -f "$config_backup" ]; then
|
||||
size=$(du -h "$config_backup" | cut -f1)
|
||||
echo "Configuration backup created: $config_backup ($size)"
|
||||
fi
|
||||
register: config_backup
|
||||
become: yes
|
||||
|
||||
- name: Restart stopped containers
|
||||
shell: |
|
||||
if [ -f /tmp/non_critical_containers.txt ] && [ -s /tmp/non_critical_containers.txt ]; then
|
||||
echo "Restarting previously stopped containers..."
|
||||
cat /tmp/non_critical_containers.txt | xargs -r docker start
|
||||
echo "Restarted containers:"
|
||||
cat /tmp/non_critical_containers.txt
|
||||
rm -f /tmp/non_critical_containers.txt
|
||||
fi
|
||||
when: stop_containers_for_backup | default(false) | bool
|
||||
become: yes
|
||||
|
||||
- name: Verify backup integrity
|
||||
shell: |
|
||||
echo "=== Backup Verification ==="
|
||||
|
||||
# Check volume backup
|
||||
latest_volume_backup=$(ls -t /volume1/backups/containers/docker_volumes_*.tar.gz 2>/dev/null | head -1)
|
||||
if [ -n "$latest_volume_backup" ]; then
|
||||
echo "Volume backup: $latest_volume_backup"
|
||||
tar -tzf "$latest_volume_backup" >/dev/null 2>&1 && echo "✓ Volume backup integrity OK" || echo "✗ Volume backup corrupted"
|
||||
fi
|
||||
|
||||
# Check database backups
|
||||
db_backup_count=$(ls /volume1/backups/databases/*.sql 2>/dev/null | wc -l)
|
||||
echo "Database backups: $db_backup_count files"
|
||||
|
||||
# Check config backup
|
||||
latest_config_backup=$(ls -t /volume1/backups/configs/container_configs_*.tar.gz 2>/dev/null | head -1)
|
||||
if [ -n "$latest_config_backup" ]; then
|
||||
echo "Config backup: $latest_config_backup"
|
||||
tar -tzf "$latest_config_backup" >/dev/null 2>&1 && echo "✓ Config backup integrity OK" || echo "✗ Config backup corrupted"
|
||||
fi
|
||||
register: backup_verification
|
||||
become: yes
|
||||
|
||||
- name: Clean old backups
|
||||
shell: |
|
||||
echo "Cleaning backups older than {{ backup_retention_days }} days..."
|
||||
|
||||
# Clean volume backups
|
||||
find /volume1/backups/containers -name "docker_volumes_*.tar.gz" -mtime +{{ backup_retention_days }} -delete
|
||||
|
||||
# Clean database backups
|
||||
find /volume1/backups/databases -name "*.sql" -mtime +{{ backup_retention_days }} -delete
|
||||
|
||||
# Clean config backups
|
||||
find /volume1/backups/configs -name "container_configs_*.tar.gz" -mtime +{{ backup_retention_days }} -delete
|
||||
|
||||
echo "Cleanup completed"
|
||||
register: backup_cleanup
|
||||
become: yes
|
||||
|
||||
- name: Generate backup report
|
||||
copy:
|
||||
content: |
|
||||
# Synology Backup Report - {{ inventory_hostname }}
|
||||
Generated: {{ ansible_date_time.iso8601 }}
|
||||
|
||||
## System Status
|
||||
```
|
||||
{{ system_status.stdout }}
|
||||
```
|
||||
|
||||
## Running Containers
|
||||
```
|
||||
{{ running_containers.stdout }}
|
||||
```
|
||||
|
||||
## Backup Operations
|
||||
|
||||
### Volume Backup
|
||||
```
|
||||
{{ volume_backup.stdout }}
|
||||
```
|
||||
|
||||
### Database Backup
|
||||
```
|
||||
{{ database_backup.stdout }}
|
||||
```
|
||||
|
||||
### Configuration Backup
|
||||
```
|
||||
{{ config_backup.stdout }}
|
||||
```
|
||||
|
||||
## Backup Verification
|
||||
```
|
||||
{{ backup_verification.stdout }}
|
||||
```
|
||||
|
||||
## Cleanup Results
|
||||
```
|
||||
{{ backup_cleanup.stdout }}
|
||||
```
|
||||
|
||||
## Critical Containers Status
|
||||
{% for container in critical_containers %}
|
||||
- {{ container }}: {{ 'Running' if container in running_containers.stdout else 'Not Found' }}
|
||||
{% endfor %}
|
||||
dest: "/tmp/synology_backup_{{ inventory_hostname }}_{{ ansible_date_time.epoch }}.md"
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Display backup summary
|
||||
debug:
|
||||
msg: |
|
||||
Backup Summary for {{ inventory_hostname }}:
|
||||
- Volume Backup: {{ 'Completed' if volume_backup.rc == 0 else 'Failed' }}
|
||||
- Database Backup: {{ 'Completed' if database_backup.rc == 0 else 'Failed' }}
|
||||
- Config Backup: {{ 'Completed' if config_backup.rc == 0 else 'Failed' }}
|
||||
- Verification: {{ 'Passed' if backup_verification.rc == 0 else 'Failed' }}
|
||||
- Report: /tmp/synology_backup_{{ inventory_hostname }}_{{ ansible_date_time.epoch }}.md
|
||||
Reference in New Issue
Block a user