refactor: change to litterate config

Configuration is now held by the `.org` files. All `.nix` files are
tangled from the org-mode files.
This commit is contained in:
2026-10-08 15:18:56 +02:00
parent 5f4a7a4a42
commit 216065c4f2
80 changed files with 3099 additions and 581 deletions
+4 -12
View File
@@ -1,16 +1,8 @@
{
flake.modules.nixos.appimage = {
lib,
config,
...
}:
with lib; let
cfg = config.mySystem.packages.appimage;
in {
options.mySystem.packages.appimage.enable = mkEnableOption "Enables AppImage support";
config.programs.appimage = mkIf cfg.enable {
inherit (cfg) enable;
binfmt = true;
};
programs.appimage = {
enable = true;
binfmt = true;
};
};
}
+24
View File
@@ -0,0 +1,24 @@
#+title: AppImage
#+setupfile: ../headers
* AppImage
A small module to let AppImages run directly, without having to
extract or wrap them by hand first. Here’s the =nixos.appimage= module.
#+begin_src nix :tangle yes
{
flake.modules.nixos.appimage = {
<<enable-appimage>>
};
}
#+end_src
=binfmt= registers AppImages with the kernel’s =binfmt_misc=, so running
one is as simple as executing it directly, the same as any other
binary.
#+name: enable-appimage
#+begin_src nix
programs.appimage = {
enable = true;
binfmt = true;
};
#+end_src
+26
View File
@@ -0,0 +1,26 @@
#+title: Base Packages
#+setupfile: ../headers
* Base Packages
A handful of command-line tools I expect to have available on every
single machine, no matter how minimal. Here’s the =nixos.base-packages=
module.
#+begin_src nix :tangle yes
{
flake.modules.nixos.base-packages = {pkgs, ...}: {
<<packages>>
};
}
#+end_src
=curl= and =wget= cover fetching things over HTTP one way or another, and
=openssl= comes in handy for anything involving certificates or quick
cryptographic one-liners.
#+name: packages
#+begin_src nix
environment.systemPackages = with pkgs; [
curl
openssl
wget
];
#+end_src
+136
View File
@@ -0,0 +1,136 @@
#+title: Bun (Baseline)
#+setupfile: ../headers
* Bun (Baseline)
Some of my CPUs don’t support AVX2, which the regular =bun= package
needs, so I keep my own baseline build of it around instead. This page
covers both the derivation itself and the small module that wires it
into the flake’s own =packages= output.
** The Derivation
The regular =bun= package from =nixpkgs= is compiled assuming AVX2, which
crashes with SIGILL on my ThinkPad x220 (=gampo=). Oven’s own release
ships a “baseline” build that doesn’t need AVX2, so this derivation
just fetches and installs that instead. It tangles out to
=packages/bun-baseline.nix=, separate from the module below.
#+begin_src nix :tangle ../../packages/bun-baseline.nix
{
lib,
stdenvNoCC,
fetchurl,
autoPatchelfHook,
unzip,
makeBinaryWrapper,
glibc,
stdenv,
version ? "1.3.13",
}: let
<<version-hash>>
in
stdenvNoCC.mkDerivation {
pname = "bun-baseline";
inherit version;
<<src>>
<<build-inputs>>
<<phases>>
<<meta>>
}
#+end_src
*** Keeping the Version in Sync
I try to keep =version= in step with whatever =bun= nixpkgs itself ships.
Bumping it means adding a new entry to this table, with the hash
computed via =nix store prefetch-file= against the matching GitHub
release URL.
#+name: version-hash
#+begin_src nix
hash = {
"1.3.13" = "sha256-nYokKSpwaAkCBdqsCloiP19pc29Sh+N7+I07QDHtx1A=";
};
#+end_src
*** Fetching the Release
Oven-sh publishes the baseline build as a prebuilt zip directly on
GitHub releases, so there’s no building Bun from source here, just
downloading and unpacking it.
#+name: src
#+begin_src nix
src = fetchurl {
url = "https://github.com/oven-sh/bun/releases/download/bun-v${version}/bun-linux-x64-baseline.zip";
hash = hash.${version};
};
#+end_src
*** Build Inputs
=autoPatchelfHook= patches the prebuilt binary’s dynamic linker and
rpath to point at the Nix store instead of the FHS paths it was built
against, and =glibc= / =stdenv.cc.cc= are the libraries it actually needs
at runtime.
#+name: build-inputs
#+begin_src nix
nativeBuildInputs =
[unzip]
++ lib.optionals stdenvNoCC.hostPlatform.isLinux [
autoPatchelfHook
makeBinaryWrapper
];
buildInputs = lib.optionals stdenvNoCC.hostPlatform.isLinux [
glibc
(lib.getLib stdenv.cc.cc)
];
#+end_src
*** Unpacking and Installing
There’s nothing to configure or build here, just unzip the release and
copy the =bun= binary into place, with =bunx= symlinked alongside it as
usual.
#+name: phases
#+begin_src nix
dontConfigure = true;
dontBuild = true;
unpackPhase = ''
runHook preUnpack
mkdir -p source
cd source
${lib.getExe unzip} -q $src
runHook postUnpack
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
find . -type f -name "bun" -not -path "./__MACOSX/*" -exec cp {} $out/bin/bun \;
chmod +x $out/bin/bun
ln -s $out/bin/bun $out/bin/bunx
runHook postInstall
'';
#+end_src
*** Metadata
#+name: meta
#+begin_src nix
meta = {
description = "Bun JavaScript runtime (baseline variant, works without AVX2)";
homepage = "https://bun.sh";
license = lib.licenses.mit;
platforms = ["x86_64-linux"];
mainProgram = "bun";
};
#+end_src
** Wiring It Into the Flake
This module just exposes the derivation above as a per-system flake
package. It tangles out to =modules/packages/bun-baseline.nix=.
#+begin_src nix :tangle yes
{
perSystem = {pkgs, ...}: {
packages.bun-baseline = pkgs.callPackage ../../packages/bun-baseline.nix {};
};
}
#+end_src
+3 -8
View File
@@ -8,13 +8,8 @@
with lib; let
cfg = config.mySystem.packages.flatpak;
in {
options.mySystem.packages.flatpak = {
enable = mkEnableOption "Enable Flatpak support";
builder.enable = mkEnableOption "Enable Flatpak builder";
};
config = mkIf cfg.enable {
environment.systemPackages = lists.optional cfg.builder.enable pkgs.flatpak-builder;
services.flatpak.enable = true;
};
config.services.flatpak.enable = true;
options.mySystem.packages.flatpak.builder.enable = mkEnableOption "Enable Flatpak builder";
config.environment.systemPackages = lists.optional cfg.builder.enable pkgs.flatpak-builder;
};
}
+39
View File
@@ -0,0 +1,39 @@
#+title: Flatpak
#+setupfile: ../headers
* Flatpak
Here’s the =nixos.flatpak= module, enabling Flatpak itself and
optionally pulling in its builder for the rare occasion I want to
build a Flatpak myself.
#+begin_src nix :tangle yes
{
flake.modules.nixos.flatpak = {
pkgs,
lib,
config,
...
}:
with lib; let
cfg = config.mySystem.packages.flatpak;
in {
<<enable-flatpak>>
<<builder>>
};
}
#+end_src
** Enabling Flatpak
Flatpak support itself is always on once this module is imported.
#+name: enable-flatpak
#+begin_src nix
config.services.flatpak.enable = true;
#+end_src
** Flatpak Builder
=flatpak-builder= is only worth installing on the machines where I
actually build Flatpaks, if any, so it stays behind its own toggle.
#+name: builder
#+begin_src nix
options.mySystem.packages.flatpak.builder.enable = mkEnableOption "Enable Flatpak builder";
config.environment.systemPackages = lists.optional cfg.builder.enable pkgs.flatpak-builder;
#+end_src
+1 -1
View File
@@ -7,7 +7,7 @@
set tabsize 2
set autoindent
set atblanks
set linenumber
set linenumbers
set smarthome
set softwrap
'';
+66
View File
@@ -0,0 +1,66 @@
#+title: Nano
#+setupfile: ../headers
* Nano
I mostly live in Emacs, but I still want a sane fallback editor for
quick edits over SSH. Here’s the =nixos.nano= module.
#+begin_src nix :tangle yes
{
flake.modules.nixos.nano = {
programs.nano = {
<<enable-nano>>
<<syntax-highlight>>
<<nanorc>>
};
};
}
#+end_src
** Enabling Nano
#+name: enable-nano
#+begin_src nix
enable = true;
#+end_src
** Configuration
First of all, let’s enable syntax highlighting. Nothing fancy here,
the basics are enough.
#+name: syntax-highlight
#+begin_src nix
syntaxHighlight = true;
#+end_src
A handful of =nanorc= settings make it behave a bit more like a modern
editor.
#+name: nanorc-settings
| Setting | Why |
|-------------+-------------------------------------------------------------------|
| =tabsize 2= | Two spaces per tab, matching how I indent code |
| =autoindent= | Keep a new line at the same indentation as the one above it |
| =atblanks= | Let soft-wrapped lines indent to match the line above, blanks too |
| =linenumbers= | Show line numbers in the margin |
| =smarthome= | Make Home jump to the first non-blank character, not column 0 |
| =softwrap= | Wrap long lines visually instead of running them off-screen |
#+name: make-nanorc
#+begin_src emacs-lisp :exports none :var settings=nanorc-settings :cache yes
(mapconcat (lambda (setting)
(concat "set " (s-chop-prefix "=" (s-chop-suffix "=" (car setting)))))
settings
"\n")
#+end_src
#+RESULTS[6aaf0a64a52e9d9f15f39ce4396583cec8896c58]: make-nanorc
: set tabsize 2
: set autoindent
: set atblanks
: set linenumbers
: set smarthome
: set softwrap
#+name: nanorc
#+begin_src nix
nanorc = ''
<<make-nanorc()>>
'';
#+end_src
+6 -12
View File
@@ -33,19 +33,13 @@
};
config = {
nix = {
inherit (cfg) gc;
settings = {
inherit (cfg) trusted-users;
sandbox = cfg.disableSandbox;
experimental-features = ["nix-command" "flakes"];
auto-optimise-store = true;
};
};
nixpkgs.config.allowUnfree = true;
programs = {
inherit (cfg) nix-ld;
};
nix.settings.sandbox = cfg.disableSandbox;
nix.gc = cfg.gc;
programs.nix-ld = cfg.nix-ld;
nix.settings.trusted-users = cfg.trusted-users;
nix.settings.experimental-features = ["nix-command" "flakes"];
nix.settings.auto-optimise-store = true;
};
};
}
+122
View File
@@ -0,0 +1,122 @@
#+title: Nix Settings
#+setupfile: ../headers
* Nix Settings
This module gathers the Nix daemon settings I want tuned on every
host: unfree packages, the build sandbox, garbage collection, trusted
users, and a couple of things I just want on everywhere. Here’s the
skeleton of the =nixos.nix-settings= module.
#+begin_src nix :tangle yes
{
flake.modules.nixos.nix-settings = {
lib,
config,
...
}:
with lib; let
cfg = config.mySystem.packages.nix;
in {
options.mySystem.packages.nix = {
<<opt-allow-unfree>>
<<opt-disable-sandbox>>
<<opt-gc>>
<<opt-nix-ld>>
<<opt-trusted-users>>
};
config = {
<<cfg-allow-unfree>>
<<cfg-disable-sandbox>>
<<cfg-gc>>
<<cfg-nix-ld>>
<<cfg-trusted-users>>
<<fixed-settings>>
};
};
}
#+end_src
** Unfree Packages
#+name: opt-allow-unfree
#+begin_src nix
allowUnfree = mkEnableOption "Enable unfree packages";
#+end_src
#+name: cfg-allow-unfree
#+begin_src nix
nixpkgs.config.allowUnfree = true;
#+end_src
** Nix Sandbox
#+name: opt-disable-sandbox
#+begin_src nix
disableSandbox = mkEnableOption "Disable Nix sandbox";
#+end_src
#+name: cfg-disable-sandbox
#+begin_src nix
nix.settings.sandbox = cfg.disableSandbox;
#+end_src
** Garbage Collection
By default, this runs automatically once a week, early Monday morning,
and deletes anything older than 30 days.
#+name: opt-gc
#+begin_src nix
gc = {
automatic = mkOption {
type = types.bool;
default = true;
};
dates = mkOption {
type = types.str;
default = "Monday 01:00 UTC";
};
options = mkOption {
type = types.str;
default = "--delete-older-than 30d";
};
};
#+end_src
#+name: cfg-gc
#+begin_src nix
nix.gc = cfg.gc;
#+end_src
** nix-ld
=nix-ld= lets prebuilt binaries that weren’t built for NixOS — a
downloaded compiler toolchain, a VS Code extension’s native binary —
find the shared libraries they expect at the usual FHS paths.
#+name: opt-nix-ld
#+begin_src nix
nix-ld.enable = mkEnableOption "Enable unpatched binaries support";
#+end_src
#+name: cfg-nix-ld
#+begin_src nix
programs.nix-ld = cfg.nix-ld;
#+end_src
** Trusted Users
Trusted users can do things like point Nix at arbitrary substituters,
which I need so my own binary cache and the nix-community one are
actually trusted.
#+name: opt-trusted-users
#+begin_src nix
trusted-users = mkOption {
type = types.listOf types.str;
example = ["alice" "bob"];
default = ["@wheel" "root"];
};
#+end_src
#+name: cfg-trusted-users
#+begin_src nix
nix.settings.trusted-users = cfg.trusted-users;
#+end_src
** Always-On Settings
=flakes= and the new =nix= command are on everywhere, since this whole
configuration is itself a flake, and =auto-optimise-store= hardlinks
identical files across store paths to save some disk space.
#+name: fixed-settings
#+begin_src nix
nix.settings.experimental-features = ["nix-command" "flakes"];
nix.settings.auto-optimise-store = true;
#+end_src
+24 -29
View File
@@ -1,36 +1,31 @@
{
flake.modules.nixos.steam = {pkgs, ...}: {
programs = {
steam = {
enable = true;
protontricks.enable = true;
remotePlay.openFirewall = true;
localNetworkGameTransfers.openFirewall = true;
gamescopeSession.enable = true;
extraCompatPackages = [pkgs.proton-ge-bin];
package = pkgs.steam.override {
extraEnv = {
MANGOHUD = true;
OBS_VKCAPTURE = true;
RADV_TEX_ANISO = 16;
};
extraLibraries = p: with p; [atk];
extraPkgs = pkgs:
with pkgs; [
qt5.qtmultimedia
qt5.qtbase
libpulseaudio
];
};
programs.steam.enable = true;
programs.steam.protontricks.enable = true;
programs.steam.remotePlay.openFirewall = true;
programs.steam.localNetworkGameTransfers.openFirewall = true;
programs.steam.extraCompatPackages = [pkgs.proton-ge-bin];
programs.steam.package = pkgs.steam.override {
extraEnv = {
OBS_VKCAPTURE = true;
RADV_TEX_ANISO = 16;
};
gamescope = {
enable = true;
capSysNice = true;
args = [
"--rt"
"--expose-wayland"
extraLibraries = p: with p; [atk];
extraPkgs = pkgs:
with pkgs; [
qt5.qtmultimedia
qt5.qtbase
libpulseaudio
];
};
};
programs.gamescope = {
enable = true;
capSysNice = true;
args = [
"--rt"
"--expose-wayland"
];
};
hardware.steam-hardware.enable = true;
};
+100
View File
@@ -0,0 +1,100 @@
#+title: Steam
#+setupfile: ../headers
* Steam
This module sets up Steam and gamescope for gaming on my desktop,
along with a few tweaks for Proton and controller support. Here’s the
skeleton of the =nixos.steam= module.
#+begin_src nix :tangle yes
{
flake.modules.nixos.steam = {pkgs, ...}: {
<<steam-enable>>
<<remote-play>>
<<gamescope-session>>
<<proton-ge>>
<<steam-package>>
<<gamescope>>
<<controller-support>>
};
}
#+end_src
** Enabling Steam
=protontricks= lets me run winetricks-style tweaks against a specific
game’s own Proton prefix, which some finicky titles still need.
#+name: steam-enable
#+begin_src nix
programs.steam.enable = true;
programs.steam.protontricks.enable = true;
#+end_src
** Remote Play and Local Transfers
These punch the firewall holes Steam needs: one for streaming games
over Remote Play, the other for transferring an install to another
machine on the LAN instead of re-downloading it.
#+name: remote-play
#+begin_src nix
programs.steam.remotePlay.openFirewall = true;
programs.steam.localNetworkGameTransfers.openFirewall = true;
#+end_src
** Proton-GE
[[https://github.com/GloriousEggroll/proton-ge-custom][Proton-GE]] is a community Proton build with extra compatibility
patches, and it often supports a game before official Proton catches
up.
#+name: proton-ge
#+begin_src nix
programs.steam.extraCompatPackages = [pkgs.proton-ge-bin];
#+end_src
** The Steam Package Itself
=OBS_VKCAPTURE= lets OBS Studio capture Vulkan games directly through
game capture instead of a slower screen/window capture. =RADV_TEX_ANISO=
forces anisotropic filtering on Mesa’s RADV driver for games that
don’t expose the setting themselves. =atk= fixes some GTK-based Steam
dialogs that otherwise complain about a missing accessibility toolkit,
and the extra Qt5 and =libpulseaudio= packages patch up older games and
launchers that load those libraries dynamically at runtime.
#+name: steam-package
#+begin_src nix
programs.steam.package = pkgs.steam.override {
extraEnv = {
OBS_VKCAPTURE = true;
RADV_TEX_ANISO = 16;
};
extraLibraries = p: with p; [atk];
extraPkgs = pkgs:
with pkgs; [
qt5.qtmultimedia
qt5.qtbase
libpulseaudio
];
};
#+end_src
** Gamescope
[[https://github.com/ValveSoftware/gamescope][gamescope]] is Valve’s micro-compositor, the same one powering the
session above. =capSysNice= lets it set realtime scheduling priority
(=--rt=) without running as root, and =--expose-wayland= lets
Wayland-native games run inside it directly instead of being forced
through XWayland.
#+name: gamescope
#+begin_src nix
programs.gamescope = {
enable = true;
capSysNice = true;
args = [
"--rt"
"--expose-wayland"
];
};
#+end_src
** Controller Support
This installs the udev rules for the Steam Controller, Steam Deck
controls, and other Valve input hardware, so they work without root.
In my case, that’s my original Steam controller and Valve Index.
#+name: controller-support
#+begin_src nix
hardware.steam-hardware.enable = true;
#+end_src