1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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;
};
}
```
|