nix/modules/schedule.nix
2026-02-13 07:33:30 +01:00

110 lines
2.9 KiB
Nix

{ config, pkgs, lib, ... }:
with lib;
let
cfg = config.services.scheduled-commands;
makeCommandScript = name: instanceCfg: pkgs.writeScriptBin "${name}-run" ''
#!${pkgs.zsh}/bin/zsh
# Source user shell to get environment and functions
source ${config.home.homeDirectory}/.zshrc
# Execute commands sequentially
${concatStringsSep "\n" instanceCfg.commands}
'';
enabledInstances = filterAttrs (_: instanceCfg: instanceCfg.enable) cfg;
in
{
options.services.scheduled-commands = mkOption {
type = types.attrsOf (types.submodule {
options = {
enable = mkEnableOption "this scheduled command instance";
commands = mkOption {
type = types.listOf types.str;
default = [];
example = [
"echo 'Starting backup...'"
"rsync -av /source /destination"
"echo 'Backup completed'"
];
description = "List of shell commands to execute sequentially";
};
interval = mkOption {
type = types.str;
default = "daily";
example = "*-*-* 08:00:00";
description = "Systemd timer schedule (OnCalendar format)";
};
randomDelay = mkOption {
type = types.str;
default = "0";
example = "1h";
description = "Random delay before execution (e.g., '30m', '1h')";
};
description = mkOption {
type = types.str;
default = "Execute scheduled commands";
example = "Download YouTube videos from subscriptions";
description = "Description for the systemd service";
};
};
});
default = {};
description = "Scheduled command execution services";
};
config = mkMerge [
{
home.packages = mapAttrsToList (name: instanceCfg:
makeCommandScript name instanceCfg
) enabledInstances;
}
{
systemd.user.services = mapAttrs' (name: instanceCfg:
nameValuePair name {
Unit = {
Description = instanceCfg.description;
After = [ "network-online.target" ];
};
Service = {
Type = "oneshot";
ExecStart = "${makeCommandScript name instanceCfg}/bin/${name}-run";
StandardOutput = "journal";
StandardError = "journal";
};
Install = {
WantedBy = mkForce [];
};
}
) enabledInstances;
systemd.user.timers = mapAttrs' (name: instanceCfg:
nameValuePair name {
Unit = {
Description = "Timer for ${instanceCfg.description}";
};
Timer = {
OnCalendar = instanceCfg.interval;
Persistent = true;
RandomizedDelaySec = instanceCfg.randomDelay;
};
Install = {
WantedBy = [ "timers.target" ];
};
}
) enabledInstances;
}
];
}