NixOSConfig/lib/modules/rclone.nix

217 lines
5.6 KiB
Nix

{ config, lib, pkgs, ... }:
let
cfg = config.programs.rclone;
targetName = "rclone";
mkSystemdDependencyOption =
{ default, ... }: lib.mkOption {
type = lib.types.attrsOf (lib.types.listOf lib.types.str);
description = "The systemd services this sync depends on.";
example = {
secrets = [
"sops-nix.service"
];
};
inherit default;
};
mkProvider =
{
secretLoader ? ({ ... }: ""),
envLoader ? ({ ... }: { }),
configLoader ? ({ ... }: { }),
options ? {},
...
}: {
inherit
secretLoader
envLoader
configLoader
options
;
};
mkWebdavOptions = { vendorName }: {
username = lib.mkOption {
type = lib.types.str;
description = "The name of the user to log in to ${vendorName}.";
};
password = lib.mkOption {
type = lib.types.nullOr lib.types.str;
description = "The password for logging in to ${vendorName}.";
default = null;
};
passwordFile = lib.mkOption {
type = lib.types.nullOr (lib.types.either lib.types.path lib.types.str);
description = "A path to a file to read the password from for logging in to ${vendorName}.";
default = null;
};
};
mkOwncloudOptions =
{ vendorName ? "Nextcloud" }: (mkWebdavOptions { inherit vendorName; }) // {
baseUrl = lib.mkOption {
type = lib.types.str;
description = "The base URL of the ${vendorName} server.";
};
};
syncProviders = {
nextcloud = mkProvider {
options = lib.types.submodule (
(mkOwncloudOptions { }));
};
proton = mkProvider {};
manual = mkProvider {};
};
syncType = lib.types.submodule (
{ config, name, ... }: {
options = {
type = lib.mkOption {
description = "The type of the sync";
type = lib.types.enum (builtins.attrNames syncProviders);
default = "manual";
};
autoStart = lib.mkOption {
type = lib.types.bool;
description = "Whether to start this sync automatically.";
default = true;
};
providerOptions = lib.mkOption {
description = "The options of the sync";
type = lib.types.oneOf [
(builtins.map
(provider: provider.options)
syncProviders)
];
};
systemdDependencies = mkSystemdDependencyOption {
default = cfg.systemdDependencies;
};
environment = lib.mkOption {
type = lib.types.attrsOf lib.types.envVar;
description = "The environment variables to pass to the service.";
default = {};
};
secretsScript = lib.mkOption {
type = lib.types.lines;
description = "A script for loading secrets before launching the sync.";
default = [];
};
config = lib.mkOption {
type = lib.types.attrs;
description = "The rclone config to use for creating the mount.";
visible = false;
};
};
config = {
environment = syncProviders.${config.type}.envLoader config;
secretsScript = syncProviders.${config.type}.secretLoader config;
config = syncProviders.${config.type}.configLoader config;
};
});
in {
options = {
programs.rclone = {
enable = lib.mkEnableOption "rclone";
systemdDependencies = mkSystemdDependencyOption {
default = {};
};
configs = lib.mkOption {
type = lib.types.attrsOf syncType;
description = "The synchronizations to set up.";
default = {};
};
};
};
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
(name: sync:
let
serviceName = "rclone-sync-${name}";
in {
${serviceName} = {
Unit = {
Description = "${sync.type}";
};
Service = {
Environment = lib.mapAttrsToList
(key: val: (lib.escapeShellArg "${key}=${val}"))
sync.environment;
ExecStart =
let
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);
};
};
})
cfg.configs);
targets.${targetName} = {
Unit = {
Description = "rclone Mounts";
Documentation = "man:rclone(1)";
};
};
};
};
}