{ config, lib, pkgs, ... }: let inherit (lib) mkIf; cfg = config.pepe.services.navidrome; beetsConfigTemplate = pkgs.writeText "beets.conf.template" '' directory: ${cfg.musicFolder} plugins: embedart fetchart scrub lastgenre chroma import: write: yes move: yes incremental: yes from_scratch: yes group_albums: yes log: ${cfg.musicFolder}/beets.log original_date: yes discogs: user_token: "__DISCOGS_TOKEN__" paths: default: $albumartist/$album ($original_year)/$track - $title singleton: $artist/singles/$title match: strong_rec_thresh: 0.20 musicbrainz: extra_tags: [year] lastfm: user: peperunas api_key: "__LASTFM_KEY__" embedart: auto: yes fetchart: auto: yes lastfmkey: "__LASTFM_KEY__" enforce_ratio: 0.5% scrub: auto: yes lastgenre: auto: yes count: 5 min_weight: 10 prefer_specific: yes force: yes chroma: auto: yes ''; preStartBeetsDecrypt = '' set -eu sed \ -e "s|__DISCOGS_TOKEN__|$(cat ${config.age.secrets.discogs.path})|g" \ -e "s|__LASTFM_KEY__|$(cat ${config.age.secrets.lastfmKey.path})|g" \ ${beetsConfigTemplate} > /run/beets.conf ''; navidromeWrapped = pkgs.writeShellScriptBin "navidrome-wrapped" '' set -eu ${preStartNavidromeDecrypt} exec ${cfg.package}/bin/navidrome "$@" ''; preStartNavidromeDecrypt = '' set -eu # export ND_LASTFM_APIKEY=$(cat ${config.age.secrets.lastfmKey.path}) # export ND_LASTFM_SECRET=$(cat ${config.age.secrets.lastfmSecret.path}) # export ND_SPOTIFY_ID=$(cat ${config.age.secrets.spotifyID.path}) # export ND_SPOTIFY_SECRET=$(cat ${config.age.secrets.spotifySecret.path}) ''; in { options.pepe.services.navidrome = with lib; { enable = mkEnableOption "Enable navidrome"; enableBeets = mkEnableOption "Enable beets"; package = mkPackageOption pkgs "navidrome" { }; beetsPackage = mkPackageOption pkgs "beets" { }; domain = mkOption { type = types.str; default = null; }; musicFolder = mkOption { type = types.str; default = "/media/Music"; description = "Path to the music library"; }; settings = mkOption { type = types.attrs; default = { }; description = "Additional settings for Navidrome"; }; }; config = mkIf cfg.enable { services.navidrome = { enable = true; package = navidromeWrapped; settings = { MusicFolder = cfg.musicFolder; LastFM.enable = true; EnableGravatar = true; LogLevel = "WARN"; } // cfg.settings; }; pepe.core.vhost.hosts.${cfg.domain} = { locations."/" = { port = config.services.navidrome.settings.Port; allowLAN = true; allowVPN = true; allowWAN = true; }; }; age.secrets = { discogs = mkIf cfg.enableBeets { file = ../../../secrets/discogs.age; }; lastfmKey = { file = ../../../secrets/lastfm-key.age; }; lastfmSecret = { file = ../../../secrets/lastfm-key.age; }; spotifyID = { file = ../../../secrets/spotify-id.age; }; spotifySecret = { file = ../../../secrets/spotify-secret.age; }; }; systemd.services = { "navidrome".preStart = preStartNavidromeDecrypt; } // mkIf cfg.enableBeets { "beets-update" = { enable = true; preStart = preStartBeetsDecrypt; before = [ "beets-import.service" ]; serviceConfig = { Type = "oneshot"; ExecStart = "${cfg.beetsPackage}/bin/beet -c /run/beets.conf update"; }; }; "beets-import" = { enable = true; path = [ pkgs.imagemagick ]; requires = [ "beets-update.service" ]; after = [ "beets-update.service" ]; serviceConfig = { Type = "oneshot"; ExecStart = "${cfg.beetsPackage}/bin/beet -c /run/beets.conf import --flat -q ${cfg.musicFolder}"; }; startAt = "weekly"; }; }; pepe.core.media.groupMembers = mkIf config.pepe.core.media.enable [ "navidrome" ]; }; }