Schedule daily Atlas Navidrome music copy

This commit is contained in:
Fabio Scotto di Santolo
2026-10-01 10:32:48 +02:00
parent 5a1047adde
commit f491362365
8 changed files with 124 additions and 5 deletions

View File

@@ -148,6 +148,7 @@ backend_phase1_bind_address: "{{ ansible_host }}"
backend_phase1_firewalld_zone: "{{ atlas_firewalld_zone }}"
backend_phase1_npm_source_ip: "{{ atlas_aegis_ip }}"
backend_phase1_syncthing_native_subnet: "{{ atlas_lan_subnet }}"
backend_phase1_music_sync_enabled: true
rocky_manage_openzfs_repo: true
rocky_manage_syncthing_binary: false

View File

@@ -30,3 +30,7 @@ backend_phase1_timezone: Europe/Rome
backend_phase1_services:
- atlas-navidrome.service
- atlas-syncthing.service
backend_phase1_music_sync_enabled: false
backend_phase1_music_source_dir: "{{ backend_phase1_archive_dir }}/Music"
backend_phase1_music_sync_calendar: "*-*-* 00:45:00 Europe/Rome"
backend_phase1_user_systemd_dir: "{{ backend_phase1_user_home }}/.config/systemd/user"

View File

@@ -18,21 +18,28 @@
- backend_phase1_app_data_root.startswith('/')
- backend_phase1_navidrome_data_dir.startswith(backend_phase1_app_data_root + '/')
- backend_phase1_syncthing_root.startswith(backend_phase1_app_data_root + '/')
- >-
not (backend_phase1_music_sync_enabled | bool) or
(backend_phase1_music_source_dir.startswith(backend_phase1_archive_dir + '/')
and backend_phase1_music_sync_calendar | length > 0)
fail_msg: >-
Disable the rootful media-stack gate and provide the Atlas LAN bind
address, firewall sources, and absolute ZFS-backed paths before
enabling phase one. This role does not manage Prometheus or migrate
application data.
tags: [music_sync]
- name: Read the rootless service account
ansible.builtin.getent:
database: passwd
key: "{{ backend_phase1_username }}"
tags: [music_sync]
- name: Record rootless service account IDs
ansible.builtin.set_fact:
backend_phase1_uid: "{{ ansible_facts['getent_passwd'][backend_phase1_username][1] }}"
backend_phase1_gid: "{{ ansible_facts['getent_passwd'][backend_phase1_username][2] }}"
tags: [music_sync]
- name: Read system service state before starting rootless Syncthing
ansible.builtin.service_facts:
@@ -65,6 +72,7 @@
loop_control:
label: "{{ item.dataset }}"
register: backend_phase1_zfs_facts
tags: [music_sync]
- name: Require mounted datasets at the declared paths
ansible.builtin.assert:
@@ -79,6 +87,23 @@
loop: "{{ backend_phase1_zfs_facts.results }}"
loop_control:
label: "{{ item.item.dataset }}"
tags: [music_sync]
- name: Inspect the music copy source
ansible.builtin.stat:
path: "{{ backend_phase1_music_source_dir }}"
register: backend_phase1_music_source_stat
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Require an existing music source directory
ansible.builtin.assert:
that:
- backend_phase1_music_source_stat.stat.isdir | default(false)
fail_msg: >-
{{ backend_phase1_music_source_dir }} must exist before enabling the daily music copy.
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Enable lingering for the rootless service account
ansible.builtin.command:
@@ -87,12 +112,14 @@
- enable-linger
- "{{ backend_phase1_username }}"
creates: "/var/lib/systemd/linger/{{ backend_phase1_username }}"
tags: [music_sync]
- name: Start the rootless user systemd manager
ansible.builtin.systemd:
name: "user@{{ backend_phase1_uid }}.service"
state: started
when: not ansible_check_mode
tags: [music_sync]
- name: Create rootless Quadlet and application directories
ansible.builtin.file:
@@ -113,6 +140,43 @@
loop_control:
label: "{{ item.path }}"
- name: Install rsync for the daily music copy
ansible.builtin.dnf:
name: rsync
state: present
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Create the rootless user systemd directory
ansible.builtin.file:
path: "{{ backend_phase1_user_systemd_dir }}"
state: directory
owner: "{{ backend_phase1_username }}"
group: "{{ backend_phase1_user_group }}"
mode: "0700"
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Install the daily music copy service
ansible.builtin.template:
src: atlas-music-sync.service.j2
dest: "{{ backend_phase1_user_systemd_dir }}/atlas-music-sync.service"
owner: "{{ backend_phase1_username }}"
group: "{{ backend_phase1_user_group }}"
mode: "0644"
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Install the daily music copy timer
ansible.builtin.template:
src: atlas-music-sync.timer.j2
dest: "{{ backend_phase1_user_systemd_dir }}/atlas-music-sync.timer"
owner: "{{ backend_phase1_username }}"
group: "{{ backend_phase1_user_group }}"
mode: "0644"
when: backend_phase1_music_sync_enabled | bool
tags: [music_sync]
- name: Render the rootless Navidrome Quadlet
ansible.builtin.template:
src: atlas-navidrome.container.j2
@@ -140,6 +204,7 @@
XDG_RUNTIME_DIR: "/run/user/{{ backend_phase1_uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ backend_phase1_uid }}/bus"
when: not ansible_check_mode
tags: [music_sync]
- name: Permit NPM access to phase-one web interfaces through Aegis
ansible.posix.firewalld:
@@ -186,3 +251,19 @@
when:
- backend_phase1_start_services | bool
- not ansible_check_mode
- name: Enable the daily music copy timer
become_user: "{{ backend_phase1_username }}"
ansible.builtin.systemd:
name: atlas-music-sync.timer
scope: user
state: started
enabled: true
daemon_reload: true
environment:
XDG_RUNTIME_DIR: "/run/user/{{ backend_phase1_uid }}"
DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ backend_phase1_uid }}/bus"
when:
- backend_phase1_music_sync_enabled | bool
- not ansible_check_mode
tags: [music_sync]

View File

@@ -0,0 +1,10 @@
# Managed by Ansible. Do not edit manually.
[Unit]
Description=Copy Atlas Archive music to the Navidrome library
[Service]
Type=oneshot
ExecStartPre=/usr/bin/mountpoint -q {{ backend_phase1_archive_dir }}
ExecStartPre=/usr/bin/mountpoint -q {{ backend_phase1_music_dir }}
ExecStartPre=/usr/bin/test -d {{ backend_phase1_music_source_dir }}
ExecStart=/usr/bin/rsync -aH --no-perms --no-owner --no-group --delay-updates --stats -- {{ backend_phase1_music_source_dir }}/ {{ backend_phase1_music_dir }}/

View File

@@ -0,0 +1,11 @@
# Managed by Ansible. Do not edit manually.
[Unit]
Description=Schedule the daily Atlas Navidrome music copy
[Timer]
OnCalendar={{ backend_phase1_music_sync_calendar }}
Persistent=true
Unit=atlas-music-sync.service
[Install]
WantedBy=timers.target