# Navidrome Configuration Variables # https://www.navidrome.org/docs/usage/configuration-options/ # --- Version ---------------------------------------------------------------- # Bump navidrome_version and navidrome_sha256 TOGETHER. The hash is the one # for the linux_amd64 tarball in that release's navidrome_checksums.txt: # curl -sL https://github.com/navidrome/navidrome/releases/download/v/navidrome_checksums.txt \ # | grep linux_amd64.tar.gz navidrome_version: "0.64.0" navidrome_arch: "linux_amd64" navidrome_sha256: "efd94d11253234035b5d3cf284da917111736e72daeeda4f45a58251c60553ac" navidrome_url: "https://github.com/navidrome/navidrome/releases/download/v{{ navidrome_version }}/navidrome_{{ navidrome_version }}_{{ navidrome_arch }}.tar.gz" # --- Service user ----------------------------------------------------------- navidrome_user: navidrome navidrome_group: navidrome # --- Paths ------------------------------------------------------------------ navidrome_bin_path: /usr/local/bin/navidrome navidrome_config_dir: /etc/navidrome navidrome_config_file: "{{ navidrome_config_dir }}/navidrome.toml" # SQLite database, cache, transcoding scratch. The only thing Navidrome writes. navidrome_data_dir: /var/lib/navidrome # The canonical library. Navidrome READS this and never writes it, which is why # it is absent from ReadWritePaths in the unit. beets is what writes here. navidrome_music_dir: /srv/music # Staging area. Whatever lands here is unsorted and has NOT been through beets; # Navidrome never looks at it. navidrome_incoming_dir: /srv/incoming # The human who curates the library with beets. Owns both directories above; # navidrome only needs group read. navidrome_curator_user: "{{ new_user }}" # --- HTTP ------------------------------------------------------------------- # 0.0.0.0, not loopback: the edge host reaches this across the tailnet. UFW # denies the port from the LAN and the internet, and tailnet traffic bypasses # UFW entirely (-A INPUT -j ts-input sits ahead of every ufw-* chain), so # binding wide here does not widen exposure. Confirmed on mempool-box. navidrome_bind_address: "0.0.0.0" navidrome_port: 4533 navidrome_log_level: info # Navidrome's telemetry. Off. navidrome_enable_insights: false # --- Secrets ---------------------------------------------------------------- # Navidrome CANNOT store user passwords as a one-way hash: the Subsonic API # authenticates with md5(password + salt), so the server has to be able to # recover the plaintext. It encrypts them at rest with this key instead. # # Consequences, both real: # - root on this box means every Navidrome password in plaintext. Use a # password unique to this service and nowhere else. # - CHANGING THIS KEY INVALIDATES EVERY STORED PASSWORD. Set it before the # first account exists and then leave it alone. # Injected by the playbook from group_vars/all/vault.yml; empty here so the # role stays self-contained and asserts loudly rather than starting insecure. navidrome_password_encryption_key: "" # Set true to see the rendered config in --diff. It carries the key above, so # the template is diff-suppressed by default. navidrome_reveal_config: false # --- beets ------------------------------------------------------------------ # beets is NOT a service. It is an interactive CLI the curator runs over SSH to # fix tags before Navidrome ever indexes them; there is no unit and no timer. navidrome_beets_enabled: true navidrome_beets_dir: /var/lib/beets navidrome_beets_config: "{{ '/home/' ~ navidrome_curator_user ~ '/.config/beets/config.yaml' }}" # --- Health check ----------------------------------------------------------- # "Does Navidrome actually answer", as opposed to infra/401's "is the unit # active". The exit code is the answer and systemd keeps it: # systemctl is-failed navidrome-healthcheck.service navidrome_healthcheck_script_path: /usr/local/bin/navidrome-healthcheck-push.sh navidrome_healthcheck_service_name: navidrome-healthcheck # WHERE TO REPORT HEALTH — the one place to plug in monitoring. # Empty means check, log, exit honestly, report nowhere. healthcheck_push_url: "" # Bearer token for the Gatus external endpoint. Required whenever a push URL # is set: Gatus rejects an unauthenticated push with 401. healthcheck_push_token: ""