Add sanoid Ansible role for ZFS snapshots and replication
Replaces manually deployed config files with a fully idempotent role: installs sanoid, templates sanoid.conf and syncoid service/timer from variables, enables both systemd timers. Removes static proxmox/sanoid.* files. README rebuild section updated accordingly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -173,19 +173,7 @@ ansible-playbook playbooks/claude-code-vm.yml
|
||||
|
||||
### 6. Set up sanoid/syncoid for ZFS snapshots
|
||||
|
||||
Sanoid and syncoid are not yet in an Ansible role — deploy manually:
|
||||
|
||||
```bash
|
||||
apt install sanoid
|
||||
|
||||
# Copy config from repo
|
||||
cp proxmox/sanoid.conf /etc/sanoid/sanoid.conf
|
||||
cp proxmox/syncoid.service /etc/systemd/system/syncoid.service
|
||||
cp proxmox/syncoid.timer /etc/systemd/system/syncoid.timer
|
||||
|
||||
systemctl enable --now sanoid.timer
|
||||
systemctl enable --now syncoid.timer
|
||||
```
|
||||
Handled automatically by `playbooks/host.yml` (the `sanoid` role). No manual steps needed.
|
||||
|
||||
### 7. Restore Grafana password
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@
|
||||
hosts: proxmox_hosts
|
||||
roles:
|
||||
- proxmox_host
|
||||
- sanoid
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
---
|
||||
sanoid_datasets:
|
||||
- dataset: rpool/data
|
||||
template: vms
|
||||
recursive: true
|
||||
- dataset: rpool/ROOT
|
||||
template: system
|
||||
recursive: true
|
||||
|
||||
sanoid_templates:
|
||||
vms:
|
||||
daily: 7
|
||||
weekly: 4
|
||||
monthly: 0
|
||||
hourly: 0
|
||||
frequently: 0
|
||||
autosnap: true
|
||||
autoprune: true
|
||||
system:
|
||||
daily: 3
|
||||
weekly: 2
|
||||
monthly: 0
|
||||
hourly: 0
|
||||
frequently: 0
|
||||
autosnap: true
|
||||
autoprune: true
|
||||
|
||||
syncoid_jobs:
|
||||
- src: rpool/data
|
||||
dst: hdd/backups/rpool-data
|
||||
recursive: true
|
||||
- src: rpool/ROOT/pve-1
|
||||
dst: hdd/backups/pve-root
|
||||
recursive: false
|
||||
|
||||
syncoid_schedule: "*-*-* 02:00:00"
|
||||
syncoid_randomized_delay: 10min
|
||||
@@ -0,0 +1,12 @@
|
||||
---
|
||||
- name: Restart sanoid timer
|
||||
ansible.builtin.systemd:
|
||||
name: sanoid.timer
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
|
||||
- name: Restart syncoid timer
|
||||
ansible.builtin.systemd:
|
||||
name: syncoid.timer
|
||||
state: restarted
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,47 @@
|
||||
---
|
||||
- name: Install sanoid
|
||||
ansible.builtin.apt:
|
||||
name: sanoid
|
||||
state: present
|
||||
update_cache: true
|
||||
|
||||
- name: Deploy sanoid.conf
|
||||
ansible.builtin.template:
|
||||
src: sanoid.conf.j2
|
||||
dest: /etc/sanoid/sanoid.conf
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart sanoid timer
|
||||
|
||||
- name: Deploy syncoid systemd service
|
||||
ansible.builtin.template:
|
||||
src: syncoid.service.j2
|
||||
dest: /etc/systemd/system/syncoid.service
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart syncoid timer
|
||||
|
||||
- name: Deploy syncoid systemd timer
|
||||
ansible.builtin.template:
|
||||
src: syncoid.timer.j2
|
||||
dest: /etc/systemd/system/syncoid.timer
|
||||
owner: root
|
||||
group: root
|
||||
mode: '0644'
|
||||
notify: Restart syncoid timer
|
||||
|
||||
- name: Enable and start sanoid timer
|
||||
ansible.builtin.systemd:
|
||||
name: sanoid.timer
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
|
||||
- name: Enable and start syncoid timer
|
||||
ansible.builtin.systemd:
|
||||
name: syncoid.timer
|
||||
enabled: true
|
||||
state: started
|
||||
daemon_reload: true
|
||||
@@ -0,0 +1,19 @@
|
||||
{% for entry in sanoid_datasets %}
|
||||
[{{ entry.dataset }}]
|
||||
use_template = {{ entry.template }}
|
||||
{% if entry.recursive %}
|
||||
recursive = yes
|
||||
{% endif %}
|
||||
|
||||
{% endfor %}
|
||||
{% for name, t in sanoid_templates.items() %}
|
||||
[template_{{ name }}]
|
||||
daily = {{ t.daily }}
|
||||
weekly = {{ t.weekly }}
|
||||
monthly = {{ t.monthly }}
|
||||
hourly = {{ t.hourly }}
|
||||
frequently = {{ t.frequently }}
|
||||
autosnap = {{ 'yes' if t.autosnap else 'no' }}
|
||||
autoprune = {{ 'yes' if t.autoprune else 'no' }}
|
||||
|
||||
{% endfor %}
|
||||
@@ -0,0 +1,9 @@
|
||||
[Unit]
|
||||
Description=Syncoid ZFS replication to HDD
|
||||
After=zfs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
{% for job in syncoid_jobs %}
|
||||
ExecStart=/usr/sbin/syncoid --no-privilege-elevation{% if job.recursive %} --recursive{% endif %} {{ job.src }} {{ job.dst }}
|
||||
{% endfor %}
|
||||
@@ -3,8 +3,8 @@ Description=Daily ZFS replication to HDD
|
||||
After=sanoid.timer
|
||||
|
||||
[Timer]
|
||||
OnCalendar=*-*-* 02:00:00
|
||||
RandomizedDelaySec=10min
|
||||
OnCalendar={{ syncoid_schedule }}
|
||||
RandomizedDelaySec={{ syncoid_randomized_delay }}
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
@@ -1,28 +0,0 @@
|
||||
# VM disks on SSD pool — snapshot daily/weekly
|
||||
[rpool/data]
|
||||
use_template = vms
|
||||
recursive = yes
|
||||
|
||||
# Proxmox OS root — lighter schedule, mainly for recovery
|
||||
[rpool/ROOT]
|
||||
use_template = system
|
||||
recursive = yes
|
||||
|
||||
#############################
|
||||
[template_vms]
|
||||
daily = 7
|
||||
weekly = 4
|
||||
monthly = 0
|
||||
hourly = 0
|
||||
frequently = 0
|
||||
autosnap = yes
|
||||
autoprune = yes
|
||||
|
||||
[template_system]
|
||||
daily = 3
|
||||
weekly = 2
|
||||
monthly = 0
|
||||
hourly = 0
|
||||
frequently = 0
|
||||
autosnap = yes
|
||||
autoprune = yes
|
||||
@@ -1,8 +0,0 @@
|
||||
[Unit]
|
||||
Description=Syncoid ZFS replication to HDD
|
||||
After=zfs.target
|
||||
|
||||
[Service]
|
||||
Type=oneshot
|
||||
ExecStart=/usr/sbin/syncoid --recursive --no-privilege-elevation rpool/data hdd/backups/rpool-data
|
||||
ExecStart=/usr/sbin/syncoid --no-privilege-elevation rpool/ROOT/pve-1 hdd/backups/pve-root
|
||||
Reference in New Issue
Block a user