my attempt at a declarative and functional system config
Note
im still a noob with nix, so pardon my shitty code
The basis for my flake.nix was straight up ripped from sodiboo's config so special thanks to them. You should also visit their repo for a better grasp of how this setup works.
From my understanding, the flake scans for .mod.nix files and loads them
through the mapAttrsToList() function where each module is loaded through
import("${mod_file}"), and saves me the trouble of explicitly specifying the
module. Each .mod.nix file can also define configs for different systems or
inherit different layers.
The key thing I definitely wanted is how inheritance is handled. Specifically
configurations found in _inheritance.mod.nix and what it exactly its being
used for. That's all handled by Sodiboo's merge function:
merge = prev: this: {
modules = prev.modules or [] ++ this.modules or [];
home_modules = prev.home_modules or [] ++ this.home_modules or [];
} // (optionalAttrs (prev ? system || this ? system) {
system = prev.system or this.system;
});Too be clear, I'm pretty sure this sort of combines configs rather than create
inheritance. And when they are merged, the modules and home_modules arrays
are concatted as well as the system specific config, I believe this is what
optionalAttrs handles.
The setup also uses zipAttrsWith to automatically combine all modules by
machine name. So if multiple .mod.nix files define configs for the same machine
like desky, they get automatically combined using the merge function through
folding.
This all sort of lets me use a layered config setup where machines can inherit the configs they would need, I can also specify a config on a per machine level.
In practice, this is what it would look like:
desky = merge configs.universal configs.personal
lappy = merge configs.universal configs.personalThis automatically creates and combines configs as like so:
- modules ->
universal.modules ++ personal.modules - home_modules ->
universal.home_modules ++ personal.home_modules
To put it all together, declaring a new module is as simple as:
# some.mod.nix
{...} : {
universal.modules = [
({pkgs, lib, ...} : {
...
})
];
# and/or
personal.modules = [{
...
}];
# for specific hosts
lappy.modules = [];
desky.modules = [];
# same goes for home_modules
universal.home_modules = [];
personal.home_modules = [];
lappy.home_modules = [];
...
}There are two main setups that are configured here: desky, and lappy - my desktop and laptop respectively. I also plan to add a nix-darwin config for my mac mini - macky, later on. They both currently inherit personal, and universal, ideally when I setup more machines, like macky for instance, it wouldn't need to inherit both.
All modules are in root, I want to avoid nesting as much as possible, to reduce both the amount of default.nix files I would need but also the amount of directories I have to navigate through. Aside from hardware there is very little difference between them.
They both share:
- niri niri-flake - scrolling window manager.
- greetd - login manager, previously I used ly but I got skill-issued so hard and gave that up.
- foot - my terminal emulator, it's responsive, and is relatively lightweight. I don't need gpu acceleration and fancy shader support!
- nushell - current shell, it gives me good looking output, that's all.
- nvf - neovim flake that abstracts a lot of neovim setup and lua out, it keeps my entire config in nix.
- eww - widgets, the system information panel that sits as a overlay on the center of the screen. This replaces waybar for me and it will also soon replace dunst as my notification daemon.
- dunst - notification daemon, its lightweight and pretty easy to config.
- tofi - app launcher, it's wicked fast, even with my minimal optimizations (no direct path to fonts) it still launches super quick.
Aesthetically I wanted to keep them relatively simple, functional and high contrast. Not only to compliment my OLED monitor but also because it helps me concentrate without overly annoying colors or any other on-screen distractions. For this I went with very tiny gaps (0 vertical gaps), a tiny focus-ring, and no bar - system info like volume, brightness, etc are all handled on the sys_info panel that I can toggle on/off.
In terms of hardware:
| component | lappy | desky |
|---|---|---|
| CPU | 7640U | 9700X |
| GPU | 700M | 7900XTX |
| RAM | 32GB | 32GB |
| DISPLAY | 13' 1080p | 32' 4K |
desky currently has a dual boot setup with shitdows on two separate nvme
drives, and it's why I need grub instead of systemd - makes it easier to
setup a dual boot system using os-prober without having to manually specify
disks.
g80sd 4k @ 240hz needs additional setup
something about edid and displayid being blocked, idrk
here's some details:
reddit
arch forums
relevant issue
arch wiki for edid
nixos issue
drm kernel commit
UPDATE: I had to 'overclock' my amdgpu, specifically set it to the
Highest Clocks option on lact
sodiboo's setup
nix builtins
debug nix expressions
eww config
nix.dev
greetd/tuigreet
uwu ascii