diff --git a/roles/lemonldap_ng/files/logos/navidrome.png b/roles/lemonldap_ng/files/logos/navidrome.png new file mode 100644 index 0000000..1eac6a8 Binary files /dev/null and b/roles/lemonldap_ng/files/logos/navidrome.png differ diff --git a/roles/navidrome/defaults/main.yml b/roles/navidrome/defaults/main.yml new file mode 100644 index 0000000..5e16f9a --- /dev/null +++ b/roles/navidrome/defaults/main.yml @@ -0,0 +1,35 @@ +--- + +# Version to deploy +nd_version: 0.44.1 +# URL of the archive +nd_archive_url: https://github.com/navidrome/navidrome/releases/download/v{{ nd_version }}/navidrome_{{ nd_version }}_Linux_x86_64.tar.gz +# Expected sha1 of the archive +nd_archive_sha1: 39acb4fc6f4375d50da96c00ecc07045b0263dca + +# Should ansible handle upgrades, or only initial install ? +nd_manage_upgrade: True + +# Where navidrome will be installed +nd_root_dir: /opt/navidrome + +# User account under which the service will run. Will be created +nd_user: navidrome + +# Port navidrome will listen on +nd_port: 4533 +# List of IP addresses or CIDR allowed to access the port (only if iptables_manage is True) +nd_src_ip: {} + + +# Directory where music is available (can, and should be read only for nd_user +nd_music_dir: '{{ nd_root_dir }}/music' +# Size of the cache for transcoding +nd_transcoding_cache_size: 200M +# Image cache +nd_image_cache_size: 100M + +# Proxy authentication. Set nd_header_auth to the name of the header containing the user name +# nd_header_auth: Auth-User +nd_proxy_whitelist: "{{ nd_src_ip }}" + diff --git a/roles/navidrome/handlers/main.yml b/roles/navidrome/handlers/main.yml new file mode 100644 index 0000000..7b2cedd --- /dev/null +++ b/roles/navidrome/handlers/main.yml @@ -0,0 +1,4 @@ +--- + +- name: restart navidrome + service: name=navidrome state=restarted diff --git a/roles/navidrome/meta/main.yml b/roles/navidrome/meta/main.yml new file mode 100644 index 0000000..a6e9cf7 --- /dev/null +++ b/roles/navidrome/meta/main.yml @@ -0,0 +1,5 @@ +--- + +dependencies: + - role: mkdir + - role: repo_rpmfusion # For ffmpeg diff --git a/roles/navidrome/tasks/archive_post.yml b/roles/navidrome/tasks/archive_post.yml new file mode 100644 index 0000000..4ca87f7 --- /dev/null +++ b/roles/navidrome/tasks/archive_post.yml @@ -0,0 +1,7 @@ +--- + +- import_tasks: ../includes/webapps_compress_archive.yml + vars: + - root_dir: "{{ nd_root_dir }}" + - version: "{{ nd_current_version }}" + tags: navidrome diff --git a/roles/navidrome/tasks/archive_pre.yml b/roles/navidrome/tasks/archive_pre.yml new file mode 100644 index 0000000..d11c82e --- /dev/null +++ b/roles/navidrome/tasks/archive_pre.yml @@ -0,0 +1,23 @@ +--- + +- name: Create archive directory + file: path={{ nd_root_dir }}/archives/{{ nd_current_version }} state=directory mode=700 + tags: navidrome + +- name: Archive previous version + copy: src={{ nd_root_dir }}/bin/navidrome dest={{ nd_root_dir }}/archives/{{ nd_current_version }}/ remote_src=True + tags: navidrome + +- name: Stop navidrome during upgrade + service: name=navidrome state=stopped + tags: navidrome + +- name: Archive the database and the configuration + copy: src={{ nd_root_dir }}/{{ item }} dest={{ nd_root_dir }}/archives/{{ nd_current_version }}/ remote_src=True + loop: + - data/navidrome.db + - etc/navidrome.toml + tags: navidrome + + + diff --git a/roles/navidrome/tasks/cleanup.yml b/roles/navidrome/tasks/cleanup.yml new file mode 100644 index 0000000..7fe9b3c --- /dev/null +++ b/roles/navidrome/tasks/cleanup.yml @@ -0,0 +1,8 @@ +--- + +- name: Remove tmp and obsolete files + file: path={{ item }} state=absent + loop: + - "{{ nd_root_dir }}/tmp/navidrome" + - "{{ nd_root_dir }}/tmp/navidrome_{{ nd_version }}_Linux_x86_64.tar.gz" + tags: navidrome diff --git a/roles/navidrome/tasks/conf.yml b/roles/navidrome/tasks/conf.yml new file mode 100644 index 0000000..d93799a --- /dev/null +++ b/roles/navidrome/tasks/conf.yml @@ -0,0 +1,6 @@ +--- + +- name: Deploy configuration + template: src=navidrome.toml.j2 dest={{ nd_root_dir }}/etc/navidrome.toml + notify: restart navidrome + tags: navidrome diff --git a/roles/navidrome/tasks/directories.yml b/roles/navidrome/tasks/directories.yml new file mode 100644 index 0000000..c035270 --- /dev/null +++ b/roles/navidrome/tasks/directories.yml @@ -0,0 +1,29 @@ +--- + +- name: Create directory structure + file: + path: "{{ nd_root_dir }}/{{ item.dir }}" + state: directory + owner: "{{ item.owner | default(omit) }}" + group: "{{ item.group | default(omit) }}" + mode: "{{ item.mode | default(omit) }}" + loop: + - dir: / + group: "{{ nd_user }}" + mode: 750 + - dir: /data + owner: "{{ nd_user }}" + - dir: /etc + group: "{{ nd_user }}" + mode: 750 + - dir: /music + - dir: /bin + - dir: /tmp + - dir: meta + mode: 700 + - dir: backup + mode: 700 + - dir: archives + mode: 700 + tags: navidrome + diff --git a/roles/navidrome/tasks/facts.yml b/roles/navidrome/tasks/facts.yml new file mode 100644 index 0000000..cfe1add --- /dev/null +++ b/roles/navidrome/tasks/facts.yml @@ -0,0 +1,11 @@ +--- + +- block: + - import_tasks: ../includes/webapps_set_install_mode.yml + vars: + - root_dir: "{{ nd_root_dir }}" + - version: "{{ nd_version }}" + - set_fact: nd_install_mode={{ (install_mode == 'upgrade' and not nd_manage_upgrade) | ternary('none',install_mode) }} + - set_fact: nd_current_version={{ current_version | default('') }} + tags: navidrome + diff --git a/roles/navidrome/tasks/install.yml b/roles/navidrome/tasks/install.yml new file mode 100644 index 0000000..c8e114d --- /dev/null +++ b/roles/navidrome/tasks/install.yml @@ -0,0 +1,43 @@ +--- + +- name: Install dependencies + package: + name: + - ffmpeg + tags: navidrome + +- when: nd_install_mode != 'none' + block: + - name: Download navidrome + get_url: + url: "{{ nd_archive_url }}" + dest: "{{ nd_root_dir }}/tmp/" + checksum: sha1:{{ nd_archive_sha1 }} + + - name: Extract navidrome + unarchive: + src: "{{ nd_root_dir }}/tmp/navidrome_{{ nd_version }}_Linux_x86_64.tar.gz" + dest: "{{ nd_root_dir }}/tmp/" + remote_src: True + + - name: Install navidrome binary + copy: src={{ nd_root_dir }}/tmp/navidrome dest={{ nd_root_dir }}/bin/navidrome mode=755 remote_src=True + + tags: navidrome + +- name: Install systemd unit + template: src=navidrome.service.j2 dest=/etc/systemd/system/navidrome.service + register: nd_systemd_unit + tags: navidrome + +- name: Reload systemd + systemd: daemon_reload=True + when: nd_systemd_unit.changed + tags: navidrome + +- name: Install pre/post backup hooks + template: src={{ item }}-backup.j2 dest=/etc/backup/{{ item }}.d/navidrom mode=755 + loop: + - pre + - post + tags: navidrome diff --git a/roles/navidrome/tasks/iptables.yml b/roles/navidrome/tasks/iptables.yml new file mode 100644 index 0000000..284d290 --- /dev/null +++ b/roles/navidrome/tasks/iptables.yml @@ -0,0 +1,8 @@ +--- + +- name: Handle navidrome ports in the firewall + iptables_raw: + name: navidrome_port + state: "{{ (nd_src_ip | length > 0) | ternary('present','absent') }}" + rules: "-A INPUT -m state --state NEW -p tcp --dport {{ nd_port }} -s {{ nd_src_ip | join(',') }} -j ACCEPT" + tags: firewall,navidrome diff --git a/roles/navidrome/tasks/main.yml b/roles/navidrome/tasks/main.yml new file mode 100644 index 0000000..ca8f997 --- /dev/null +++ b/roles/navidrome/tasks/main.yml @@ -0,0 +1,16 @@ +--- + +- include: user.yml +- include: directories.yml +- include: facts.yml +- include: archive_pre.yml + when: nd_install_mode == 'upgrade' +- include: install.yml +- include: conf.yml +- include: iptables.yml + when: iptables_manage | default(True) +- include: services.yml +- include: write_version.yml +- include: archive_post.yml + when: nd_install_mode == 'upgrade' +- include: cleanup.yml diff --git a/roles/navidrome/tasks/services.yml b/roles/navidrome/tasks/services.yml new file mode 100644 index 0000000..7fa6566 --- /dev/null +++ b/roles/navidrome/tasks/services.yml @@ -0,0 +1,5 @@ +--- + +- name: Start and enable service + service: name=navidrome state=started enabled=True + tags: navidrome diff --git a/roles/navidrome/tasks/user.yml b/roles/navidrome/tasks/user.yml new file mode 100644 index 0000000..a98d234 --- /dev/null +++ b/roles/navidrome/tasks/user.yml @@ -0,0 +1,5 @@ +--- + +- name: Create navidrome user + user: name={{ nd_user }} system=True shell=/sbin/nologin + tags: navidrome diff --git a/roles/navidrome/tasks/write_version.yml b/roles/navidrome/tasks/write_version.yml new file mode 100644 index 0000000..f1093c2 --- /dev/null +++ b/roles/navidrome/tasks/write_version.yml @@ -0,0 +1,5 @@ +--- + +- name: Write installed version + copy: content={{ nd_version }} dest={{nd_root_dir }}/meta/ansible_version + tags: navidrome diff --git a/roles/navidrome/templates/navidrome.service.j2 b/roles/navidrome/templates/navidrome.service.j2 new file mode 100644 index 0000000..a5509df --- /dev/null +++ b/roles/navidrome/templates/navidrome.service.j2 @@ -0,0 +1,44 @@ +[Unit] +Description=Navidrome Music Server and Streamer compatible with Subsonic/Airsonic +After=remote-fs.target network.target +AssertPathExists={{ nd_root_dir }}/data + +[Install] +WantedBy=multi-user.target + +[Service] +User={{ nd_user }} +Group={{ nd_user }} +Type=simple +ExecStart={{ nd_root_dir }}/bin/navidrome --configfile "{{ nd_root_dir }}/etc/navidrome.toml" +WorkingDirectory={{ nd_root_dir }} +TimeoutStopSec=20 +KillMode=process +Restart=on-failure + +# See https://www.freedesktop.org/software/systemd/man/systemd.exec.html +DevicePolicy=closed +NoNewPrivileges=yes +PrivateTmp=yes +PrivateUsers=yes +ProtectControlGroups=yes +ProtectKernelModules=yes +ProtectKernelTunables=yes +RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 +RestrictNamespaces=yes +RestrictRealtime=yes +SystemCallFilter=~@clock @debug @module @mount @obsolete @reboot @setuid @swap +ReadWritePaths={{ nd_root_dir }}/data + +# You can uncomment the following line if you're not using the jukebox This +# will prevent navidrome from accessing any real (physical) devices +PrivateDevices=yes + +# You can change the following line to `strict` instead of `full` if you don't +# want navidrome to be able to write anything on your filesystem outside of +# /var/lib/navidrome. +ProtectSystem=full + +# You can uncomment the following line if you don't have any media in /home/*. +# This will prevent navidrome from ever reading/writing anything there. +ProtectHome=true diff --git a/roles/navidrome/templates/navidrome.toml.j2 b/roles/navidrome/templates/navidrome.toml.j2 new file mode 100644 index 0000000..0739e3b --- /dev/null +++ b/roles/navidrome/templates/navidrome.toml.j2 @@ -0,0 +1,9 @@ +Port = '{{ nd_port }}' +MusicFolder = '{{ nd_music_dir }}' +DataFolder = '{{ nd_root_dir }}/data' +TranscodingCacheSize = '{{ nd_transcoding_cache_size }}' +ImageCacheSize = '{{ nd_image_cache_size }}' +{% if nd_proxy_auth is defined %} +ReverseProxyUserHeader = '{{ nd_proxy_auth }}' +ReverseProxyWhitelist = '{{ nd_proxy_whitelist | join(',') }}' +{% endif %} diff --git a/roles/navidrome/templates/post-backup.j2 b/roles/navidrome/templates/post-backup.j2 new file mode 100644 index 0000000..4036bd6 --- /dev/null +++ b/roles/navidrome/templates/post-backup.j2 @@ -0,0 +1,3 @@ +#!/bin/bash -e + +rm -f {{ nd_root_dir }}/backup/* diff --git a/roles/navidrome/templates/pre-backup.j2 b/roles/navidrome/templates/pre-backup.j2 new file mode 100644 index 0000000..3a2d782 --- /dev/null +++ b/roles/navidrome/templates/pre-backup.j2 @@ -0,0 +1,4 @@ +#!/bin/bash -e + +sqlite3 {{ nd_root_dir }}/data/navidrome.db .dump | zstd -c > {{ nd_root_dir }}/backup/navidrome.sql.zst +cp {{ nd_root_dir }}/etc/navidrome.toml {{ nd_root_dir }}/backup/