AAP Backup Script for Containerized Bundle

How I set up an automated backup system for Ansible Automation Platform (AAP) using the containerized installer. The script and the crontab setup run a daily backup, store it on a remote NFS location, and clean up older backups over time.

The backup script must be launched using the dedicated non-root user (in this case, aap). This user also needs access to the AAP installation directory, since the backup command has to be run from there.

Prerequises

Packages

You have to install the following packages:

# yum install nfs-utils
# yum intall s-nail

Create directory for the distant storage

Create directory for the distant storage:

# mkdir /mnt/aap-backup

Mount the distant storage

The following line shall be added to /etc/fstab:

distant-storage.my.company.org:/distant-directory/aap  /mnt/aap-backups         nfs     defaults        0 0

Then reload the daemon:

systemctl daemon-reload

Crontab

Connect as the aap user then edit the crontab:

$ crontab -e

Then add the following line:

0 8 * * 1 /home/aap/MyInstallDir/aap-backup.sh | mailx -v -s "[AAP] - Config Backup of $HOSTNAME" -S smtp=mail.my.company.org -S from="[email protected]" [email protected]

Script bash

Disclaimer

This Bash script automates the backup process for Ansible Automation Platform (AAP) installed via the containerized installer. It is designed to run under a dedicated non-root user (aap) and handles the full workflow of creating, storing, and maintaining backups on a remote NFS storage.

Here is a breakdown of its main steps:

  • Variable definitions: sets paths for the backup storage (BCK_DIR), the AAP installation directory (PATH_Ansible), and the log file (LOGS_FILE).
  • Mount remote NFS storage: the script mounts the configured NFS share where backups will be stored.
  • Run the AAP backup: it navigates to the AAP installation directory and runs the built-in backup playbook, saving output in a temporary directory and logging all details to backup.log.
  • Copy backup files: creates a dated directory on the NFS storage and copies the generated backup files from the temporary location.
  • List existing backups: prints a summary of all backup directories currently stored on the NFS share, including the total count and detailed listing.
  • Purge old backups: finds directories older than 120 days (excluding the certificates directory here) and deletes them to keep the storage clean.
  • Unmount the NFS storage: safely unmounts the remote share once the backup and cleanup are complete.
  • Display Ansible logs: outputs the detailed logs of the backup playbook run for review and troubleshooting.
  • Main program execution: the script runs all the above steps sequentially: mount, backup, copy, list, purge, sleep for a short delay, unmount, and display logs.

In short, this script provides a fully automated, reliable, and traceable backup workflow for AAP, ensuring daily backups are securely stored and older backups are cleaned up automatically.

Concerning the non-root container environment

It is important to note that this script cannot be run directly as root. This is due to the way the containerized AAP installer works: the backup playbook runs inside a non-root container environment (Podman), and executing it as root would break permissions and the containerized workflow.

For this reason, all backup operations are performed under the dedicated non-root aap user, which has the required access to the installation directory and can safely run the backup playbook while still allowing certain operations (like copying to the NFS storage) to use sudo when necessary.

This approach ensures consistency with container security practices while still providing full automation of the backup process.

Backup script

Connect as the aap user and go to the installation directory then create the aap-backup.sh file:

$ cd MyInstallDir
$ vim aap-backup.sh

Then add the following lines:

#!/bin/bash
# Last version : 2025-11-25

#=======================================
# VARIABLES DEFINITION
#=======================================
BCK_DIR=/mnt/aap-backups/
PATH_Ansible=/home/aap/MyInstallDir
LOGS_FILE=/tmp/backup.log

#=======================================
# MOUNT REMOTE NFS STORAGE
#=======================================
mount_dir(){

sudo mount "${BCK_DIR}"
}

#=======================================
# AAP BACKUP CONFIG FILE
#=======================================
make_AAP_backup(){

# Make a backup with Ansible built-in function
cd $PATH_Ansible
ansible-playbook -i inventory-growth ansible.containerized_installer.backup -e "backup_dir=/tmp/$(date +%F)_AAP_Backup" &> "$LOGS_FILE"
}

#=======================================
# COPY BACKUP FILE
#=======================================
copy_AAP_backup(){

sudo mkdir ${BCK_DIR}/$(date +%F)_AAP_Backup
sudo cp /tmp/$(date +%F)_AAP_Backup/backups/* ${BCK_DIR}/$(date +%F)_AAP_Backup
}

#=======================================
# COPY BACKUP FILE
#=======================================
list_AAP_backup(){

echo -e "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ BACKUP SUMMARY OF $HOSTNAME"
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ => Number of backups: `sudo ls -rtl "${BCK_DIR}" | sudo grep -v total | sudo wc -l`"
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ Listing in ${BCK_DIR}:"
echo -e "$(sudo ls -rtl "${BCK_DIR}" | sudo sed 's/^/┃ /')"
echo -e "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

#========================================
# PURGE BACKUPS +120 DAYS ON STORAGE
#========================================
purge_old_backups(){

echo -e "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ BACKUP PURGE"
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

# Find only directory old than +120 days, except /certificates
OLD_DIRS=$(sudo find "${BCK_DIR}" -mindepth 1 -maxdepth 1 -type d ! -name "certificates" -mtime +120)

COUNT=$(echo "$OLD_DIRS" | grep -v '^$' | wc -l)

echo -e "┃=> Number of directories older than 120 days: ($COUNT)"
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃=> Purge of the following directories:"

if [ "$COUNT" -gt 0 ]; then
echo "$OLD_DIRS" | while read -r dir; do
echo "┃ $dir"
sudo rm -rf "$dir"
done
else
echo -e "┃=> NONE"
fi

echo -e "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"

}

#========================================
# UMOUNT REMOTE NFS STORAGE
#========================================
unmount_dir(){

sudo umount "${BCK_DIR}"
}

#========================================
# ANSIBLE LOGS DETAILS
#========================================
display_log(){

echo -e "┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ ANSIBLE LOGS DETAILS"
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo -e "┃ DATE:" $(date +'%Y-%m-%d_%H:%M:%S')
echo -e "┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
echo "$(sudo cat $LOGS_FILE | sudo sed 's/^/┃ /')"
echo -e "┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}

#========================================
# Main Program
#========================================
mount_dir
make_AAP_backup
copy_AAP_backup
list_AAP_backup
purge_old_backups
sleep 10
unmount_dir
display_log
exit 0

Documentation

Internet

Partager