AAP 2.6 Backup, Restore, and Disaster Recovery Guide
By Luca Berton · Published 2024-01-01 · Category: installation
Complete guide to backup, restore, and disaster recovery for AAP 2.6. Protect Automation Controller, Hub, EDA, and Platform Gateway data.
Why Backup Matters for AAP
Ansible Automation Platform stores critical data that cannot be easily recreated: • Job history and output — audit trail of all automation runs • Credentials (encrypted) — SSH keys, API tokens, cloud secrets • Inventories — static host definitions and group variables • Job templates and workflows — your automation configurations • RBAC settings — users, teams, organizations, permissions • Projects — SCM configurations and sync settings • Schedules and notifications — recurring automation and alerting • EDA rulebook activations — event-driven automation configurations • Hub content — approved collections, namespaces, EE image metadata
Losing this data means rebuilding your entire automation platform from scratch.
See also: Restore a PostgreSQL Database — Ansible module postgresql_db
What to Back Up
Database (Critical)
The PostgreSQL database holds all AAP state. This is the single most important backup target.
| Component | Database Contents | |-----------|-------------------| | Platform Gateway | Session data, service routing, SSO config | | Automation Controller | Jobs, inventories, credentials, templates, RBAC | | Automation Hub | Collection metadata, namespaces, approvals | | EDA Controller | Rulebook activations, event logs, credentials |
Files (Important)
| Path | Contents |
|------|----------|
| /etc/ansible-automation-platform/ | Configuration files |
| Secret key file | Encryption key for credential storage |
| TLS certificates | SSL certs for all components |
| Custom EE images | If stored locally (also in Hub registry) |
| Hub collection artifacts | Uploaded collection tarballs |
External Systems (Plan Separately)
• Git repositories (Projects) — backed up via your SCM • LDAP/SAML identity providers — backed up separately • External secret backends (HashiCorp Vault, CyberArk) — separate backup • Load balancers and DNS — infrastructure backupBackup Methods by Deployment Type
Containerized Deployment
The containerized installer includes backup and restore commands:
# Run backup
cd /path/to/ansible-automation-platform-containerized-setup/
ansible-playbook -i inventory ansible.containerized_installer.backup
# Backup output location
ls /var/lib/ansible-automation-platform/backups/
# backup-2026-04-26T020000.tar.gz
The backup includes: • PostgreSQL database dump • Configuration files • Secret keys • TLS certificates
RPM Deployment
Use the RPM installer's backup playbook:
cd /path/to/ansible-automation-platform-setup/
./setup.sh -b
# Or with a specific inventory
./setup.sh -b -i inventory
Backup files are stored in the backup directory specified in your inventory:
[all:vars]
backup_dir=/var/backups/aap
Operator Deployment (OpenShift)
For Operator-managed AAP on OpenShift, use the AnsibleAutomationPlatformBackup CR:
apiVersion: aap.ansible.com/v1alpha1
kind: AnsibleAutomationPlatformBackup
metadata:
name: aap-backup-20260426
namespace: ansible-automation-platform
spec:
deployment_name: aap
backup_storage_class: gp3-csi
backup_storage_requirements: 50Gi
# Apply the backup CR
oc apply -f aap-backup.yaml
# Monitor backup progress
oc get ansibleautomationplatformbackups -n ansible-automation-platform
oc logs -f job/aap-backup-20260426 -n ansible-automation-platform
Database-Only Backup
For more granular control, back up PostgreSQL directly:
# Dump all AAP databases
pg_dump -h db.example.org -U postgres -Fc gateway > gateway.dump
pg_dump -h db.example.org -U postgres -Fc controller > controller.dump
pg_dump -h db.example.org -U postgres -Fc hub > hub.dump
pg_dump -h db.example.org -U postgres -Fc eda > eda.dump
# Or dump everything
pg_dumpall -h db.example.org -U postgres > aap_full_backup.sql
See also: Ansible Private Automation Hub: Host & Manage Collections (Guide)
Restore Procedures
Containerized Restore
cd /path/to/ansible-automation-platform-containerized-setup/
ansible-playbook -i inventory ansible.containerized_installer.restore \
-e backup_file=/var/lib/ansible-automation-platform/backups/backup-2026-04-26T020000.tar.gz
RPM Restore
cd /path/to/ansible-automation-platform-setup/
./setup.sh -r
# Specify backup file
./setup.sh -r -e restore_backup_file=/var/backups/aap/backup-2026-04-26.tar.gz
Operator Restore
apiVersion: aap.ansible.com/v1alpha1
kind: AnsibleAutomationPlatformRestore
metadata:
name: aap-restore-20260426
namespace: ansible-automation-platform
spec:
deployment_name: aap
backup_name: aap-backup-20260426
oc apply -f aap-restore.yaml
oc get ansibleautomationplatformrestores -n ansible-automation-platform
Database-Only Restore
# Stop AAP services first
systemctl stop automation-controller-service
systemctl stop automation-hub-service
systemctl stop automation-eda-service
systemctl stop automation-gateway-service
# Restore databases
pg_restore -h db.example.org -U postgres -d gateway -c gateway.dump
pg_restore -h db.example.org -U postgres -d controller -c controller.dump
pg_restore -h db.example.org -U postgres -d hub -c hub.dump
pg_restore -h db.example.org -U postgres -d eda -c eda.dump
# Restart services
systemctl start automation-gateway-service
systemctl start automation-controller-service
systemctl start automation-hub-service
systemctl start automation-eda-service
Backup Automation
Scheduled Backup Playbook
---
- name: Automated AAP Backup
hosts: localhost
gather_facts: false
vars:
backup_dir: /var/backups/aap
retention_days: 30
db_host: db.example.org
db_user: postgres
notify_email: ops@example.com
tasks:
- name: Create backup directory
ansible.builtin.file:
path: "{{ backup_dir }}/{{ ansible_date_time.date }}"
state: directory
mode: '0700'
- name: Backup all databases
ansible.builtin.shell: |
pg_dump -h {{ db_host }} -U {{ db_user }} -Fc {{ item }} \
> {{ backup_dir }}/{{ ansible_date_time.date }}/{{ item }}.dump
loop:
- gateway
- controller
- hub
- eda
no_log: true
- name: Compress backup
community.general.archive:
path: "{{ backup_dir }}/{{ ansible_date_time.date }}/"
dest: "{{ backup_dir }}/aap-backup-{{ ansible_date_time.date }}.tar.gz"
format: gz
- name: Remove uncompressed files
ansible.builtin.file:
path: "{{ backup_dir }}/{{ ansible_date_time.date }}"
state: absent
- name: Clean up old backups
ansible.builtin.find:
paths: "{{ backup_dir }}"
patterns: "aap-backup-*.tar.gz"
age: "{{ retention_days }}d"
register: old_backups
- name: Remove old backups
ansible.builtin.file:
path: "{{ item.path }}"
state: absent
loop: "{{ old_backups.files }}"
- name: Verify backup exists
ansible.builtin.stat:
path: "{{ backup_dir }}/aap-backup-{{ ansible_date_time.date }}.tar.gz"
register: backup_file
- name: Report backup status
ansible.builtin.debug:
msg: "Backup completed: {{ backup_file.stat.size | human_readable }} at {{ backup_file.stat.path }}"
when: backup_file.stat.exists
Schedule in AAP Controller
Create this playbook as a job template and schedule it:
- name: Schedule nightly backup
ansible.platform.schedule:
controller_host: "{{ gateway_url }}"
controller_username: "{{ controller_user }}"
controller_password: "{{ controller_pass }}"
name: "Nightly AAP Backup"
unified_job_template: "AAP Database Backup"
rrule: "DTSTART:20260101T030000Z RRULE:FREQ=DAILY;INTERVAL=1"
enabled: true
state: present
See also: Ansible Automation Platform High Availability and Disaster Recovery: Single Topology Architecture
Disaster Recovery Strategies
Strategy 1: Cold Standby
Maintain a standby environment that can be activated from the latest backup.
| Component | Primary | Standby | |-----------|---------|---------| | AAP VMs | Active | Powered off | | Database | Primary + backup | Restored from backup | | Recovery time | — | 2-4 hours | | Data loss | — | Since last backup |
Steps: Power on standby VMs Restore latest database backup Update DNS to point to standby Verify all services are operational
Strategy 2: Warm Standby with Database Replication
PostgreSQL streaming replication keeps a hot standby database synchronized.
# Primary database postgresql.conf
wal_level = replica
max_wal_senders = 3
wal_keep_size = 1024
# Standby database recovery.conf
primary_conninfo = 'host=primary-db.example.org port=5432 user=replicator'
restore_command = 'cp /var/lib/pgsql/archive/%f %p'
| Component | Primary | Standby | |-----------|---------|---------| | AAP VMs | Active | Powered on, idle | | Database | Primary | Streaming replica | | Recovery time | — | 15-30 minutes | | Data loss | — | Seconds (near-zero) |
Strategy 3: Active-Active (Enterprise Topology)
The enterprise topology already provides HA for all components: • 2 Platform Gateway nodes behind HAProxy • 2 Automation Controller nodes • 2 Automation Hub nodes • 2 EDA Controller nodes • External PostgreSQL with HA (Patroni or RDS Multi-AZ)
This is not backup — it's availability. You still need backups for data protection (corruption, accidental deletion).
Testing Your Backups
Backups are worthless if you never test restores. Schedule quarterly restore tests:
---
- name: Quarterly Backup Validation
hosts: backup_test_environment
gather_facts: false
tasks:
- name: Restore latest backup to test environment
ansible.builtin.command:
cmd: >
pg_restore -h test-db.example.org
-U postgres -d controller -c
/var/backups/aap/latest/controller.dump
no_log: true
- name: Verify Controller API responds
ansible.builtin.uri:
url: "https://test-gateway.example.org/api/controller/v2/ping/"
validate_certs: false
status_code: 200
register: api_check
- name: Verify job templates exist
ansible.builtin.uri:
url: "https://test-gateway.example.org/api/controller/v2/job_templates/"
headers:
Authorization: "Bearer {{ test_token }}"
validate_certs: false
register: templates
- name: Validate restore
ansible.builtin.assert:
that:
- api_check.status == 200
- templates.json.count > 0
fail_msg: "Backup restore validation FAILED"
success_msg: "Backup restore validated: {{ templates.json.count }} job templates restored"
Important Considerations
Secret Key Protection
The secret key (SECRET_KEY in Controller settings) is used to encrypt all credentials in the database. Without it, encrypted credentials cannot be decrypted after restore.
Always backup:
• /etc/tower/SECRET_KEY (RPM)
• The secret key from your containerized deployment configuration
• Store securely in a separate location from database backups
PostgreSQL Version Compatibility
Per Red Hat documentation: backup and restore functionality depends on utilities provided with PostgreSQL 15. If using external PostgreSQL 16 or 17, you must use external backup and restore processes — the AAP installer's built-in backup does not support PG 16/17.
Backup Window and Performance
Database backups use pg_dump which can impact performance on large databases. Schedule backups during low-usage periods and monitor:
• Backup duration
• Database I/O during backup
• Backup file size (monitor for unexpected growth)
FAQ
How often should I back up AAP?
Daily database backups are the minimum for production. For environments with frequent changes, consider twice daily. Always back up before upgrades or major configuration changes.
Can I restore to a different version of AAP?
No. Restore must target the same AAP version as the backup. To migrate across versions, restore first, then upgrade using the standard upgrade procedure.
What about backing up Execution Environment images?
EE images in Private Automation Hub are stored in the Hub's container registry. The database backup includes metadata but not the actual container images. Back up EE images separately using podman save or ensure they're stored in an external container registry with its own backup.
Can I do point-in-time recovery?
With PostgreSQL WAL archiving and streaming replication, yes. Configure archive_mode = on and archive_command to enable point-in-time recovery (PITR). This gives recovery to any point in time, not just the last backup.
What is the backup size for a typical enterprise deployment?
Database size varies by job history retention. A deployment running 1,000 jobs/day with 90-day retention typically has a 10-50 GB database. Compressed backups are usually 30-50% of the database size.
Conclusion
A robust backup strategy is not optional for production AAP deployments. The combination of automated daily backups, tested restore procedures, and a documented disaster recovery plan ensures your automation platform can recover from any failure scenario. Test your restores regularly — an untested backup is not a backup.
Related Articles
• AAP 2.6 Architecture and Components: Complete Guide • AAP 2.6 Security Best Practices • AAP 2.6 Upgrade Guide from 2.5 • Backup Ansible Automation Platform • Restore Ansible Automation PlatformSee also
• Ansible for Database Automation: PostgreSQL, MySQL, MongoDB, and RedisCategory: installation