NixOSConfig/lib/modules/rclone.nix

226 lines
6.4 KiB
Nix
Raw Normal View History

2024-05-14 11:18:38 +00:00
{ config, lib, pkgs, ... }:
let
cfg = config.programs.rclone;
targetName = "rclone";
mkIfNotNull = value: result: lib.mkIf (value != null) result;
2024-05-15 08:01:13 +00:00
mkSystemdDependencyOption =
2024-05-15 16:16:45 +00:00
{ default, global ? false, ... }: lib.mkOption {
2024-05-15 08:01:13 +00:00
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
2024-05-15 16:16:45 +00:00
description = "The systemd services ${
if global then "all" else "this"
} sync${
if global then "s" else ""
} depend${
if global then "" else "s"
} on.";
2024-05-15 08:01:13 +00:00
example = {
secrets = [
"sops-nix.service"
];
};
inherit default;
};
2024-05-15 21:21:00 +00:00
mkProvider = (
{ config, ... }: {
2024-05-14 11:18:38 +00:00
options = {
path = lib.mkOption {
type = lib.types.str;
description = "The path to mount the remote file system to.";
};
2024-05-14 11:18:38 +00:00
autoStart = lib.mkOption {
type = lib.types.bool;
description = "Whether to start this sync automatically.";
default = true;
};
systemdDependencies = mkSystemdDependencyOption {
default = cfg.systemdDependencies;
2024-05-14 11:18:38 +00:00
};
environment = lib.mkOption {
type = lib.types.attrsOf lib.types.envVar;
description = "The environment variables to pass to the service.";
2024-05-15 21:21:00 +00:00
default = { };
2024-05-14 11:18:38 +00:00
};
2024-05-14 12:23:30 +00:00
secretsScript = lib.mkOption {
2024-05-14 11:18:38 +00:00
type = lib.types.lines;
2024-05-14 12:23:30 +00:00
description = "A script for loading secrets before launching the sync.";
2024-05-14 11:18:38 +00:00
default = [];
};
config = lib.mkOption {
type = lib.types.attrs;
description = "The rclone config to use for creating the mount.";
visible = false;
};
2024-05-14 11:18:38 +00:00
};
2024-05-15 21:21:00 +00:00
});
mkWebdavProvider = (
{ displayName, vendor, ... }: (
{ config, ... }: {
imports = [
mkProvider
];
options.providerOptions = {
vendor = lib.mkOption {
type = lib.types.str;
description = "The vendor of the WebDAV share.";
default = vendor;
};
url = lib.mkOption {
type = lib.types.str;
description = "The WebDAV URL of the ${displayName} server.";
default = null;
};
username = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "The user name for logging in to the ${displayName} server.";
default = null;
};
obscuredPassword = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "The password obscured using the `rclone obscure` command for logging in to the ${displayName} server.";
default = null;
};
2024-05-15 21:21:00 +00:00
obscuredPasswordFile = lib.mkOption {
type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str);
description = "The path to a file containing the password obscured using the `rclone obscure` command for logging in to the ${displayName} server.";
default = null;
};
};
config = {
config = lib.mkMerge [
{
inherit vendor;
url = config.providerOptions.url;
}
(mkIfNotNull config.providerOptions.username { user = config.providerOptions.username; })
(mkIfNotNull config.providerOptions.obscuredPassword { pass = config.providerOptions.obscuredPassword; })
];
};
}));
syncProviders = {
nextcloud = rec {
displayName = "Nextcloud";
module = mkWebdavProvider {
inherit displayName;
vendor = "nextcloud";
2024-05-15 15:22:34 +00:00
};
2024-05-15 21:21:00 +00:00
};
};
2024-05-14 11:18:38 +00:00
in {
options = {
programs.rclone = {
enable = lib.mkEnableOption "rclone";
2024-05-14 11:18:38 +00:00
systemdDependencies = mkSystemdDependencyOption {
default = {};
2024-05-15 16:16:45 +00:00
global = true;
};
2024-05-15 13:54:03 +00:00
configs = (builtins.mapAttrs
2024-05-15 21:21:00 +00:00
(name: provider: lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule provider.module);
description = "The ${provider.displayName} synchronizations to set up.";
default = { };
2024-05-15 13:54:03 +00:00
})
syncProviders);
};
};
config = {
home.packages = lib.optional cfg.enable pkgs.rclone;
systemd.user = lib.optionalAttrs cfg.enable {
enable = true;
services = {
rclone = {
Unit = {
Description = "rclone Starter";
Documentation = "man:rclone(1)";
};
Service = {
Type = "simple";
ExecStartPre =
let
script = pkgs.writeShellScriptBin "rclone-pre" ''
sleep 10
'';
in
(lib.getExe script);
ExecStart =
let
script = pkgs.writeShellScriptBin "rclone" ''
systemctl --user start rclone.target
'';
in
(lib.getExe script);
};
};
} // (
lib.attrsets.concatMapAttrs
2024-05-15 13:54:03 +00:00
(providerName: configs:
lib.attrsets.concatMapAttrs
(name: sync:
let
serviceName = "rclone-${providerName}-sync-${name}";
in {
${serviceName} = {
Unit = {
Description = "rclone sync service for ${name} at using ${providerName}";
};
Service = {
Environment = lib.mapAttrsToList
(key: val: (lib.escapeShellArg "${key}=${val}"))
sync.environment;
ExecStart =
let
configFile = pkgs.writeText
"${serviceName}.conf"
(lib.generators.toINI { } { name = sync.config; });
2024-05-15 13:54:03 +00:00
script = pkgs.writeShellScriptBin serviceName ''
${sync.secretsScript}
bash -c echo hello world
'';
in
(lib.getExe script);
};
Install = {
WantedBy = lib.optional sync.autoStart "${targetName}.target";
After = builtins.concatLists(builtins.attrValues sync.systemdDependencies);
};
};
2024-05-15 13:54:03 +00:00
})
configs)
cfg.configs);
targets.${targetName} = {
Unit = {
Description = "rclone Mounts";
Documentation = "man:rclone(1)";
};
};
};
};
}