Implement standardized playbook organization with master orchestrator and Ansible collections requirements for extended functionality. Playbook Structure: playbooks/ ├── gather_system_info.yml # System inventory gathering ├── deploy_vm.yml # VM deployment (placeholder) ├── security_audit.yml # Security compliance checking (placeholder) ├── maintenance.yml # Routine maintenance tasks (placeholder) ├── backup.yml # Backup operations (placeholder) └── disaster_recovery.yml # DR procedures (placeholder) Master Playbook (site.yml): - Entry point for all infrastructure operations - Import structure for modular playbook organization - Tag-based execution for selective operations - Pre-flight checks and validations - Comprehensive documentation and usage examples Collections Requirements (collections/requirements.yml): - community.general: Essential utilities and modules - community.libvirt: KVM/libvirt management - ansible.posix: POSIX system administration - amazon.aws: AWS infrastructure management (optional) - Community versions for open-source compatibility Implemented Playbooks: 1. gather_system_info.yml: - Comprehensive system information gathering - Uses system_info role - Statistics export to ./stats/machines/ - Health checks and validation - Tag support: install, gather, export, validate, health-check 2. Placeholder Playbooks (documented structure): - deploy_vm.yml: VM provisioning with deploy_linux_vm role - security_audit.yml: CIS benchmark compliance checking - maintenance.yml: Updates, cleanup, optimization - backup.yml: Backup operations orchestration - disaster_recovery.yml: DR procedures and testing site.yml Master Playbook Features: - Central orchestration point - Import-based playbook inclusion - Tag inheritance and selective execution - Environment-aware (development, staging, production) - Pre-flight validation checks - Error handling and rollback support - Comprehensive inline documentation Usage Examples: ```bash # Run all playbooks ansible-playbook site.yml # Run specific playbook ansible-playbook site.yml --tags gather_info # Gather system information only ansible-playbook playbooks/gather_system_info.yml # Check syntax ansible-playbook site.yml --syntax-check # Dry run ansible-playbook site.yml --check # Limit to specific hosts ansible-playbook site.yml -l webservers ``` Collections Management: - Install: ansible-galaxy collection install -r collections/requirements.yml - Update: ansible-galaxy collection install -r collections/requirements.yml --upgrade - Location: ./collections/ (local) and ~/.ansible/collections (user) - Version pinning for stability - Community alternatives for RHEL-free deployments CLAUDE.md Compliance: ✅ Playbooks in ./playbooks/ directory ✅ Master playbook (site.yml) at root ✅ Tag-based execution support ✅ Modular organization with import_playbook ✅ Collections requirements documented ✅ Clear separation: playbooks (lasting) vs plays (temporary) Benefits: - Standardized playbook organization - Easy-to-navigate structure - Tag-based selective execution - Collection dependency management - Scalable to 100+ playbooks - Clear entry point (site.yml) - Environment isolation Next Steps: 1. Install collections: ansible-galaxy collection install -r collections/requirements.yml 2. Implement placeholder playbooks as needed 3. Add role-specific playbooks to playbooks/ directory 4. Create temporary plays in plays/ directory (per CLAUDE.md) 5. Test site.yml orchestration: ansible-playbook site.yml --check 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
433 lines
15 KiB
YAML
433 lines
15 KiB
YAML
---
|
|
# =============================================================================
|
|
# Backup Playbook
|
|
# =============================================================================
|
|
#
|
|
# This playbook performs comprehensive backups of system configuration,
|
|
# application data, and databases across all managed hosts.
|
|
#
|
|
# Usage:
|
|
# ansible-playbook playbooks/backup.yml
|
|
# ansible-playbook playbooks/backup.yml --limit production
|
|
# ansible-playbook playbooks/backup.yml --tags config,databases
|
|
# ansible-playbook playbooks/backup.yml --extra-vars "backup_type=full"
|
|
#
|
|
# Tags:
|
|
# config - Backup system configuration files
|
|
# data - Backup application data
|
|
# databases - Backup databases
|
|
# logs - Backup log files
|
|
# verify - Verify backup integrity
|
|
# cleanup - Clean old backups
|
|
#
|
|
# =============================================================================
|
|
|
|
- name: System and Application Backup
|
|
hosts: all
|
|
become: true
|
|
gather_facts: true
|
|
|
|
vars:
|
|
backup_timestamp: "{{ ansible_date_time.date }}_{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}"
|
|
backup_base_dir: "/var/backups"
|
|
backup_remote_dir: "{{ backup_remote_dir | default(None) }}"
|
|
backup_retention_days: "{{ backup_retention_days | default(30) }}"
|
|
backup_type: "{{ backup_type | default('incremental') }}" # full | incremental
|
|
backup_compress: true
|
|
backup_verify: true
|
|
|
|
pre_tasks:
|
|
- name: Display backup banner
|
|
debug:
|
|
msg:
|
|
- "========================================="
|
|
- "Backup Process Starting"
|
|
- "========================================="
|
|
- "Host: {{ inventory_hostname }}"
|
|
- "Environment: {{ environment | default('unknown') }}"
|
|
- "Timestamp: {{ backup_timestamp }}"
|
|
- "Type: {{ backup_type }}"
|
|
- "Retention: {{ backup_retention_days }} days"
|
|
- "========================================="
|
|
tags: [always]
|
|
|
|
- name: Create backup directories
|
|
file:
|
|
path: "{{ backup_base_dir }}/{{ item }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
loop:
|
|
- config
|
|
- data
|
|
- databases
|
|
- logs
|
|
tags: [always]
|
|
|
|
- name: Check available disk space
|
|
shell: df -h {{ backup_base_dir }} | tail -1 | awk '{print $4}'
|
|
register: backup_disk_space
|
|
changed_when: false
|
|
tags: [always]
|
|
|
|
- name: Display available disk space
|
|
debug:
|
|
msg: "Available disk space for backups: {{ backup_disk_space.stdout }}"
|
|
tags: [always]
|
|
|
|
tasks:
|
|
# =========================================================================
|
|
# Configuration Backup
|
|
# =========================================================================
|
|
|
|
- name: Backup system configuration files
|
|
block:
|
|
- name: Backup /etc directory
|
|
archive:
|
|
path: /etc
|
|
dest: "{{ backup_base_dir }}/config/etc_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
tags: [config]
|
|
|
|
- name: Backup SSH configuration
|
|
archive:
|
|
path: /etc/ssh
|
|
dest: "{{ backup_base_dir }}/config/ssh_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
tags: [config]
|
|
|
|
- name: Backup network configuration (Debian)
|
|
archive:
|
|
path: /etc/network
|
|
dest: "{{ backup_base_dir }}/config/network_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
when: ansible_os_family == "Debian"
|
|
failed_when: false
|
|
tags: [config]
|
|
|
|
- name: Backup network configuration (RHEL)
|
|
archive:
|
|
path: /etc/sysconfig/network-scripts
|
|
dest: "{{ backup_base_dir }}/config/network_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
when: ansible_os_family == "RedHat"
|
|
failed_when: false
|
|
tags: [config]
|
|
|
|
- name: Backup firewall rules (RHEL)
|
|
archive:
|
|
path: /etc/firewalld
|
|
dest: "{{ backup_base_dir }}/config/firewall_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
when: ansible_os_family == "RedHat"
|
|
failed_when: false
|
|
tags: [config]
|
|
|
|
- name: Backup cron jobs
|
|
archive:
|
|
path:
|
|
- /etc/crontab
|
|
- /etc/cron.d
|
|
- /var/spool/cron
|
|
dest: "{{ backup_base_dir }}/config/cron_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
mode: '0600'
|
|
failed_when: false
|
|
tags: [config]
|
|
|
|
- name: Backup systemd services
|
|
shell: |
|
|
mkdir -p /tmp/systemd_backup
|
|
cp -r /etc/systemd/system/*.service /tmp/systemd_backup/ 2>/dev/null || true
|
|
cp -r /usr/lib/systemd/system/*.service /tmp/systemd_backup/ 2>/dev/null || true
|
|
tar czf {{ backup_base_dir }}/config/systemd_backup_{{ backup_timestamp }}.tar.gz -C /tmp systemd_backup
|
|
rm -rf /tmp/systemd_backup
|
|
changed_when: false
|
|
failed_when: false
|
|
tags: [config]
|
|
|
|
when: "'config' in ansible_run_tags or 'all' in ansible_run_tags"
|
|
tags: [config]
|
|
|
|
# =========================================================================
|
|
# Application Data Backup
|
|
# =========================================================================
|
|
|
|
- name: Backup application data
|
|
block:
|
|
- name: Backup /opt directory
|
|
archive:
|
|
path: /opt
|
|
dest: "{{ backup_base_dir }}/data/opt_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
exclude_path:
|
|
- /opt/tmp
|
|
- /opt/cache
|
|
when: backup_type == 'full'
|
|
tags: [data]
|
|
|
|
- name: Backup /var/lib application data
|
|
archive:
|
|
path: /var/lib
|
|
dest: "{{ backup_base_dir }}/data/var_lib_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
exclude_path:
|
|
- /var/lib/docker
|
|
- /var/lib/containers
|
|
- /var/lib/mysql
|
|
- /var/lib/postgresql
|
|
when: backup_type == 'full'
|
|
failed_when: false
|
|
tags: [data]
|
|
|
|
- name: Backup user home directories
|
|
archive:
|
|
path: /home
|
|
dest: "{{ backup_base_dir }}/data/home_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
when: backup_type == 'full'
|
|
failed_when: false
|
|
tags: [data]
|
|
|
|
when: "'data' in ansible_run_tags or 'all' in ansible_run_tags"
|
|
tags: [data]
|
|
|
|
# =========================================================================
|
|
# Database Backups
|
|
# =========================================================================
|
|
|
|
- name: Backup databases
|
|
block:
|
|
- name: Check if MySQL/MariaDB is installed
|
|
command: which mysqldump
|
|
register: backup_mysql_check
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Backup MySQL/MariaDB databases
|
|
shell: |
|
|
mysqldump --all-databases --single-transaction --quick --lock-tables=false \
|
|
| gzip > {{ backup_base_dir }}/databases/mysql_dump_{{ backup_timestamp }}.sql.gz
|
|
when: backup_mysql_check.rc == 0
|
|
no_log: true
|
|
tags: [databases]
|
|
|
|
- name: Check if PostgreSQL is installed
|
|
command: which pg_dumpall
|
|
register: backup_postgres_check
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Backup PostgreSQL databases
|
|
shell: |
|
|
sudo -u postgres pg_dumpall \
|
|
| gzip > {{ backup_base_dir }}/databases/postgres_dump_{{ backup_timestamp }}.sql.gz
|
|
when: backup_postgres_check.rc == 0
|
|
no_log: true
|
|
tags: [databases]
|
|
|
|
- name: Check if MongoDB is installed
|
|
command: which mongodump
|
|
register: backup_mongodb_check
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
- name: Backup MongoDB databases
|
|
command: >
|
|
mongodump --out {{ backup_base_dir }}/databases/mongodb_{{ backup_timestamp }}
|
|
--gzip
|
|
when: backup_mongodb_check.rc == 0
|
|
tags: [databases]
|
|
|
|
- name: Set database backup permissions
|
|
file:
|
|
path: "{{ backup_base_dir }}/databases"
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
recurse: yes
|
|
|
|
when: "'databases' in ansible_run_tags or 'all' in ansible_run_tags"
|
|
tags: [databases]
|
|
|
|
# =========================================================================
|
|
# Log Backups
|
|
# =========================================================================
|
|
|
|
- name: Backup important logs
|
|
block:
|
|
- name: Backup /var/log directory
|
|
archive:
|
|
path: /var/log
|
|
dest: "{{ backup_base_dir }}/logs/var_log_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
exclude_path:
|
|
- /var/log/journal
|
|
failed_when: false
|
|
tags: [logs]
|
|
|
|
- name: Backup audit logs
|
|
archive:
|
|
path: /var/log/audit
|
|
dest: "{{ backup_base_dir }}/logs/audit_backup_{{ backup_timestamp }}.tar.gz"
|
|
format: gz
|
|
when: ansible_os_family in ["RedHat", "Debian"]
|
|
failed_when: false
|
|
tags: [logs]
|
|
|
|
when: "'logs' in ansible_run_tags or 'all' in ansible_run_tags"
|
|
tags: [logs]
|
|
|
|
# =========================================================================
|
|
# Backup Verification
|
|
# =========================================================================
|
|
|
|
- name: Verify backups
|
|
block:
|
|
- name: List all backups created
|
|
find:
|
|
paths:
|
|
- "{{ backup_base_dir }}/config"
|
|
- "{{ backup_base_dir }}/data"
|
|
- "{{ backup_base_dir }}/databases"
|
|
- "{{ backup_base_dir }}/logs"
|
|
patterns: "*{{ backup_timestamp }}*"
|
|
register: backup_created_files
|
|
|
|
- name: Verify backup file integrity
|
|
command: "gzip -t {{ item.path }}"
|
|
loop: "{{ backup_created_files.files }}"
|
|
when:
|
|
- item.path.endswith('.gz')
|
|
- backup_verify
|
|
changed_when: false
|
|
failed_when: false
|
|
register: backup_integrity_check
|
|
|
|
- name: Calculate total backup size
|
|
shell: du -sh {{ backup_base_dir }} | awk '{print $1}'
|
|
register: backup_total_size
|
|
changed_when: false
|
|
|
|
- name: Display backup verification results
|
|
debug:
|
|
msg:
|
|
- "Backup Verification Results:"
|
|
- "Files created: {{ backup_created_files.files | length }}"
|
|
- "Total backup size: {{ backup_total_size.stdout }}"
|
|
- "Integrity check: {{ 'Passed' if backup_integrity_check is not failed else 'Failed' }}"
|
|
|
|
when: backup_verify
|
|
tags: [verify, always]
|
|
|
|
# =========================================================================
|
|
# Transfer to Remote Storage (Optional)
|
|
# =========================================================================
|
|
|
|
- name: Transfer backups to remote storage
|
|
block:
|
|
- name: Sync backups to remote location
|
|
synchronize:
|
|
src: "{{ backup_base_dir }}/"
|
|
dest: "{{ backup_remote_dir }}/"
|
|
archive: yes
|
|
compress: yes
|
|
delete: no
|
|
when: backup_remote_dir is defined and backup_remote_dir
|
|
delegate_to: localhost
|
|
|
|
when: backup_remote_dir is defined and backup_remote_dir
|
|
tags: [remote, never]
|
|
|
|
# =========================================================================
|
|
# Cleanup Old Backups
|
|
# =========================================================================
|
|
|
|
- name: Clean up old backups
|
|
block:
|
|
- name: Find backups older than retention period
|
|
find:
|
|
paths:
|
|
- "{{ backup_base_dir }}/config"
|
|
- "{{ backup_base_dir }}/data"
|
|
- "{{ backup_base_dir }}/databases"
|
|
- "{{ backup_base_dir }}/logs"
|
|
age: "{{ backup_retention_days }}d"
|
|
patterns: "*.tar.gz"
|
|
register: backup_old_files
|
|
|
|
- name: Display old backups to be removed
|
|
debug:
|
|
msg: "Found {{ backup_old_files.files | length }} backups older than {{ backup_retention_days }} days"
|
|
|
|
- name: Remove old backups
|
|
file:
|
|
path: "{{ item.path }}"
|
|
state: absent
|
|
loop: "{{ backup_old_files.files }}"
|
|
when: backup_old_files.files | length > 0
|
|
|
|
tags: [cleanup]
|
|
|
|
post_tasks:
|
|
- name: Generate backup manifest
|
|
copy:
|
|
content: |
|
|
Backup Manifest
|
|
===============
|
|
Host: {{ inventory_hostname }}
|
|
Environment: {{ environment | default('unknown') }}
|
|
Timestamp: {{ backup_timestamp }}
|
|
Type: {{ backup_type }}
|
|
|
|
Files Backed Up:
|
|
{% for file in backup_created_files.files %}
|
|
- {{ file.path }} ({{ file.size | filesizeformat }})
|
|
{% endfor %}
|
|
|
|
Total Size: {{ backup_total_size.stdout }}
|
|
Status: Success
|
|
dest: "{{ backup_base_dir }}/backup_manifest_{{ backup_timestamp }}.txt"
|
|
mode: '0600'
|
|
when: backup_created_files is defined
|
|
tags: [always]
|
|
|
|
- name: Display backup summary
|
|
debug:
|
|
msg:
|
|
- "========================================="
|
|
- "Backup Summary"
|
|
- "========================================="
|
|
- "Host: {{ inventory_hostname }}"
|
|
- "Environment: {{ environment | default('unknown') }}"
|
|
- "Completed: {{ ansible_date_time.iso8601 }}"
|
|
- ""
|
|
- "=== Backup Details ==="
|
|
- "Type: {{ backup_type }}"
|
|
- "Files created: {{ backup_created_files.files | length | default(0) }}"
|
|
- "Total size: {{ backup_total_size.stdout | default('Unknown') }}"
|
|
- "Location: {{ backup_base_dir }}"
|
|
- ""
|
|
- "=== Retention ==="
|
|
- "Retention period: {{ backup_retention_days }} days"
|
|
- "Old backups cleaned: {{ backup_old_files.files | length | default(0) }}"
|
|
- ""
|
|
- "=== Verification ==="
|
|
- "Integrity check: {{ 'Passed' if backup_verify and backup_integrity_check is not failed else 'Skipped' }}"
|
|
- ""
|
|
- "Manifest: {{ backup_base_dir }}/backup_manifest_{{ backup_timestamp }}.txt"
|
|
- "========================================="
|
|
tags: [always]
|
|
|
|
# =============================================================================
|
|
# Backup Manifests
|
|
# =============================================================================
|
|
# Manifests are saved to: /var/backups/backup_manifest_<timestamp>.txt
|
|
# =============================================================================
|