Files
ansible-msp-automations/roles/proxmox_config_backup/tasks/main.yml
2026-03-15 15:48:59 -07:00

114 lines
4.8 KiB
YAML

---
# =============================================================================
# proxmox_config_backup — tasks
# Creates a tarball of critical Proxmox config files and stores it locally
# or transfers via SFTP. Git destination is a TODO pending secure handling
# of sensitive files (SSL keys, shadow.cfg, etc).
#
# Required vars:
# current_node — the node being backed up (for filename)
# client_id — client identifier (for filename)
# =============================================================================
- name: "Backup | {{ current_node }} | Gather date/time facts"
ansible.builtin.setup:
gather_subset:
- date_time
when: ansible_date_time is not defined
- name: "Backup | {{ current_node }} | Set backup filename"
ansible.builtin.set_fact:
backup_filename: >-
proxmox_{{ client_id | lower | replace('-', '_') }}_{{ current_node }}_{{ ansible_date_time.date }}
- name: "Backup | {{ current_node }} | Set backup paths"
ansible.builtin.set_fact:
backup_paths: "{{ backup_paths_proxmox }}"
# ── Create tarball on node ────────────────────────────────────────────────────
- name: "Backup | {{ current_node }} | Create config tarball"
ansible.builtin.shell: |
tar czf /tmp/{{ backup_filename }}.tar.gz \
--ignore-failed-read \
--dereference \
{{ backup_paths | join(' ') }} 2>/dev/null || true
echo "done"
changed_when: true
register: backup_tarball
# ── Local backup ──────────────────────────────────────────────────────────────
- name: "Backup | {{ current_node }} | Local | Ensure backup dir exists"
ansible.builtin.file:
path: "{{ backup_local_dir }}"
state: directory
mode: '0700'
when: backup_destination == 'local'
- name: "Backup | {{ current_node }} | Local | Move tarball to backup dir"
ansible.builtin.copy:
src: "/tmp/{{ backup_filename }}.tar.gz"
dest: "{{ backup_local_dir }}/{{ backup_filename }}.tar.gz"
remote_src: true
mode: '0600'
when: backup_destination == 'local'
- name: "Backup | {{ current_node }} | Local | Rotate old backups"
ansible.builtin.shell: |
ls -1t {{ backup_local_dir }}/proxmox_*_{{ current_node }}_*.tar.gz 2>/dev/null \
| tail -n +{{ (backup_local_keep | int) + 1 }} \
| xargs -r rm -f
changed_when: false
when: backup_destination == 'local'
- name: "Backup | {{ current_node }} | Local | Log result"
ansible.builtin.debug:
msg: "✓ Config backed up locally: {{ backup_local_dir }}/{{ backup_filename }}.tar.gz"
when: backup_destination == 'local'
# ── SFTP backup ───────────────────────────────────────────────────────────────
- name: "Backup | {{ current_node }} | SFTP | Validate required vars"
ansible.builtin.fail:
msg: "SFTP backup requires backup_sftp_host and backup_sftp_user to be set."
when:
- backup_destination == 'sftp'
- backup_sftp_host == '' or backup_sftp_user == ''
- name: "Backup | {{ current_node }} | SFTP | Fetch tarball to controller"
ansible.builtin.fetch:
src: "/tmp/{{ backup_filename }}.tar.gz"
dest: "/tmp/{{ backup_filename }}.tar.gz"
flat: true
when: backup_destination == 'sftp'
- name: "Backup | {{ current_node }} | SFTP | Transfer to remote host"
ansible.builtin.shell: |
sftp_opts="-o StrictHostKeyChecking=no -o BatchMode=yes"
{% if backup_sftp_key != '' %}
sftp_opts="$sftp_opts -i {{ backup_sftp_key }}"
{% endif %}
sftp $sftp_opts {{ backup_sftp_user }}@{{ backup_sftp_host }} << EOF
cd {{ backup_sftp_remote_dir }}
put /tmp/{{ backup_filename }}.tar.gz
EOF
delegate_to: localhost
changed_when: true
when: backup_destination == 'sftp'
- name: "Backup | {{ current_node }} | SFTP | Clean up local temp tarball"
ansible.builtin.file:
path: "/tmp/{{ backup_filename }}.tar.gz"
state: absent
delegate_to: localhost
when: backup_destination == 'sftp'
- name: "Backup | {{ current_node }} | SFTP | Log result"
ansible.builtin.debug:
msg: "✓ Config backed up via SFTP: {{ backup_sftp_host }}:{{ backup_sftp_remote_dir }}/{{ backup_filename }}.tar.gz"
when: backup_destination == 'sftp'
# ── Cleanup ───────────────────────────────────────────────────────────────────
- name: "Backup | {{ current_node }} | Clean up temp tarball on node"
ansible.builtin.file:
path: "/tmp/{{ backup_filename }}.tar.gz"
state: absent