aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--flake/nixosConfigurations/common.nix33
-rw-r--r--hosts/apzu/default.nix1
-rw-r--r--hosts/tiamat/default.nix1
-rw-r--r--modules/by-name/un/unison/module.nix92
-rw-r--r--modules/by-name/un/unison/shellScript.nix95
-rw-r--r--modules/home.legacy/conf/default.nix1
-rw-r--r--modules/home.legacy/conf/unison/default.nix187
7 files changed, 221 insertions, 189 deletions
diff --git a/flake/nixosConfigurations/common.nix b/flake/nixosConfigurations/common.nix
index 585e883b..2ff85521 100644
--- a/flake/nixosConfigurations/common.nix
+++ b/flake/nixosConfigurations/common.nix
@@ -1,6 +1,6 @@
# This file contains common configuration applied to every host.
# It should only `enable` options defined in the `modules` directory.
-{...}: {
+{config, ...}: {
soispha = {
boot.enable = true;
cleanup.enable = true;
@@ -37,6 +37,37 @@
snapper.enable = true;
steam.enable = false;
systemDiff.enable = true;
+ unison = {
+ enable = true;
+
+ foreign.userName = "soispha";
+ dataDir = "${config.home-manager.users.soispha.xdg.dataHome}/unison";
+ userSourceDir = "/srv/home/soispha";
+ pathsToIgnore = [
+ # already synchronized by the taskserver
+ "~/.local/share/task"
+
+ # Should not be synchronized
+ "~/.local/share/unison"
+
+ # Is just to big to be synchronized (# TODO: Work around that <2024-08-31> )
+ "~/media/music"
+ ];
+
+ pathsToSync = [
+ "~/.local/state/mpv"
+ "~/.local/state/nvim"
+ "~/.local/share"
+ "~/.local/.Trash-1000"
+
+ "~/.mozilla/.Trash-1000"
+ "~/.mozilla/firefox"
+
+ "~/media"
+ "~/school"
+ "~/repos"
+ ];
+ };
};
programs = {
diff --git a/hosts/apzu/default.nix b/hosts/apzu/default.nix
index 98c83325..d1a83fec 100644
--- a/hosts/apzu/default.nix
+++ b/hosts/apzu/default.nix
@@ -19,6 +19,7 @@
hostName = "apzu";
mode = "NetworkManager";
};
+ services.unison.foreign.address = "tiamat.fritz.box";
nixpkgs = {
enable = true;
systemName = "x86_64-linux";
diff --git a/hosts/tiamat/default.nix b/hosts/tiamat/default.nix
index b679ec62..3e531c7d 100644
--- a/hosts/tiamat/default.nix
+++ b/hosts/tiamat/default.nix
@@ -19,6 +19,7 @@
backupDiskUuid = "c06ce163-2955-4388-b212-dfec4448fcf4";
enable = true;
};
+ unison.foreign.address = "apzu.fritz.box";
};
locale = {
enable = true;
diff --git a/modules/by-name/un/unison/module.nix b/modules/by-name/un/unison/module.nix
new file mode 100644
index 00000000..baf92b02
--- /dev/null
+++ b/modules/by-name/un/unison/module.nix
@@ -0,0 +1,92 @@
+{
+ lib,
+ config,
+ pkgs,
+ sysLib,
+ ...
+}: let
+ cfg = config.soispha.services.unison;
+
+ script = import ./shellScript.nix {inherit sysLib lib pkgs cfg;};
+in {
+ options.soispha.services.unison = let
+ homePath = lib.types.strMatching "^~.*";
+ in {
+ enable = lib.mkEnableOption "a unison home sync script";
+
+ dataDir = lib.mkOption {
+ type = lib.types.path;
+ description = ''
+ This directory is used by unison to store it's data.
+ '';
+ };
+
+ foreign = {
+ address = lib.mkOption {
+ type = lib.types.str;
+ description = ''
+ The address to contact via ssh, when syncing.
+ '';
+ };
+ userName = lib.mkOption {
+ type = lib.types.str;
+ description = ''
+ The user name to try to login with at the foreign host.
+ '';
+ };
+ };
+
+ userSourceDir = lib.mkOption {
+ description = ''
+ The directory to replace the `~` in the relative user paths with.
+ If using `impermanence`, this should be the path to the persistent home directory.
+ '';
+ };
+
+ pathsToIgnore = lib.mkOption {
+ type = lib.types.listOf homePath;
+ default = [];
+ description = ''
+ A list of the paths that should not be synced.
+ Beware that this applies not only to this path, but also to all paths under it.
+ '';
+ };
+ pathsToSync = lib.mkOption {
+ type = lib.types.listOf homePath;
+ default = [];
+ description = ''
+ A list of the paths that should be synced.
+ Beware that this applies not only to this path, but also to all paths under it.
+ '';
+ };
+
+ unisonOptions = lib.mkOption {
+ internal = true;
+ default = {
+ sshcmd = "ssh";
+ ui = "text";
+ auto = "true";
+ # This is a trap, thanks to the HM links
+ # TODO: Auto-ignore all `home.file` paths <2024-10-24>
+ links = "false";
+
+ backupdir = "${cfg.dataDir}/backups";
+ backuploc = "central";
+ };
+ type = lib.types.attrsOf lib.types.str;
+ description = "The options passed to every unison call.";
+ };
+ };
+
+ config = lib.mkIf cfg.enable {
+ home-manager.users.soispha = {
+ home.sessionVariables = {
+ UNISON = cfg.dataDir;
+ };
+ home.packages = [
+ pkgs.unison
+ script
+ ];
+ };
+ };
+}
diff --git a/modules/by-name/un/unison/shellScript.nix b/modules/by-name/un/unison/shellScript.nix
new file mode 100644
index 00000000..5ff0c219
--- /dev/null
+++ b/modules/by-name/un/unison/shellScript.nix
@@ -0,0 +1,95 @@
+{
+ sysLib,
+ lib,
+ pkgs,
+ cfg,
+}: let
+ esa = lib.strings.escapeShellArg;
+
+ expandHomePath = path:
+ if lib.strings.hasPrefix "~" path
+ then "${cfg.userSourceDir}${lib.strings.removePrefix "~" path}"
+ else
+ builtins.throw
+ ''
+ BUG: Every pathname needs to start with a '~'.
+ This should have been checked by the NixOS module system?
+ '';
+
+ getIgnored = paths_to_ignore: path:
+ serialiseArgs {
+ ignore =
+ builtins.filter (x: x != null) (builtins.map (getIgnoredSingle path) paths_to_ignore);
+ };
+
+ getIgnoredSingle = path: pathToIgnore: let
+ clean_path_to_ignore = expandHomePath pathToIgnore;
+ commonPath = builtins.substring 0 (builtins.stringLength path) clean_path_to_ignore;
+ in
+ if commonPath == path
+ then let
+ preFinalPath =
+ builtins.substring (builtins.stringLength commonPath)
+ (builtins.stringLength clean_path_to_ignore)
+ clean_path_to_ignore;
+ finalPath =
+ if lib.strings.hasPrefix "/" preFinalPath
+ then lib.strings.removePrefix "/" preFinalPath
+ else preFinalPath;
+ in "BelowPath ${finalPath}"
+ else null;
+
+ serialiseArg = key: val:
+ if builtins.typeOf val == "string"
+ then esa "-${key}=${lib.strings.escape ["="] val}"
+ else if builtins.typeOf val == "list"
+ then lib.strings.concatStringsSep " " (builtins.map (serialiseArg key) val)
+ else builtins.throw "Unsupported type: ${builtins.typeOf val}";
+
+ serialiseArgs = args:
+ lib.strings.concatStringsSep " " (
+ lib.attrsets.mapAttrsToList
+ serialiseArg
+ args
+ );
+
+ mkScriptLine = pathname: let
+ path =
+ expandHomePath pathname;
+ in
+ lib.strings.concatStringsSep " " [
+ "unison"
+ "${serialiseArgs cfg.unisonOptions}"
+ "$EXTRA_OPTIONS"
+ "${getIgnored cfg.pathsToIgnore path}"
+ "${esa path}"
+ (esa "ssh://${cfg.foreign.userName}@${cfg.foreign.address}/${path}")
+ ];
+
+ script = lib.strings.concatStringsSep "\n" (builtins.map mkScriptLine cfg.pathsToSync);
+in
+ sysLib.writeShellScript {
+ name = "unison-sync";
+ src = builtins.toFile "unison-backup" (''
+ #!/usr/bin/env dash
+
+ # shellcheck source=/dev/null
+ SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
+
+ export UNISON=${esa cfg.dataDir};
+
+ if [ "$1" = "links" ]; then
+ shift 1;
+ EXTRA_OPTIONS="-links=true";
+ fi
+ EXTRA_OPTIONS="$EXTRA_OPTIONS $*"
+ ''
+ + script);
+
+ dependencies = with pkgs; [
+ unison
+ openssh # needed to connect to the other server
+ less # needed to show diffs
+ diffutils # needed to compute diffs
+ ];
+ }
diff --git a/modules/home.legacy/conf/default.nix b/modules/home.legacy/conf/default.nix
index 217944ce..161c04a1 100644
--- a/modules/home.legacy/conf/default.nix
+++ b/modules/home.legacy/conf/default.nix
@@ -37,7 +37,6 @@
./taskwarrior
./timewarrior
./tridactyl
- ./unison
./xdg
./yambar
./yt
diff --git a/modules/home.legacy/conf/unison/default.nix b/modules/home.legacy/conf/unison/default.nix
deleted file mode 100644
index ae682235..00000000
--- a/modules/home.legacy/conf/unison/default.nix
+++ /dev/null
@@ -1,187 +0,0 @@
-{
- lib,
- config,
- nixosConfig,
- sysLib,
- pkgs,
- ...
-}: let
- unisonPath = "${config.xdg.dataHome}/unison";
-
- # These are only used for the script
- unisonOptions = {
- sshcmd = "ssh";
- ui = "text";
- auto = "true";
- # This is useless, with hm links
- links = "false";
-
- backupdir = "${unisonPath}/backups";
- backuploc = "central";
- backupcurr = paths_to_merge;
- # merge =
- # builtins.map (x: ''${x} -> diff3 --text --merge CURRENT1 CURRENTARCH CURRENT2 > NEW'')
- # paths_to_merge;
- };
-
- paths_to_merge = mkPathName {
- file_names = ["log" "history" "harpoon.json" "file_frecency.bin" "main.shada"];
- extensions = ["log"];
- };
-
- paths_to_keep = [
- "~/.local/state/mpv"
- "~/.local/state/nvim"
- "~/.local/share"
- "~/.local/.Trash-1000"
-
- "~/.mozilla/.Trash-1000"
- "~/.mozilla/firefox"
-
- "~/media"
- "~/school"
- "~/repos"
- ];
- paths_to_ignore = [
- # already synchronized by the taskserver
- "~/.local/share/task"
-
- # Should not be synchronized
- "~/.local/share/unison"
-
- # Is just to big to be synchronized (# TODO: Work around that <2024-08-31> )
- "~/media/music"
- ];
-
- hostName = let
- hn = nixosConfig.networking.hostName;
- in
- if hn == "tiamat"
- then "apzu"
- else if hn == "apzu"
- then "tiamat"
- else builtins.throw "Host (${hn}) not yet covered in the unison host mapping.";
-
- mkPathName = {
- file_names,
- extensions,
- }:
- builtins.map (x: ''Name ${x}'') (
- (builtins.map (x: ''*.${x}'') extensions)
- ++ file_names
- );
-
- unitName = name: builtins.replaceStrings ["/"] ["-"] name;
-
- mkPath = path:
- if lib.strings.hasPrefix "~" path
- then "${builtins.elemAt (builtins.attrNames config.home.persistence)
- 0}${lib.strings.removePrefix "~" path}"
- else
- builtins.throw
- "Every pathname needs to start with a '~'";
-
- mkPair = pathname: let
- path = mkPath pathname;
- in {
- name = unitName "${pathname}";
- value = {
- stateDirectory = unisonPath;
- roots = [
- "${path}"
- "ssh://${config.home.username}@${hostName}.fritz.box/${path}"
- ];
- };
- };
-
- getIgnoredSingle = path: path_to_ignore: let
- clean_path_to_ignore = mkPath path_to_ignore;
- commonPath = builtins.substring 0 (builtins.stringLength path) clean_path_to_ignore;
- in
- if commonPath == path
- then let
- preFinalPath =
- builtins.substring (builtins.stringLength commonPath)
- (builtins.stringLength clean_path_to_ignore)
- clean_path_to_ignore;
- finalPath =
- if lib.strings.hasPrefix "/" preFinalPath
- then lib.strings.removePrefix "/" preFinalPath
- else preFinalPath;
- in "BelowPath ${finalPath}"
- else null;
-
- getIgnored = paths_to_ignore: path:
- serialiseArgs {
- ignore =
- builtins.filter (x: x != null) (builtins.map (getIgnoredSingle path) paths_to_ignore);
- };
-
- serialiseArg = key: val:
- if builtins.typeOf val == "string"
- then lib.strings.escapeShellArg "-${key}=${lib.strings.escape ["="] val}"
- else if builtins.typeOf val == "list"
- then lib.strings.concatStringsSep " " (builtins.map (serialiseArg key) val)
- else builtins.throw "Unsupported type: ${builtins.typeOf val}";
-
- serialiseArgs = args:
- lib.strings.concatStringsSep " " (
- lib.attrsets.mapAttrsToList
- serialiseArg
- args
- );
-
- esa = a: lib.strings.escapeShellArg a;
-
- mkScriptLine = pathname: let
- path =
- mkPath pathname;
- in
- lib.strings.concatStringsSep " " [
- "unison"
- "${serialiseArgs unisonOptions}"
- "$EXTRA_OPTIONS"
- "${getIgnored paths_to_ignore path}"
- "${esa path}"
- (esa "ssh://${config.home.username}@${hostName}.fritz.box/${path}")
- ];
-
- script = lib.strings.concatStringsSep "\n" (builtins.map mkScriptLine paths_to_keep);
-
- pairs = builtins.listToAttrs (builtins.map mkPair paths_to_keep);
-in {
- home.sessionVariables = {
- UNISON = unisonPath;
- };
- home.packages = [
- pkgs.unison
- (sysLib.writeShellScript {
- name = "unison-sync";
- src = builtins.toFile "unison-backup" (''
- #!/usr/bin/env dash
-
- # shellcheck source=/dev/null
- SHELL_LIBRARY_VERSION="2.1.2" . %SHELL_LIBRARY_PATH
-
- export UNISON=${esa unisonPath};
-
- if [ "$1" = "links" ]; then
- shift 1;
- EXTRA_OPTIONS="-links=true";
- fi
- EXTRA_OPTIONS="$EXTRA_OPTIONS $*"
- ''
- + script);
- dependencies = with pkgs; [
- unison
- openssh # needed to connect to the other server
- less # needed to show diffs
- diffutils # needed to compute diffs
- ];
- })
- ];
- services.unison = {
- enable = false;
- inherit pairs;
- };
-}