Skip to content

Instantly share code, notes, and snippets.

@peterschristoph
Created October 27, 2024 22:39
Show Gist options
  • Select an option

  • Save peterschristoph/823263f80e1c42447f76bf76683dbcd0 to your computer and use it in GitHub Desktop.

Select an option

Save peterschristoph/823263f80e1c42447f76bf76683dbcd0 to your computer and use it in GitHub Desktop.
Ansible Configure Proxmox Backup Server PBS
---
- name: Configure Proxmox Backup Server (PBS)
hosts: localhost
connection: local
vars:
proxmox_pbs_api_url: "https://yourpbs.tld:8007/api2/json"
proxmox_pbs_username: "root@pam"
proxmox_pbs_password: "rootpassword"
proxmox_pbs_verify_ssl: true
zfs_pool_name: "your_zfs_and_datastore_name"
pbs_user: "yourbackupuser_used_by_pve@pbs"
pbs_user_password: "yourSuperSecurePasswordForPBS_USER"
keep_last: 30
keep_weekly: 3
keep_monthly: 10
keep_yearly: 50
prune_schedule: "daily"
pbs_fingerprint_file: "{{ playbook_dir }}/pbs_fingerprint.txt"
tasks:
- name: "Get Proxmox PBS authentication ticket"
uri:
url: "{{ proxmox_pbs_api_url }}/access/ticket"
method: POST
body_format: form-urlencoded
body:
username: "{{ proxmox_pbs_username }}"
password: "{{ proxmox_pbs_password }}"
headers:
Content-Type: "application/x-www-form-urlencoded"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: auth_response
no_log: true
- name: "Set authentication tokens"
set_fact:
proxmox_token: "{{ auth_response.json.data.ticket }}"
proxmox_csrf_prevention_token: "{{ auth_response.json.data.CSRFPreventionToken }}"
- name: "Check if ZFS RAID10 pool exists"
uri:
url: "{{ proxmox_pbs_api_url }}/nodes/{{ inventory_hostname }}/disks/zfs"
method: GET
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: zfs_list_response
- name: "Set fact if ZFS pool exists"
set_fact:
zfs_pool_exists: "{{ zfs_list_response.json.data | selectattr('name', 'equalto', zfs_pool_name) | list | length > 0 }}"
- name: "Retrieve list of disks from PBS"
uri:
url: "{{ proxmox_pbs_api_url }}/nodes/{{ inventory_hostname }}/disks/list"
method: GET
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: disks_list_response
when: not zfs_pool_exists
- name: "Filter unused disks"
set_fact:
unused_disks: "{{ disks_list_response.json.data | selectattr('used', 'equalto', 'unused') | map(attribute='devpath') | list }}"
when: not zfs_pool_exists
- name: "Fail if not enough disks for RAID10"
fail:
msg: "Not enough unused disks available for RAID10 (minimum 4 disks required, found {{ unused_disks | length }})"
when:
- unused_disks is defined
- (unused_disks | length) < 4
- not zfs_pool_exists
- name: "Create ZFS RAID10 pool via Proxmox API"
uri:
url: "{{ proxmox_pbs_api_url }}/nodes/{{ inventory_hostname }}/disks/zfs"
method: POST
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
CSRFPreventionToken: "{{ proxmox_csrf_prevention_token }}"
body_format: json
body:
name: "{{ zfs_pool_name }}"
raidlevel: "raid10"
devices: "{{ unused_disks | map('regex_replace', '^/dev/', '') | join(',') }}"
node: "{{ inventory_hostname }}"
add-datastore: true
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
when: not zfs_pool_exists
register: zfs_create_response
- name: "Check if PBS user exists"
uri:
url: "{{ proxmox_pbs_api_url }}/access/users"
method: GET
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: user_list_response
- name: "Set fact if PBS user exists"
set_fact:
pbs_user_exists: "{{ user_list_response.json.data | selectattr('userid', 'equalto', pbs_user) | list | length > 0 }}"
- name: "Create PBS user"
uri:
url: "{{ proxmox_pbs_api_url }}/access/users"
method: POST
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
CSRFPreventionToken: "{{ proxmox_csrf_prevention_token }}"
body_format: json
body:
userid: "{{ pbs_user }}"
password: "{{ pbs_user_password }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
when: not pbs_user_exists
register: user_create_response
- name: "Set ACL permissions for the new user"
uri:
url: "{{ proxmox_pbs_api_url }}/access/acl"
method: PUT
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
CSRFPreventionToken: "{{ proxmox_csrf_prevention_token }}"
body_format: json
body:
path: "/datastore/{{ zfs_pool_name }}"
auth-id: "{{ pbs_user }}"
role: "DatastoreBackup"
propagate: true
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: acl_response
- name: "Check if Prune job exists"
uri:
url: "{{ proxmox_pbs_api_url }}/config/prune"
method: GET
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: prune_list_response
- name: "Set fact if Prune job exists"
set_fact:
prune_job_exists: "{{ prune_list_response.json.data | selectattr('id', 'equalto', 'prune-' + zfs_pool_name) | list | length > 0 }}"
- name: "Create Prune job"
uri:
url: "{{ proxmox_pbs_api_url }}/config/prune"
method: POST
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
CSRFPreventionToken: "{{ proxmox_csrf_prevention_token }}"
body_format: json
body:
id: "prune-{{ zfs_pool_name }}"
store: "{{ zfs_pool_name }}"
schedule: "daily"
keep-last: "{{ keep_last }}"
keep-weekly: "{{ keep_weekly }}"
keep-monthly: "{{ keep_monthly }}"
keep-yearly: "{{ keep_yearly }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
when: not prune_job_exists
register: prune_create_response
- name: "Get Proxmox PBS fingerprint"
uri:
url: "{{ proxmox_pbs_api_url }}/nodes/{{ inventory_hostname }}/certificates/info"
method: GET
headers:
Cookie: "PBSAuthCookie={{ proxmox_token }}"
CSRFPreventionToken: "{{ proxmox_csrf_prevention_token }}"
validate_certs: "{{ proxmox_pbs_verify_ssl }}"
register: cert_info_response
- name: "Extract PBS fingerprint"
set_fact:
pbs_fingerprint: "{{ cert_info_response.json.data[0].fingerprint }}"
- name: "Save PBS fingerprint to file on local machine"
local_action: copy
args:
content: "{{ pbs_fingerprint }}"
dest: "{{ pbs_fingerprint_file }}"
mode: '0600'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment