Files
lidarr-mb-gap/nixos/lidarr-mb-gap.nix
Danilo Reyes 0b86143646 Refactor lidarr-mb-gap NixOS module to use configurable home directory
- Introduced a `home` option for the lidarr-mb-gap service, allowing users to specify a custom home directory.
- Updated paths for `reportDir`, `envFile`, and `sshKeyFile` to be relative to the new `home` option, enhancing flexibility and maintainability.
- Adjusted systemd tmpfiles rules and user home directory settings to align with the new configuration structure.
2025-11-11 16:49:59 -06:00

187 lines
5.8 KiB
Nix

{
config,
lib,
pkgs,
...
}:
let
defaultHome = "/var/lib/lidarr-mb-gap";
# 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;
inherit (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";
home = lib.mkOption {
type = lib.types.str;
default = defaultHome;
description = "Home directory for the lidarr-mb-gap user";
};
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 = "${config.services.lidarr-mb-gap.home}/reports";
defaultText = lib.literalExpression ''"''${home}/reports"'';
description = "Directory where reports will be generated";
};
envFile = lib.mkOption {
type = lib.types.str;
default = "${config.services.lidarr-mb-gap.home}/.env";
defaultText = lib.literalExpression ''"''${home}/.env"'';
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";
};
vpsPort = lib.mkOption {
type = lib.types.port;
default = 22;
description = "SSH port for VPS connection";
};
sshKeyFile = lib.mkOption {
type = lib.types.str;
default = "${config.services.lidarr-mb-gap.home}/.ssh/id_ed25519";
defaultText = lib.literalExpression ''"''${home}/.ssh/id_ed25519"'';
description = "Path to SSH private key file for rsync";
};
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 ${config.services.lidarr-mb-gap.home}/.ssh 0700 lidarr-mb-gap lidarr-mb-gap -"
];
users.users.lidarr-mb-gap = {
isSystemUser = true;
group = "lidarr-mb-gap";
home = config.services.lidarr-mb-gap.home;
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="-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 -p ${toString config.services.lidarr-mb-gap.vpsPort} -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;
};
};
};
}