{ pkgs, config, lib, ... }: let inherit (lib) types mkOption concatStrings getExe' mkIf mkEnableOption ; inherit (config.grimmShared) enable cloudSync; inherit (pkgs) nextcloud-client writeShellScriptBin; sync_mod = types.submodule ( { config, ... }: { options = { remote = mkOption { type = types.nonEmptyStr; description = "path on the cloud server"; }; local = mkOption { type = types.nonEmptyStr; default = "$HOME/" + (concatStrings (builtins.match "/*(.+)" config.remote)); description = "local path to sync"; }; }; } ); in { config = mkIf (enable && cloudSync.enable) ( let cloud_cmd = ''${getExe' nextcloud-client "nextcloudcmd"} -u ${cloudSync.username} -p "$(${getExe' pkgs.coreutils-full "cat"} ${cloudSync.passwordFile})" -h -n --path''; sync_server = "https://${cloudSync.server}"; in { environment.systemPackages = [ (writeShellScriptBin "cloudsync-cmd" (cloud_cmd + " $@ " + sync_server)) nextcloud-client ]; systemd.services = lib.mkMerge ( lib.mapAttrsToList ( local_user: user_conf: let paths = user_conf.syncPaths; sync_script = lib.strings.concatLines ( map ( { local, remote }: let remote_clean = lib.strings.concatStrings (builtins.match "/*(.+)" remote); in "${cloud_cmd} /${remote_clean} ${local} ${sync_server}" ) paths ); in { # user-specific sync jobs "nextcloud-autosync-${local_user}" = lib.mkIf (paths != [ ]) { description = "Auto sync Nextcloud"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig.Type = "simple"; serviceConfig.User = local_user; serviceConfig.Group = "users"; script = sync_script; # TimeoutStopSec = "180"; # KillMode = "process"; # KillSignal = "SIGINT"; wantedBy = [ "multi-user.target" ]; enable = true; }; } ) config.users.users ); systemd.timers = lib.mkMerge ( lib.mapAttrsToList ( local_user: user_conf: let paths = user_conf.syncPaths; in { # user-specific sync jobs "nextcloud-autosync-${local_user}" = lib.mkIf (paths != [ ]) { description = "Automatic sync files with Nextcloud when booted up after 5 minutes then rerun every 60 minutes"; timerConfig.OnBootSec = "5min"; timerConfig.OnUnitActiveSec = "60min"; wantedBy = [ "multi-user.target" "timers.target" ]; enable = true; }; } ) config.users.users ); } ); options.users.users = mkOption { type = types.attrsOf ( types.submodule { options = { syncPaths = mkOption { type = types.listOf sync_mod; default = [ ]; description = "paths to sync via nextcloud"; }; }; } ); }; options.grimmShared.cloudSync = { enable = mkEnableOption "cloud_sync"; username = mkOption { type = types.nonEmptyStr; description = "username to use for cloud login"; }; server = mkOption { type = types.nonEmptyStr; description = "server url to use for cloud sync"; }; passwordFile = mkOption { type = types.nonEmptyStr; description = "password file to use for login"; }; }; }