{ config, lib, pkgs, ... }: let reportDir = "/var/lib/lidarr-mb-gap/reports"; envFile = "/var/lib/lidarr-mb-gap/.env"; # Determine which package to use lidarrMbGapPackage = if config.services.lidarr-mb-gap.package != null then config.services.lidarr-mb-gap.package else if config.services.lidarr-mb-gap.src != null then import ../nix/package.nix { inherit pkgs; lib = pkgs.lib; src = config.services.lidarr-mb-gap.src; } else throw "services.lidarr-mb-gap: Either 'package' or 'src' must be set."; in { options.services.lidarr-mb-gap = { enable = lib.mkEnableOption "Lidarr MusicBrainz Gap Reporter"; package = lib.mkOption { type = lib.types.nullOr lib.types.package; default = null; description = "The lidarr-mb-gap package to use. If null, will be built from src."; }; src = lib.mkOption { type = lib.types.nullOr lib.types.path; default = null; description = "Source path for building the package. Required if package is not explicitly set."; }; reportDir = lib.mkOption { type = lib.types.str; default = reportDir; description = "Directory where reports will be generated"; }; envFile = lib.mkOption { type = lib.types.str; default = envFile; description = "Path to .env file with LIDARR_URL and LIDARR_API_KEY"; }; runInterval = lib.mkOption { type = lib.types.str; default = "daily"; description = "systemd timer interval (e.g., 'daily', 'hourly', '*-*-* 02:00:00')"; }; syncToVPS = lib.mkOption { type = lib.types.bool; default = false; description = "Whether to sync reports to VPS via rsync"; }; vpsHost = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "VPS hostname or IP for rsync (e.g., 'vps' or 'user@vps.example.com')"; }; vpsPath = lib.mkOption { type = lib.types.str; default = "/var/www/html"; description = "Path on VPS where reports should be synced"; }; sshKeyFile = lib.mkOption { type = lib.types.nullOr lib.types.str; default = null; description = "Path to SSH private key file for rsync. If null, uses default SSH key location."; }; sshKnownHosts = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { hostNames = lib.mkOption { type = lib.types.listOf lib.types.str; description = "List of hostnames/IPs for this known host"; }; publicKey = lib.mkOption { type = lib.types.str; description = "SSH public key for the host"; }; }; } ); default = { }; description = "SSH known hosts configuration for the VPS (same format as programs.ssh.knownHosts)"; }; }; config = lib.mkIf config.services.lidarr-mb-gap.enable { systemd.tmpfiles.rules = [ "d ${config.services.lidarr-mb-gap.reportDir} 0755 lidarr-mb-gap lidarr-mb-gap -" "d /var/lib/lidarr-mb-gap/.ssh 0700 lidarr-mb-gap lidarr-mb-gap -" ]; users.users.lidarr-mb-gap = { isSystemUser = true; group = "lidarr-mb-gap"; home = "/var/lib/lidarr-mb-gap"; createHome = true; }; users.groups.lidarr-mb-gap = { }; programs.ssh.knownHosts = config.services.lidarr-mb-gap.sshKnownHosts; systemd.services.lidarr-mb-gap = { description = "Generate Lidarr MusicBrainz Gap Report"; after = [ "network.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { Type = "oneshot"; User = "lidarr-mb-gap"; Group = "lidarr-mb-gap"; WorkingDirectory = config.services.lidarr-mb-gap.reportDir; EnvironmentFile = config.services.lidarr-mb-gap.envFile; ExecStart = pkgs.writeShellScript "lidarr-mb-gap-run" '' set -euo pipefail # Export OUTPUT_DIR to environment export OUTPUT_DIR=${config.services.lidarr-mb-gap.reportDir} # Run the binary ${lib.getExe lidarrMbGapPackage} || { echo "Failed to generate report" exit 1 } # Sync to VPS if enabled ${lib.optionalString (config.services.lidarr-mb-gap.syncToVPS && config.services.lidarr-mb-gap.vpsHost != null) '' # Set up SSH options SSH_OPTS="" ${lib.optionalString (config.services.lidarr-mb-gap.sshKeyFile != null) '' SSH_OPTS="-i ${config.services.lidarr-mb-gap.sshKeyFile}" ''} # Use SSH options with rsync (use full path to ssh) ${pkgs.rsync}/bin/rsync -avz --delete \ -e "${pkgs.openssh}/bin/ssh $SSH_OPTS -o StrictHostKeyChecking=yes" \ ${config.services.lidarr-mb-gap.reportDir}/ \ ${config.services.lidarr-mb-gap.vpsHost}:${config.services.lidarr-mb-gap.vpsPath}/ '' } ''; StandardOutput = "journal"; StandardError = "journal"; }; }; systemd.timers.lidarr-mb-gap = { description = "Timer for Lidarr MusicBrainz Gap Report"; wantedBy = [ "timers.target" ]; timerConfig = { OnCalendar = config.services.lidarr-mb-gap.runInterval; Persistent = true; }; }; }; }