{ config, lib, pkgs, ... }: let cfg = config.zpha.websites."music.zaphyra.eu"; in { options.zpha.websites."music.zaphyra.eu" = { enable = lib.mkEnableOption ""; subdomain = lib.mkOption { type = lib.types.str; default = "music"; }; }; config = lib.mkIf cfg.enable { dns.zones."zaphyra.eu".subdomains."${cfg.subdomain}".CNAME = [ "${config.networking.fqdn}." ]; sops.secrets."environments/navidrome" = { restartUnits = [ "navidrome.service" ]; }; users = { users = { navidrome.uid = config.services.navidrome.settings.Port; piegames = { isNormalUser = true; createHome = true; home = "/mnt/music/piegames"; group = "navidrome"; extraGroups = [ "ssh" ]; openssh.authorizedKeys.keys = config.users.users.zaphyra.openssh.authorizedKeys.keys ++ [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABgQC0+vFmtDUgIg18r6a2ezNBRMrZVpAB6dhj37JDhYUu7CSr7o1pR8Sp/UUe/yAEjeyo0R/GfvKIKugCBDCd+6VsDuTkcWX9bwVdrelG3X7pIIt3tWdbqVVGZHFJ/qgdngvIYu3pY++ci6zFlBl8Z8SIXYXpDnVFYTvvBhDIOZJzvyyqL7B/Wm19fTf/HPLTtbuPFMg2gQxo8o5GW3Ow2keJRR1daSGYmGSA1y/F3UumoLuK85Zm0+Kt+yYTO2pMAUBN7Axv1yvnNGbdX9l+3eRHdKatfhCscs720cwR+HtMAfqvN1G5FAWnXdxPa8XIzyZIyrWRoEGPPuK1w2GlWUnDdYLVDMJOmLDz4TvYx2eodfWMRIdppLJYwWpv+Eg8JirO5bnbOnKzVM4C5ESYU8b1mRBI23ncqV+BAno+zehdzLPYg0q3N9wNDF6jqyw08YyiTDwlua4aZJzHDrDt7OjcFaC6t8W1/VimtE0bylhAzVeenJ8C+o3q2jPBvuNLIxk= piegames" ]; }; music = { isNormalUser = true; home = "/mnt/music/inbox"; group = "users"; extraGroups = [ "ssh" ]; openssh.authorizedKeys.keys = config.users.users.zaphyra.openssh.authorizedKeys.keys ++ [ # yuka "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbzUmOJuuAYn/3ODyw3WKjz7SnKjMq4iHE+mEpwVVmw" # rootile "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINkk3bjlkJWq5y4S9sMfW2Wzo5jQFodVqm/Vn226etjW" # ember "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFsEf6O4VWZFtIholRze7bUi/emzpwTQL4wRJaoPSzrG" "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBJWEf+o3fw937guIiiZs8hYiBwrhkrxhul3xr0eRUI2RVGz9OHVOdz6WC5W0+lvQZAIeCmEyCF6DwX7aUANXqUg= misc@secretive.Ember’s-MacBook-Pro.local" # nyaaa (nia) "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMyMojaOLRaEb8+aMrdUZVfTN2V/VoUW8NeyQyNGOedu fly@kinkpad" ]; }; }; groups.navidrome.gid = config.services.navidrome.settings.Port; }; sops.secrets = { "restic/navidrome/repositoryPassword" = { }; "restic/navidrome/sshPrivateKey" = { }; }; fileSystems."/mnt/music-ro" = { device = config.services.syncthing.settings.folders.zaphyra-music-orig.path; fsType = "fuse.bindfs"; options = [ "ro" "perms=0000:a+rX" ]; }; common = { configure.persist.system.dirs = [ { inherit (config.services.navidrome) user group; directory = "/var/lib/navidrome"; mode = "0700"; } { inherit (config.services.navidrome) user group; directory = "/var/cache/navidrome"; mode = "0700"; } ]; services.openssh.enableRSASupport = true; services.resticBackup.navidrome = { inherit (config.services.navidrome) user; enable = true; targets = [ "restic-target.fc9f.de" "isodon.fc9f.de" ]; sshKeyFile = config.sops.secrets."restic/navidrome/sshPrivateKey".path; passwordFile = config.sops.secrets."restic/navidrome/repositoryPassword".path; postgresDatabases = [ "audiomuse" ]; sqliteDatabases = [ "${config.services.navidrome.settings.DataFolder}/navidrome.db" ]; runBeforeBackup = '' ${config.systemd.services.navidrome.serviceConfig.ExecStart} backup create ${config.systemd.services.navidrome.serviceConfig.ExecStart} backup prune ''; paths = [ config.services.navidrome.settings.Backup.Path ]; }; }; systemd.services.navidrome.serviceConfig = { MemoryDenyWriteExecute = lib.mkForce false; BindReadOnlyPaths = [ "/mnt/music-ro" ]; }; networking.firewall.allowedTCPPorts = [ config.services.postgresql.settings.port ]; services = { openssh.extraConfig = '' Match User "music" # AllowTcpForwarding no X11Forwarding no ''; postgresql = { enable = true; settings = { ssl = true; password_encryption = "scram-sha-256"; }; enableTCPIP = true; authentication = lib.mkOverride 10 '' #type database DBuser origin-address auth-method local all all peer # ipv4 host audiomuse audiomuse 172.0.0.0/8 scram-sha-256 hostssl audiomuse audiomuse ::/0 scram-sha-256 ''; ensureDatabases = [ "audiomuse" ]; ensureUsers = [ { name = "audiomuse"; ensureDBOwnership = true; ensureClauses.login = true; } ]; }; navidrome = { enable = true; environmentFile = config.sops.secrets."environments/navidrome".path; package = pkgs.unstable.navidrome.overrideAttrs { CGO_CFLAGS_ALLOW = ".*--define-prefix.*"; }; settings = { Address = "0.0.0.0"; BaseUrl = "https://${cfg.subdomain}.zaphyra.eu"; MusicFolder = "/mnt/music-ro/defaultLibrary"; Deezer.Enabled = true; LastFM.Enabled = true; EnableInsightsCollector = false; EnableExternalServices = true; EnableSharing = true; EnableArtworkPrecache = true; FFmpegPath = lib.getExe pkgs.ffmpeg; DataFolder = "/var/lib/navidrome/state"; CacheFolder = "/var/cache/navidrome"; ImageCacheSize = "2GB"; TranscodingCacheSize = "10GB"; UIWelcomeMessage = "sailing on pcm waves"; Agents = "audiomuseai,lastfm,spotify,deezer"; Backup = { Path = "/var/lib/navidrome/backup"; Count = 2; Schedule = "0 0 * * *"; }; Plugins = { Enabled = true; Folder = "/var/lib/navidrome/plugins"; # Optional: custom plugins folder AutoReload = true; # Useful during development/testing LogLevel = "debug"; # Enable detailed plugin logging CacheSize = "200MB"; }; }; }; nginx.virtualHosts."${cfg.subdomain}.zaphyra.eu" = { useACMEHost = config.networking.fqdn; forceSSL = true; kTLS = true; root = pkgs.zpha.domsonic; locations = { "/".tryFiles = "$uri $uri/ /index.html"; } // (lib.genAttrs [ "/rest" "/auth" "/api" "/app" "/share" ] (name: { proxyPass = "http://127.0.0.1:${toString config.services.navidrome.settings.Port}"; })); }; }; }; }