--- # vzdump of selected guests on the Proxmox host. vzdump prunes old dumps of # each guest itself (keep-last), so nothing else touches the dump directory. # Every run is appended to {{ backup_dir }}/proxmox_backup.log on the host. # # backup_mode "stop" shuts the guest down for the whole backup. Never list # the guest that runs Semaphore with mode stop: the job would stop itself # half way through. Use "snapshot" for that one (falls back to suspend on # storage without snapshot support). # # Extra vars (optional): # guests - list of { id, type, name } # keep_last - dumps kept per guest (default 3) # backup_mode - stop | snapshot | suspend (default stop) # storage - target PVE storage id (default local) # compression - zstd | gzip | lzo (default zstd) - name: Backup selected Proxmox VMs and LXCs hosts: proxmox become: true gather_facts: false vars: backup_dir: /var/lib/vz/dump storage: local compression: zstd keep_last: 3 backup_mode: stop guests: # - { id: 104, type: lxc, name: courses } - { id: 108, type: lxc, name: docker } # - { id: 101, type: qemu, name: pnetlab } tasks: - name: Ensure the log directory exists ansible.builtin.file: path: "{{ backup_dir }}" state: directory mode: '0755' - name: Run vzdump ansible.builtin.shell: | set -o pipefail LOGFILE="{{ backup_dir }}/proxmox_backup.log" START=$(date +%s) echo "[$(date '+%Y-%m-%d %H:%M:%S')] START {{ item.name }} ({{ item.type }} {{ item.id }}) mode={{ backup_mode }}" >> "$LOGFILE" OUTPUT=$(vzdump {{ item.id }} --mode {{ backup_mode }} --compress {{ compression }} \ --storage {{ storage }} --prune-backups keep-last={{ keep_last }} 2>&1) STATUS=$? DURATION=$(( $(date +%s) - START )) if [ "$STATUS" -eq 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS {{ item.name }} ({{ item.id }}) ${DURATION}s" >> "$LOGFILE" echo "$OUTPUT" | grep -E 'archive file size|pruned|removing backup' || true else echo "[$(date '+%Y-%m-%d %H:%M:%S')] FAILURE {{ item.name }} ({{ item.id }}) ${DURATION}s" >> "$LOGFILE" printf -- '---- vzdump output ----\n%s\n-----------------------\n' "$OUTPUT" >> "$LOGFILE" echo "$OUTPUT" | tail -n 20 fi exit "$STATUS" args: executable: /bin/bash loop: "{{ guests }}" loop_control: label: "{{ item.name }} ({{ item.type }} {{ item.id }})" changed_when: true - name: List the dumps kept for each guest ansible.builtin.command: pvesm list {{ storage }} --content backup --vmid {{ item.id }} loop: "{{ guests }}" loop_control: label: "{{ item.name }} ({{ item.id }})" register: dump_lists changed_when: false - name: Backup summary ansible.builtin.debug: msg: | {% for r in dump_lists.results %} {{ r.item.name }} ({{ r.item.type }} {{ r.item.id }}) - mode {{ backup_mode }}, keeping the last {{ keep_last }}: {{ r.stdout }} {% endfor %}