mirror of
https://github.com/foo-dogsquared/website.git
synced 2025-01-31 01:57:54 +00:00
Publish "Managing mutable files in NixOS"
This commit is contained in:
parent
5503468032
commit
5b71e2c48b
@ -0,0 +1,33 @@
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.home.mutableFiles;
|
||||
file = { config, name, ... }: {
|
||||
};
|
||||
in
|
||||
{
|
||||
options.home.mutableFile = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule file);
|
||||
default = { };
|
||||
description = lib.mkDoc ''
|
||||
An attribute set of mutable files and directories to be fetched into the home
|
||||
directory.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
"''${config.xdg.userDirs.documents}/dotfiles" = {
|
||||
url = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
type = "git";
|
||||
};
|
||||
|
||||
"''${config.xdg.userDirs.documents}/top-secret" = {
|
||||
url = "https://example.com/file.zip";
|
||||
type = "fetch";
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.user.services.fetch-mutable-files = {
|
||||
};
|
||||
};
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
{ config, options, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.home.mutableFiles;
|
||||
file = baseDir: { config, name, ... }: {
|
||||
options = {
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = lib.mkDoc ''
|
||||
The URL of the file to be fetched.
|
||||
'';
|
||||
example = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
};
|
||||
|
||||
path = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
description = lib.mkDoc ''
|
||||
Output path of the resource relative to ${baseDir}.
|
||||
'';
|
||||
default = name;
|
||||
apply = p:
|
||||
if lib.hasPrefix "/" p then p else "${baseDir}/${p}";
|
||||
};
|
||||
|
||||
type = lib.mkOption {
|
||||
type = lib.types.enum [ "git" "fetch" ];
|
||||
description = lib.mkDoc ''
|
||||
Type that configures the behavior for fetching the URL.
|
||||
|
||||
This accept only certain keywords.
|
||||
|
||||
- For `fetch`, the file will be fetched with `curl`.
|
||||
- For `git`, it will be fetched with `git clone`.
|
||||
|
||||
The default type is `fetch`.
|
||||
'';
|
||||
default = "fetch";
|
||||
example = "git";
|
||||
};
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.home.mutableFile = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule (file config.home.homeDirectory));
|
||||
default = { };
|
||||
description = lib.mkDoc ''
|
||||
An attribute set of mutable files and directories to be fetched into the
|
||||
home directory.
|
||||
'';
|
||||
example = lib.literalExpression ''
|
||||
"''${config.xdg.userDirs.documents}/dotfiles" = {
|
||||
url = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
type = "git";
|
||||
};
|
||||
|
||||
"''${config.xdg.userDirs.documents}/top-secret" = {
|
||||
url = "https://example.com/file.zip";
|
||||
type = "fetch";
|
||||
};
|
||||
'';
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.user.services.fetch-mutable-files = {
|
||||
Unit = {
|
||||
Description = "Fetch mutable files from home-manager";
|
||||
After = [ "default.target" "network-online.target" ];
|
||||
Wants = [ "network-online.target" ];
|
||||
};
|
||||
|
||||
Service = {
|
||||
# We'll assume this service will download lots of files. We want the
|
||||
# temporary files to only last along with the service.
|
||||
PrivateUsers = true;
|
||||
PrivateTmp = true;
|
||||
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
ExecStart = let
|
||||
curl = "${lib.getBin pkgs.curl}/bin/curl";
|
||||
git = "${lib.getBin pkgs.curl}/bin/git";
|
||||
fetchCmds = lib.mapAttrsToList (file: value:
|
||||
let
|
||||
inherit (value) type;
|
||||
path = lib.escapeShellArg value.path;
|
||||
url = lib.escapeURL value.url;
|
||||
in ''
|
||||
${lib.optionalString (type == "git") "[ -d ${path} ] || ${git} clone ${url} ${path}"}
|
||||
${lib.optionalString (type == "fetch") "[ -d ${path} ] || ${curl} ${url} --output ${path}"}
|
||||
'') cfg;
|
||||
shellScript = pkgs.writeShellScript "fetch-mutable-files" ''
|
||||
${lib.concatStringsSep "\n" fetchCmds}
|
||||
'';
|
||||
in builtins.toString shellScript;
|
||||
};
|
||||
|
||||
Install.WantedBy = [ "default.target" ];
|
||||
};
|
||||
};
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
dotfiles = config.lib.file.mkOutOfStoreSymlink "/home/foo-dogsquared/dotfiles";
|
||||
in
|
||||
{
|
||||
# Putting the dotfiles in their rightful place.
|
||||
xdg.configFile = {
|
||||
doom.source = "${dotfiles}/emacs";
|
||||
wezterm.source = "${dotfiles}/wezterm";
|
||||
nvim.source = "${dotfiles}/nvim";
|
||||
};
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
diff --git a/modules/home-manager/fetch-mutable-files.nix b/modules/home-manager/fetch-mutable-files.nix
|
||||
new file mode 100644
|
||||
index 0000000..9c66e05
|
||||
--- /dev/null
|
||||
+++ b/modules/home-manager/fetch-mutable-files.nix
|
||||
@@ -0,0 +1,33 @@
|
||||
+{ config, options, lib, pkgs, ... }:
|
||||
+
|
||||
+let
|
||||
+ cfg = config.home.mutableFiles;
|
||||
+ file = { config, name, ... }: {
|
||||
+ };
|
||||
+in
|
||||
+{
|
||||
+ options.home.mutableFile = lib.mkOption {
|
||||
+ type = with lib.types; attrsOf (submodule file);
|
||||
+ default = { };
|
||||
+ description = lib.mkDoc ''
|
||||
+ An attribute set of mutable files and directories to be fetched into the
|
||||
+ home directory.
|
||||
+ '';
|
||||
+ example = lib.literalExpression ''
|
||||
+ "''${config.xdg.userDirs.documents}/dotfiles" = {
|
||||
+ url = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
+ type = "git";
|
||||
+ };
|
||||
+
|
||||
+ "''${config.xdg.userDirs.documents}/top-secret" = {
|
||||
+ url = "https://example.com/file.zip";
|
||||
+ type = "fetch";
|
||||
+ };
|
||||
+ '';
|
||||
+ };
|
||||
+
|
||||
+ config = {
|
||||
+ systemd.user.services.fetch-mutable-files = {
|
||||
+ };
|
||||
+ };
|
||||
+}
|
@ -0,0 +1,54 @@
|
||||
diff --git a/modules/home-manager/fetch-mutable-files.nix b/modules/home-manager/fetch-mutable-files.nix
|
||||
index 9c66e05..aa00cac 100644
|
||||
--- a/modules/home-manager/fetch-mutable-files.nix
|
||||
+++ b/modules/home-manager/fetch-mutable-files.nix
|
||||
@@ -2,12 +2,47 @@
|
||||
|
||||
let
|
||||
cfg = config.home.mutableFiles;
|
||||
- file = { config, name, ... }: {
|
||||
+ file = baseDir: { config, name, ... }: {
|
||||
+ options = {
|
||||
+ url = lib.mkOption {
|
||||
+ type = lib.types.str;
|
||||
+ description = lib.mkDoc ''
|
||||
+ The URL of the file to be fetched.
|
||||
+ '';
|
||||
+ example = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
+ };
|
||||
+
|
||||
+ path = lib.mkOption {
|
||||
+ type = lib.types.str;
|
||||
+ description = lib.mkDoc ''
|
||||
+ Output path of the resource relative to ${baseDir}.
|
||||
+ '';
|
||||
+ default = name;
|
||||
+ apply = p:
|
||||
+ if lib.hasPrefix "/" p then p else "${baseDir}/${p}";
|
||||
+ };
|
||||
+
|
||||
+ type = lib.mkOption {
|
||||
+ type = lib.types.enum [ "git" "fetch" ];
|
||||
+ description = lib.mkDoc ''
|
||||
+ Type that configures the behavior for fetching the URL.
|
||||
+
|
||||
+ This accept only certain keywords.
|
||||
+
|
||||
+ - For `fetch`, the file will be fetched with `curl`.
|
||||
+ - For `git`, it will be fetched with `git clone`.
|
||||
+
|
||||
+ The default type is `fetch`.
|
||||
+ '';
|
||||
+ default = "fetch";
|
||||
+ example = "git";
|
||||
+ };
|
||||
+ };
|
||||
};
|
||||
in
|
||||
{
|
||||
options.home.mutableFile = lib.mkOption {
|
||||
- type = with lib.types; attrsOf (submodule file);
|
||||
+ type = with lib.types; attrsOf (submodule (file config.home.homeDirectory));
|
||||
default = { };
|
||||
description = lib.mkDoc ''
|
||||
An attribute set of mutable files and directories to be fetched into the
|
@ -0,0 +1,30 @@
|
||||
diff --git a/modules/home-manager/fetch-mutable-files.nix b/modules/home-manager/fetch-mutable-files.nix
|
||||
index aa00cac..3d75414 100644
|
||||
--- a/modules/home-manager/fetch-mutable-files.nix
|
||||
+++ b/modules/home-manager/fetch-mutable-files.nix
|
||||
@@ -63,6 +63,25 @@ in
|
||||
|
||||
config = {
|
||||
systemd.user.services.fetch-mutable-files = {
|
||||
+ Unit = {
|
||||
+ Description = "Fetch mutable files from home-manager";
|
||||
+ After = [ "default.target" "network-online.target" ];
|
||||
+ Wants = [ "network-online.target" ];
|
||||
+ };
|
||||
+
|
||||
+ Service = {
|
||||
+ # We'll assume this service will download lots of files. We want the
|
||||
+ # temporary files to only last along with the service.
|
||||
+ PrivateUsers = true;
|
||||
+ PrivateTmp = true;
|
||||
+
|
||||
+ Type = "oneshot";
|
||||
+ RemainAfterExit = true;
|
||||
+ # TODO: Complete this
|
||||
+ ExecStart = "";
|
||||
+ };
|
||||
+
|
||||
+ Install.WantedBy = [ "default.target" ];
|
||||
};
|
||||
};
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
diff --git a/modules/home-manager/fetch-mutable-files.nix b/modules/home-manager/fetch-mutable-files.nix
|
||||
index 3d75414..c3e349b 100644
|
||||
--- a/modules/home-manager/fetch-mutable-files.nix
|
||||
+++ b/modules/home-manager/fetch-mutable-files.nix
|
||||
@@ -77,8 +77,22 @@ in
|
||||
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
- # TODO: Complete this
|
||||
- ExecStart = "";
|
||||
+ ExecStart = let
|
||||
+ curl = "${lib.getBin pkgs.curl}/bin/curl";
|
||||
+ git = "${lib.getBin pkgs.curl}/bin/git";
|
||||
+ fetchCmds = lib.mapAttrsToList (file: value:
|
||||
+ let
|
||||
+ inherit (value) type;
|
||||
+ path = lib.escapeShellArg value.path;
|
||||
+ url = lib.escapeURL value.url;
|
||||
+ in ''
|
||||
+ ${lib.optionalString (type == "git") "[ -d ${path} ] || ${git} clone ${url} ${path}"}
|
||||
+ ${lib.optionalString (type == "fetch") "[ -d ${path} ] || ${curl} ${url} --output ${path}"}
|
||||
+ '') cfg;
|
||||
+ shellScript = pkgs.writeShellScript "fetch-mutable-files" ''
|
||||
+ ${lib.concatStringsSep "\n" fetchCmds}
|
||||
+ '';
|
||||
+ in builtins.toString shellScript;
|
||||
};
|
||||
|
||||
Install.WantedBy = [ "default.target" ];
|
@ -0,0 +1,13 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
path = lib.escapeShellArg "/etc/dotfiles";
|
||||
dotfiles = pkgs.runCommandLocal "nixos-mutable-file-${builtins.baseNameOf path}" { } ''ln -s ${path} $out'';
|
||||
in
|
||||
{
|
||||
enviroment.etc = {
|
||||
"i3".source = "${dotfiles}/i3";
|
||||
"polybar".source = "${dotfiles}/polybar";
|
||||
"zathurarc".source = "${dotfiles}/zathura/zathurarc";
|
||||
};
|
||||
}
|
@ -0,0 +1,316 @@
|
||||
---
|
||||
title: "Managing mutable files in NixOS"
|
||||
date: 2023-03-24T00:00:00+00:00
|
||||
---
|
||||
|
||||
= Managing mutable files in NixOS
|
||||
Gabriel Arazas <foodogsquared@foodogsquared.one>
|
||||
2023-03-24
|
||||
|
||||
:home-manager-rev: bb4b25b302dbf0f527f190461b080b5262871756
|
||||
:nix-flakes-post: ../2023-03-05-combining-traditional-dotfiles-and-nixos-configurations-with-nix-flakes/index.adoc
|
||||
|
||||
|
||||
Some weeks ago, xref:{nix-flakes-post}[I've made a post describing how to combine traditional dotfiles and NixOS config with Nix flakes].
|
||||
That seems all well and good but it comes with a few problems.
|
||||
|
||||
* Changes from the dotfiles have to be pushed first to the remote repo.
|
||||
|
||||
* Then, the dotfile flake input have to be updated.
|
||||
After pushing changes from the dotfiles, you have to update it as depicted from xref:{nix-flakes-post}#workflows-and-its-caveats[Workflows and its caveats].
|
||||
While managing with flakes is less tedious than managing it with fetchers, you're essentially just reducing the source of updates from two to one.
|
||||
|
||||
While it is reproducible, it's a tedious process especially if you need immediate changes from your dotfiles.
|
||||
|
||||
One of the responses I got from the aforementioned post is link:https://www.reddit.com/r/NixOS/comments/11kme1n/comment/jb80qgy[an alternative solution for managing dotfiles] by mtndewforbreakfast.
|
||||
|
||||
[quote]
|
||||
I'm more likely to use home-manager's link:https://github.com/nix-community/home-manager/blob/bb4b25b302dbf0f527f190461b080b5262871756/modules/files.nix#L64[mkOutOfStoreSymlink] if I find myself in situations where I need non-generational or mutable file content.
|
||||
I have a trivial personal HM module that git-clones things to a desired path as part of the activation script if they're absent and then manage them out of band from then on.
|
||||
|
||||
Long story short, I tried this approach and I found it to be a better solution overall.
|
||||
It is more flexible and lends itself as a great solution for managing mutable files — files that are not meant to be managed by Nix.
|
||||
This also reduces the things I need to do post-installation which is already contained in a script so that's a nice benefit.
|
||||
Anyways, here's my take on the posted solution.
|
||||
|
||||
|
||||
|
||||
|
||||
[#a-better-way-to-manage-traditional-dotfiles-in-home-manager]
|
||||
== A better way to manage traditional dotfiles in home-manager
|
||||
|
||||
As hinted from the quoted statement, github:nix-community/home-manager[`mkOutOfStoreSymlink`, rev={home-manager-rev}, path=modules/files.nix] is a home-manager function that accepts a path string and returns a derivation.
|
||||
This derivation contains a builder script that links the given path to a store path.
|
||||
|
||||
Using it should be simple.
|
||||
The following listing simply links my dotfiles located on `/home/foo-dogsquared/dotfiles` and creates a path on the Nix store.
|
||||
|
||||
.An example of using the function
|
||||
[source, nix]
|
||||
----
|
||||
mkOutOfStoreSymlink "/home/foo-dogsquared/dotfiles"
|
||||
----
|
||||
|
||||
This pretty much allows us to interact with various options from home-manager that normally accepts a link:https://nixos.org/manual/nix/stable/glossary.html#gloss-store-path[store path].
|
||||
In my case, I mainly use it for linking various files with `home.file.<name>.source`, `xdg.configFile.<name>.source`, and so forth.
|
||||
To give some more context, here's an example usage of the function with my use case.
|
||||
|
||||
[#lst:dotfiles-mkoutofstoresymlink]
|
||||
.`home.nix`, this time with `mkOutOfStoreSymlink` instead of flakes
|
||||
[source, nix]
|
||||
----
|
||||
include::./assets/mkoutofstoresymlink.nix[]
|
||||
----
|
||||
|
||||
[#sidebar:what-is-dotfiles-yet-again]
|
||||
.What is `dotfiles` yet again?
|
||||
****
|
||||
Just to continue the tradition from the last post, `dotfiles` is now a derivation from `mkOutOfStoreSymlink`.
|
||||
The very same type as xref:{nix-flakes-post}#sidebar:what-is-dotfiles-this-time[to what `fetchFromGitHub` returns].
|
||||
Since it is a derivation, it will evaluate to the output path if coerced into a string which should be a store path that is symlinked to the dotfiles.
|
||||
This is why the code works still unchanged for the most part.
|
||||
****
|
||||
|
||||
Compared to the approach of making the dotfiles as a flake input, this reduces the reproducibility of our home-manager configuration a little bit.
|
||||
Instead of fully including the dotfiles, we only assume we have the dotfiles at the given location.
|
||||
However, this does remove the xref:{nix-flakes-post}#workflow-and-its-caveats[workflow of managing the flake input and its caveats] altogether.
|
||||
|
||||
You don't have to do `nix flake update` or anything else in your NixOS config and manage them separately.
|
||||
We're compromising reproducibility with this but it is worth it considering I want the changes immediately.
|
||||
|
||||
|
||||
|
||||
|
||||
[#adding-a-declarative-interface-for-fetching-mutable-files]
|
||||
== Adding a declarative interface for fetching mutable files
|
||||
|
||||
Take note with the above method, we did reduce from fully including the dotfiles to only assuming we have the dotfiles.
|
||||
I still want to include the dotfiles declared somewhere in the configuration.
|
||||
The closest we'll ever get is to create a module that accepts a list of files to download and put it in the filesystem which is exactly what I did.
|
||||
Anyhoo, here's how I would use the imaginary module.
|
||||
|
||||
[#lst:fetch-mutable-files-module-use-case]
|
||||
[source, nix]
|
||||
----
|
||||
{
|
||||
home.mutableFile = {
|
||||
"${config.xdg.userDirs.documents}/dotfiles" = {
|
||||
url = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
type = "git";
|
||||
};
|
||||
|
||||
"${config.xdg.userDirs.documents}/top-secret" = {
|
||||
url = "https://example.com/file.zip";
|
||||
type = "fetch";
|
||||
};
|
||||
};
|
||||
}
|
||||
----
|
||||
|
||||
This module is meant to be used for fetching mutable files.
|
||||
It would have different methods for fetching the file indicated by the `type` attribute.
|
||||
For the initial version of this module, we'll consider two use cases: cloning the Git repos and downloading the file.
|
||||
Let's first create the skeleton for the module.
|
||||
|
||||
.`modules/home-manager/fetch-mutable-files.nix`
|
||||
[source, nix]
|
||||
----
|
||||
include::./assets/fetch-mutable-files-skeleton.nix[]
|
||||
----
|
||||
|
||||
We have yet to define certain parts including what each attribute could contain.
|
||||
Each of the attribute in the `home.mutableFile.<name>` expects at least two attributes: the URL to be downloaded and the download method.
|
||||
The file should only be downloaded if the path doesn't exist.
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
At this point, updates to the code are shown as diffs.
|
||||
It is meant to be used with `git apply` and similar tools.
|
||||
|
||||
[source, shell]
|
||||
----
|
||||
git apply file.patch
|
||||
----
|
||||
====
|
||||
|
||||
[source, patch]
|
||||
----
|
||||
include::./assets/patches/0002-fetch-mutable-files-add-file-submodule.patch[]
|
||||
----
|
||||
|
||||
Take note we also added the `path` attribute that comes with a function to handle the path.
|
||||
It's for cleanly passing absolute paths and relative paths when it needs to.
|
||||
|
||||
[source, nix]
|
||||
----
|
||||
{
|
||||
# Absolute paths should be acceptable.
|
||||
home.mutableFile."${config.xdg.userDirs.documents}/top-secret" = { };
|
||||
home.mutableFile."${config.xdg.configHome}/doom" = { };
|
||||
home.mutableFile."${config.home.homeDirectory}/hello" = { };
|
||||
home.mutableFile."/home/foo-dogsquared/writings" = { };
|
||||
|
||||
# So does relative paths...
|
||||
home.mutableFile."dotfiles" = { };
|
||||
home.mutableFile."library" = { };
|
||||
}
|
||||
----
|
||||
|
||||
With the interface done, we can then proceed with the implementation which is just a shell script managed by systemd.
|
||||
Let's first build the systemd service before we proceed with the shell script.
|
||||
|
||||
[TIP]
|
||||
====
|
||||
Remember, we're using systemd to manage the service.
|
||||
The service is run in a completely new environment and isn't in a shell with programming features like Bash and zsh.
|
||||
This means you cannot run the following command on `Service.ExecStart` directive like how one would expect on the shell.
|
||||
|
||||
[source, shell]
|
||||
----
|
||||
curl "https://example.org" || echo "ERROR"
|
||||
----
|
||||
====
|
||||
|
||||
[source, patch]
|
||||
----
|
||||
include::./assets/patches/0003-fetch-mutable-files-add-initial-systemd-service.patch[]
|
||||
----
|
||||
|
||||
Creating the shell script should be trivial.
|
||||
We could generate the entire script by iterating each of the file from `home.mutableFile.<name>` and mapping the methods from it.
|
||||
Here's one way to let Nix generate our shell script featuring link:https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeText[`writeShellScript` builder].
|
||||
|
||||
[source, patch]
|
||||
----
|
||||
include::./assets/patches/0004-fetch-mutable-files-add-the-shell-script-for-the-ser.patch[]
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
For those who want a complete version of the module directly without applying all of the above patches, you can see it link:./assets/fetch-mutable-files.nix[with this link].
|
||||
====
|
||||
|
||||
With the module being complete for the most part, we just have to include it to our home-manager configuration...
|
||||
|
||||
.`flake.nix`
|
||||
[source, nix]
|
||||
----
|
||||
{
|
||||
outputs = { nixpkgs, home-manager, ... }@inputs: {
|
||||
homeConfigurations.foodogsquared = home-manager.lib.homeManagerConfiguration {
|
||||
modules = [
|
||||
./modules/home-manager/fetch-mutable-files.nix
|
||||
./home.nix
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
----
|
||||
|
||||
...and finally use it.
|
||||
Like I said previously, the nice thing with this module for me is allowing me beyond fetching my dotfiles.
|
||||
I could, for example, fetch Doom Emacs alongside my home-manager configuration.
|
||||
Very nice!
|
||||
|
||||
.`home.nix`
|
||||
[source, nix]
|
||||
----
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
dotfiles = config.lib.file.mkOutOfStoreSymlink config.home.mutableFile."dotfiles".path;
|
||||
in
|
||||
{
|
||||
home.mutableFile = {
|
||||
"dotfiles" = {
|
||||
url = "https://github.com/foo-dogsquared/dotfiles.git";
|
||||
type = "git";
|
||||
};
|
||||
|
||||
"${config.xdg.configHome}/emacs" = {
|
||||
url = "https://github.com/doomemacs/doomemacs";
|
||||
type = "git";
|
||||
};
|
||||
};
|
||||
|
||||
# Putting the dotfiles in their rightful place.
|
||||
xdg.configFile = {
|
||||
doom.source = "${dotfiles}/emacs";
|
||||
wezterm.source = "${dotfiles}/wezterm";
|
||||
nvim.source = "${dotfiles}/nvim";
|
||||
};
|
||||
}
|
||||
----
|
||||
|
||||
[#sidebar:fetch-mutable-files-reader-exercise]
|
||||
.Some room for improvement
|
||||
****
|
||||
The given code from this post is just one minimal starting point for this module.
|
||||
In my NixOS configuration, github:foo-dogsquared/nixos-config[my version of the module, rev=c5bf67553c84efb1e0d3f1859f2d98736d66f616, path=modules/home-manager/files/mutable-files.nix] has expanded with the ability to declare archived files which is already extracted in the filesystem.
|
||||
link:https://github.com/foo-dogsquared/nixos-config/blob/e04d31afeb9b3c1f1fb341ff068062d32def480f/users/home-manager/foo-dogsquared/default.nix#L335-L369[I use it for fetching several things] including Doom Emacs (even automatically installing it).
|
||||
|
||||
Starting from the version of the module featured here, there are room for improvement.
|
||||
You could implement the following suggestions as an exercise.
|
||||
|
||||
* Add a type for fetching archived files.
|
||||
The archive should already be extracted into the path.
|
||||
Additionally, you could add an option for extracting a single file or directory.
|
||||
|
||||
* Each resource to be fetched may require different tweaks.
|
||||
For example, you may want to shallow clone link:https://github.com/doomemacs/doomemacs/[Doom Emacs] since the repo history is too large.
|
||||
You might want to add an option (e.g., `home.mutableFile.<name>.extraArgs`) to set extra arguments to each file.
|
||||
|
||||
* Add the option to allow changing the package to be used for the shell script.
|
||||
This would also require restructuring (and possibly renaming) of the module though.
|
||||
|
||||
* Add an attribute that links to a store path (e.g., `home.mutableFile.<name>.outPath`) for each of the given URL.
|
||||
You could also add an attribute (e.g., `home.mutableFile.<name>.dontLinkToStore`) that either opts-in/-out of including the file in the store directory.
|
||||
Take note this value should be automatically applied and shouldn't be set by the user.
|
||||
****
|
||||
|
||||
|
||||
|
||||
|
||||
[#mutable-files-in-nixos]
|
||||
== Mutable files in NixOS
|
||||
|
||||
So far, we only manage them mutable files in home-manager.
|
||||
I cannot find an equivalent in NixOS but it should be pretty trivial to recreate it especially that the things that made `mkOutOfStoreSymlink` possible is readily available in nixpkgs.
|
||||
All we have to do is to recreate them.
|
||||
|
||||
For this case, we'll use the link:https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-runCommandLocal[`runCommandLocal` builder] typically used for cheap commands.
|
||||
This also what `mkOutOfStoreSymlink` uses in the source code.
|
||||
|
||||
[#lst:runcommandlocal-example]
|
||||
[source, nix]
|
||||
----
|
||||
let
|
||||
path = lib.escapeShellArg "/etc/dotfiles";
|
||||
in
|
||||
pkgs.runCommandLocal "nixos-mutable-file-${builtins.baseNameOf path}" { } ''ln -s ${path} $out''
|
||||
----
|
||||
|
||||
Similarly, this can be used for various NixOS options that normally accepts a store path (e.g., `environment.etc.<name>.source`).
|
||||
For example, if you have a minimal i3 setup that you want to link from a non-NixOS-managed folder, all you have to do is to link it from the dotfiles.
|
||||
|
||||
[source, nix]
|
||||
----
|
||||
include::./assets/runcommandlocal.nix[]
|
||||
----
|
||||
|
||||
[#sidebar:implementing-a-similar-module-for-nixos]
|
||||
.Implementing a similar module for NixOS
|
||||
****
|
||||
If you want to create a declarative interface similar to <<adding-a-declarative-interface-for-fetching-mutable-files, the featured module>> for NixOS, you can create your implementation based from that.
|
||||
However, there's more moving parts that you have to worry about since we're using NixOS where the scope includes the whole system unlike with home-manager where it focuses on the home environment.
|
||||
Here are some things you may need to pay attention to.
|
||||
|
||||
- Since we're using system-level services with systemd, the fetched files will be owned the user of the fetching service (which is root by default).
|
||||
You may want to add an option for the group and owner for each files.
|
||||
|
||||
- Reject (or at least discourage) relative paths since it will be confusing to use.
|
||||
It's best if the module encourages the user to use absolute paths instead.
|
||||
|
||||
- Making sure the fetching service does not modify the generated files from NixOS.
|
||||
Even though this is already handled by the previous module, it is something to keep in mind now that we're modifying the whole operating system.
|
||||
****
|
Loading…
Reference in New Issue
Block a user