Compare commits

...
33 Commits
Author SHA1 Message Date
christoph 6519ae6625 Home/Nixinator: Update opencode permissions 2026-09-16 11:05:18 +02:00
christoph 2229f79617 Services/Jellyfin: Update to v12.1 2026-09-15 21:38:16 +02:00
christoph 44d832fdda Home/Nixinator: Disable opencode-dcp 2026-09-15 16:31:34 +02:00
christoph 5d1791914e Home/Nixinator: Configure context7, zotero and obsidian MCP servers 2026-09-14 23:19:04 +02:00
christoph 5fe5c81916 System/Nixinator: Update mounted sops secrets 2026-09-14 23:18:51 +02:00
christoph fbec41ba10 Modules/SopsNix: Add context7 + local obsidian API keys 2026-09-14 23:18:40 +02:00
christoph ebd306ee98 Services/Immich: Update to v3.2.0-cuda 2026-09-13 22:38:52 +02:00
christoph d240aac403 Add AGENTS.md 2026-09-13 21:59:47 +02:00
christoph 258119c5c8 Flake: Update lock 2026-09-13 21:59:22 +02:00
christoph 1d04dc984f Modules/Impermanence: Persist opencode-desktop state 2026-09-13 21:59:16 +02:00
christoph a2b5cfaed3 Modules/Packages: Add opencode-desktop 2026-09-13 21:59:07 +02:00
christoph 82dfa98c07 Home/Nixinator: Add deepwiki mcp server 2026-09-13 21:58:57 +02:00
christoph 1dcc27f378 Modules/Neovim: Add pyyaml 2026-09-13 18:47:21 +02:00
christoph e97bfb6262 Modules/Mime: Update epub associations 2026-09-13 17:59:29 +02:00
christoph bf5778476e Modules/Yazi: Update to new selected files syntax 2026-09-13 17:41:05 +02:00
christoph f2b1bedcf0 Modules/Packages: Add calibre 2026-09-13 17:39:26 +02:00
christoph 5f6ca72f6c Overlays/LatexMinted: Fix latexminted package 2026-09-10 20:47:18 +02:00
christoph ea39c929ae Modules/Impermanence: Persist codex-desktop-unofficial state 2026-09-10 20:46:27 +02:00
christoph 06e1c4390c System: Update to new journald settings schema 2026-09-10 20:46:13 +02:00
christoph 01ec6d15db Overlays: Disable clion overlay (outdated) 2026-09-10 20:45:56 +02:00
christoph e2267e8978 Modules/Packages: Re-enable feishing + font-manager 2026-09-10 20:45:42 +02:00
christoph 044d2742ed Home/Nixinator: Re-enable makemkv 2026-09-10 20:45:23 +02:00
christoph 3f92349857 Flake: Update lock 2026-09-10 20:45:07 +02:00
christoph 39eb99e021 Home/Nixinator: Enable unofficial codex desktop app 2026-09-08 11:03:29 +02:00
christoph c4476bf1b7 Derivations/Tiddl: Remove obsolete typer dependency override 2026-08-31 20:32:09 +02:00
christoph b4a04567e0 Modules/Niri: Explicitly set home.pointerCursor.enable 2026-08-31 20:31:56 +02:00
christoph f493275ea0 Modules/Packages: Disable currently broken packages (nps, font-manager) 2026-08-31 20:31:37 +02:00
christoph 8e118c5a3f Modules/Impermanence: Persist /var/lib/auto-cryptenroll for lanzaboote 2026-08-31 20:30:41 +02:00
christoph 76c28f65ff Modules/Bootloader: Update lanzaboote config (enable automatic key generation and enrollment) 2026-08-31 20:30:27 +02:00
christoph daf7eb8d75 Update stdenv.isLinux and stdenv.isDarwin calls 2026-08-31 20:30:05 +02:00
christoph 08c2eb8bfe Home/Nixinator: Disable makemkv (currently broken) 2026-08-31 20:29:25 +02:00
christoph f3b6087440 Flake: Update lock 2026-08-31 20:29:11 +02:00
christoph 672c269841 Flake: Update lanzaboote to v1.1.0 2026-08-31 20:29:07 +02:00
26 changed files with 736 additions and 397 deletions
+128
View File
@@ -0,0 +1,128 @@
# AGENTS.md
## Common Commands
```bash
# Enter the dev shell (provides helper utilities)
nix develop
# Preferred shorthand (nh must be enabled in config)
nh os switch # rebuild and switch
nh os boot # new boot entry without switching
# Direct nixos-rebuild (fallback)
sudo nixos-rebuild switch --flake .#nixinator
sudo nixos-rebuild switch --flake .#nixtop
sudo nixos-rebuild switch --flake .#servenix
sudo nixos-rebuild switch --flake .#thinknix
sudo darwin-rebuild switch --flake .#darwinix
# Validate flake without building
nix flake check
# Dev shell helpers (run inside `nix develop`)
list-system-packages # show installed system packages
list-user-packages # show installed user packages
store-optimise # nix store --optimise
store-verify # nix store --verify --repair
```
## MCP Tools
The **nixos** MCP server is available and should be used for any Nix-related lookups instead of `nix search` or manual web searches. It queries live APIs (search.nixos.org, NixHub, FlakeHub) and is more current than training data.
```
# Common intents
nix {"action":"info","query":"<pkg>","channel":"unstable"} # package info
nix {"action":"search","query":"<term>","type":"options"} # NixOS options
nix {"action":"search","source":"home-manager","query":"<term>"} # HM options
nix {"action":"cache","query":"<pkg>"} # binary cache status
nix_versions {"package":"<attr>","version":"<ver>"} # commit that shipped a version
```
## Architecture
This is a multi-host NixOS/nix-darwin flake. Home-manager runs **as a NixOS module** — not standalone. A single `nixos-rebuild switch` rebuilds system and user config together. The HM config can access the system config via the `nixosConfig` special arg.
### Hosts
| Host | Type | Notes |
|------|------|-------|
| `nixinator` | Desktop (x86_64) | Primary machine; disko, lanzaboote, impermanence |
| `nixtop` | Laptop (x86_64) | Intel GPU, NetworkManager |
| `servenix` | Server (x86_64) | Headless; runs OCI container services |
| `thinknix` | Headless (x86_64) | Generic headless config |
| `darwinix` | macOS (aarch64) | Darwin-specific configuration |
### Config Layering (resolved in this order)
1. **Global defaults**`system/default.nix` / `home/christoph/default.nix`
2. **Host overrides**`system/<hostname>/default.nix` / `home/christoph/<hostname>/default.nix`
3. **Hardware**`system/<hostname>/hardware-configuration.nix` (auto-generated, **do not hand-edit**)
The builder (`lib/nixos.nix`: `mkNixosConfigWithHomeManagerModule`) wires these together.
### Special Args
Injected into **all system and HM modules**:
`inputs` `system` `hostname` `mylib` `username` `publicKeys` `headless`
Use `headless` (boolean) to gate anything graphical. Use `mylib.<fn>` instead of reimplementing helpers.
### Module System
Two parallel hierarchies, identical pattern:
| Scope | Path | Option prefix |
|-------|------|---------------|
| System | `system/systemmodules/<name>/` | `systemmodules.<name>.*` |
| Home-manager | `home/homemodules/<name>/` | `homemodules.<name>.*` |
**System modules**`system/systemmodules/<name>/`
- `options.nix` — declares `systemmodules.<name>.*` options
- `default.nix` — imports `./options.nix`, implements `lib.mkIf <name>.enable { ... }`
**Home-manager modules**`home/homemodules/<name>/`
- `options.nix` — declares `homemodules.<name>.*` options
- `default.nix` — same pattern under `homemodules.*`
When adding a new module, copy from `0_template/` in either hierarchy. Modules under `1_deprecated/` are kept for reference only — not imported anywhere.
HM modules are placed in `home-manager.sharedModules` (not `users.<user>.imports`) — this enables proper nixd completions.
### Custom Library (`lib/`)
Always available as `mylib`. Key files:
- `nixos.nix` — host config builders, `mkNixosConfigWithHomeManagerModule`, `mkDarwinConfigWithHomeManagerModule`
- `modules.nix``mkBoolOption`, `mkElse`, `attrName`, `attrValue`, `contains`
- `networking.nix``mkSystemdNetwork`, `mkStaticSystemdNetwork`
- `generators.nix``toLuaObject`, `toLuaKeymap` (used by Neovim module)
- `containers.nix` — OCI container helpers for services
- `color.nix` — theming
Always use `mylib.<fn>` (available as a special arg) rather than reimplementing these utilities.
### Services
Server services are OCI containers (podman/docker) defined in `system/services/`. Each file defines one or more containers. These are only enabled on `servenix`. Use the template at `system/services/0_TEMPLATE.nix`.
### Secrets
Managed via **sops-nix**. Age keys stored in `flake.nix` under `publicKeys.christoph`. Encrypted `.yaml`/`.json` files live alongside the module that uses them, referenced as `sops.secrets.<name>`.
### Overlays and Custom Derivations
- `overlays/default.nix` — package overrides (e.g., patched JetBrains CLion version)
- `derivations/default.nix` — custom packages: `monolisa`, `msty`, `unityhub`, `tidal-dl-ng`, `tiddl`
- `derivations/1_deprecated/` — kept for reference, not imported
### Sub-projects
`config/flake.nix` is a separate, reusable development-project template — **not part of the main NixOS flake**. It uses `flake-utils` for multi-system shells.
## Constraints
- No CI, no tests, no linting — this is a configuration repo
- `nix flake check` is the only validation available
- `documentation.enable = false` by default (slow); toggle it if you need man pages
- Hardware config files are auto-generated — never edit them by hand
+13 -11
View File
@@ -4,17 +4,19 @@
pkgs, pkgs,
}: let }: let
pythonPkgs = pkgs.python314Packages.overrideScope (self: super: { pythonPkgs = pkgs.python314Packages.overrideScope (self: super: {
typer = super.typer.overridePythonAttrs (old: { # NOTE: Typer override apparently no longer required on 2026-08-31
version = "0.20.1"; #
src = pkgs.fetchPypi { # typer = super.typer.overridePythonAttrs (old: {
pname = "typer"; # version = "0.20.1";
version = "0.20.0"; # src = pkgs.fetchPypi {
sha256 = "sha256-Gq9klAMXk+SHb7C6z6apErVRz0PB5jyADfixqGZyDDc="; # pname = "typer";
}; # version = "0.20.0";
propagatedBuildInputs = with pythonPkgs; [ # sha256 = "sha256-Gq9klAMXk+SHb7C6z6apErVRz0PB5jyADfixqGZyDDc=";
typing-extensions # };
]; # propagatedBuildInputs = with pythonPkgs; [
}); # typing-extensions
# ];
# });
aiofiles = super.aiofiles.overridePythonAttrs (old: { aiofiles = super.aiofiles.overridePythonAttrs (old: {
version = "25.1.0"; version = "25.1.0";
Generated
+302 -269
View File
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -36,7 +36,7 @@
sops-nix.inputs.nixpkgs.follows = "nixpkgs"; sops-nix.inputs.nixpkgs.follows = "nixpkgs";
# Secure boot # Secure boot
lanzaboote.url = "github:nix-community/lanzaboote/v0.4.3"; lanzaboote.url = "github:nix-community/lanzaboote/v1.1.0";
lanzaboote.inputs.nixpkgs.follows = "nixpkgs"; lanzaboote.inputs.nixpkgs.follows = "nixpkgs";
# Nix User Repository (e.g. Firefox addons) # Nix User Repository (e.g. Firefox addons)
@@ -100,6 +100,10 @@
claude-desktop.url = "github:aaddrick/claude-desktop-debian"; claude-desktop.url = "github:aaddrick/claude-desktop-debian";
claude-desktop.inputs.nixpkgs.follows = "nixpkgs"; claude-desktop.inputs.nixpkgs.follows = "nixpkgs";
# Unofficial
codex-desktop-linux.url = "github:ilysenko/codex-desktop-linux";
codex-desktop-linux.inputs.nixpkgs.follows = "nixpkgs";
stylix.url = "github:nix-community/stylix"; stylix.url = "github:nix-community/stylix";
stylix.inputs.nixpkgs.follows = "nixpkgs"; stylix.inputs.nixpkgs.follows = "nixpkgs";
@@ -273,6 +277,7 @@
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
inputs.stylix.nixosModules.stylix inputs.stylix.nixosModules.stylix
inputs.nix-gaming.nixosModules.platformOptimizations inputs.nix-gaming.nixosModules.platformOptimizations
inputs.codex-desktop-linux.nixosModules.default
] ]
++ commonModules; ++ commonModules;
}; };
+84 -20
View File
@@ -78,6 +78,17 @@
enableMcpIntegration = true; enableMcpIntegration = true;
}; };
codexDesktopLinux = {
enable = true;
linuxFeatures = [
"frameless-titlebar"
"global-dictation"
"read-aloud"
"tray-usage"
"ui-tweaks"
];
};
# NOTE: Starts extremely slow # NOTE: Starts extremely slow
ghostty = { ghostty = {
enable = true; enable = true;
@@ -131,10 +142,37 @@
mcp = { mcp = {
enable = true; enable = true;
servers = { servers = {
context7 = {
command = "npx";
args = ["-y" "@upstash/context7-mcp"];
env = {
CONTEXT7_API_KEY.file = nixosConfig.sops.secrets.context7-api-key.path;
};
};
# deepwiki = {
# # https://mcpservers.org/servers/devin/deepwiki
# url = "https://mcp.deepwiki.com/mcp";
# };
# github = {
# # https://mcpservers.org/servers/github-mcp-server
# url = "https://api.githubcopilot.com/mcp/";
# headers = {
# Authorization = "Bearer ${input:github_mcp_pat}";
# };
# };
nixos = { nixos = {
command = "uvx"; command = "uvx";
args = ["mcp-nixos"]; args = ["mcp-nixos"];
}; };
obsidian = {
command = "uvx";
args = ["mcp-obsidian"];
env = {
OBSIDIAN_API_KEY.file = nixosConfig.sops.secrets.obsidian-rest-api-key.path;
OBSIDIAN_HOST = "127.0.0.1";
OBSIDIAN_PORT = "27124";
};
};
svelte = { svelte = {
# claude mcp add -t stdio -s [scope] svelte -- npx -y @sveltejs/mcp # claude mcp add -t stdio -s [scope] svelte -- npx -y @sveltejs/mcp
command = "npx"; command = "npx";
@@ -146,6 +184,10 @@
command = "npx"; command = "npx";
args = ["-y" "shadcn@latest" "mcp"]; args = ["-y" "shadcn@latest" "mcp"];
}; };
zotero = {
command = "uvx";
args = ["zotero-mcp-server"];
};
}; };
}; };
@@ -239,19 +281,37 @@
"*" = "ask"; "*" = "ask";
"bash" = { "bash" = {
"*" = "ask"; "*" = "ask";
"ls *" = "allow"; "awk *" = "ask"; # Can modify files
"find *" = "ask"; # Don't want find -exec
"file *" = "allow";
"wc *" = "allow";
"grep *" = "allow";
"rg *" = "allow";
"test *" = "allow";
"echo *" = "allow";
"which *" = "allow";
"pwd *" = "allow";
"dirname *" = "allow";
"basename *" = "allow"; "basename *" = "allow";
"cmp *" = "allow";
"cut *" = "allow";
"df *" = "allow";
"dirname *" = "allow";
"du *" = "allow";
"echo *" = "allow";
"fd *" = "ask"; # Can execute commands
"file *" = "allow";
"find *" = "ask"; # Can execute commands
"grep *" = "allow";
"head *" = "allow";
"ls *" = "allow";
"nl *" = "allow";
"od *" = "allow";
"pwd *" = "allow";
"readlink *" = "allow"; "readlink *" = "allow";
"rg *" = "ask"; # Can execute commands
"sed *" = "ask"; # Can modify files
"sha256sum *" = "allow";
"sha512sum *" = "allow";
"sort *" = "ask"; # Can modify files
"stat *" = "allow";
"tail *" = "allow";
"test *" = "allow";
"tr *" = "allow";
"uniq *" = "ask"; # Can modify files
"wc *" = "allow";
"which *" = "allow";
"xargs *" = "ask"; # Can modify files
"cat *.env" = "deny"; "cat *.env" = "deny";
"cat *.env.*" = "deny"; "cat *.env.*" = "deny";
@@ -266,11 +326,19 @@
"nix why-depends *" = "allow"; "nix why-depends *" = "allow";
"nix derivation show *" = "allow"; "nix derivation show *" = "allow";
"nix store ping *" = "allow"; "nix store ping *" = "allow";
"nix stire diff-closures *" = "allow"; "nix store diff-closures *" = "allow";
"git status *" = "allow"; "git branch *" = "ask";
"git log *" = "allow"; "git check-ignore *" = "allow";
"git diff *" = "allow"; "git diff *" = "allow";
"git log *" = "allow";
"git ls-files *" = "allow";
"git ls-tree *" = "allow";
"git remote *" = "ask";
"git rev-list *" = "allow";
"git rev-parse *" = "allow";
"git stash *" = "ask";
"git status *" = "allow";
}; };
"external_directory" = { "external_directory" = {
"/nix/store/**" = "allow"; "/nix/store/**" = "allow";
@@ -294,8 +362,8 @@
"question" = "allow"; "question" = "allow";
}; };
plugin = [ plugin = [
"opencode-claude-auth@latest" # https://github.com/griffinmartin/opencode-claude-auth # "opencode-claude-auth@latest" # https://github.com/griffinmartin/opencode-claude-auth
"@tarquinen/opencode-dcp@latest" # better compacting # "@tarquinen/opencode-dcp@latest" # better compacting
# "opencode-lmstudio@0.3.1" # "opencode-lmstudio@0.3.1"
# "@slkiser/opencode-quota" # "@slkiser/opencode-quota"
]; ];
@@ -404,12 +472,8 @@
makemkv makemkv
lrcget lrcget
# msty # msty
# jellyfin-media-player # CVE, can't install
jellyfin-desktop jellyfin-desktop
jellyfin-mpv-shim jellyfin-mpv-shim
# tidal-hifi
# tidal-dl-ng # TODO: Borked
# spotdl
tiddl tiddl
picard picard
handbrake handbrake
+1
View File
@@ -44,6 +44,7 @@
inputs.nixvim.homeModules.nixvim inputs.nixvim.homeModules.nixvim
inputs.textfox.homeManagerModules.default inputs.textfox.homeManagerModules.default
inputs.walker.homeManagerModules.default inputs.walker.homeManagerModules.default
inputs.codex-desktop-linux.homeManagerModules.default
# inputs.stylix.homeModules.stylix # inputs.stylix.homeModules.stylix
# inputs.direnv-instant.homeModules.direnv-instant # inputs.direnv-instant.homeModules.direnv-instant
# inputs.niri.homeModules.niri # Imported by system module # inputs.niri.homeModules.niri # Imported by system module
+2 -2
View File
@@ -58,7 +58,7 @@ in {
in in
lib.mkMerge [ lib.mkMerge [
# Darwin exclusive config # Darwin exclusive config
(lib.mkIf pkgs.stdenv.isDarwin { (lib.mkIf pkgs.stdenv.hostPlatform.isDarwin {
shellInit = '' shellInit = ''
set fish_greeting set fish_greeting
yes | fish_config theme save "system-theme" yes | fish_config theme save "system-theme"
@@ -81,7 +81,7 @@ in {
}) })
# Linux exclusive config # Linux exclusive config
(lib.mkIf pkgs.stdenv.isLinux { (lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
generateCompletions = nixosConfig.programs.fish.generateCompletions; generateCompletions = nixosConfig.programs.fish.generateCompletions;
# TODO: There's a bug with the direnv mechanism: # TODO: There's a bug with the direnv mechanism:
+1
View File
@@ -48,6 +48,7 @@ in {
home = { home = {
pointerCursor = { pointerCursor = {
enable = true;
gtk.enable = lib.mkDefault true; gtk.enable = lib.mkDefault true;
x11.enable = lib.mkDefault true; x11.enable = lib.mkDefault true;
package = lib.mkDefault color.cursorPackage; package = lib.mkDefault color.cursorPackage;
+4 -4
View File
@@ -10,7 +10,7 @@
inherit (config.homemodules) jellyfin-tui color; inherit (config.homemodules) jellyfin-tui color;
systemConfig = systemConfig =
if pkgs.stdenv.isLinux if pkgs.stdenv.hostPlatform.isLinux
then nixosConfig then nixosConfig
else darwinConfig; else darwinConfig;
in { in {
@@ -24,7 +24,7 @@ in {
file = let file = let
jellyfinUrl = jellyfinUrl =
if pkgs.stdenv.isLinux if pkgs.stdenv.hostPlatform.isLinux
then "https://jellyfin.local.chriphost.de" then "https://jellyfin.local.chriphost.de"
else "https://jellyfin.vps.chriphost.de"; else "https://jellyfin.vps.chriphost.de";
@@ -79,10 +79,10 @@ in {
''; '';
in in
lib.mkMerge [ lib.mkMerge [
(lib.optionalAttrs pkgs.stdenv.isLinux { (lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
".config/jellyfin-tui/config.yaml".text = configFile; ".config/jellyfin-tui/config.yaml".text = configFile;
}) })
(lib.optionalAttrs pkgs.stdenv.isDarwin { (lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
"Library/Application Support/jellyfin-tui/config.yaml".text = configFile; "Library/Application Support/jellyfin-tui/config.yaml".text = configFile;
}) })
]; ];
+1 -1
View File
@@ -36,7 +36,7 @@ in {
settings = lib.mkMerge [ settings = lib.mkMerge [
# Linux config # Linux config
(lib.mkIf pkgs.stdenv.isLinux { (lib.mkIf pkgs.stdenv.hostPlatform.isLinux {
allow_remote_control = true; # For nnn file preview or nvim scrollback allow_remote_control = true; # For nnn file preview or nvim scrollback
listen_on = lib.mkDefault "unix:@mykitty"; # This conflicts with direnv-instant listen_on = lib.mkDefault "unix:@mykitty"; # This conflicts with direnv-instant
}) })
+1
View File
@@ -124,6 +124,7 @@ in {
matplotlib matplotlib
requests requests
pygments pygments
pyyaml
])) ]))
(rWrapper.override { (rWrapper.override {
+3 -1
View File
@@ -224,6 +224,7 @@ in {
}; };
pointerCursor = { pointerCursor = {
enable = true;
gtk.enable = true; gtk.enable = true;
x11.enable = true; x11.enable = true;
package = color.cursorPackage; package = color.cursorPackage;
@@ -242,7 +243,7 @@ in {
# GTK # GTK
nautilus # Fallback file chooser used by xdg-desktop-portal-gnome nautilus # Fallback file chooser used by xdg-desktop-portal-gnome
sassc sassc
gtk-engine-murrine # gtk-engine-murrine # No longer in nixpkgs
gnome-themes-extra gnome-themes-extra
# Qt # Qt
@@ -304,6 +305,7 @@ in {
# TODO: Module # TODO: Module
walker = { walker = {
enable = true; enable = true;
package = pkgs.walker; # NOTE: The flake package was broken on 2026-08-31
runAsService = true; runAsService = true;
# https://github.com/abenz1267/walker/blob/master/resources/config.toml # https://github.com/abenz1267/walker/blob/master/resources/config.toml
+11 -6
View File
@@ -43,7 +43,9 @@ in {
# Nix # Nix
nix-search-tv # Search nixpkgs, nur, nixos options and homemanager options nix-search-tv # Search nixpkgs, nur, nixos options and homemanager options
nix-tree # Browse the nix store sorted by size (gdu for closures) nix-tree # Browse the nix store sorted by size (gdu for closures)
inputs.nps.packages.${pkgs.stdenv.hostPlatform.system}.default # Search nixpkgs
# TODO: Still broken on 2026-09-09
# inputs.nps.packages.${pkgs.stdenv.hostPlatform.system}.default # Search nixpkgs
# Video/Image/Audio utils # Video/Image/Audio utils
ffmpeg-full # I love ffmpeg (including ffplay) ffmpeg-full # I love ffmpeg (including ffplay)
@@ -81,7 +83,7 @@ in {
]) ])
# Linux exclusive packages # Linux exclusive packages
(lib.optionals (pkgs.stdenv.isLinux) [ (lib.optionals (pkgs.stdenv.hostPlatform.isLinux) [
pastel # Color tools pastel # Color tools
nvd # Nix rebuild diff nvd # Nix rebuild diff
nurl # Generate nix fetcher sections based on URLs nurl # Generate nix fetcher sections based on URLs
@@ -139,7 +141,7 @@ in {
]) ])
# Linux exclusive packages (!headless) # Linux exclusive packages (!headless)
(lib.optionals (pkgs.stdenv.isLinux && (!headless)) [ (lib.optionals (pkgs.stdenv.hostPlatform.isLinux && (!headless)) [
wl-clipboard wl-clipboard
asciicam asciicam
@@ -159,7 +161,7 @@ in {
vlc vlc
audacity audacity
# ferdium # ferdium
# feishin # electron :( feishin # electron :(
playerctl # Media player control playerctl # Media player control
czkawka-full # file deduplicator czkawka-full # file deduplicator
binaryninja-free # reverse engineering binaryninja-free # reverse engineering
@@ -167,6 +169,9 @@ in {
# opencode-desktop # opencode-desktop
lmstudio # TODO: Ollama lmstudio # TODO: Ollama
claude-desktop claude-desktop
opencode-desktop
upscayl
calibre
# Office # Office
kdePackages.wacomtablet # For xournalpp/krita kdePackages.wacomtablet # For xournalpp/krita
@@ -175,7 +180,7 @@ in {
hunspellDicts.en_US hunspellDicts.en_US
hunspellDicts.de_DE hunspellDicts.de_DE
# GTK-Apps # GTK-Apps because I hate nice software
# gnome-calculator # gnome-calculator
# gnome-calendar # gnome-calendar
# helvum # unmaintained # helvum # unmaintained
@@ -192,7 +197,7 @@ in {
]) ])
# Darwin exclusive packages # Darwin exclusive packages
(lib.optionals pkgs.stdenv.isDarwin [ (lib.optionals pkgs.stdenv.hostPlatform.isDarwin [
# Use homebrew instead # Use homebrew instead
# alt-tab-macos # alt-tab-macos
# discord # discord
+1 -1
View File
@@ -19,7 +19,7 @@ in {
"*" = { "*" = {
ForwardAgent = false; ForwardAgent = false;
AddKeysToAgent = AddKeysToAgent =
if pkgs.stdenv.isLinux if pkgs.stdenv.hostPlatform.isLinux
then "no" then "no"
else "yes"; # Don't have keychain on darwin else "yes"; # Don't have keychain on darwin
Compression = true; Compression = true;
+18 -15
View File
@@ -65,9 +65,10 @@ in {
''; '';
# https://yazi-rs.github.io/docs/configuration/yazi # https://yazi-rs.github.io/docs/configuration/yazi
# "$n": The n-th selected file (1...n) # %sN: The N-th selected file (1...n)
# "$@": All selected files # %s: All selected files
# "$0": The hovered file # %h: The hovered file (shell keybindings)
# File placeholders are shell-escaped by Yazi; do not quote them.
settings = { settings = {
mgr = { mgr = {
show_hidden = false; show_hidden = false;
@@ -80,41 +81,43 @@ in {
opener = { opener = {
play = [ play = [
{ {
run = ''mpv "$@"''; run = ''mpv %s'';
orphan = true; orphan = true;
desc = "Play selection with mpv"; desc = "Play selection with mpv";
} }
{ {
run = ''vlc "$@"''; run = ''vlc %s'';
orphan = true; orphan = true;
desc = "Play selection with vlc"; desc = "Play selection with vlc";
} }
]; ];
edit = [ edit = [
{ {
run = ''$EDITOR "$@"''; run = ''$EDITOR %s'';
block = true; block = true;
desc = "Edit selection"; desc = "Edit selection";
} }
]; ];
open = [ open = [
{ {
run = ''xdg-open "$@"''; run = ''xdg-open %s1'';
desc = "Open selection with xdg-open"; orphan = true;
desc = "Open first selected file with xdg-open";
} }
{ {
run = ''imv "$@"''; run = ''imv %s'';
orphan = true;
desc = "Open selection with imv"; desc = "Open selection with imv";
} }
{ {
# TODO: For some reason, junction does not exit after choosing an application... run = ''junction %s'';
run = ''junction "$@"''; orphan = true;
desc = "Open selection with junction"; desc = "Open selection with junction";
} }
]; ];
extract = [ extract = [
{ {
run = ''ouch decompress -y "$@"''; run = ''ouch decompress -y %s'';
desc = "Extract selection"; desc = "Extract selection";
} }
]; ];
@@ -219,7 +222,7 @@ in {
"<C-p>" "<C-p>"
"d" "d"
]; ];
run = ''shell -- ripdrag -a -n "$@"''; run = ''shell --orphan -- ripdrag -a -n %s'';
desc = "Drag & drop selection"; desc = "Drag & drop selection";
} }
{ {
@@ -243,7 +246,7 @@ in {
"<C-p>" "<C-p>"
"w" "w"
]; ];
run = ''wl-copy < "$0"''; run = ''shell -- wl-copy < %h'';
desc = "Copy hovered file contents using wl-copy"; desc = "Copy hovered file contents using wl-copy";
} }
@@ -255,7 +258,7 @@ in {
{ {
on = "y"; on = "y";
run = [ run = [
''shell -- for path in "$@"; do echo "file://$path"; done | wl-copy -t text/uri-list'' ''shell -- for path in %s; do echo "file://$path"; done | wl-copy -t text/uri-list''
"yank" "yank"
]; ];
desc = "Copy files to system clipboard on yank"; desc = "Copy files to system clipboard on yank";
+37 -31
View File
@@ -29,36 +29,36 @@
# Remove this after jetbrains.jdk builds again (nixpkgs issue 425328) # Remove this after jetbrains.jdk builds again (nixpkgs issue 425328)
# jetbrains.rider = pkgs-stable.jetbrains.rider; # jetbrains.rider = pkgs-stable.jetbrains.rider;
jetbrains = # jetbrains =
prev.jetbrains # prev.jetbrains
// { # // {
clion = prev.jetbrains.clion.overrideAttrs (oldAttrs: rec { # clion = prev.jetbrains.clion.overrideAttrs (oldAttrs: rec {
version = "261.22158.47"; # March 6, 2026 # version = "261.22158.47"; # March 6, 2026
#
src = prev.fetchurl { # src = prev.fetchurl {
url = "https://download-cdn.jetbrains.com/cpp/CLion-${version}.tar.gz"; # url = "https://download-cdn.jetbrains.com/cpp/CLion-${version}.tar.gz";
#
# hash = "sha256-h6tnemVnV1YEsvIndwrq2sMsRZYuvTWMU5oqj/hkjdY="; # 261.21849.6 # # hash = "sha256-h6tnemVnV1YEsvIndwrq2sMsRZYuvTWMU5oqj/hkjdY="; # 261.21849.6
hash = "sha256-FUHNRioJvjwOWN+FkXEr3+NWR+QVxaZUOkJ0egQkcCQ="; # 261.22158.47 # hash = "sha256-FUHNRioJvjwOWN+FkXEr3+NWR+QVxaZUOkJ0egQkcCQ="; # 261.22158.47
}; # };
#
# autoPatchelfIgnoreMissingDeps = [ # # autoPatchelfIgnoreMissingDeps = [
# "libcrypto.so.1.1" # # "libcrypto.so.1.1"
# "libssl.so.1.1" # # "libssl.so.1.1"
# ]; # # ];
#
postFixup = '' # postFixup = ''
# Patch python3.12 shared libs that the upstream glob (python3.8) misses # # Patch python3.12 shared libs that the upstream glob (python3.8) misses
find $out -path '*/python3.*/lib-dynload/*.so' -exec patchelf \ # find $out -path '*/python3.*/lib-dynload/*.so' -exec patchelf \
--replace-needed libssl.so.1.1 libssl.so \ # --replace-needed libssl.so.1.1 libssl.so \
--replace-needed libcrypto.so.1.1 libcrypto.so \ # --replace-needed libcrypto.so.1.1 libcrypto.so \
--replace-needed libcrypt.so.1 libcrypt.so \ # --replace-needed libcrypt.so.1 libcrypt.so \
{} + # {} +
#
${oldAttrs.postFixup or ""} # ${oldAttrs.postFixup or ""}
''; # '';
}); # });
}; # };
# Now in Nixpkgs # Now in Nixpkgs
# neovide = prev.neovide.overrideAttrs (finalAttrs: prevAttrs: { # neovide = prev.neovide.overrideAttrs (finalAttrs: prevAttrs: {
@@ -94,4 +94,10 @@
}; };
in in
# Composes a list of overlays and returns a single overlay function that combines them. # Composes a list of overlays and returns a single overlay function that combines them.
nixpkgs.lib.composeManyExtensions [additions modifications] nixpkgs.lib.composeManyExtensions [
additions
modifications
# This is already a complete overlay with final: prev:, so it must be composed directly
(import ./latexminted.nix)
]
+67
View File
@@ -0,0 +1,67 @@
# Workaround for a broken `minted` in nixpkgs.
#
# The TeX Live snapshot in nixpkgs (2026-03-01) predates minted 3.8.0
# (2026-03-04) and still ships 3.7.0 together with a bundled `latexminted`
# 0.6.0 that does not run. Two independent replacements are needed:
#
# - the run container: minted.sty from the upstream 3.8.0 release, which
# requires `latexminted` >= 0.7.0;
# - the bin container: `pkgs.latexminted` (0.7.1), which works.
#
# The LaTeX package and the Python executable are versioned separately, hence
# the two unrelated version numbers.
#
# Delete this file once nixpkgs ships minted >= 3.8.0.
final: prev: let
version = "3.8.0";
# Byte-identical to the CTAN 3.8.0 release, but pinned and already unpacked
# (CTAN only ships minted.dtx, which would have to be run through docstrip).
src = prev.fetchFromGitHub {
owner = "gpoore";
repo = "minted";
rev = "631f7e8e93f37d4f6e7767ff45692d53e7c7360d"; # "[latex] minted v3.8.0"
hash = "sha256-xUWScWRR62ikRxxz/YEauWLirvhsQPCcyE1O6cpWZRw=";
};
minted = prev.texlive.pkgs.minted;
# texlive.withPackages reads pname/tlType/tlDeps/... off the containers, so
# reuse the original metadata instead of reconstructing it.
container = name: container: script:
prev.runCommand "minted-${version}${name}" {
inherit (container) meta;
passthru =
container.passthru
// {
inherit version;
};
}
script;
in {
texlive =
prev.texlive
// {
pkgs =
prev.texlive.pkgs
// {
minted =
minted
// {
tex = container "-tex" minted.tex ''
install -Dm444 -t "$out"/tex/latex/minted \
${src}/latex/minted/minted.sty \
${src}/latex/minted/minted1.sty \
${src}/latex/minted/minted2.sty
'';
# A bare symlink is enough: texlive.withPackages resolves and wraps
# everything under bin/ itself.
out = container "" minted.out ''
mkdir -p "$out"/bin
ln -s ${prev.lib.getExe prev.latexminted} "$out"/bin/latexminted
'';
};
};
};
}
+27 -26
View File
@@ -394,9 +394,9 @@ with mylib.networking; {
}; };
# Trims the journal if too large # Trims the journal if too large
journald.extraConfig = '' journald.settings.Journal = {
SystemMaxUse=50M SystemMaxUse = "50M";
''; };
acpid.enable = true; acpid.enable = true;
dbus.enable = true; dbus.enable = true;
@@ -418,29 +418,30 @@ with mylib.networking; {
systemd = { systemd = {
# TODO: Technically this should be a user service if it runs as ${username}? # TODO: Technically this should be a user service if it runs as ${username}?
timers."refresh-nps-cache" = {
wantedBy = ["timers.target"];
timerConfig = {
OnCalendar = "weekly"; # or however often you'd like
Persistent = true;
Unit = "refresh-nps-cache.service";
};
};
services."refresh-nps-cache" = { # timers."refresh-nps-cache" = {
# Make sure `nix` and `nix-env` are findable by systemd.services. # wantedBy = ["timers.target"];
path = ["/run/current-system/sw/"]; # timerConfig = {
after = ["network.target"]; # OnCalendar = "weekly"; # or however often you'd like
serviceConfig = { # Persistent = true;
Type = "oneshot"; # Unit = "refresh-nps-cache.service";
User = "${username}"; # };
}; # };
script = ''
set -eu # services."refresh-nps-cache" = {
echo "Start refreshing nps cache..." # # Make sure `nix` and `nix-env` are findable by systemd.services.
${inputs.nps.packages.${pkgs.stdenv.hostPlatform.system}.default}/bin/nps -dddd -e -r # path = ["/run/current-system/sw/"];
echo "... finished nps cache with exit code $?." # after = ["network.target"];
''; # serviceConfig = {
}; # Type = "oneshot";
# User = "${username}";
# };
# script = ''
# set -eu
# echo "Start refreshing nps cache..."
# ${inputs.nps.packages.${pkgs.stdenv.hostPlatform.system}.default}/bin/nps -dddd -e -r
# echo "... finished nps cache with exit code $?."
# '';
# };
}; };
} }
+2
View File
@@ -139,6 +139,8 @@
sops-nix.secrets.${username} = [ sops-nix.secrets.${username} = [
"makemkv-app-key" "makemkv-app-key"
"restic-repo-key" "restic-repo-key"
"context7-api-key"
"obsidian-rest-api-key"
]; ];
}; };
+1 -1
View File
@@ -7,7 +7,7 @@
}: let }: let
vectorchordVersion = "0.4.2"; vectorchordVersion = "0.4.2";
pgvectorsVersion = "0.2.0"; pgvectorsVersion = "0.2.0";
immichVersion = "3.0.1-cuda"; immichVersion = "3.2.0-cuda";
in { in {
virtualisation.oci-containers.containers = { virtualisation.oci-containers.containers = {
immich-database = { immich-database = {
+1 -1
View File
@@ -5,7 +5,7 @@
pkgs, pkgs,
... ...
}: let }: let
jellyfinVersion = "10.11.2"; jellyfinVersion = "version-12.1ubu2604";
in { in {
virtualisation.oci-containers.containers = { virtualisation.oci-containers.containers = {
jellyfin = { jellyfin = {
@@ -42,6 +42,13 @@ in {
boot.lanzaboote = { boot.lanzaboote = {
enable = true; enable = true;
autoGenerateKeys.enable = true;
# WARN: Needs persistent /var/lib/auto-cryptenroll
autoEnrollKeys = {
enable = true;
includeMicrosoftKeys = true;
};
# WARN: Make sure to persist this if using impermanence! # WARN: Make sure to persist this if using impermanence!
pkiBundle = "/var/lib/sbctl"; pkiBundle = "/var/lib/sbctl";
@@ -76,6 +76,7 @@ in {
(mkRDir "/var/db/sudo" m711) (mkRDir "/var/db/sudo" m711)
(mkRDir "/var/lib/auto-cryptenroll" m755) # Lanzaboote
(mkRDir "/var/lib/bluetooth" m755) # m700 (mkRDir "/var/lib/bluetooth" m755) # m700
(mkRDir "/var/lib/btrfs" m755) (mkRDir "/var/lib/btrfs" m755)
(mkRDir "/var/lib/containers" m755) (mkRDir "/var/lib/containers" m755)
@@ -84,7 +85,7 @@ in {
(mkRDir "/var/lib/libvirt" m755) (mkRDir "/var/lib/libvirt" m755)
(mkRDir "/var/lib/NetworkManager" m755) (mkRDir "/var/lib/NetworkManager" m755)
(mkRDir "/var/lib/nixos" m755) (mkRDir "/var/lib/nixos" m755)
(mkRDir "/var/lib/sbctl" m755) (mkRDir "/var/lib/sbctl" m755) # Lanzaboote
(mkRDir "/var/lib/systemd" m755) (mkRDir "/var/lib/systemd" m755)
(mkRDir "/var/tmp" m777) (mkRDir "/var/tmp" m777)
@@ -121,6 +122,7 @@ in {
# The shit some applications add to ~/ without asking # The shit some applications add to ~/ without asking
# (mkUDir ".android" m755) # Unity # (mkUDir ".android" m755) # Unity
(mkUDir ".claude" m755) (mkUDir ".claude" m755)
(mkUDir ".codex" m755)
# (mkUDir ".comfy" m755) # (mkUDir ".comfy" m755)
(mkUDir ".docker" m755) (mkUDir ".docker" m755)
# (mkUDir ".gradle" m755) # Unity # (mkUDir ".gradle" m755) # Unity
@@ -156,12 +158,14 @@ in {
# Config # Config
# (mkUDir ".config/.android" m755) # Unity # (mkUDir ".config/.android" m755) # Unity
(mkUDir ".config/ai.opencode.desktop" m755)
# (mkUDir ".config/beekeeper-studio" m755) # (mkUDir ".config/beekeeper-studio" m755)
(mkUDir ".config/beets" m755) (mkUDir ".config/beets" m755)
(mkUDir ".config/blender" m755) (mkUDir ".config/blender" m755)
(mkUDir ".config/chromium" m755) (mkUDir ".config/chromium" m755)
(mkUDir ".config/Claude" m755) # Claude desktop (mkUDir ".config/Claude" m755) # Claude desktop
(mkUDir ".config/Code" m755) (mkUDir ".config/Code" m755)
(mkUDir ".config/Codex" m755)
(mkUDir ".config/Ferdium" m755) (mkUDir ".config/Ferdium" m755)
(mkUDir ".config/feishin" m755) (mkUDir ".config/feishin" m755)
(mkUDir ".config/fish/completions" m755) (mkUDir ".config/fish/completions" m755)
+6 -1
View File
@@ -21,7 +21,7 @@ in {
${mime.defaultTextEditor} = mime.textTypes; ${mime.defaultTextEditor} = mime.textTypes;
${mime.defaultFileBrowser} = ["inode/directory"]; ${mime.defaultFileBrowser} = ["inode/directory"];
${mime.defaultWebBrowser} = mime.webTypes; ${mime.defaultWebBrowser} = mime.webTypes;
${mime.defaultPdfViewer} = ["application/pdf"]; ${mime.defaultPdfViewer} = ["application/pdf" "application/epub+zip"];
${mime.defaultImageViewer} = mime.imageTypes; ${mime.defaultImageViewer} = mime.imageTypes;
# If audio and video player are equal, we assign all types to the audio player, # If audio and video player are equal, we assign all types to the audio player,
@@ -75,6 +75,11 @@ in {
"chromium-browser.desktop" "chromium-browser.desktop"
"com.google.Chrome.desktop" "com.google.Chrome.desktop"
"firefox.desktop" "firefox.desktop"
"org.onlyoffice.desktopeditors.desktop"
"calibre-ebook-edit.desktop"
"calibre-ebook-viewer.desktop"
"calibre-gui.desktop"
"calibre-lrfviewer.desktop"
]; ];
"text/plain" = [ "text/plain" = [
"firefox.desktop" "firefox.desktop"
+2 -2
View File
@@ -34,11 +34,11 @@ in {
secrets = let secrets = let
mkSecret = name: { mkSecret = name: {
${name} = lib.mkMerge [ ${name} = lib.mkMerge [
(lib.optionalAttrs pkgs.stdenv.isLinux { (lib.optionalAttrs pkgs.stdenv.hostPlatform.isLinux {
owner = config.users.users.${username}.name; owner = config.users.users.${username}.name;
group = config.users.users.${username}.group; group = config.users.users.${username}.group;
}) })
(lib.optionalAttrs pkgs.stdenv.isDarwin { (lib.optionalAttrs pkgs.stdenv.hostPlatform.isDarwin {
owner = config.users.users.${username}.name; owner = config.users.users.${username}.name;
group = "staff"; # Apparently there's no way to get the primary group? group = "staff"; # Apparently there's no way to get the primary group?
}) })
+5 -3
View File
@@ -11,6 +11,8 @@ jellyfin-password: ENC[AES256_GCM,data:ugfwgpkIiLY0O+m/UGnBB5AFPBkCcai+RQOkxiCSo
# #
makemkv-app-key: ENC[AES256_GCM,data:/pTxr4q4ucJLx5VI8ySzOgd4g1s+6lcZNe4crxRmidTYrhJ0I6V3CIhm4wLC105W+Xka6HIZTqPn8SbqcMC4Dt3wSus=,iv:aYsGobD+Vl/VUNAHcAxQb7HEmLT8aXyKNOELgzvKDH4=,tag:xhnVb/ns6VZEnTuoUv9w5A==,type:str] makemkv-app-key: ENC[AES256_GCM,data:/pTxr4q4ucJLx5VI8ySzOgd4g1s+6lcZNe4crxRmidTYrhJ0I6V3CIhm4wLC105W+Xka6HIZTqPn8SbqcMC4Dt3wSus=,iv:aYsGobD+Vl/VUNAHcAxQb7HEmLT8aXyKNOELgzvKDH4=,tag:xhnVb/ns6VZEnTuoUv9w5A==,type:str]
restic-repo-key: ENC[AES256_GCM,data:lSFuhjbhdQq4cabAVFGQ4kuaJxb7EhXgBDlgoEQWJhs=,iv:7IhGDBYEwY1TwLvc/4DOkUBQ3eqSszZcKwnT7Lllfps=,tag:yJVlMi9X0W+Kh3zMkb0QuA==,type:str] restic-repo-key: ENC[AES256_GCM,data:lSFuhjbhdQq4cabAVFGQ4kuaJxb7EhXgBDlgoEQWJhs=,iv:7IhGDBYEwY1TwLvc/4DOkUBQ3eqSszZcKwnT7Lllfps=,tag:yJVlMi9X0W+Kh3zMkb0QuA==,type:str]
context7-api-key: ENC[AES256_GCM,data:lZfrz5pBDybBkswgZM3jKLM9bdXOXeFUI9wFB8BJ5aLYqmf2oRHIJi/85w==,iv:MQYZKsTG++CYfpJret1WSv7+q2ZmONCDl4OwdRo+YUk=,tag:MrWBn3CKDUDZLLIFZWV0tA==,type:str]
obsidian-rest-api-key: ENC[AES256_GCM,data:+CmQAX0AoSmCPMF9QL3NkWVArt7N0Ci9obHKpwQUPolcdsTnAsPMWu6GAWVvqs8Qmjz5Hk3gwM0YP2JdLEF0cw==,iv:U1SsPdiJIT7q+md1Q61Ro530s7vrl+XBgu+6/ffcrEQ=,tag:xrTRPve9DcumQjlr+aKsLg==,type:str]
# #
#ENC[AES256_GCM,data:Raagjz1qPvXC,iv:OSWTKaIlmo1paU2ZZn20XMeZ2gdM52pHmVZ3m2ngCdI=,tag:bPCdvjOFjpxxkrwA7Mhl5Q==,type:comment] #ENC[AES256_GCM,data:Raagjz1qPvXC,iv:OSWTKaIlmo1paU2ZZn20XMeZ2gdM52pHmVZ3m2ngCdI=,tag:bPCdvjOFjpxxkrwA7Mhl5Q==,type:comment]
# #
@@ -39,7 +41,7 @@ sops:
FAbbvZZ/EdIk/njLEcayFN7B4ftTcD/f4XJZiyosilZnIkk76bMOHA== FAbbvZZ/EdIk/njLEcayFN7B4ftTcD/f4XJZiyosilZnIkk76bMOHA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----
recipient: age14ph8vrj657e7s35d60xehzuq46t9zd6pzcm6pw4jragzrvf6xs9s77usnm recipient: age14ph8vrj657e7s35d60xehzuq46t9zd6pzcm6pw4jragzrvf6xs9s77usnm
lastmodified: "2026-07-02T19:27:51Z" lastmodified: "2026-09-14T21:08:40Z"
mac: ENC[AES256_GCM,data:IkpzDK4F1pEoGx1WyG8ksgMFuEa2h9KeF3m3PzM8KQkWo9iVt3jJn80jHEzWAm8riWIbo7fRkxyRetlSFTZf+MrByotgkWVVx6dMIVNYAOcg2IOK3s4NnX0L65MjbfWGQp/d27QzzEbd14WyklMWm2UO3ei82tF+UKYUEFJ2BWk=,iv:8LimsncylU+HhvVKNnjfyqZskZA72FQe92C4VrNWyQ0=,tag:L6CEno9m3ZncOskjZibq+Q==,type:str] mac: ENC[AES256_GCM,data:tfkmsJfWYV11ruw8fCUkJ2gWQAvQJ4Gmsz72LnmiCdlvzeo4x9iM268ZJnuaPRuv6BXLp2XGGA4CbqhfZbO6cRxAawVfbxY2IRSo1JWITIY8qxKLb07jDMpQu/JjJz7J5T556UEvOsW6HrK3d0xvNlJ4yQIuVCBjttKTdRu5g9Y=,iv:mV5i0xJGu6fnSNPLm9J3NDDgN+sB6iadue917UjR+oU=,tag:h/vaeQ02wK/qKANerWIywQ==,type:str]
unencrypted_suffix: _unencrypted unencrypted_suffix: _unencrypted
version: 3.13.1 version: 3.13.3