aboutsummaryrefslogtreecommitdiff
path: root/docs/homogenous_modules.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/homogenous_modules.md')
-rw-r--r--docs/homogenous_modules.md87
1 files changed, 87 insertions, 0 deletions
diff --git a/docs/homogenous_modules.md b/docs/homogenous_modules.md
new file mode 100644
index 0000000..aa2cbda
--- /dev/null
+++ b/docs/homogenous_modules.md
@@ -0,0 +1,87 @@
+# Homogenous Nix Modules: Why and How
+In the creation of my nixos configuration, I came to a (possibly unique) issue:
+many services that I wanted to configure required a "system" piece, and a "home" piece.
+
+For example, in configuring a shell, it makes sense to configure that shell as the default shell for the user in the same place.
+However, in standard nixos configuration, you configure the actual shell with home-manager, and the default-ness with nixos.
+
+My solution to this was to create a new way of managing my nixos modules, which I coined "Homogenous Modules."
+
+The idea is as follows: each module contains three parts:
+1. a shared `options.nix` file,
+2. a nixos part, and
+3. a home-manager part (or [Hjem](github.com/feel-co/hjem), in my case).
+
+The `options.nix` file contains _only_ the `options` section of a module.
+The nixos part contains the `config` section of the module, as if it was a nixos module.
+The home-manager part contains the `config` section of the module, as if it was a home-manager module.
+
+Now, `{imports = [./options.nix ./nixos.nix];}` is a valid nixos module, and
+`{imports = [./options.nix ./home.nix];}` is a valid home-manager module.
+
+## Example
+Let's implement that shell example from the start, from scratch.
+We'll start with with the `options.nix`:
+```nix
+{lib, ...}: let
+ inherit (lib) mkOption mkEnableOption;
+in {
+ options = {
+ collinux.shells = {
+ zsh = {
+ enable = mkEnableOption "the zsh shell and customizations to it";
+ default = mkEnableOption "make zsh the default shell";
+ };
+ bash = {
+ enable = mkEnableOption "the bash shell and customizations to it";
+ default = mkEnableOption "make bash the default shell";
+ };
+ };
+ };
+ config.assertions = [
+ {
+ assertion = with collinux.shells; !(zsh.default && bash.default);
+ message = "You can only have one default shell!";
+ }
+ ];
+}
+```
+
+Here, we define a simple configuration.
+
+In the nixos part, we'll set the default shell:
+```nix
+{pkgs, config, lib, ...}: let
+ cfg = config.collinux.shells;
+in {
+ users.users."collin".shell =
+ if config.zsh.enable
+ then pkgs.zsh
+ else if config.bash.enable
+ then pkgs.bash
+ else null;
+}
+```
+
+And in the home-manager part, we'll set some customization options:
+```nix
+{pkgs, config, lib, ...}: let
+ cfg = config.collinux.shells;
+
+ shellAliases = {
+ ll = "ls -l";
+ update = "home-manager switch";
+ };
+in {
+ programs.zsh = {
+ enable = cfg.zsh.enable;
+ syntaxHighlighting.enable = true;
+ inherit shellAliases;
+ };
+
+ programs.bash = {
+ enable = cfg.bash.enable;
+ inherit shellAliases;
+ };
+}
+```