diff --git a/nix/configuration/configuration.nix b/nix/configuration/configuration.nix
index bf55f68..383b40d 100644
--- a/nix/configuration/configuration.nix
+++ b/nix/configuration/configuration.nix
@@ -2,7 +2,6 @@
config,
lib,
pkgs,
- home-manager,
...
}:
@@ -74,6 +73,7 @@
./roles/zfs
./roles/zrepl
./roles/zsh
+ ./util/install_files
./util/unfree_polyfill
];
@@ -122,21 +122,6 @@
];
};
users.groups.talexander.gid = 11235;
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- # The state version is required and should stay at the version you
- # originally installed.
- home.stateVersion = "24.11";
- };
-
- home-manager.users.root =
- { pkgs, ... }:
- {
- # The state version is required and should stay at the version you
- # originally installed.
- home.stateVersion = "24.11";
- };
# Automatic garbage collection
nix.gc = lib.mkIf (!config.me.buildingIso) {
diff --git a/nix/configuration/flake.lock b/nix/configuration/flake.lock
index a5eaabe..455a82b 100644
--- a/nix/configuration/flake.lock
+++ b/nix/configuration/flake.lock
@@ -147,26 +147,6 @@
"type": "github"
}
},
- "home-manager": {
- "inputs": {
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1751549056,
- "narHash": "sha256-miKaJ4SFNxhZ/WVDADae2jNd9zka5bV9hKmXspAzvxo=",
- "owner": "nix-community",
- "repo": "home-manager",
- "rev": "1fa73bb2cc39e250eb01e511ae6ac83bfbf9f38c",
- "type": "github"
- },
- "original": {
- "owner": "nix-community",
- "repo": "home-manager",
- "type": "github"
- }
- },
"impermanence": {
"locked": {
"lastModified": 1737831083,
@@ -303,7 +283,6 @@
"inputs": {
"ansible-sshjail": "ansible-sshjail",
"disko": "disko",
- "home-manager": "home-manager",
"impermanence": "impermanence",
"lanzaboote": "lanzaboote",
"nixpkgs": "nixpkgs",
diff --git a/nix/configuration/flake.nix b/nix/configuration/flake.nix
index dec37cf..54b2c84 100644
--- a/nix/configuration/flake.nix
+++ b/nix/configuration/flake.nix
@@ -45,8 +45,6 @@
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs-dda3dcd3f.url = "github:NixOS/nixpkgs/dda3dcd3fe03e991015e9a74b22d35950f264a54";
nixpkgs-unoptimized.url = "github:NixOS/nixpkgs/nixos-unstable";
- home-manager.url = "github:nix-community/home-manager";
- home-manager.inputs.nixpkgs.follows = "nixpkgs";
lanzaboote = {
url = "github:nix-community/lanzaboote/v0.4.2";
@@ -78,7 +76,6 @@
nixpkgs-unoptimized,
nixpkgs-dda3dcd3f,
impermanence,
- home-manager,
lanzaboote,
zsh-histdb,
ansible-sshjail,
@@ -99,13 +96,8 @@
};
modules = [
impermanence.nixosModules.impermanence
- home-manager.nixosModules.home-manager
lanzaboote.nixosModules.lanzaboote
inputs.disko.nixosModules.disko
- {
- home-manager.useGlobalPkgs = true;
- home-manager.useUserPackages = true;
- }
{
nixpkgs.overlays = [
zsh-histdb.overlays.default
diff --git a/nix/configuration/roles/alacritty/default.nix b/nix/configuration/roles/alacritty/default.nix
index e691ad8..e6e85f7 100644
--- a/nix/configuration/roles/alacritty/default.nix
+++ b/nix/configuration/roles/alacritty/default.nix
@@ -24,13 +24,11 @@
xdg-utils # for xdg-open
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/alacritty/alacritty.toml" = {
- source = ./files/alacritty.toml;
- };
+ me.install.user.talexander.file = {
+ ".config/alacritty/alacritty.toml" = {
+ source = ./files/alacritty.toml;
};
+ };
})
]
);
diff --git a/nix/configuration/roles/emacs/default.nix b/nix/configuration/roles/emacs/default.nix
index 4fd70ee..8689db6 100644
--- a/nix/configuration/roles/emacs/default.nix
+++ b/nix/configuration/roles/emacs/default.nix
@@ -141,14 +141,12 @@ in
})
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/emacs" = {
- source = ./files/emacs;
- recursive = true;
- };
+ me.install.user.talexander.file = {
+ ".config/emacs" = {
+ source = ./files/emacs;
+ recursive = true;
};
+ };
})
(lib.mkIf (config.me.emacs_flavor == "plainmacs") {
nixpkgs.overlays = [
diff --git a/nix/configuration/roles/git/default.nix b/nix/configuration/roles/git/default.nix
index 5f0e57d..db65e52 100644
--- a/nix/configuration/roles/git/default.nix
+++ b/nix/configuration/roles/git/default.nix
@@ -36,13 +36,11 @@ in
];
}
(lib.mkIf (config.me.git.config != null) {
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".gitconfig" = {
- source = config.me.git.config;
- };
+ me.install.user.talexander.file = {
+ ".gitconfig" = {
+ source = config.me.git.config;
};
+ };
})
(lib.mkIf (config.me.graphical) {
nixpkgs.overlays = [
diff --git a/nix/configuration/roles/gpg/default.nix b/nix/configuration/roles/gpg/default.nix
index cb8b4b2..eeab4d3 100644
--- a/nix/configuration/roles/gpg/default.nix
+++ b/nix/configuration/roles/gpg/default.nix
@@ -57,14 +57,11 @@ in
# disable-ccid = true;
# };
- # .gnupg/scdaemon.conf
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".gnupg/scdaemon.conf" = {
- source = ./files/scdaemon.conf;
- };
+ me.install.user.talexander.file = {
+ ".gnupg/scdaemon.conf" = {
+ source = ./files/scdaemon.conf;
};
+ };
# programs.gnupg.dirmngr.enable = true;
programs.gnupg.agent = {
diff --git a/nix/configuration/roles/kanshi/default.nix b/nix/configuration/roles/kanshi/default.nix
index b1fdbb9..be886c4 100644
--- a/nix/configuration/roles/kanshi/default.nix
+++ b/nix/configuration/roles/kanshi/default.nix
@@ -41,15 +41,11 @@ in
exec_kanshi
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file = {
- ".config/kanshi/config" = {
- source = ./files/config_kanshi;
- };
- };
+ me.install.user.talexander.file = {
+ ".config/kanshi/config" = {
+ source = ./files/config_kanshi;
};
+ };
})
]
);
diff --git a/nix/configuration/roles/kodi/default.nix b/nix/configuration/roles/kodi/default.nix
index b37bf06..d67e3fd 100644
--- a/nix/configuration/roles/kodi/default.nix
+++ b/nix/configuration/roles/kodi/default.nix
@@ -78,21 +78,13 @@
};
};
- home-manager.users.kodi =
- { pkgs, ... }:
- {
- # home.file.".kodi/userdata/mediasources.xml".source = ./files/mediasources.xml;
+ # home.file.".kodi/userdata/mediasources.xml".source = ./files/mediasources.xml;
- # home.file.".kodi/userdata/addon_data/peripheral.joystick/resources/buttonmaps/xml/linux/DualSense_Wireless_Controller_13b_8a.xml".source =
- # ./files/DualSense_Wireless_Controller_13b_8a.xml;
+ # home.file.".kodi/userdata/addon_data/peripheral.joystick/resources/buttonmaps/xml/linux/DualSense_Wireless_Controller_13b_8a.xml".source =
+ # ./files/DualSense_Wireless_Controller_13b_8a.xml;
- # TODO: Maybe .kodi/userdata/sources.xml
- # TODO: ./userdata/guisettings.xml:303: 128
-
- # The state version is required and should stay at the version you
- # originally installed.
- home.stateVersion = "24.11";
- };
+ # TODO: Maybe .kodi/userdata/sources.xml
+ # TODO: ./userdata/guisettings.xml:303: 128
})
]
);
diff --git a/nix/configuration/roles/media/default.nix b/nix/configuration/roles/media/default.nix
index 7fd4e67..e121fc0 100644
--- a/nix/configuration/roles/media/default.nix
+++ b/nix/configuration/roles/media/default.nix
@@ -52,13 +52,11 @@ in
imv
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/mpv/mpv.conf" = {
- source = ./files/mpv.conf;
- };
+ me.install.user.talexander.file = {
+ ".config/mpv/mpv.conf" = {
+ source = ./files/mpv.conf;
};
+ };
})
(lib.mkIf (config.me.graphics_card_type == "amd" || config.me.graphics_card_type == "intel") {
environment.systemPackages = with pkgs; [
diff --git a/nix/configuration/roles/pcsx2/default.nix b/nix/configuration/roles/pcsx2/default.nix
index 2af42ea..a5866da 100644
--- a/nix/configuration/roles/pcsx2/default.nix
+++ b/nix/configuration/roles/pcsx2/default.nix
@@ -82,13 +82,11 @@
};
};
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/PCSX2/inis/PCSX2.ini" = {
- source = ./files/PCSX2.ini;
- };
+ me.install.user.talexander.file = {
+ ".config/PCSX2/inis/PCSX2.ini" = {
+ source = ./files/PCSX2.ini;
};
+ };
})
]
);
diff --git a/nix/configuration/roles/rpcs3/default.nix b/nix/configuration/roles/rpcs3/default.nix
index 2182cd3..7d2d074 100644
--- a/nix/configuration/roles/rpcs3/default.nix
+++ b/nix/configuration/roles/rpcs3/default.nix
@@ -70,28 +70,26 @@ in
}
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/rpcs3/config.yml" = lib.mkIf (config.me.rpcs3.config != null) {
- source = rpcs3_config_yaml;
- };
- home.file.".config/rpcs3/GuiConfigs/CurrentSettings.ini" = {
- source = ./files/CurrentSettings.ini;
- };
- home.file.".config/rpcs3/custom_configs/config_BLUS30443.yml" = {
- # Demon's Souls per-game config.
- source = ./files/config_BLUS30443.yml;
- };
- home.file.".config/rpcs3/patches/patch.yml" = {
- # All of the available patches.
- source = ./files/patch.yml;
- };
- home.file.".config/rpcs3/patch_config.yml" = {
- # Patches that I have enabled.
- source = ./files/patch_config.yml;
- };
+ me.install.user.talexander.file = {
+ ".config/rpcs3/config.yml" = lib.mkIf (config.me.rpcs3.config != null) {
+ source = rpcs3_config_yaml;
};
+ ".config/rpcs3/GuiConfigs/CurrentSettings.ini" = {
+ source = ./files/CurrentSettings.ini;
+ };
+ ".config/rpcs3/custom_configs/config_BLUS30443.yml" = {
+ # Demon's Souls per-game config.
+ source = ./files/config_BLUS30443.yml;
+ };
+ ".config/rpcs3/patches/patch.yml" = {
+ # All of the available patches.
+ source = ./files/patch.yml;
+ };
+ ".config/rpcs3/patch_config.yml" = {
+ # Patches that I have enabled.
+ source = ./files/patch_config.yml;
+ };
+ };
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
diff --git a/nix/configuration/roles/rust/default.nix b/nix/configuration/roles/rust/default.nix
index 8482484..4ac6cb2 100644
--- a/nix/configuration/roles/rust/default.nix
+++ b/nix/configuration/roles/rust/default.nix
@@ -48,18 +48,14 @@ in
# ? cargo-public-api
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file = {
- ".cargo/config.toml" = {
- source = ./files/cargo_config.toml;
- };
- ".rustup/settings.toml" = {
- source = ./files/rustup_settings.toml;
- };
- };
+ me.install.user.talexander.file = {
+ ".cargo/config.toml" = {
+ source = ./files/cargo_config.toml;
};
+ ".rustup/settings.toml" = {
+ source = ./files/rustup_settings.toml;
+ };
+ };
environment.persistence."/state" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
diff --git a/nix/configuration/roles/shadps4/default.nix b/nix/configuration/roles/shadps4/default.nix
index 8615466..08bc049 100644
--- a/nix/configuration/roles/shadps4/default.nix
+++ b/nix/configuration/roles/shadps4/default.nix
@@ -24,13 +24,11 @@
shadps4
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".local/share/shadPS4/config.toml" = {
- source = ./files/config.toml;
- };
+ me.install.user.talexander.file = {
+ ".local/share/shadPS4/config.toml" = {
+ source = ./files/config.toml;
};
+ };
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
diff --git a/nix/configuration/roles/shikane/default.nix b/nix/configuration/roles/shikane/default.nix
index 728bb4f..1d79348 100644
--- a/nix/configuration/roles/shikane/default.nix
+++ b/nix/configuration/roles/shikane/default.nix
@@ -36,15 +36,11 @@ in
exec_shikane
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file = {
- ".config/shikane/config.toml" = {
- source = ./files/config.toml;
- };
- };
+ me.install.user.talexander.file = {
+ ".config/shikane/config.toml" = {
+ source = ./files/config.toml;
};
+ };
})
]
);
diff --git a/nix/configuration/roles/ssh/default.nix b/nix/configuration/roles/ssh/default.nix
index f4c1d8b..3c7dc68 100644
--- a/nix/configuration/roles/ssh/default.nix
+++ b/nix/configuration/roles/ssh/default.nix
@@ -27,19 +27,14 @@
};
};
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".ssh/config" = {
- source = ./files/ssh_config;
- };
+ me.install.user.root.file = {
+ ".ssh/config" = {
+ source = ./files/ssh_config_root;
};
-
- home-manager.users.root =
- { pkgs, ... }:
- {
- home.file.".ssh/config" = {
- source = ./files/ssh_config_root;
- };
+ };
+ me.install.user.talexander.file = {
+ ".ssh/config" = {
+ source = ./files/ssh_config;
};
+ };
}
diff --git a/nix/configuration/roles/sway/default.nix b/nix/configuration/roles/sway/default.nix
index 6100cab..04a636a 100644
--- a/nix/configuration/roles/sway/default.nix
+++ b/nix/configuration/roles/sway/default.nix
@@ -376,26 +376,18 @@ in
};
};
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file = {
- # Configure default programs (for example, default browser)
- ".config/mimeapps.list" = {
- source = ./files/mimeapps.list;
- };
- };
- home.file = {
- ".config/gtk-3.0/settings.ini" = {
- source = ./files/settings.ini;
- };
- };
- home.file = {
- ".icons/default" = {
- source = "${pkgs.adwaita-icon-theme}/share/icons/Adwaita";
- };
- };
+ me.install.user.talexander.file = {
+ ".config/mimeapps.list" = {
+ # Configure default programs (for example, default browser)
+ source = ./files/mimeapps.list;
};
+ ".config/gtk-3.0/settings.ini" = {
+ source = ./files/settings.ini;
+ };
+ ".icons/default" = {
+ source = "${pkgs.adwaita-icon-theme}/share/icons/Adwaita";
+ };
+ };
# For mounting drives in pcmanfm
services.gvfs.enable = true;
diff --git a/nix/configuration/roles/vscode/default.nix b/nix/configuration/roles/vscode/default.nix
index af50003..b37b0e0 100644
--- a/nix/configuration/roles/vscode/default.nix
+++ b/nix/configuration/roles/vscode/default.nix
@@ -48,16 +48,14 @@
})
];
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".config/Code/User/settings.json" = {
- source = ./files/settings.json;
- };
- home.file.".config/Code/User/keybindings.json" = {
- source = ./files/keybindings.json;
- };
+ me.install.user.talexander.file = {
+ ".config/Code/User/settings.json" = {
+ source = ./files/settings.json;
};
+ ".config/Code/User/keybindings.json" = {
+ source = ./files/keybindings.json;
+ };
+ };
})
]
);
diff --git a/nix/configuration/roles/waybar/default.nix b/nix/configuration/roles/waybar/default.nix
index ea03b4f..b2ef5d3 100644
--- a/nix/configuration/roles/waybar/default.nix
+++ b/nix/configuration/roles/waybar/default.nix
@@ -113,18 +113,14 @@ in
services.upower.enable = true; # for battery
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file = {
- ".config/waybar/config" = {
- source = ./files/waybar_config.json;
- };
- ".config/waybar/style.css" = {
- source = ./files/style.css;
- };
- };
+ me.install.user.talexander.file = {
+ ".config/waybar/config" = {
+ source = ./files/waybar_config.json;
};
+ ".config/waybar/style.css" = {
+ source = ./files/style.css;
+ };
+ };
})
]
);
diff --git a/nix/configuration/roles/zsh/default.nix b/nix/configuration/roles/zsh/default.nix
index 518fdda..2a4fdfe 100644
--- a/nix/configuration/roles/zsh/default.nix
+++ b/nix/configuration/roles/zsh/default.nix
@@ -90,13 +90,11 @@ in
enable = true;
};
- home-manager.users.talexander =
- { pkgs, ... }:
- {
- home.file.".zshrc" = {
- source = "${zshrc}";
- };
+ me.install.user.talexander.file = {
+ ".zshrc" = {
+ source = "${zshrc}";
};
+ };
environment.persistence."/persist" = lib.mkIf (!config.me.buildingIso) {
hideMounts = true;
diff --git a/nix/configuration/util/install_files/default.nix b/nix/configuration/util/install_files/default.nix
new file mode 100644
index 0000000..7be496d
--- /dev/null
+++ b/nix/configuration/util/install_files/default.nix
@@ -0,0 +1,333 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+
+let
+ cfg = config.me.install;
+ inherit (lib)
+ filter
+ attrNames
+ ;
+
+ get_shell_values =
+ target:
+ let
+ homedir = config.users.users."${target.username}".home;
+ group = config.users.users."${target.username}".group;
+ in
+ {
+ source = lib.strings.escapeShellArg "${target.source}";
+ destination = lib.strings.escapeShellArg "${homedir}/${target.target}";
+ mode = lib.strings.escapeShellArg "${target.mode}";
+ dir_mode = lib.strings.escapeShellArg "${target.dir_mode}";
+ username = lib.strings.escapeShellArg "${target.username}";
+ group = lib.strings.escapeShellArg "${group}";
+ };
+ install_user_file =
+ let
+ constructors = {
+ "overwrite" = install_user_file_overwrite;
+ "symlink" = install_user_file_symlink;
+ };
+ in
+ stage: target: (constructors."${target.method}"."${stage}" target);
+ install_user_file_overwrite = {
+ "check" = (target: "");
+ "install" = (
+ target:
+ let
+ inherit (get_shell_values target)
+ source
+ destination
+ mode
+ dir_mode
+ username
+ group
+ ;
+ flags = lib.strings.concatStringsSep " " [
+ (if mode != "" then "-m ${mode}" else "")
+ (if username != "" then "-o ${username}" else "")
+ (if group != "" then "-g ${group}" else "")
+ ];
+ dir_flags = lib.strings.concatStringsSep " " [
+ (if dir_mode != "" then "-m ${dir_mode}" else "")
+ (if username != "" then "-o ${username}" else "")
+ (if group != "" then "-g ${group}" else "")
+ ];
+ in
+ if target.recursive then
+ [
+ ''
+ find ${source} -type f -print0 | while read -r -d "" file; do
+ relative_path=$(realpath -s --relative-to ${source} "$file")
+ full_dest=${destination}/"$relative_path"
+ create_containing_directories "$full_dest" ${dir_flags}
+ $DRY_RUN_CMD install $VERBOSE_ARG --compare ${flags} "$file" "$full_dest"
+ done
+ ''
+ ]
+ else
+ [
+ ''
+ create_containing_directories ${destination} ${dir_flags}
+ $DRY_RUN_CMD install $VERBOSE_ARG --compare ${flags} ${source} ${destination}
+ ''
+ ]
+ );
+ "uninstall" = (
+ target:
+ let
+ inherit (get_shell_values target)
+ source
+ destination
+ ;
+ in
+ if target.recursive then
+ [
+ ''
+ find ${source} -type f -print0 | while read -r -d "" file; do
+ relative_path=$(realpath -s --relative-to ${source} "$file")
+ full_dest=${destination}/"$relative_path"
+ $DRY_RUN_CMD echo rm -f "$full_dest"
+ done
+ ''
+ ]
+ else
+ [
+ ''
+ $DRY_RUN_CMD echo rm -f ${destination}
+ ''
+ ]
+ );
+ };
+ install_user_file_symlink = {
+ "check" = (target: "");
+ "install" = (
+ target:
+ let
+ inherit (get_shell_values target)
+ source
+ destination
+ mode
+ dir_mode
+ username
+ group
+ ;
+ owner = lib.strings.concatStringsSep ":" (
+ filter (val: val != "") [
+ username
+ group
+ ]
+ );
+ dir_flags = lib.strings.concatStringsSep " " [
+ (if dir_mode != "" then "-m ${dir_mode}" else "")
+ (if username != "" then "-o ${username}" else "")
+ (if group != "" then "-g ${group}" else "")
+ ];
+ in
+ if target.recursive then
+ [
+ ''
+ find ${source} -type f -print0 | while read -r -d "" file; do
+ relative_path=$(realpath -s --relative-to ${source} "$file")
+ full_dest=${destination}/"$relative_path"
+ create_containing_directories "$full_dest" ${dir_flags}
+ $DRY_RUN_CMD ln $VERBOSE_ARG -s "$file" "$full_dest"
+ $DRY_RUN_CMD chown $VERBOSE_ARG -h ${owner} "$full_dest"
+ done
+ ''
+ ]
+ else
+ [
+ ''
+ create_containing_directories ${destination} ${dir_flags}
+ $DRY_RUN_CMD ln $VERBOSE_ARG -s ${source} ${destination}
+ $DRY_RUN_CMD chown $VERBOSE_ARG -h ${owner} ${destination}
+ ''
+ ]
+ );
+ "uninstall" = (
+ target:
+ let
+ inherit (get_shell_values target)
+ source
+ destination
+ ;
+ in
+ if target.recursive then
+ [
+ ''
+ find ${source} -type f -print0 | while read -r -d "" file; do
+ relative_path=$(realpath -s --relative-to ${source} "$file")
+ full_dest=${destination}/"$relative_path"
+ $DRY_RUN_CMD echo rm -f "$full_dest"
+ done
+ ''
+ ]
+ else
+ [
+ ''
+ $DRY_RUN_CMD echo rm -f ${destination}
+ ''
+ ]
+ );
+ };
+in
+{
+ imports = [ ];
+
+ options.me.install = {
+ user = lib.mkOption {
+ type = lib.types.attrsOf (
+ lib.types.submodule (
+ { name, config, ... }:
+ let
+ username = name;
+ in
+ {
+ options = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = true;
+ defaultText = "enable";
+ example = lib.literalExpression false;
+ description = "Whether we want to install files in this user's home directory.";
+ };
+
+ file = lib.mkOption {
+ type = lib.types.attrsOf (
+ lib.types.submodule (
+ { name, config, ... }:
+ let
+ path = name;
+ in
+ {
+ options = {
+ enable = lib.mkOption {
+ type = lib.types.bool;
+ default = true;
+ defaultText = "enable";
+ example = lib.literalExpression false;
+ description = "Whether we want to install this file in this user's home directory.";
+ };
+ username = lib.mkOption {
+ type = lib.types.str;
+ defaultText = "username";
+ example = "root";
+ description = "The username for the user whose home directory will contain the file.";
+ };
+ target = lib.mkOption {
+ type = lib.types.str;
+ defaultText = "target";
+ example = ".local/share/foo/bar.txt";
+ description = "The path where the file should be written.";
+ };
+ method = lib.mkOption {
+ type = lib.types.enum [
+ "symlink"
+ "overwrite"
+ # "bind_mount" TODO: for directories?
+ ];
+ default = "symlink";
+ defaultText = "me.install.file.‹path›.method";
+ example = "overwrite";
+ description = "The way in which the file should be installed.";
+ };
+ mode = lib.mkOption {
+ type = lib.types.str;
+ default = "0444";
+ defaultText = "me.install.file.‹path›.mode";
+ example = "0750";
+ description = "The read, write, execute permission flags.";
+ };
+ dir_mode = lib.mkOption {
+ type = lib.types.str;
+ default = "0755";
+ defaultText = "dir_mode";
+ example = "0755";
+ description = "The read, write, execute permission flags for any parent directories that need to be created.";
+ };
+ source = lib.mkOption {
+ type = lib.types.path;
+ defaultText = "me.install.file.‹path›.source";
+ example = ./files/foo.txt;
+ description = "The source file to install into the destination.";
+ };
+ recursive = lib.mkOption {
+ type = lib.types.bool;
+ default = false;
+ defaultText = "recursive";
+ example = lib.literalExpression false;
+ description = "Whether we want to recurse through the directory doing individual installs for each file.";
+ };
+ };
+
+ config = {
+ username = lib.mkDefault username;
+ target = lib.mkDefault path;
+ };
+ }
+ )
+ );
+ };
+ };
+ }
+ )
+ );
+ };
+ };
+
+ config =
+ let
+ all_users = builtins.map (username: cfg.user."${username}") (attrNames cfg.user);
+ enabled_users = filter (user: user.enable) all_users;
+ all_file_targets = lib.flatten (
+ builtins.map (user: (builtins.map (path: user.file."${path}") (attrNames user.file))) enabled_users
+ );
+ enabled_file_targets = filter (target: target.enable) all_file_targets;
+ check_commands = lib.flatten (builtins.map (install_user_file "check") enabled_file_targets);
+ install_commands = lib.flatten (builtins.map (install_user_file "install") enabled_file_targets);
+ uninstall_commands = lib.flatten (
+ builtins.map (install_user_file "uninstall") enabled_file_targets
+ );
+ in
+ {
+ systemd.services.me-install-file = {
+ enable = true;
+ description = "me-install-file";
+ wantedBy = [ "multi-user.target" ];
+ wants = [ "multi-user.target" ];
+ before = [ "multi-user.target" ];
+ # path = with pkgs; [
+ # zfs
+ # ];
+ unitConfig.DefaultDependencies = "no";
+ serviceConfig = {
+ Type = "oneshot";
+ RemainAfterExit = "yes";
+ };
+ script =
+ ''
+ set -o pipefail
+ IFS=$'\n\t'
+ source ${./files/lib.bash}
+ ''
+ + (lib.strings.concatStringsSep "\n" (
+ [
+ ]
+ ++ check_commands
+ ++ install_commands
+ ));
+ preStop =
+ ''
+ set -o pipefail
+ IFS=$'\n\t'
+ source ${./files/lib.bash}
+ ''
+ + (lib.strings.concatStringsSep "\n" uninstall_commands);
+ };
+ };
+}
diff --git a/nix/configuration/util/install_files/files/lib.bash b/nix/configuration/util/install_files/files/lib.bash
new file mode 100644
index 0000000..1a5c178
--- /dev/null
+++ b/nix/configuration/util/install_files/files/lib.bash
@@ -0,0 +1,38 @@
+#!/usr/bin/env bash
+#
+
+############## Setup #########################
+
+function die {
+ local status_code="$1"
+ shift
+ (>&2 echo "${@}")
+ exit "$status_code"
+}
+
+function log {
+ (>&2 echo "${@}")
+}
+
+############## Program #########################
+
+function create_containing_directories {
+ local full_dest="$1"
+ shift 1
+ local dirs_to_create=()
+ local containing_directory="$full_dest"
+ while true; do
+ containing_directory=$(dirname "$containing_directory")
+ if [ -e "$containing_directory" ] || [ "$containing_directory" = "/" ]; then
+ break
+ fi
+ dirs_to_create+=($containing_directory)
+ done
+
+ for (( idx=${#dirs_to_create[@]}-1 ; idx>=0 ; idx-- )) ; do
+ local containing_directory="${dirs_to_create[idx]}"
+ log "Creating $containing_directory"
+ $DRY_RUN_CMD install $VERBOSE_ARG -d "${@}" "$containing_directory"
+ done
+
+}