mirror of
https://github.com/RWejlgaard/pez-infra.git
synced 2026-10-31 19:11:03 +00:00
Neither Proxmox host had a single backup job, so the game servers, the k3s control planes and the workspace VMs had no backups at all. copenhagen-a has nowhere local to keep them (`local` is the root LV and already 82% full), so both hosts now back up to a new pve-backups Samba share on london-b, each into its own directory. VMIDs overlap between the two hosts, and retention prunes by VMID, so they can't share one. - media_stack creates a Samba-only pvebackup user on london-b, the share and the per-host directories. The password comes from SOPS and gets re-set if the login stops working. smb.conf is now checked with testparm before it's deployed. - proxmox_ve adds a backup-only london-b-backups CIFS storage, pushes the credentials again if the storage goes inactive, and fails the deploy if it still can't reach london-b. - Jobs are defined in host_vars. Each job keeps a hash of its settings in its comment, so the role only touches jobs that changed and removes ones I delete from host_vars. Jobs made by hand are left alone. london-a backs up the control plane every night. copenhagen-a backs up the control plane and game servers every night and the workspace VMs weekly, since every run is a full archive going over the WAN.
209 lines
5.6 KiB
YAML
209 lines
5.6 KiB
YAML
---
|
|
# media_stack role — deploys the full media stack on london-b
|
|
# Manages: *arr suite, jellyfin, plex, transmission, samba,
|
|
# ollama, vsftpd, and cron jobs.
|
|
|
|
# ── Systemd service units (custom, not package-managed) ──
|
|
|
|
- name: Deploy custom systemd unit files
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/services/{{ item }}/{{ item }}.service"
|
|
dest: "/etc/systemd/system/{{ item }}.service"
|
|
mode: '0644'
|
|
loop:
|
|
- radarr
|
|
- sonarr
|
|
- prowlarr
|
|
- lidarr
|
|
- whisparr
|
|
- ollama
|
|
notify: Reload systemd daemon
|
|
|
|
- name: Enable and start custom systemd services
|
|
ansible.builtin.systemd:
|
|
name: "{{ item }}"
|
|
state: started
|
|
enabled: true
|
|
loop:
|
|
- radarr
|
|
- sonarr
|
|
- prowlarr
|
|
- lidarr
|
|
- ollama
|
|
|
|
# Whisparr is installed but disabled (kept as-is)
|
|
- name: Ensure whisparr unit is present but disabled
|
|
ansible.builtin.systemd:
|
|
name: whisparr
|
|
enabled: false
|
|
|
|
# Readarr was retired in favour of the bookshelf Docker service (a Readarr
|
|
# revival). Decommission the old custom unit so the host stops it and frees
|
|
# port 8787, which bookshelf now binds.
|
|
- name: Stop and disable retired readarr unit
|
|
ansible.builtin.systemd:
|
|
name: readarr
|
|
state: stopped
|
|
enabled: false
|
|
failed_when: false
|
|
|
|
- name: Remove retired readarr unit file
|
|
ansible.builtin.file:
|
|
path: /etc/systemd/system/readarr.service
|
|
state: absent
|
|
notify: Reload systemd daemon
|
|
|
|
# ── Package-managed services (ensure enabled) ──
|
|
|
|
- name: Ensure package-managed services are enabled
|
|
ansible.builtin.systemd:
|
|
name: "{{ item }}"
|
|
state: started
|
|
enabled: true
|
|
loop:
|
|
- jellyfin
|
|
- plexmediaserver
|
|
- transmission-daemon
|
|
- smbd
|
|
- vsftpd
|
|
|
|
# ── Snap packages ──
|
|
|
|
- name: Install Overseerr via snap
|
|
community.general.snap:
|
|
name: overseerr
|
|
channel: latest/beta
|
|
state: present
|
|
|
|
- name: Ensure Overseerr snap service is running
|
|
ansible.builtin.command: snap start overseerr
|
|
changed_when: false
|
|
failed_when: false
|
|
|
|
# ── APT-managed services ──
|
|
|
|
- name: Install Syncthing
|
|
ansible.builtin.apt:
|
|
name: syncthing
|
|
state: present
|
|
|
|
- name: Enable and start Syncthing for pez user
|
|
ansible.builtin.systemd:
|
|
name: syncthing@pez
|
|
state: started
|
|
enabled: true
|
|
|
|
# ── Proxmox backup share ──
|
|
# london-a and copenhagen-a write vzdump archives to the [pve-backups] share
|
|
# as a dedicated Samba-only user, one directory per Proxmox host.
|
|
|
|
- name: Create Proxmox backup user
|
|
ansible.builtin.user:
|
|
name: "{{ proxmox_ve_backup_smb_user }}"
|
|
system: true
|
|
shell: /usr/sbin/nologin
|
|
create_home: false
|
|
|
|
- name: Ensure Proxmox backup directories exist
|
|
ansible.builtin.file:
|
|
path: "{{ item }}"
|
|
state: directory
|
|
owner: "{{ proxmox_ve_backup_smb_user }}"
|
|
group: "{{ proxmox_ve_backup_smb_user }}"
|
|
mode: '0750'
|
|
loop: "{{ ['/hdd/pve/backups'] + groups['proxmox_hosts'] | map('regex_replace', '^', '/hdd/pve/backups/') | list }}"
|
|
|
|
# ── Configuration files ──
|
|
|
|
- name: Deploy samba config
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/services/samba/config/london-b.conf"
|
|
dest: /etc/samba/smb.conf
|
|
mode: '0644'
|
|
backup: true
|
|
validate: testparm -s %s
|
|
notify: Restart smbd
|
|
|
|
# smbd has to be serving [pve-backups] before the login check below means
|
|
# anything, so don't wait for the end-of-play handler.
|
|
- name: Apply samba config before checking the backup login
|
|
ansible.builtin.meta: flush_handlers
|
|
|
|
# A failed login against the share (valid users only, so no guest fallback) is
|
|
# the only reliable way to tell whether the Samba password matches SOPS.
|
|
- name: Check Proxmox backup user's Samba login
|
|
ansible.builtin.command: smbclient //localhost/pve-backups -U {{ proxmox_ve_backup_smb_user }} -c exit
|
|
environment:
|
|
PASSWD: "{{ proxmox_ve_backup_smb_password }}"
|
|
register: media_stack_pve_backup_login
|
|
changed_when: false
|
|
failed_when: false
|
|
check_mode: false
|
|
no_log: true
|
|
|
|
- name: Set Proxmox backup user's Samba password
|
|
ansible.builtin.shell: |
|
|
set -o pipefail
|
|
printf '%s\n%s\n' "$SMB_PASSWORD" "$SMB_PASSWORD" | smbpasswd -s -a {{ proxmox_ve_backup_smb_user }}
|
|
args:
|
|
executable: /bin/bash
|
|
environment:
|
|
SMB_PASSWORD: "{{ proxmox_ve_backup_smb_password }}"
|
|
changed_when: true
|
|
when: media_stack_pve_backup_login.rc != 0
|
|
no_log: true
|
|
|
|
- name: Deploy transmission settings
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/services/transmission/config/settings.json"
|
|
dest: /etc/transmission-daemon/settings.json
|
|
owner: debian-transmission
|
|
group: debian-transmission
|
|
mode: '0600'
|
|
notify: Restart transmission
|
|
|
|
- name: Deploy vsftpd config
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/services/vsftpd/config/london-b.conf"
|
|
dest: /etc/vsftpd.conf
|
|
mode: '0644'
|
|
notify: Restart vsftpd
|
|
|
|
# ── Scripts ──
|
|
|
|
- name: Ensure scripts directory exists
|
|
ansible.builtin.file:
|
|
path: /root/scripts
|
|
state: directory
|
|
mode: '0755'
|
|
|
|
- name: Deploy movie-rename-fix script
|
|
ansible.builtin.copy:
|
|
src: "{{ playbook_dir }}/scripts/movie-rename-fix.fish"
|
|
dest: /root/scripts/movie-rename-fix.fish
|
|
mode: '0755'
|
|
|
|
# ── Cron jobs ──
|
|
|
|
- name: Movie rename fix (hourly)
|
|
ansible.builtin.cron:
|
|
name: "Movie rename fix"
|
|
minute: "0"
|
|
job: "/root/scripts/movie-rename-fix.fish"
|
|
user: root
|
|
|
|
- name: Restart radarr at midnight
|
|
ansible.builtin.cron:
|
|
name: "Restart radarr"
|
|
minute: "0"
|
|
hour: "0"
|
|
job: "systemctl restart radarr"
|
|
user: root
|
|
|
|
- name: Restart sonarr at midnight
|
|
ansible.builtin.cron:
|
|
name: "Restart sonarr"
|
|
minute: "0"
|
|
hour: "0"
|
|
job: "systemctl restart sonarr"
|
|
user: root
|