refactor: move from den based to flake-parts based

This commit is contained in:
2026-04-21 00:59:54 +02:00
parent d2ab961c48
commit 5bed1336c0
71 changed files with 1832 additions and 2472 deletions
+56 -74
View File
@@ -1,101 +1,83 @@
# Repository Guidelines # Repository Guidelines
## Project Structure & Module Organization ## Project Structure & Module Organization
This repository is a Den-based NixOS flake. `flake.nix` evaluates `./modules` through `import-tree`, so normal `.nix` files under `modules/` are auto-imported. This repository is a simplified `flake-parts` NixOS flake. `flake.nix` imports `./modules` through `import-tree`, so normal `.nix` files under `modules/` are loaded automatically unless their file or directory name starts with `_`.
- `modules/den.nix` imports the Den flake module and the `lux` namespace. - `modules/flake-parts.nix` defines the `flake-parts` setup, formatter, and the exported `nixosConfigurations`.
- `modules/defaults.nix` sets repo-wide Den defaults, enables `den._.mutual-provider`, and configures `den.ctx.hm-host`. - `modules/hosts/<name>/default.nix` defines one top-level `flake.modules.nixos.<host>` module and assembles that machine by importing reusable features, user modules, and host-local helpers.
- `modules/schema.nix` defines the custom Den host and user schema used by this repo. - `modules/hosts/<name>/_*.nix` are private host-local helper modules such as hardware and disk layout files.
- `modules/infra.nix` defines `den.hosts.x86_64-linux.<name>`, each host entity's `users` attrset, and the host/user data attached to those entities. - `modules/users/<name>.nix` defines one reusable NixOS user module and the baseline Home Manager imports for that account.
- `modules/bundles.nix` defines bundle aspects that group other aspects. A bundle aspect may exist only to compose `includes`; `local-session` is an example. - `modules/features/*.nix` contains reusable NixOS and Home Manager feature modules.
- `modules/hosts/` contains host-specific composition and hardware data for `orion`, `polaris`, and `zenith`. - `modules/features/<feature>/default.nix` is used when a feature needs private helper files, for example `niri/_bindings.nix`.
- `modules/features/` contains reusable aspects. In this repo, "feature" is only a directory label, not a Den primitive. - `modules/features/services/*.nix` contains reusable service-oriented NixOS modules.
- `modules/users/` defines per-user aspects. - `modules/secrets/sops.nix` wires `sops-nix` for both NixOS and Home Manager.
- `modules/secrets/` wires `sops-nix` and stores the encrypted `secrets.yaml`. - `modules/secrets/secrets.yaml` stores encrypted secrets, with `.sops.yaml` defining SOPS creation rules.
- `.agents/den/` is a local checkout of Den with source, docs, and examples. - `modules/_treefmt.nix` configures repository formatting.
Keep host files thin. Shared behavior belongs in `modules/features/` or `modules/bundles.nix`. Keep host files thin. Shared behavior belongs in `modules/features/` or `modules/users/`. Host files should mainly compose imports and hold host-only settings such as monitor layouts, hardware quirks, boot tweaks, and machine-local firewall or service choices.
When Den behavior is unclear, read `.agents/den/modules/` and `.agents/den/nix/lib/` first. Use `.agents/den/templates/ci/` as example code. Use `.agents/den/docs/` only for design rationale, terminology, and usage guidance.
Do not infer Den behavior from surface symptoms or from where an aspect is included; reason from the actual context pipeline.
## Den Mental Model ## Mental Model
Den is aspect-first and context-driven. This repo is direct module composition around `flake.modules`, not the old inventory-driven dendritic design.
- Host, user, and home are entity kinds in Den. This repo defines host and user entities; it does not define standalone home entities under `modules/`. - Reusable building blocks are exposed as `flake.modules.nixos.<name>` and `flake.modules.homeManager.<name>`.
- An aspect is the unit of behavior. A single aspect may define `nixos`, `homeManager`, `darwin`, `user`, or other class fragments for one concern. - Host modules are the composition root. They import the reusable NixOS modules they need, enable Home Manager, and add any host-specific Home Manager imports inline.
- A context stage applies a resolved aspect to a context; Den then follows `into.*` and `provides.*`. - User modules define the Unix user plus that accounts baseline Home Manager setup.
- `homeManager` is a forwarding class. - There is no `config.repo`, inventory schema, profiles layer, or attachment builder anymore.
In practice: In practice:
- Including an aspect does not by itself create a forwarding path. - Prefer importing a feature module directly over inventing a repo-local option just to toggle it.
- Parametric matching does not by itself create a forwarding path. - Put cross-host reusable behavior in `modules/features/`.
- A class fragment reaches its final option path only if a context stage or forwarding class actually puts it there. - Put account-specific defaults in `modules/users/`.
- If you cannot name the context stage and forwarding path, treat the claim as unverified. - Keep private helper files `_`-prefixed so `import-tree` does not expose them as top-level modules.
- Match the existing split between NixOS composition in host modules and Home Manager composition in user or host modules.
## Den Context Stages And Forwarding Mechanisms ## Current Host Composition
These are the mechanisms most relevant to the context pipeline in this repo. There are three exported hosts:
- `den.ctx.host`: host context stage; applies `fixedTo { host; } host.aspect` - `orion`: server-oriented host with `kiri`, SOPS, and service modules such as Caddy, Gitea, Vaultwarden, Radicale, Actual, and OpenSSH.
- `den.ctx.user`: user context stage from `den.ctx.host.into.user`; applies `fixedTo { host; user; } user.aspect` - `polaris`: graphical desktop host with `kiri` and `ergon`, hardware imports, Niri, Steam, local desktop features, and host-specific monitor layout.
- `den._.mutual-provider`: battery included on `den.ctx.user` in this repo; routes host-to-user and user-to-host through `provides.<name>`, host-to-all-users through `provides.to-users`, user-to-hosts through `provides.to-hosts`, and user-to-other-users on the same host through the same user context pipeline. In Den generally it also has standalone-home behavior, but this repo does not use standalone `den.homes` - `zenith`: graphical laptop host with `kiri` and `ergon`, Niri, laptop hardware support, firmware updates, and host-specific monitor layout.
- `den.ctx.hm-host` / `den.ctx.hm-user`: derived home-env context stages
- `den._.define-user`: battery included by `den.default` in this repo; defines base OS user fields and base `homeManager.home.username` / `home.homeDirectory` fields
- `homeManager`: forwarding class into `home-manager.users.<name>`
- `den._.os-user`: framework battery forwarding the `user` class into `users.users.<name>`; useful in Den generally, but not used in this repo today
- `den._.forward`: battery for custom class/path forwarding
## Den Helper Functions When adjusting user-facing software, check whether it belongs in:
These are the Den helpers that matter most in this repo.
- `den.lib.perHost`: exact `{ host }` wrapper - a user baseline in `modules/users/<name>.nix`
- `den.lib.perUser`: exact `{ host, user }` wrapper - a reusable Home Manager feature in `modules/features/*.nix`
- `den.lib.perHome`: exact `{ home }` wrapper; not used by this flake today - a host-local extension inside `modules/hosts/<name>/default.nix`
- `den.lib.parametric`: explicit parametric wrapper; default matching is `atLeast`
- `den.lib.parametric.exactly`: explicit exact-match wrapper
## Den Forwarding Proof Obligation Be careful not to move host-specific Home Manager imports into a user baseline unless that behavior should apply on every host that imports that user module.
When making or reviewing any Den forwarding change, do not infer behavior from where code is declared or included.
You must identify all four of these explicitly:
1. Source: which aspect actually owns the class fragment?
2. Context stage: which `den.ctx.*` stage applies it?
3. Destination: which final evaluated option path should contain the result?
4. Mechanism: which `into.*` transition reaches the context stage, and which class application, `provides.*`, forwarding class, or `den._.forward` step places it at the destination?
If any of those answers are missing, unclear, or based on analogy, treat the claim as unverified.
Before presenting a forwarding claim as a recommendation or review finding, verify it at the evaluated destination with `nix eval`.
Minimum checks:
- host-selected `homeManager` behavior: inspect `nixosConfigurations.<host>.config.home-manager.users.<user>`
- OS user forwarding via `user` class: inspect `nixosConfigurations.<host>.config.users.users.<user>`
- mutual host/user forwarding through `provides.<name>`, `provides.to-users`, or `provides.to-hosts`: inspect the final destination option, not the declaration site
- custom forwarding through `den._.forward`: inspect the exact target path created by the forwarder
## Validation And Development Commands ## Validation And Development Commands
Run commands from the repository root. Run commands from the repository root.
- `nix build --no-link --show-trace .#nixosConfigurations.<host>.config.system.build.toplevel`: baseline validation for one host without activation and without creating a `result` symlink. - `nix build --no-link --show-trace .#nixosConfigurations.<host>.config.system.build.toplevel`: baseline validation for one host.
- `nix build --no-link --show-trace .#nixosConfigurations.orion.config.system.build.toplevel .#nixosConfigurations.polaris.config.system.build.toplevel .#nixosConfigurations.zenith.config.system.build.toplevel`: validate all currently defined hosts in one invocation. - `nix build --no-link --show-trace .#nixosConfigurations.orion.config.system.build.toplevel .#nixosConfigurations.polaris.config.system.build.toplevel .#nixosConfigurations.zenith.config.system.build.toplevel`: validate all defined hosts in one invocation.
- `nixos-rebuild build --flake .#<host>`: use the standard rebuild path without activation when you specifically want `nixos-rebuild` semantics. - `nixos-rebuild build --flake .#<host>`: use when you specifically want `nixos-rebuild` semantics without activation.
- `nix fmt`: format Nix files using the flake-provided `nixfmt` formatter. - `nix eval --json .#nixosConfigurations.<host>.config.<option>`: inspect a single evaluated option while iterating.
- `nix eval .#nixosConfigurations.<host>.config.<option>`: inspect a single option while iterating. - `nix fmt`: format the repository using the flake-provided formatter from `modules/_treefmt.nix`.
- `nix store diff-closures <old> <new>`: compare built system closures when reviewing refactors for parity or regressions.
This repo does not define a `checks` output or a first-party test suite. Treat evaluation and build-only checks as the baseline. `nix flake check` is therefore not the baseline validation command here. `nixos-rebuild dry-activate` is not a baseline validation command either: it is activation-oriented, applies to the target system being rebuilt, and its own help text says the reported change set is not guaranteed to be complete. This repo does not define a first-party `checks` output. Validation is primarily host builds plus targeted `nix eval` checks.
For Den context-stage or forwarding changes, use the destination checks above.
## Coding Style & Naming Conventions ## Coding Style & Naming Conventions
Use two-space indentation and standard Nix attrset formatting. Prefer small `let` bindings, lowerCamelCase local names, and lowercase file names such as `sops-password.nix`. Match the surrounding module style instead of reformatting unrelated code. Use two-space indentation and standard Nix attrset formatting. Prefer small `let` bindings, lowerCamelCase local names, and lowercase file names.
Prefer Den composition through `includes`; avoid host-specific duplication when a reusable aspect or bundle aspect is clearer. - Define reusable modules as `flake.modules.nixos.<name>` or `flake.modules.homeManager.<name>`.
Keep the configuration aspect-first. When a class fragment must cross context boundaries, express that through an explicit forwarding mechanism instead of relying on implicit host/user propagation. - Keep one obvious feature per file or directory.
- Use `default.nix` only when the feature needs private helper files alongside it.
- Match surrounding style instead of reformatting unrelated code.
- Prefer explicit host imports over hidden indirection.
## Commit ## Commit
Follow the history style: short imperative subjects, optionally with a conventional prefix, for example `refactor: restructure openssh config`. Keep each commit focused on one concern. Follow the existing history style: short imperative subjects, optionally with a conventional prefix, for example `refactor: simplify host composition`.
## Security & Configuration Tips ## Security & Configuration Tips
Never commit plaintext secrets. Add or update secrets through `modules/secrets/secrets.yaml` and reference them via `config.sops.secrets.<name>.path`. Be explicit about firewall, SSH, disk, boot, or firmware changes; those are the highest-risk edits here. Never commit plaintext secrets. Add or update secrets through `modules/secrets/secrets.yaml` and reference them via `config.sops.secrets.<name>.path`.
Be explicit and cautious with changes to:
- firewall and OpenSSH settings
- disk layout and boot configuration
- SOPS key handling and admin user access
- firmware, hardware, and authentication settings
- host-vs-user module boundaries, because it is easy to accidentally broaden behavior to the wrong machines
Generated
+42 -166
View File
@@ -1,21 +1,5 @@
{ {
"nodes": { "nodes": {
"den": {
"locked": {
"lastModified": 1776133621,
"narHash": "sha256-RNbDvS6voiq2GalVHRt6w2EpdlEmmCjUAb6fvPO9PnE=",
"owner": "vic",
"repo": "den",
"rev": "927f4d8e2be40d05c976a91bbec66238c622bbf5",
"type": "github"
},
"original": {
"owner": "vic",
"ref": "v0.16.0",
"repo": "den",
"type": "github"
}
},
"disko": { "disko": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
@@ -35,22 +19,6 @@
} }
}, },
"flake-compat": { "flake-compat": {
"flake": false,
"locked": {
"lastModified": 1751685974,
"narHash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=",
"ref": "refs/heads/main",
"rev": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1",
"revCount": 92,
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
},
"original": {
"type": "git",
"url": "https://git.lix.systems/lix-project/flake-compat.git"
}
},
"flake-compat_2": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1767039857, "lastModified": 1767039857,
@@ -84,27 +52,6 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1769996383,
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_2" "nixpkgs": "nixpkgs_2"
@@ -157,43 +104,6 @@
"url": "ssh://gitea@orion/kiri/lux-pkgs" "url": "ssh://gitea@orion/kiri/lux-pkgs"
} }
}, },
"mnw": {
"locked": {
"lastModified": 1770419553,
"narHash": "sha256-b1XqsH7AtVf2dXmq2iyRr2NC1yG7skY7Z6N2MpWHlK4=",
"owner": "Gerg-L",
"repo": "mnw",
"rev": "2aaffa8030d0b262176146adbb6b0e6374ce2957",
"type": "github"
},
"original": {
"owner": "Gerg-L",
"repo": "mnw",
"type": "github"
}
},
"ndg": {
"inputs": {
"nixpkgs": [
"nvf",
"nixpkgs"
]
},
"locked": {
"lastModified": 1768214250,
"narHash": "sha256-hnBZDQWUxJV3KbtvyGW5BKLO/fAwydrxm5WHCWMQTbw=",
"owner": "feel-co",
"repo": "ndg",
"rev": "a6bd3c1ce2668d096e4fdaaa03ad7f03ba1fbca8",
"type": "github"
},
"original": {
"owner": "feel-co",
"ref": "refs/tags/v2.6.0",
"repo": "ndg",
"type": "github"
}
},
"niri": { "niri": {
"inputs": { "inputs": {
"niri-stable": "niri-stable", "niri-stable": "niri-stable",
@@ -331,22 +241,6 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1776067740,
"narHash": "sha256-B35lpsqnSZwn1Lmz06BpwF7atPgFmUgw1l8KAV3zpVQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7e495b747b51f95ae15e74377c5ce1fe69c1765f",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_10": { "nixpkgs_10": {
"locked": { "locked": {
"lastModified": 1768564909, "lastModified": 1768564909,
@@ -457,22 +351,6 @@
} }
}, },
"nixpkgs_8": { "nixpkgs_8": {
"locked": {
"lastModified": 1774386573,
"narHash": "sha256-4hAV26quOxdC6iyG7kYaZcM3VOskcPUrdCQd/nx8obc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "46db2e09e1d3f113a13c0d7b81e2f221c63b8ce9",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_9": {
"locked": { "locked": {
"lastModified": 1775888245, "lastModified": 1775888245,
"narHash": "sha256-nwASzrRDD1JBEu/o8ekKYEXm/oJW6EMCzCRdrwcLe90=", "narHash": "sha256-nwASzrRDD1JBEu/o8ekKYEXm/oJW6EMCzCRdrwcLe90=",
@@ -488,6 +366,22 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_9": {
"locked": {
"lastModified": 1776329215,
"narHash": "sha256-a8BYi3mzoJ/AcJP8UldOx8emoPRLeWqALZWu4ZvjPXw=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "b86751bc4085f48661017fa226dee99fab6c651b",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"noctalia": { "noctalia": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_7", "nixpkgs": "nixpkgs_7",
@@ -530,33 +424,13 @@
"type": "github" "type": "github"
} }
}, },
"nvf": {
"inputs": {
"flake-compat": "flake-compat",
"flake-parts": "flake-parts_2",
"mnw": "mnw",
"ndg": "ndg",
"nixpkgs": "nixpkgs_8",
"systems": "systems_2"
},
"locked": {
"lastModified": 1776331518,
"narHash": "sha256-Hj6Rqmyv7f2CkQN4f3NLnK0VUJM/ypfHIrkGckA4WQA=",
"owner": "notashelf",
"repo": "nvf",
"rev": "39416a521dbbc3b722de1bb3607cddaa1e698f4a",
"type": "github"
},
"original": {
"owner": "notashelf",
"repo": "nvf",
"type": "github"
}
},
"root": { "root": {
"inputs": { "inputs": {
"den": "den",
"disko": "disko", "disko": "disko",
"flake-parts": [
"lux-pkgs",
"flake-parts"
],
"home-manager": "home-manager", "home-manager": "home-manager",
"import-tree": "import-tree", "import-tree": "import-tree",
"lux-pkgs": "lux-pkgs", "lux-pkgs": "lux-pkgs",
@@ -564,16 +438,15 @@
"nix-wrapper-modules": "nix-wrapper-modules", "nix-wrapper-modules": "nix-wrapper-modules",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
"nixpkgs": "nixpkgs_6", "nixpkgs": "nixpkgs_6",
"nixpkgs-stable": "nixpkgs-stable_2",
"noctalia": "noctalia", "noctalia": "noctalia",
"nvf": "nvf",
"sops-nix": "sops-nix", "sops-nix": "sops-nix",
"treefmt-nix": "treefmt-nix_2",
"vicinae-extensions": "vicinae-extensions" "vicinae-extensions": "vicinae-extensions"
} }
}, },
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_9" "nixpkgs": "nixpkgs_8"
}, },
"locked": { "locked": {
"lastModified": 1776119890, "lastModified": 1776119890,
@@ -619,21 +492,6 @@
"type": "github" "type": "github"
} }
}, },
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": { "treefmt-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -656,6 +514,24 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix_2": {
"inputs": {
"nixpkgs": "nixpkgs_9"
},
"locked": {
"lastModified": 1775636079,
"narHash": "sha256-pc20NRoMdiar8oPQceQT47UUZMBTiMdUuWrYu2obUP0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"vicinae": { "vicinae": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -683,9 +559,9 @@
}, },
"vicinae-extensions": { "vicinae-extensions": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat",
"nixpkgs": "nixpkgs_10", "nixpkgs": "nixpkgs_10",
"systems": "systems_3", "systems": "systems_2",
"vicinae": "vicinae" "vicinae": "vicinae"
}, },
"locked": { "locked": {
+3 -17
View File
@@ -2,18 +2,17 @@
description = "NixOS Configuration"; description = "NixOS Configuration";
inputs = { inputs = {
den.url = "github:vic/den/v0.16.0";
disko.url = "github:nix-community/disko"; disko.url = "github:nix-community/disko";
flake-parts.follows = "lux-pkgs/flake-parts";
home-manager.url = "github:nix-community/home-manager"; home-manager.url = "github:nix-community/home-manager";
import-tree.url = "github:vic/import-tree"; import-tree.url = "github:vic/import-tree";
niri.url = "github:sodiboo/niri-flake"; niri.url = "github:sodiboo/niri-flake";
nix-wrapper-modules.url = "github:BirdeeHub/nix-wrapper-modules"; nix-wrapper-modules.url = "github:BirdeeHub/nix-wrapper-modules";
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz"; nixpkgs.url = "https://channels.nixos.org/nixpkgs-unstable/nixexprs.tar.xz";
nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-25.11";
noctalia.url = "github:noctalia-dev/noctalia-shell"; noctalia.url = "github:noctalia-dev/noctalia-shell";
nvf.url = "github:notashelf/nvf";
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
treefmt-nix.url = "github:numtide/treefmt-nix";
#vicinae.url = "github:vicinaehq/vicinae"; #vicinae.url = "github:vicinaehq/vicinae";
vicinae-extensions.url = "github:vicinaehq/extensions"; vicinae-extensions.url = "github:vicinaehq/extensions";
@@ -21,18 +20,5 @@
lux-pkgs.url = "git+ssh://gitea@orion/kiri/lux-pkgs"; lux-pkgs.url = "git+ssh://gitea@orion/kiri/lux-pkgs";
}; };
outputs = outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules);
inputs:
let
flake = (inputs.nixpkgs.lib.evalModules {
modules = [ (inputs.import-tree ./modules) ];
specialArgs.inputs = inputs;
}).config.flake;
in
flake
// {
formatter = inputs.nixpkgs.lib.genAttrs flake.den.systems (
system: inputs.nixpkgs.legacyPackages.${system}.nixfmt
);
};
} }
-50
View File
@@ -1,50 +0,0 @@
{ den, lux, ... }:
{
lux.bundles._.local-session = {
includes = with lux; [
nix
region-nl
sddm
niri
audio
bluetooth
clipboard
flatpak
fonts
local-apps
networking
pinentry
printing
qbittorrent-client
system-base
vicinae
xdg
theme
noctalia
];
};
lux.bundles._.local-session-user = {
includes = with lux; [
nix
niri
clipboard
local-apps
pinentry
qbittorrent-client
vicinae
xdg
theme
noctalia
];
};
lux.bundles._.development = {
includes = with lux; [
git
dev-tools
podman
gemini
];
};
}
-23
View File
@@ -1,23 +0,0 @@
{ den, ... }:
let
configState = "24.05";
in
{
den.default = {
includes = [
den._.define-user
den._.hostname
];
nixos.system.stateVersion = configState;
homeManager.home.stateVersion = configState;
};
den.ctx.user.includes = [ den._.mutual-provider ];
_module.args.__findFile = den.lib.__findFile;
den.ctx.hm-host.nixos.home-manager = {
useGlobalPkgs = true;
backupFileExtension = "bak";
};
}
-9
View File
@@ -1,9 +0,0 @@
{ inputs, den, ... }:
{
imports = [
inputs.den.flakeModule
(inputs.den.namespace "lux" true)
];
flake.den = den;
}
+16 -16
View File
@@ -3,7 +3,7 @@
bar = { bar = {
barType = "simple"; barType = "simple";
position = "top"; position = "top";
monitors = []; monitors = [ ];
density = "default"; density = "default";
showOutline = false; showOutline = false;
showCapsule = false; showCapsule = false;
@@ -69,13 +69,13 @@
]; ];
right = [ right = [
{ {
blacklist = []; blacklist = [ ];
chevronColor = "none"; chevronColor = "none";
colorizeIcons = false; colorizeIcons = false;
drawerEnabled = true; drawerEnabled = true;
hidePassive = false; hidePassive = false;
id = "Tray"; id = "Tray";
pinned = []; pinned = [ ];
} }
{ {
displayMode = "onhover"; displayMode = "onhover";
@@ -95,7 +95,7 @@
} }
]; ];
}; };
screenOverrides = []; screenOverrides = [ ];
}; };
general = { general = {
avatarImage = "/home/kiri/.face"; avatarImage = "/home/kiri/.face";
@@ -130,7 +130,7 @@
clockStyle = "custom"; clockStyle = "custom";
clockFormat = "hh\\nmm"; clockFormat = "hh\\nmm";
passwordChars = false; passwordChars = false;
lockScreenMonitors = []; lockScreenMonitors = [ ];
lockScreenBlur = 0; lockScreenBlur = 0;
lockScreenTint = 0; lockScreenTint = 0;
keybinds = { keybinds = {
@@ -210,7 +210,7 @@
enabled = true; enabled = true;
overviewEnabled = false; overviewEnabled = false;
directory = "/home/kiri/media/images/wallpapers"; directory = "/home/kiri/media/images/wallpapers";
monitorDirectories = []; monitorDirectories = [ ];
enableMultiMonitorDirectories = false; enableMultiMonitorDirectories = false;
showHiddenFiles = false; showHiddenFiles = false;
viewMode = "recursive"; viewMode = "recursive";
@@ -242,7 +242,7 @@
wallhavenResolutionWidth = ""; wallhavenResolutionWidth = "";
wallhavenResolutionHeight = ""; wallhavenResolutionHeight = "";
sortOrder = "name"; sortOrder = "name";
favorites = []; favorites = [ ];
}; };
appLauncher = { appLauncher = {
enableClipboardHistory = true; enableClipboardHistory = true;
@@ -252,7 +252,7 @@
clipboardWatchTextCommand = "wl-paste --type text --watch cliphist store"; clipboardWatchTextCommand = "wl-paste --type text --watch cliphist store";
clipboardWatchImageCommand = "wl-paste --type image --watch cliphist store"; clipboardWatchImageCommand = "wl-paste --type image --watch cliphist store";
position = "top_center"; position = "top_center";
pinnedApps = []; pinnedApps = [ ];
useApp2Unit = false; useApp2Unit = false;
sortByMostUsed = true; sortByMostUsed = true;
terminalCommand = "kitty -e"; terminalCommand = "kitty -e";
@@ -362,8 +362,8 @@
floatingRatio = 1; floatingRatio = 1;
size = 1; size = 1;
onlySameOutput = true; onlySameOutput = true;
monitors = []; monitors = [ ];
pinnedApps = []; pinnedApps = [ ];
colorizeIcons = false; colorizeIcons = false;
showLauncherIcon = false; showLauncherIcon = false;
launcherPosition = "end"; launcherPosition = "end";
@@ -454,7 +454,7 @@
enabled = true; enabled = true;
enableMarkdown = false; enableMarkdown = false;
density = "default"; density = "default";
monitors = []; monitors = [ ];
location = "top_right"; location = "top_right";
overlayLayer = true; overlayLayer = true;
backgroundOpacity = 1; backgroundOpacity = 1;
@@ -492,14 +492,14 @@
1 1
2 2
]; ];
monitors = []; monitors = [ ];
}; };
audio = { audio = {
volumeStep = 5; volumeStep = 5;
volumeOverdrive = false; volumeOverdrive = false;
cavaFrameRate = 30; cavaFrameRate = 30;
visualizerType = "linear"; visualizerType = "linear";
mprisBlacklist = []; mprisBlacklist = [ ];
preferredPlayer = ""; preferredPlayer = "";
volumeFeedback = false; volumeFeedback = false;
volumeFeedbackSoundFile = ""; volumeFeedbackSoundFile = "";
@@ -508,7 +508,7 @@
brightnessStep = 5; brightnessStep = 5;
enforceMinimum = true; enforceMinimum = true;
enableDdcSupport = false; enableDdcSupport = false;
backlightDeviceMappings = []; backlightDeviceMappings = [ ];
}; };
colorSchemes = { colorSchemes = {
useWallpaperColors = false; useWallpaperColors = false;
@@ -521,7 +521,7 @@
monitorForColors = ""; monitorForColors = "";
}; };
templates = { templates = {
activeTemplates = []; activeTemplates = [ ];
enableUserTheming = false; enableUserTheming = false;
}; };
nightLight = { nightLight = {
@@ -559,6 +559,6 @@
enabled = false; enabled = false;
overviewEnabled = true; overviewEnabled = true;
gridSnap = false; gridSnap = false;
monitorWidgets = []; monitorWidgets = [ ];
}; };
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.audio.nixos = { flake.modules.nixos.audio = {
security.rtkit.enable = true; security.rtkit.enable = true;
services.pipewire = { services.pipewire = {
enable = true; enable = true;
+11 -22
View File
@@ -1,25 +1,14 @@
{ den, lib, ... }: { ... }:
let
getPrimaryEmail =
user:
(lib.findFirst (email: email.primary) (throw "Missing primary email for ${user.userName}") (builtins.attrValues user.emails)).address;
in
{ {
lux.bitwarden = den.lib.parametric { flake.modules.homeManager.bitwarden =
includes = [ { pkgs, ... }:
( {
{ host, user }: programs.rbw = {
{ enable = true;
homeManager.programs.rbw.settings = { settings = {
email = getPrimaryEmail user; base_url = "https://vault.jelles.net";
base_url = "https://vault.${host.serviceDomain}"; pinentry = pkgs.pinentry-gnome3;
}; };
} };
)
];
homeManager = {
programs.rbw.enable = true;
}; };
};
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.bluetooth.nixos = { flake.modules.nixos.bluetooth = {
hardware.bluetooth.enable = true; hardware.bluetooth.enable = true;
services.blueman.enable = true; services.blueman.enable = true;
}; };
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.clipboard.homeManager = flake.modules.homeManager.clipboard =
{ pkgs, ... }: { pkgs, ... }:
{ {
home.packages = [ pkgs.wl-clipboard ]; home.packages = [ pkgs.wl-clipboard ];
+35
View File
@@ -0,0 +1,35 @@
{ inputs, config, ... }:
let
nixosModules = config.flake.modules.nixos;
in
{
flake.modules.nixos.desktopBase = {
imports = [
inputs.home-manager.nixosModules.home-manager
nixosModules.nix
nixosModules.systemBase
nixosModules.standardBoot
nixosModules.regionNl
nixosModules.sddm
nixosModules.niri
nixosModules.audio
nixosModules.bluetooth
nixosModules.flatpak
nixosModules.fonts
nixosModules.networking
nixosModules.printing
nixosModules.qbittorrentClient
nixosModules.sopsHost
];
home-manager = {
useGlobalPkgs = true;
backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; };
};
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
};
}
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.dev-tools.homeManager = flake.modules.homeManager.devTools =
{ config, ... }: { config, ... }:
{ {
home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo"; home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo";
+90 -75
View File
@@ -1,84 +1,99 @@
{ den, lib, ... }: { ... }:
{ {
lux.email = den.lib.perUser ( flake.modules.homeManager.email =
{ user, ... }: { config, ... }:
let let
mkEmailAccount = realName = "Jelle Spreeuwenberg";
_: email: mkOffice365Account =
{
address,
primary,
}:
{ {
enable = true; enable = true;
address = email.address; inherit address primary realName;
primary = email.primary; userName = address;
realName = user.realName; thunderbird = {
userName = email.address;
thunderbird =
{
enable = true;
}
// lib.optionalAttrs (email.kind == "office365") {
settings = id: {
"mail.smtpserver.smtp_${id}.authMethod" = 10;
"mail.server.server_${id}.authMethod" = 10;
};
};
}
// (
if email.kind == "mxrouting" then
{
imap = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 993;
tls.enable = true;
};
smtp = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 465;
tls.enable = true;
};
}
else
{
flavor = "outlook.office365.com";
}
);
in
{
homeManager = { ... }: {
programs.thunderbird = {
enable = true; enable = true;
profiles.${user.name} = { settings = id: {
isDefault = true; "mail.smtpserver.smtp_${id}.authMethod" = 10;
withExternalGnupg = true; "mail.server.server_${id}.authMethod" = 10;
settings = {
# LAYOUT: Force 3-Pane Vertical View (Folders | List | Message)
"mail.ui.display.message_pane_vertical" = true;
# APPEARANCE: Enable "Cards View" (modern multi-line list)
# Note: 'cards' is the value for the new view
"mail.ui.display.thread_pane_view_type" = "cards";
# DENSITY: "Compact" is usually cleaner for tech-savvy users
"mail.uidensity" = 1; # 0=Default, 1=Compact, 2=Touch
# PRIVACY & CLEANUP
"privacy.donottrackheader.enabled" = true;
"mail.server.server2.hidden" = true; # Hide "Local Folders"
# Start page disable for faster boot
"mailnews.start_page.enabled" = false;
# Disable the "Get a new email address" feature in account manager
"mail.provider.enabled" = false;
"layout.css.devPixelsPerPx" = 0.85;
};
}; };
}; };
flavor = "outlook.office365.com";
accounts.email.accounts = lib.mapAttrs mkEmailAccount user.emails;
}; };
} mkMxrouteAccount =
); {
address,
primary,
}:
{
enable = true;
inherit address primary realName;
userName = address;
thunderbird.enable = true;
imap = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 993;
tls.enable = true;
};
smtp = {
authentication = "plain";
host = "taylor.mxrouting.net";
port = 465;
tls.enable = true;
};
};
in
{
programs.thunderbird = {
enable = true;
profiles.${config.home.username} = {
isDefault = true;
withExternalGnupg = true;
settings = {
"mail.ui.display.message_pane_vertical" = true;
"mail.ui.display.thread_pane_view_type" = "cards";
"mail.uidensity" = 1;
"privacy.donottrackheader.enabled" = true;
"mail.server.server2.hidden" = true;
"mailnews.start_page.enabled" = false;
"mail.provider.enabled" = false;
"layout.css.devPixelsPerPx" = 0.85;
};
};
};
accounts.email.accounts =
if config.home.username == "ergon" then
{
work = mkOffice365Account {
address = "jelle.spreeuwenberg@yookr.org";
primary = true;
};
}
else
{
main = mkMxrouteAccount {
address = "mail@jelles.net";
primary = true;
};
old = mkMxrouteAccount {
address = "mail@jellespreeuwenberg.nl";
primary = false;
};
uni = mkOffice365Account {
address = "j.spreeuwenberg@student.tue.nl";
primary = false;
};
work = mkOffice365Account {
address = "jelle.spreeuwenberg@yookr.org";
primary = false;
};
};
};
} }
+3 -1
View File
@@ -1,3 +1,5 @@
{ {
lux.flatpak.nixos.services.flatpak.enable = true; flake.modules.nixos.flatpak = {
services.flatpak.enable = true;
};
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.fonts.nixos = flake.modules.nixos.fonts =
{ pkgs, ... }: { pkgs, ... }:
{ {
fonts = { fonts = {
+8 -12
View File
@@ -1,15 +1,11 @@
{ {
lux.gemini = { flake.modules.homeManager.gemini =
homeManager = { config, ... }:
{ config, ... }: {
{ home.sessionVariables.GEMINI_CONFIG_DIR = "${config.xdg.configHome}/gemini";
home.sessionVariables.GEMINI_CONFIG_DIR = "${config.xdg.configHome}/gemini";
programs.gemini-cli.enable = true; programs.gemini-cli.enable = true;
programs.opencode.enable = true; programs.opencode.enable = true;
programs.npm.enable = true;
# Needed for extensions };
programs.npm.enable = true;
};
};
} }
+16 -30
View File
@@ -1,32 +1,18 @@
{ den, lib, ... }: { ... }:
let
getPrimaryEmail =
user:
(lib.findFirst (email: email.primary) (throw "Missing primary email for ${user.userName}") (
builtins.attrValues user.emails
)).address;
in
{ {
lux.git = den.lib.parametric { flake.modules.homeManager.git =
includes = [ { ... }:
( {
{ user, ... }: programs.git = {
{ enable = true;
homeManager.programs.git = { signing.format = "ssh";
enable = true; ignores = [
signing.format = "ssh"; ".claude/"
ignores = [ ".codex/"
".claude/" ];
".codex/" settings = {
]; init.defaultBranch = "main";
settings = { };
user.name = user.realName; };
user.email = getPrimaryEmail user; };
init.defaultBranch = "main";
};
};
}
)
];
};
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.local-apps.homeManager = flake.modules.homeManager.localApps =
{ pkgs, ... }: { pkgs, ... }:
{ {
home.sessionVariables.BROWSER = "vivaldi"; home.sessionVariables.BROWSER = "vivaldi";
+43 -45
View File
@@ -1,49 +1,47 @@
{ {
lux.mpv = { flake.modules.homeManager.mpv =
homeManager = { pkgs, ... }:
{ pkgs, ... }: {
{ programs.mpv = {
programs.mpv = { enable = true;
enable = true; bindings = {
bindings = { D = "cycle deband";
D = "cycle deband";
};
config = {
profile = "high-quality";
osc = "no";
border = "no";
vo = "gpu-next";
gpu-api = "vulkan";
hwdec = "vulkan";
demuxer-mkv-subtitle-preroll = "yes";
sub-auto = "fuzzy";
sub-gauss = 1.0;
sub-gray = "yes";
tone-mapping = "bt.2446a";
keep-open = "yes";
save-position-on-quit = "yes";
volume-max = 150;
deband = "yes";
deband-iterations = 2;
deband-threshold = 64;
deband-range = 17;
deband-grain = 12;
};
scripts = with pkgs.mpvScripts; [
modernz
thumbfast
mpris
autosub
];
}; };
config = {
profile = "high-quality";
osc = "no";
border = "no";
vo = "gpu-next";
gpu-api = "vulkan";
hwdec = "vulkan";
demuxer-mkv-subtitle-preroll = "yes";
sub-auto = "fuzzy";
sub-gauss = 1.0;
sub-gray = "yes";
tone-mapping = "bt.2446a";
keep-open = "yes";
save-position-on-quit = "yes";
volume-max = 150;
deband = "yes";
deband-iterations = 2;
deband-threshold = 64;
deband-range = 17;
deband-grain = 12;
};
scripts = with pkgs.mpvScripts; [
modernz
thumbfast
mpris
autosub
];
}; };
}; };
} }
+6 -9
View File
@@ -1,10 +1,11 @@
{ inputs, ... }:
{ {
lux.neovim.homeManager = flake.modules.homeManager.neovim =
{ {
pkgs, pkgs,
lib, lib,
config, config,
inputs,
osConfig,
... ...
}: }:
{ {
@@ -13,7 +14,6 @@
VISUAL = "nvim"; VISUAL = "nvim";
}; };
imports = [ imports = [
(inputs.nix-wrapper-modules.lib.mkInstallModule { (inputs.nix-wrapper-modules.lib.mkInstallModule {
name = "neovim"; name = "neovim";
@@ -26,7 +26,7 @@
]; ];
# Configure sops-nix secret # Configure sops-nix secret
sops.secrets.gemini-api-key-neovim = {}; sops.secrets.gemini-api-key-neovim = { };
wrappers.neovim = { wrappers.neovim = {
enable = true; enable = true;
@@ -117,13 +117,10 @@
# We put these in `settings` so they appear in require('nix-info').settings # We put these in `settings` so they appear in require('nix-info').settings
settings = { settings = {
# Hostname/ConfigDir needed for nixd # Hostname/ConfigDir needed for nixd
# NOTE: Adjust these paths to match your actual denful/flake variables
nixdExtras = { nixdExtras = {
nixpkgs = "import ${pkgs.path} {}"; nixpkgs = "import ${pkgs.path} {}";
# Assuming you have access to the flake path in your config, nixos_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.${osConfig.networking.hostName}.options'';
# otherwise hardcode or pass via specialArgs home_manager_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.${osConfig.networking.hostName}.options.home-manager.users.type.getSubOptions []'';
nixos_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.polaris.config.networking.hostName}.options'';
home_manager_options = ''(builtins.getFlake "path://${config.home.homeDirectory}/.config/nixos").nixosConfigurations.polaris.config.networking.hostName}.options.home-manager.users.type.getSubOptions []'';
}; };
# TODO: Put in separate theme file # TODO: Put in separate theme file
+5 -3
View File
@@ -1,6 +1,8 @@
{ {
lux.networking.nixos.networking = { flake.modules.nixos.networking = {
nftables.enable = true; networking = {
networkmanager.enable = true; nftables.enable = true;
networkmanager.enable = true;
};
}; };
} }
-374
View File
@@ -1,374 +0,0 @@
{ den, inputs, lib, ... }:
let
mkOutputs =
host:
lib.mapAttrs (
_: display:
lib.optionalAttrs display.primary {
focus-at-startup = true;
}
// lib.filterAttrs (_: value: value != null) {
position = display.position;
scale = display.scale;
mode = display.mode;
}
) host.displays;
in
{
lux.niri = {
includes = [
(den.lib.perHost {
nixos =
{ pkgs, ... }:
{
imports = [ inputs.niri.nixosModules.niri ];
nixpkgs.overlays = [ inputs.niri.overlays.niri ];
programs.niri.enable = true;
programs.niri.package = pkgs.niri-unstable;
programs.dconf.enable = true;
# Essential services for Nautilus (Trash, Networking, Disks, Search)
services.gvfs.enable = true;
services.udisks2.enable = true;
};
})
(den.lib.perUser (
{ host, ... }:
{
homeManager =
{ config, pkgs, ... }:
{
home.sessionVariables.NIXOS_OZONE_WL = "1";
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
};
home.packages = with pkgs; [
playerctl
nautilus
brightnessctl
xwayland-satellite
];
programs.niri = {
settings = {
outputs = mkOutputs host;
environment = {
DISPLAY = ":0";
};
spawn-at-startup = [
{ command = [ "xwayland-satellite" ]; }
{ command = [ "noctalia-shell" ]; }
{ command = [ "qbittorrent" ]; }
];
prefer-no-csd = true;
hotkey-overlay.skip-at-startup = true;
screenshot-path = "${config.xdg.userDirs.pictures}/screenshots/%Y-%m-%dT%H:%M:%S.png";
# -----------------------------------------------------------------
# Aesthetics & Visuals
# -----------------------------------------------------------------
# Fast, snappy animations
animations.slowdown = 0.6;
cursor = with config.home.pointerCursor; {
size = size;
theme = name;
hide-after-inactive-ms = 3000;
hide-when-typing = true;
};
layout = {
always-center-single-column = true;
gaps = 14;
focus-ring.enable = false;
default-column-width = {
proportion = 1. / 2.;
};
# Kanagawa-wave Colorscheme for border
border = {
enable = true;
width = 3;
active.color = "#7E9CD8"; # Crystal Blue
inactive.color = "#54546D"; # Sumi Ink 4
urgent.color = "#E82424"; # Samurai Red
};
};
window-rules = [
{
# Sleek rounded corners
geometry-corner-radius =
let
radius = 10.0;
in
{
bottom-left = radius;
bottom-right = radius;
top-left = radius;
top-right = radius;
};
clip-to-geometry = true;
}
];
# -----------------------------------------------------------------
# System & Input
# -----------------------------------------------------------------
debug = {
honor-xdg-activation-with-invalid-serial = true;
};
input = {
focus-follows-mouse.enable = true;
keyboard = {
repeat-delay = 300;
repeat-rate = 50;
xkb.options = "caps:escape";
};
mouse.accel-speed = 0.4;
};
# -----------------------------------------------------------------
# Keybinds
# -----------------------------------------------------------------
binds = {
# --- Applications & Launchers ---
"Mod+Return" = {
action.spawn = "kitty";
hotkey-overlay.title = "Terminal";
};
"Mod+B" = {
action.spawn = "vivaldi";
hotkey-overlay.title = "Browser";
};
"Mod+Space" = {
repeat = false;
action.spawn = [
"vicinae"
"toggle"
];
hotkey-overlay.title = "App Launcher";
};
# --- Media & Brightness Controls ---
"XF86AudioPlay" = {
action.spawn-sh = "playerctl play-pause";
allow-when-locked = true;
};
"XF86AudioStop" = {
action.spawn-sh = "playerctl stop";
allow-when-locked = true;
};
"XF86AudioPrev" = {
action.spawn-sh = "playerctl previous";
allow-when-locked = true;
};
"XF86AudioNext" = {
action.spawn-sh = "playerctl next";
allow-when-locked = true;
};
"XF86AudioRaiseVolume" = {
action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+";
allow-when-locked = true;
};
"XF86AudioLowerVolume" = {
action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-";
allow-when-locked = true;
};
"XF86AudioMute" = {
action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
allow-when-locked = true;
};
"XF86AudioMicMute" = {
action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle";
allow-when-locked = true;
};
"XF86MonBrightnessUp" = {
action.spawn-sh = "brightnessctl s 10%+";
allow-when-locked = true;
};
"XF86MonBrightnessDown" = {
action.spawn-sh = "brightnessctl s 10%-";
allow-when-locked = true;
};
# --- Screenshots ---
"Mod+S".action.screenshot = [ ];
"Mod+Ctrl+S".action.screenshot-screen = [ ];
"Mod+Alt+S".action.screenshot-window = [ ];
# --- Session & System ---
"Mod+Shift+Slash".action.show-hotkey-overlay = [ ];
"Mod+Escape" = {
action.toggle-keyboard-shortcuts-inhibit = [ ];
allow-inhibiting = false;
};
"Mod+Alt+L" = {
action.spawn-sh = "loginctl lock-session";
hotkey-overlay.title = "Lock Screen";
};
"Mod+Shift+E".action.quit = [ ];
"Ctrl+Alt+Delete".action.quit = [ ];
"Mod+Shift+P".action.power-off-monitors = [ ];
# --- Overview & Window Management ---
"Mod+O" = {
action.toggle-overview = [ ];
repeat = false;
};
"Mod+Q" = {
action.close-window = [ ];
repeat = false;
};
# Focus Movement (Vim-like + Arrows)
"Mod+H".action.focus-column-or-monitor-left = [ ];
"Mod+J".action.focus-window-down = [ ];
"Mod+K".action.focus-window-up = [ ];
"Mod+L".action.focus-column-or-monitor-right = [ ];
# Window Movement
"Mod+Ctrl+Left".action.move-column-left = [ ];
"Mod+Ctrl+Down".action.move-window-down = [ ];
"Mod+Ctrl+Up".action.move-window-up = [ ];
"Mod+Ctrl+Right".action.move-column-right = [ ];
"Mod+Ctrl+H".action.move-column-left = [ ];
"Mod+Ctrl+J".action.move-window-down = [ ];
"Mod+Ctrl+K".action.move-window-up = [ ];
"Mod+Ctrl+L".action.move-column-right = [ ];
# Column Focus & Movement
"Mod+Home".action.focus-column-first = [ ];
"Mod+End".action.focus-column-last = [ ];
"Mod+Ctrl+Home".action.move-column-to-first = [ ];
"Mod+Ctrl+End".action.move-column-to-last = [ ];
# Monitor Focus
"Mod+Shift+Left".action.focus-monitor-left = [ ];
"Mod+Shift+Down".action.focus-monitor-down = [ ];
"Mod+Shift+Up".action.focus-monitor-up = [ ];
"Mod+Shift+Right".action.focus-monitor-right = [ ];
"Mod+Shift+H".action.focus-monitor-left = [ ];
"Mod+Shift+J".action.focus-monitor-down = [ ];
"Mod+Shift+K".action.focus-monitor-up = [ ];
"Mod+Shift+L".action.focus-monitor-right = [ ];
# Monitor Movement
"Mod+Shift+Ctrl+Left".action.move-column-to-monitor-left = [ ];
"Mod+Shift+Ctrl+Down".action.move-column-to-monitor-down = [ ];
"Mod+Shift+Ctrl+Up".action.move-column-to-monitor-up = [ ];
"Mod+Shift+Ctrl+Right".action.move-column-to-monitor-right = [ ];
"Mod+Shift+Ctrl+H".action.move-column-to-monitor-left = [ ];
"Mod+Shift+Ctrl+J".action.move-column-to-monitor-down = [ ];
"Mod+Shift+Ctrl+K".action.move-column-to-monitor-up = [ ];
"Mod+Shift+Ctrl+L".action.move-column-to-monitor-right = [ ];
# Workspace Focus
"Mod+Page_Down".action.focus-workspace-down = [ ];
"Mod+Page_Up".action.focus-workspace-up = [ ];
"Mod+U".action.focus-workspace-down = [ ];
"Mod+I".action.focus-workspace-up = [ ];
# Workspace Movement (Column)
"Mod+Ctrl+Page_Down".action.move-column-to-workspace-down = [ ];
"Mod+Ctrl+Page_Up".action.move-column-to-workspace-up = [ ];
"Mod+Ctrl+U".action.move-column-to-workspace-down = [ ];
"Mod+Ctrl+I".action.move-column-to-workspace-up = [ ];
# Workspace Movement (Entire Workspace)
"Mod+Shift+Page_Down".action.move-workspace-down = [ ];
"Mod+Shift+Page_Up".action.move-workspace-up = [ ];
"Mod+Shift+U".action.move-workspace-down = [ ];
"Mod+Shift+I".action.move-workspace-up = [ ];
# --- Mouse Wheel Scrolling ---
"Mod+WheelScrollDown" = {
action.focus-workspace-down = [ ];
cooldown-ms = 150;
};
"Mod+WheelScrollUp" = {
action.focus-workspace-up = [ ];
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollDown" = {
action.move-column-to-workspace-down = [ ];
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollUp" = {
action.move-column-to-workspace-up = [ ];
cooldown-ms = 150;
};
"Mod+WheelScrollRight".action.focus-column-right = [ ];
"Mod+WheelScrollLeft".action.focus-column-left = [ ];
"Mod+Ctrl+WheelScrollRight".action.move-column-right = [ ];
"Mod+Ctrl+WheelScrollLeft".action.move-column-left = [ ];
"Mod+Shift+WheelScrollDown".action.focus-column-right = [ ];
"Mod+Shift+WheelScrollUp".action.focus-column-left = [ ];
"Mod+Ctrl+Shift+WheelScrollDown".action.move-column-right = [ ];
"Mod+Ctrl+Shift+WheelScrollUp".action.move-column-left = [ ];
# --- Workspace Indices ---
"Mod+1".action.focus-workspace = 1;
"Mod+2".action.focus-workspace = 2;
"Mod+3".action.focus-workspace = 3;
"Mod+4".action.focus-workspace = 4;
"Mod+5".action.focus-workspace = 5;
"Mod+6".action.focus-workspace = 6;
"Mod+7".action.focus-workspace = 7;
"Mod+8".action.focus-workspace = 8;
"Mod+9".action.focus-workspace = 9;
"Mod+Ctrl+1".action.move-column-to-workspace = 1;
"Mod+Ctrl+2".action.move-column-to-workspace = 2;
"Mod+Ctrl+3".action.move-column-to-workspace = 3;
"Mod+Ctrl+4".action.move-column-to-workspace = 4;
"Mod+Ctrl+5".action.move-column-to-workspace = 5;
"Mod+Ctrl+6".action.move-column-to-workspace = 6;
"Mod+Ctrl+7".action.move-column-to-workspace = 7;
"Mod+Ctrl+8".action.move-column-to-workspace = 8;
"Mod+Ctrl+9".action.move-column-to-workspace = 9;
# --- Column/Window Reshaping & Organization ---
"Mod+BracketLeft".action.consume-or-expel-window-left = [ ];
"Mod+BracketRight".action.consume-or-expel-window-right = [ ];
"Mod+Comma".action.consume-window-into-column = [ ];
"Mod+Period".action.expel-window-from-column = [ ];
"Mod+R".action.switch-preset-column-width = [ ];
"Mod+Shift+R".action.switch-preset-window-height = [ ];
"Mod+Ctrl+R".action.reset-window-height = [ ];
"Mod+F".action.maximize-column = [ ];
"Mod+Shift+F".action.fullscreen-window = [ ];
"Mod+M".action.maximize-window-to-edges = [ ];
"Mod+Ctrl+F".action.expand-column-to-available-width = [ ];
"Mod+C".action.center-column = [ ];
"Mod+Ctrl+C".action.center-visible-columns = [ ];
"Mod+Minus".action.set-column-width = "-10%";
"Mod+Equal".action.set-column-width = "+10%";
"Mod+Shift+Minus".action.set-window-height = "-10%";
"Mod+Shift+Equal".action.set-window-height = "+10%";
"Mod+V".action.toggle-window-floating = [ ];
"Mod+Shift+V".action.switch-focus-between-floating-and-tiling = [ ];
"Mod+W".action.toggle-column-tabbed-display = [ ];
};
};
};
};
}
))
];
};
}
+207
View File
@@ -0,0 +1,207 @@
{
"Mod+Return" = {
action.spawn = "kitty";
hotkey-overlay.title = "Terminal";
};
"Mod+B" = {
action.spawn = "vivaldi";
hotkey-overlay.title = "Browser";
};
"Mod+Space" = {
repeat = false;
action.spawn = [
"vicinae"
"toggle"
];
hotkey-overlay.title = "App Launcher";
};
"XF86AudioPlay" = {
action.spawn-sh = "playerctl play-pause";
allow-when-locked = true;
};
"XF86AudioStop" = {
action.spawn-sh = "playerctl stop";
allow-when-locked = true;
};
"XF86AudioPrev" = {
action.spawn-sh = "playerctl previous";
allow-when-locked = true;
};
"XF86AudioNext" = {
action.spawn-sh = "playerctl next";
allow-when-locked = true;
};
"XF86AudioRaiseVolume" = {
action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+";
allow-when-locked = true;
};
"XF86AudioLowerVolume" = {
action.spawn-sh = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-";
allow-when-locked = true;
};
"XF86AudioMute" = {
action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle";
allow-when-locked = true;
};
"XF86AudioMicMute" = {
action.spawn-sh = "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle";
allow-when-locked = true;
};
"XF86MonBrightnessUp" = {
action.spawn-sh = "brightnessctl s 10%+";
allow-when-locked = true;
};
"XF86MonBrightnessDown" = {
action.spawn-sh = "brightnessctl s 10%-";
allow-when-locked = true;
};
"Mod+S".action.screenshot = [ ];
"Mod+Ctrl+S".action.screenshot-screen = [ ];
"Mod+Alt+S".action.screenshot-window = [ ];
"Mod+Shift+Slash".action.show-hotkey-overlay = [ ];
"Mod+Escape" = {
action.toggle-keyboard-shortcuts-inhibit = [ ];
allow-inhibiting = false;
};
"Mod+Alt+L" = {
action.spawn-sh = "loginctl lock-session";
hotkey-overlay.title = "Lock Screen";
};
"Mod+Shift+E".action.quit = [ ];
"Ctrl+Alt+Delete".action.quit = [ ];
"Mod+Shift+P".action.power-off-monitors = [ ];
"Mod+O" = {
action.toggle-overview = [ ];
repeat = false;
};
"Mod+Q" = {
action.close-window = [ ];
repeat = false;
};
"Mod+H".action.focus-column-or-monitor-left = [ ];
"Mod+J".action.focus-window-down = [ ];
"Mod+K".action.focus-window-up = [ ];
"Mod+L".action.focus-column-or-monitor-right = [ ];
"Mod+Ctrl+Left".action.move-column-left = [ ];
"Mod+Ctrl+Down".action.move-window-down = [ ];
"Mod+Ctrl+Up".action.move-window-up = [ ];
"Mod+Ctrl+Right".action.move-column-right = [ ];
"Mod+Ctrl+H".action.move-column-left = [ ];
"Mod+Ctrl+J".action.move-window-down = [ ];
"Mod+Ctrl+K".action.move-window-up = [ ];
"Mod+Ctrl+L".action.move-column-right = [ ];
"Mod+Home".action.focus-column-first = [ ];
"Mod+End".action.focus-column-last = [ ];
"Mod+Ctrl+Home".action.move-column-to-first = [ ];
"Mod+Ctrl+End".action.move-column-to-last = [ ];
"Mod+Shift+Left".action.focus-monitor-left = [ ];
"Mod+Shift+Down".action.focus-monitor-down = [ ];
"Mod+Shift+Up".action.focus-monitor-up = [ ];
"Mod+Shift+Right".action.focus-monitor-right = [ ];
"Mod+Shift+H".action.focus-monitor-left = [ ];
"Mod+Shift+J".action.focus-monitor-down = [ ];
"Mod+Shift+K".action.focus-monitor-up = [ ];
"Mod+Shift+L".action.focus-monitor-right = [ ];
"Mod+Shift+Ctrl+Left".action.move-column-to-monitor-left = [ ];
"Mod+Shift+Ctrl+Down".action.move-column-to-monitor-down = [ ];
"Mod+Shift+Ctrl+Up".action.move-column-to-monitor-up = [ ];
"Mod+Shift+Ctrl+Right".action.move-column-to-monitor-right = [ ];
"Mod+Shift+Ctrl+H".action.move-column-to-monitor-left = [ ];
"Mod+Shift+Ctrl+J".action.move-column-to-monitor-down = [ ];
"Mod+Shift+Ctrl+K".action.move-column-to-monitor-up = [ ];
"Mod+Shift+Ctrl+L".action.move-column-to-monitor-right = [ ];
"Mod+Page_Down".action.focus-workspace-down = [ ];
"Mod+Page_Up".action.focus-workspace-up = [ ];
"Mod+U".action.focus-workspace-down = [ ];
"Mod+I".action.focus-workspace-up = [ ];
"Mod+Ctrl+Page_Down".action.move-column-to-workspace-down = [ ];
"Mod+Ctrl+Page_Up".action.move-column-to-workspace-up = [ ];
"Mod+Ctrl+U".action.move-column-to-workspace-down = [ ];
"Mod+Ctrl+I".action.move-column-to-workspace-up = [ ];
"Mod+Shift+Page_Down".action.move-workspace-down = [ ];
"Mod+Shift+Page_Up".action.move-workspace-up = [ ];
"Mod+Shift+U".action.move-workspace-down = [ ];
"Mod+Shift+I".action.move-workspace-up = [ ];
"Mod+WheelScrollDown" = {
action.focus-workspace-down = [ ];
cooldown-ms = 150;
};
"Mod+WheelScrollUp" = {
action.focus-workspace-up = [ ];
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollDown" = {
action.move-column-to-workspace-down = [ ];
cooldown-ms = 150;
};
"Mod+Ctrl+WheelScrollUp" = {
action.move-column-to-workspace-up = [ ];
cooldown-ms = 150;
};
"Mod+WheelScrollRight".action.focus-column-right = [ ];
"Mod+WheelScrollLeft".action.focus-column-left = [ ];
"Mod+Ctrl+WheelScrollRight".action.move-column-right = [ ];
"Mod+Ctrl+WheelScrollLeft".action.move-column-left = [ ];
"Mod+Shift+WheelScrollDown".action.focus-column-right = [ ];
"Mod+Shift+WheelScrollUp".action.focus-column-left = [ ];
"Mod+Ctrl+Shift+WheelScrollDown".action.move-column-right = [ ];
"Mod+Ctrl+Shift+WheelScrollUp".action.move-column-left = [ ];
"Mod+1".action.focus-workspace = 1;
"Mod+2".action.focus-workspace = 2;
"Mod+3".action.focus-workspace = 3;
"Mod+4".action.focus-workspace = 4;
"Mod+5".action.focus-workspace = 5;
"Mod+6".action.focus-workspace = 6;
"Mod+7".action.focus-workspace = 7;
"Mod+8".action.focus-workspace = 8;
"Mod+9".action.focus-workspace = 9;
"Mod+Ctrl+1".action.move-column-to-workspace = 1;
"Mod+Ctrl+2".action.move-column-to-workspace = 2;
"Mod+Ctrl+3".action.move-column-to-workspace = 3;
"Mod+Ctrl+4".action.move-column-to-workspace = 4;
"Mod+Ctrl+5".action.move-column-to-workspace = 5;
"Mod+Ctrl+6".action.move-column-to-workspace = 6;
"Mod+Ctrl+7".action.move-column-to-workspace = 7;
"Mod+Ctrl+8".action.move-column-to-workspace = 8;
"Mod+Ctrl+9".action.move-column-to-workspace = 9;
"Mod+BracketLeft".action.consume-or-expel-window-left = [ ];
"Mod+BracketRight".action.consume-or-expel-window-right = [ ];
"Mod+Comma".action.consume-window-into-column = [ ];
"Mod+Period".action.expel-window-from-column = [ ];
"Mod+R".action.switch-preset-column-width = [ ];
"Mod+Shift+R".action.switch-preset-window-height = [ ];
"Mod+Ctrl+R".action.reset-window-height = [ ];
"Mod+F".action.maximize-column = [ ];
"Mod+Shift+F".action.fullscreen-window = [ ];
"Mod+M".action.maximize-window-to-edges = [ ];
"Mod+Ctrl+F".action.expand-column-to-available-width = [ ];
"Mod+C".action.center-column = [ ];
"Mod+Ctrl+C".action.center-visible-columns = [ ];
"Mod+Minus".action.set-column-width = "-10%";
"Mod+Equal".action.set-column-width = "+10%";
"Mod+Shift+Minus".action.set-window-height = "-10%";
"Mod+Shift+Equal".action.set-window-height = "+10%";
"Mod+V".action.toggle-window-floating = [ ];
"Mod+Shift+V".action.switch-focus-between-floating-and-tiling = [ ];
"Mod+W".action.toggle-column-tabbed-display = [ ];
}
+103
View File
@@ -0,0 +1,103 @@
{ inputs, ... }:
{
flake.modules.nixos.niri =
{ pkgs, ... }:
{
imports = [ inputs.niri.nixosModules.niri ];
nixpkgs.overlays = [ inputs.niri.overlays.niri ];
programs.niri.enable = true;
programs.niri.package = pkgs.niri-unstable;
programs.dconf.enable = true;
services.gvfs.enable = true;
services.udisks2.enable = true;
xdg.portal.enable = true;
};
flake.modules.homeManager.niri =
{ config, pkgs, ... }:
{
home.sessionVariables.NIXOS_OZONE_WL = "1";
dconf.settings = {
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
};
home.packages = with pkgs; [
playerctl
nautilus
brightnessctl
xwayland-satellite
];
programs.niri.settings = {
environment.DISPLAY = ":0";
spawn-at-startup = [
{ command = [ "xwayland-satellite" ]; }
{ command = [ "noctalia-shell" ]; }
{ command = [ "qbittorrent" ]; }
];
prefer-no-csd = true;
hotkey-overlay.skip-at-startup = true;
screenshot-path = "${config.xdg.userDirs.pictures}/screenshots/%Y-%m-%dT%H:%M:%S.png";
animations.slowdown = 0.6;
cursor = with config.home.pointerCursor; {
size = size;
theme = name;
hide-after-inactive-ms = 3000;
hide-when-typing = true;
};
layout = {
always-center-single-column = true;
gaps = 14;
focus-ring.enable = false;
default-column-width.proportion = 1. / 2.;
border = {
enable = true;
width = 3;
active.color = "#7E9CD8";
inactive.color = "#54546D";
urgent.color = "#E82424";
};
};
window-rules = [
{
geometry-corner-radius =
let
radius = 10.0;
in
{
bottom-left = radius;
bottom-right = radius;
top-left = radius;
top-right = radius;
};
clip-to-geometry = true;
}
];
debug.honor-xdg-activation-with-invalid-serial = true;
input = {
focus-follows-mouse.enable = true;
keyboard = {
repeat-delay = 300;
repeat-rate = 50;
xkb.options = "caps:escape";
};
mouse.accel-speed = 0.4;
};
binds = import ./_bindings.nix;
};
};
}
+43 -48
View File
@@ -1,55 +1,50 @@
{ den, inputs, ... }:
{ {
lux.nix = { flake.modules.nixos.nix =
includes = [ { inputs, ... }:
(den.lib.perHost { {
nixos = { nixpkgs.config.allowUnfree = true;
nixpkgs.config.allowUnfree = true;
nix = { nix = {
gc.automatic = true; gc.automatic = true;
optimise.automatic = true; optimise.automatic = true;
registry.nixpkgs.flake = inputs.nixpkgs; registry.nixpkgs.flake = inputs.nixpkgs;
channel.enable = false; channel.enable = false;
settings = { settings = {
trusted-users = [ "@wheel" ]; trusted-users = [ "@wheel" ];
use-xdg-base-directories = true; use-xdg-base-directories = true;
auto-optimise-store = true; auto-optimise-store = true;
experimental-features = [ experimental-features = [
"nix-command" "nix-command"
"flakes" "flakes"
]; ];
};
};
};
})
];
homeManager =
{ pkgs, ... }:
{
home.packages = [
(pkgs.writeShellApplication {
name = "ns";
runtimeInputs = [
pkgs.fzf
pkgs.nix-search-tv
];
text = builtins.readFile "${pkgs.nix-search-tv.src}/nixpkgs.sh";
})
];
programs.television = {
enable = true;
enableZshIntegration = false;
};
programs.nix-search-tv = {
enable = true;
enableTelevisionIntegration = true;
}; };
}; };
}; };
flake.modules.homeManager.nix =
{ pkgs, ... }:
{
home.packages = [
(pkgs.writeShellApplication {
name = "ns";
runtimeInputs = [
pkgs.fzf
pkgs.nix-search-tv
];
text = builtins.readFile "${pkgs.nix-search-tv.src}/nixpkgs.sh";
})
];
programs.television = {
enable = true;
enableZshIntegration = false;
};
programs.nix-search-tv = {
enable = true;
enableTelevisionIntegration = true;
};
};
} }
+7 -3
View File
@@ -1,7 +1,11 @@
{ inputs, ... }:
{ {
lux.noctalia.homeManager = flake.modules.homeManager.noctalia =
{ lib, pkgs, ... }: {
inputs,
lib,
pkgs,
...
}:
{ {
imports = [ inputs.noctalia.homeModules.default ]; imports = [ inputs.noctalia.homeModules.default ];
+65 -76
View File
@@ -1,86 +1,75 @@
{ den, ... }: {
let flake.modules.homeManager.pim =
calendarAccount = den.lib.perUser (
{ host, user }:
{ {
homeManager = config,
{ config, ... }: ...
let }:
calendarsPath = "${config.xdg.dataHome}/calendars"; let
in calendarsPath = "${config.xdg.dataHome}/calendars";
{ in
programs.pimsync.enable = true; {
services.pimsync.enable = true; programs.pimsync.enable = true;
services.pimsync.enable = true;
programs.khal = { programs.khal = {
# FIXME: Temporarily disabled because of bug in nixpkgs-unstable (27-02-26) enable = false;
enable = false; locale = {
locale = { timeformat = "%H:%M";
timeformat = "%H:%M"; dateformat = "$m-$d";
dateformat = "$m-$d"; };
}; };
programs.todoman = {
enable = true;
glob = "*/*";
extraConfig = ''
date_format = "%Y-%m-%d"
time_format = "%H:%M"
default_list = "personal"
default_due = 0
default_command = "list --sort priority,due"
humanize = True
'';
};
accounts.calendar = {
basePath = calendarsPath;
accounts.radicale = {
primary = true;
primaryCollection = "personal";
local = {
type = "filesystem";
fileExt = ".ics";
}; };
programs.todoman = { remote = {
url = "https://radicale.jelles.net/";
type = "caldav";
userName = config.home.username;
passwordCommand = [
"rbw"
"get"
"Radicale"
];
};
pimsync = {
enable = true; enable = true;
glob = "*/*"; extraPairDirectives = [
extraConfig = '' {
date_format = "%Y-%m-%d" name = "collections";
time_format = "%H:%M" params = [ "from b" ];
default_list = "personal" }
default_due = 0 ];
default_command = "list --sort priority,due"
humanize = True
'';
}; };
accounts.calendar = { khal = {
basePath = calendarsPath; enable = true;
accounts = { type = "discover";
"radicale" = { color = "light blue";
primary = true;
primaryCollection = "personal";
local = {
type = "filesystem";
fileExt = ".ics";
};
remote = {
url = "https://radicale.${host.serviceDomain}/";
type = "caldav";
userName = user.userName;
passwordCommand = [
"rbw"
"get"
"Radicale"
];
};
pimsync = {
enable = true;
extraPairDirectives = [
{
name = "collections";
params = [ "from b" ];
}
];
};
khal = {
enable = true;
type = "discover";
color = "light blue";
};
};
};
}; };
}; };
} };
); };
in
{
lux.pim = {
includes = [ calendarAccount ];
};
} }
-7
View File
@@ -1,7 +0,0 @@
{
lux.pinentry.homeManager =
{ pkgs, ... }:
{
programs.rbw.settings.pinentry = pkgs.pinentry-gnome3;
};
}
+3 -5
View File
@@ -1,10 +1,8 @@
{ ... }: { ... }:
{ {
lux.podman = { flake.modules.homeManager.podman = {
homeManager = { services.podman = {
services.podman = { enable = true;
enable = true;
};
}; };
}; };
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.printing.nixos = flake.modules.nixos.printing =
{ pkgs, ... }: { pkgs, ... }:
{ {
services.printing = { services.printing = {
+11 -16
View File
@@ -1,19 +1,14 @@
{ den, ... }:
{ {
lux.qbittorrent-client = { flake.modules.nixos.qbittorrentClient = {
includes = [ networking.firewall = {
(den.lib.perHost { allowedTCPPorts = [ 43864 ];
nixos.networking.firewall = { allowedUDPPorts = [ 43864 ];
allowedTCPPorts = [ 43864 ]; };
allowedUDPPorts = [ 43864 ];
};
})
];
homeManager =
{ pkgs, ... }:
{
home.packages = [ pkgs.qbittorrent ];
};
}; };
flake.modules.homeManager.qbittorrentClient =
{ pkgs, ... }:
{
home.packages = [ pkgs.qbittorrent ];
};
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ ... }: { ... }:
{ {
lux.region-nl.nixos = { flake.modules.nixos.regionNl = {
time.timeZone = "Europe/Amsterdam"; time.timeZone = "Europe/Amsterdam";
i18n.defaultLocale = "en_US.UTF-8"; i18n.defaultLocale = "en_US.UTF-8";
+11 -14
View File
@@ -1,17 +1,14 @@
{ inputs, ... }:
{ {
lux.sddm = { flake.modules.nixos.sddm =
nixos = { pkgs, ... }:
{ pkgs, ... }: {
{ services.displayManager.sddm = {
services.displayManager.sddm = { enable = true;
enable = true; wayland.enable = true;
wayland.enable = true; theme = "${pkgs.sddm-astronaut}/share/sddm/themes/sddm-astronaut-theme";
theme = "${pkgs.sddm-astronaut}/share/sddm/themes/sddm-astronaut-theme"; extraPackages = with pkgs; [
extraPackages = with pkgs; [ kdePackages.qtmultimedia
kdePackages.qtmultimedia ];
];
};
}; };
}; };
} }
+13 -18
View File
@@ -1,22 +1,17 @@
{ den, ... }:
{ {
lux.services._.actual = den.lib.perHost ( flake.modules.nixos.actual =
{ host, ... }: { config, ... }:
{ {
nixos = services.actual = {
{ config, ... }: enable = true;
{ openFirewall = false;
services.actual = { settings = {
enable = true; port = 3000;
openFirewall = false; hostname = "127.0.0.1";
settings = {
port = 3000;
hostname = "127.0.0.1";
};
};
services.caddy.virtualHosts."finance.${host.serviceDomain}".extraConfig =
"reverse_proxy :${toString config.services.actual.settings.port}";
}; };
} };
);
services.caddy.virtualHosts."finance.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.actual.settings.port}";
};
} }
+3 -4
View File
@@ -1,10 +1,9 @@
{ den, ... }:
{ {
lux.services._.caddy = den.lib.perHost ({ host }: { flake.modules.nixos.caddy = {
nixos.services.caddy = { services.caddy = {
enable = true; enable = true;
email = "mail@jelles.net"; email = "mail@jelles.net";
openFirewall = true; openFirewall = true;
}; };
}); };
} }
+14 -16
View File
@@ -1,20 +1,18 @@
{ {
lux.deluge = { flake.modules.nixos.delugeService =
nixos = { ... }:
{ config, ... }: {
{ sops.secrets.deluge-auth-file = { };
sops.secrets.deluge-auth-file = { };
services.deluge = { services.deluge = {
enable = true; enable = true;
# For some reason passwords never match?? declarative = false;
declarative = false;
};
}; };
homeManager = };
{ pkgs, ... }:
{ flake.modules.homeManager.delugeClient =
home.packages = [ pkgs.deluge ]; { pkgs, ... }:
}; {
}; home.packages = [ pkgs.deluge ];
};
} }
+20 -28
View File
@@ -1,36 +1,28 @@
{ den, ... }:
{ {
lux.services._.gitea = den.lib.perHost ( flake.modules.nixos.gitea =
{ host }: { config, ... }:
{ {
nixos = services.gitea = {
{ config, ... }: enable = true;
{
services.gitea = {
enable = true;
settings = { settings = {
server = { server = {
DOMAIN = "git.${host.serviceDomain}"; DOMAIN = "git.jelles.net";
ROOT_URL = "https://git.${host.serviceDomain}/"; ROOT_URL = "https://git.jelles.net/";
HTTP_PORT = 3001; HTTP_PORT = 3001;
HTTP_ADDR = "127.0.0.1"; HTTP_ADDR = "127.0.0.1";
START_SSH_SERVER = false; START_SSH_SERVER = false;
SSH_PORT = 22; SSH_PORT = 22;
};
service = {
DISABLE_REGISTRATION = true;
};
};
}; };
services.openssh.settings.AllowUsers = [ "gitea" ]; service.DISABLE_REGISTRATION = true;
services.caddy.virtualHosts."git.${host.serviceDomain}".extraConfig =
"reverse_proxy :${toString config.services.gitea.settings.server.HTTP_PORT}";
}; };
} };
);
services.openssh.settings.AllowUsers = [ "gitea" ];
services.caddy.virtualHosts."git.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.gitea.settings.server.HTTP_PORT}";
};
} }
+26 -78
View File
@@ -1,80 +1,28 @@
{ den, lib, ... }: { ... }:
let
hostConfig =
{ host }:
{
nixos =
{ config, ... }:
{
services.openssh = {
enable = true;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
AllowUsers = lib.attrNames host.users;
};
};
users.users = lib.mapAttrs (_: user: {
openssh.authorizedKeys.keys = user.authorizedSshKeys;
}) host.users;
assertions = lib.optionals host.requiresSshRecovery (
let
missingUsers = lib.filter (userName: !(builtins.hasAttr userName host.users)) host.sshRecoveryUsers;
usersWithoutKeys = lib.filter (
userName:
(builtins.hasAttr userName host.users) && host.users.${userName}.authorizedSshKeys == [ ]
) host.sshRecoveryUsers;
in
[
{
assertion = config.services.openssh.enable;
message = "Hosts with requiresSshRecovery must enable OpenSSH.";
}
{
assertion = config.services.openssh.settings.PasswordAuthentication == false;
message = "Hosts with requiresSshRecovery must disable SSH password authentication.";
}
{
assertion =
let
rootLogin = config.services.openssh.settings.PermitRootLogin;
in
rootLogin == false || rootLogin == "no";
message = "Hosts with requiresSshRecovery must disable SSH root login.";
}
{
assertion = host.sshRecoveryUsers != [ ];
message = "Hosts with requiresSshRecovery must declare at least one sshRecoveryUser.";
}
{
assertion = missingUsers == [ ];
message =
"All sshRecoveryUsers must exist on the host. Missing: "
+ lib.concatStringsSep ", " missingUsers;
}
{
assertion = usersWithoutKeys == [ ];
message =
"All sshRecoveryUsers must have plain authorizedSshKeys. Missing keys for: "
+ lib.concatStringsSep ", " usersWithoutKeys;
}
{
assertion = host.sopsHostSshKeyPath != null;
message = "Hosts with requiresSshRecovery must set sopsHostSshKeyPath.";
}
{
assertion = config.services.openssh.openFirewall || lib.elem 22 config.networking.firewall.allowedTCPPorts;
message = "Hosts with requiresSshRecovery must expose SSH through the firewall.";
}
]
);
};
};
in
{ {
lux.services._.openssh = den.lib.parametric.exactly { flake.modules.nixos.openssh =
includes = [ hostConfig ]; {
}; config,
lib,
host ? {
isServer = false;
},
...
}:
let
hostUserNames = builtins.attrNames (
lib.filterAttrs (_: user: user.isNormalUser or false) config.users.users
);
in
{
services.openssh = {
enable = true;
openFirewall = host.isServer;
settings = {
PermitRootLogin = "no";
PasswordAuthentication = false;
AllowUsers = hostUserNames;
};
};
};
} }
+6 -8
View File
@@ -1,13 +1,11 @@
{ ... }: { ... }:
{ {
lux.qbittorrent = { flake.modules.nixos.qbittorrent = {
nixos = { services.qbittorrent = {
services.qbittorrent = { enable = true;
enable = true; openFirewall = true;
openFirewall = true; torrentingPort = 43864;
torrentingPort = 43864; webuiPort = 8123;
webuiPort = 8123;
};
}; };
}; };
} }
+20 -26
View File
@@ -1,33 +1,27 @@
{ den, ... }:
{ {
lux.services._.radicale = den.lib.perHost ( flake.modules.nixos.radicale =
{ host }: { ... }:
{ {
nixos = services.radicale = {
{ config, ... }: enable = true;
{ settings = {
services.radicale = { server.hosts = [ "127.0.0.1:5232" ];
enable = true;
settings = {
server.hosts = [ "127.0.0.1:5232" ];
auth = { auth = {
type = "htpasswd"; type = "htpasswd";
htpasswd_filename = "/var/lib/radicale/users"; htpasswd_filename = "/var/lib/radicale/users";
htpasswd_encryption = "bcrypt"; htpasswd_encryption = "bcrypt";
};
storage.filesystem_folder = "/var/lib/radicale/collections";
};
}; };
services.caddy.virtualHosts."radicale.${host.serviceDomain}".extraConfig = '' storage.filesystem_folder = "/var/lib/radicale/collections";
reverse_proxy :5232 {
header_up X-Script-Name /
header_up X-Forwarded-For {remote}
header_up X-Remote-User {http.auth.user.id}
}'';
}; };
} };
);
services.caddy.virtualHosts."radicale.jelles.net".extraConfig = ''
reverse_proxy :5232 {
header_up X-Script-Name /
header_up X-Forwarded-For {remote}
header_up X-Remote-User {http.auth.user.id}
}'';
};
} }
+5 -6
View File
@@ -1,20 +1,19 @@
{ den, ... }:
{ {
lux.services._.vaultwarden = den.lib.perHost ({ host }: { flake.modules.nixos.vaultwarden =
nixos = { config, ... }: { { config, ... }:
{
services.vaultwarden = { services.vaultwarden = {
enable = true; enable = true;
backupDir = "/var/backup/vaultwarden"; backupDir = "/var/backup/vaultwarden";
config = { config = {
DOMAIN = "https://vault.${host.serviceDomain}"; DOMAIN = "https://vault.jelles.net";
SIGNUPS_ALLOWED = false; SIGNUPS_ALLOWED = false;
ROCKET_PORT = 8100; ROCKET_PORT = 8100;
ROCKET_LOG = "critical"; ROCKET_LOG = "critical";
}; };
}; };
services.caddy.virtualHosts."vault.${host.serviceDomain}".extraConfig = services.caddy.virtualHosts."vault.jelles.net".extraConfig =
"reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT}"; "reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT}";
}; };
});
} }
+137 -167
View File
@@ -1,184 +1,154 @@
{ inputs, ... }:
{ {
lux.shell = { flake.modules.homeManager.shell =
homeManager = { lib, config, ... }:
{ lib, config, ... }: {
{ home.sessionVariables = {
home.sessionVariables = { STARSHIP_CACHE = "${config.xdg.cacheHome}/starship";
STARSHIP_CACHE = "${config.xdg.cacheHome}/starship"; };
};
# Delete zcompdump on config switch, so that we regenerate completions home.activation = {
home.activation = { clearZshCompDump = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
clearZshCompDump = lib.hm.dag.entryAfter [ "writeBoundary" ] '' rm -f "${config.programs.zsh.dotDir}"/.zcompdump*
rm -f "${config.programs.zsh.dotDir}"/.zcompdump* '';
''; };
};
programs.zsh = { programs.zsh = {
enable = true;
dotDir = "${config.xdg.configHome}/zsh";
enableCompletion = true;
completionInit = ''
autoload -U compinit
compinit -C
ZCOMPDUMP="${config.programs.zsh.dotDir}/.zcompdump"
{
if [[ -s "$ZCOMPDUMP" && (! -s "''${ZCOMPDUMP}.zwc" || "$ZCOMPDUMP" -nt "''${ZCOMPDUMP}.zwc") ]]; then
zcompile "$ZCOMPDUMP"
fi
} &!
'';
autosuggestion.enable = true;
syntaxHighlighting = {
enable = true; enable = true;
dotDir = "${config.xdg.configHome}/zsh"; highlighters = [
"main"
"brackets"
"pattern"
"regexp"
"root"
"line"
];
};
enableCompletion = true; historySubstringSearch.enable = true;
completionInit = ''
autoload -U compinit
compinit -C
ZCOMPDUMP="${config.programs.zsh.dotDir}/.zcompdump" history = {
# Compile it in the background ignoreDups = true;
{ save = 10000;
if [[ -s "$ZCOMPDUMP" && (! -s "''${ZCOMPDUMP}.zwc" || "$ZCOMPDUMP" -nt "''${ZCOMPDUMP}.zwc") ]]; then size = 10000;
zcompile "$ZCOMPDUMP" path = "${config.xdg.dataHome}/zsh_history";
fi };
} &!
'';
autosuggestion.enable = true;
syntaxHighlighting = { profileExtra = lib.optionalString (config.home.sessionPath != [ ]) ''
enable = true; export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}"
highlighters = [ '';
"main"
"brackets" initContent = ''
"pattern" bindkey -v
"regexp"
"root" export KEYTIMEOUT=1
"line"
]; autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
zstyle ':completion:*' completer _extensions _complete _approximate
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache"
zstyle ':completion:*' complete true
zstyle ':completion:*' complete-options true
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true
zstyle ':completion:*' menu select
zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name '''
zstyle ':completion:*' verbose yes
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:warnings' format '%F{red}%B-- No match for: %d --%b%f'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*:descriptions' format '[%d]'
zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS}
zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
zstyle ':completion:*:*:-command-:*:*' group-order aliases builtins functions commands
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' squeeze-slashes true
zstyle ':completion:*' sort false
zstyle ":completion:*:git-checkout:*" sort false
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:eza' sort false
zstyle ':completion:complete:*:options' sort false
zstyle ':completion:files' sort false
'';
};
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = {
add_newline = true;
format = lib.concatStrings [
"$nix_shell"
"$hostname"
"$directory"
"$git_branch"
"$git_state"
"$git_status"
"$line_break"
"$character"
];
directory = {
truncation_length = 99;
truncate_to_repo = false;
}; };
historySubstringSearch.enable = true; nix_shell = {
format = "[$symbol]($style) ";
history = { symbol = "🐚";
ignoreDups = true; style = "";
save = 10000;
size = 10000;
path = "${config.xdg.dataHome}/zsh_history";
}; };
profileExtra = lib.optionalString (config.home.sessionPath != [ ]) '' git_status = {
export PATH="$PATH''${PATH:+:}${lib.concatStringsSep ":" config.home.sessionPath}" format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](218)($ahead_behind$stashed)]($style)";
''; style = "cyan";
conflicted = "";
initContent = renamed = "";
# bash deleted = "";
'' stashed = "";
bindkey -v
export KEYTIMEOUT=1
# search history based on what's typed in the prompt
autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end
# General completion behavior
zstyle ':completion:*' completer _extensions _complete _approximate
# Use cache
zstyle ':completion:*' use-cache on
zstyle ':completion:*' cache-path "$XDG_CACHE_HOME/zsh/.zcompcache"
# Complete the alias
zstyle ':completion:*' complete true
# Autocomplete options
zstyle ':completion:*' complete-options true
# Completion matching control
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true
# Group matches and describe
zstyle ':completion:*' menu select
zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name '''
zstyle ':completion:*' verbose yes
zstyle ':completion:*:matches' group 'yes'
zstyle ':completion:*:warnings' format '%F{red}%B-- No match for: %d --%b%f'
zstyle ':completion:*:messages' format '%d'
zstyle ':completion:*:corrections' format '%B%d (errors: %e)%b'
zstyle ':completion:*:descriptions' format '[%d]'
# Colors
zstyle ':completion:*' list-colors ''${(s.:.)LS_COLORS}
# case insensitive tab completion
zstyle ':completion:*:*:cd:*' tag-order local-directories directory-stack path-directories
zstyle ':completion:*:*:cd:*:directory-stack' menu yes select
zstyle ':completion:*:-tilde-:*' group-order 'named-directories' 'path-directories' 'users' 'expand'
zstyle ':completion:*:*:-command-:*:*' group-order aliases builtins functions commands
zstyle ':completion:*' special-dirs true
zstyle ':completion:*' squeeze-slashes true
# Sort
zstyle ':completion:*' sort false
zstyle ":completion:*:git-checkout:*" sort false
zstyle ':completion:*' file-sort modification
zstyle ':completion:*:eza' sort false
zstyle ':completion:complete:*:options' sort false
zstyle ':completion:files' sort false
'';
};
programs.starship = {
enable = true;
enableZshIntegration = true;
settings = {
add_newline = true;
format = lib.concatStrings [
"$nix_shell"
"$hostname"
"$directory"
"$git_branch"
"$git_state"
"$git_status"
"$line_break"
"$character"
];
directory = {
truncation_length = 99;
truncate_to_repo = false;
};
nix_shell = {
format = "[$symbol]($style) ";
symbol = "🐚";
style = "";
};
git_status = {
format = "[[(*$conflicted$untracked$modified$staged$renamed$deleted)](218)($ahead_behind$stashed)]($style)";
style = "cyan";
conflicted = "";
renamed = "";
deleted = "";
stashed = "";
};
git_state = {
format = "([$state( $progress_current/$progress_total)]($style)) ";
style = "bright-black";
};
line_break = {
disabled = false;
};
}; };
};
programs.eza = { git_state = {
enable = true; format = "([$state( $progress_current/$progress_total)]($style)) ";
}; style = "bright-black";
};
programs.fzf = { line_break.disabled = false;
enable = true;
enableZshIntegration = true;
}; };
}; };
};
programs.eza.enable = true;
programs.fzf = {
enable = true;
enableZshIntegration = true;
};
};
} }
-14
View File
@@ -1,14 +0,0 @@
{ den, ... }:
{
lux.sops-password = den.lib.perUser (
{ user, ... }:
{
nixos =
{ config, ... }:
{
sops.secrets."hashed-password-${user.userName}".neededForUsers = true;
users.users.${user.userName}.hashedPasswordFile = config.sops.secrets."hashed-password-${user.userName}".path;
};
}
);
}
+16 -23
View File
@@ -1,27 +1,20 @@
{ den, ... }:
{ {
lux.ssh = { flake.modules.homeManager.sshClient =
homeManager = { config, ... }:
{ config, ... }: {
{ programs.ssh = {
programs.ssh = { enable = true;
enable = true; enableDefaultConfig = false;
enableDefaultConfig = false; includes = [
includes = [ config.sops.templates."ssh-config-orion".path
config.sops.templates."ssh-config-orion".path ];
];
};
sops.secrets."orion-ip" = { };
sops.templates."ssh-config-orion".content = ''
Host orion
HostName ${config.sops.placeholder."orion-ip"}
ForwardAgent yes
'';
}; };
nixos.security.sudo.extraConfig = '' sops.secrets."orion-ip" = { };
Defaults env_keep+=SSH_AUTH_SOCK sops.templates."ssh-config-orion".content = ''
''; Host orion
}; HostName ${config.sops.placeholder."orion-ip"}
ForwardAgent yes
'';
};
} }
+20
View File
@@ -0,0 +1,20 @@
{ ... }:
{
flake.modules.nixos.standardBoot =
{ pkgs, ... }:
{
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot = {
enable = true;
consoleMode = "auto";
configurationLimit = 5;
};
};
tmp.cleanOnBoot = true;
kernelPackages = pkgs.linuxPackages_latest;
};
};
}
+5 -9
View File
@@ -1,13 +1,9 @@
{ ... }: { ... }:
{ {
lux.steam = { flake.modules.nixos.steam = {
nixos = programs.steam = {
{ pkgs, ... }: enable = true;
{ protontricks.enable = true;
programs.steam = { };
enable = true;
protontricks.enable = true;
};
};
}; };
} }
+36 -51
View File
@@ -1,56 +1,41 @@
{ {
den, flake.modules.homeManager.syncthing =
lib, { ... }:
... let
}: syncthingMesh = {
let "kiri@orion" = {
meshDevices = lib.listToAttrs ( name = "kiri@orion";
lib.concatMap ( id = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI";
host: };
lib.mapAttrsToList (
userName: user:
let
name = "${userName}@${host.name}";
in
{
inherit name;
value = {
inherit name;
id = user.syncthingId;
};
}
) (lib.filterAttrs (_: u: u.syncthingId != null) host.users)
) (lib.attrValues den.hosts.x86_64-linux)
);
in
{
lux.syncthing = den.lib.perUser (
{ host, user }:
{
homeManager = {
services.syncthing = {
enable = true;
overrideDevices = true; "kiri@polaris" = {
overrideFolders = true; name = "kiri@polaris";
id = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
settings = {
folders = {
sync = {
path = "~/sync";
label = "sync";
devices = lib.attrNames meshDevices;
};
calibre = {
path = "~/calibre";
label = "calibre";
devices = lib.attrNames meshDevices;
};
};
devices = meshDevices;
};
}; };
}; };
} in
); {
services.syncthing = {
enable = true;
overrideDevices = true;
overrideFolders = true;
settings = {
folders = {
sync = {
path = "~/sync";
label = "sync";
devices = builtins.attrNames syncthingMesh;
};
calibre = {
path = "~/calibre";
label = "calibre";
devices = builtins.attrNames syncthingMesh;
};
};
devices = syncthingMesh;
};
};
};
} }
+1 -1
View File
@@ -1,5 +1,5 @@
{ {
lux.system-base.nixos = { flake.modules.nixos.systemBase = {
users.mutableUsers = false; users.mutableUsers = false;
services.dbus.implementation = "broker"; services.dbus.implementation = "broker";
+62 -79
View File
@@ -1,82 +1,65 @@
{ inputs, ... }:
{ {
lux.terminal = { flake.modules.homeManager.terminal =
homeManager = { pkgs, ... }:
{ pkgs, ... }: {
{ xdg.terminal-exec = {
xdg.terminal-exec = { enable = true;
enable = true; settings.default = [ "kitty.desktop" ];
settings.default = [ "kitty.desktop" ];
};
programs.kitty = {
enable = true;
font = {
name = "JetBrains Mono";
size = 11;
};
settings = {
# Fonts
disable_ligatures = "always";
# Scrollback
scrollback_lines = 10000;
# Terminal bell
enable_audio_bell = false;
# Window layout
confirm_os_window_close = 0;
window_padding_width = 3;
# Advanced
update_check_interval = 0;
};
extraConfig = ''
## name: Kanagawa
## license: MIT
## author: Tommaso Laurenzi
## upstream: https://github.com/rebelot/kanagawa.nvim/
background #1F1F28
foreground #DCD7BA
selection_background #2D4F67
selection_foreground #C8C093
url_color #72A7BC
cursor #C8C093
# Tabs
active_tab_background #1F1F28
active_tab_foreground #C8C093
inactive_tab_background #1F1F28
inactive_tab_foreground #727169
#tab_bar_background #15161E
# normal
color0 #16161D
color1 #C34043
color2 #76946A
color3 #C0A36E
color4 #7E9CD8
color5 #957FB8
color6 #6A9589
color7 #C8C093
# bright
color8 #727169
color9 #E82424
color10 #98BB6C
color11 #E6C384
color12 #7FB4CA
color13 #938AA9
color14 #7AA89F
color15 #DCD7BA
# extended colors
color16 #FFA066
color17 #FF5D62
'';
};
}; };
};
programs.kitty = {
enable = true;
font = {
name = "JetBrains Mono";
size = 11;
};
settings = {
disable_ligatures = "always";
scrollback_lines = 10000;
enable_audio_bell = false;
confirm_os_window_close = 0;
window_padding_width = 3;
update_check_interval = 0;
};
extraConfig = ''
## name: Kanagawa
## license: MIT
## author: Tommaso Laurenzi
## upstream: https://github.com/rebelot/kanagawa.nvim/
background #1F1F28
foreground #DCD7BA
selection_background #2D4F67
selection_foreground #C8C093
url_color #72A7BC
cursor #C8C093
active_tab_background #1F1F28
active_tab_foreground #C8C093
inactive_tab_background #1F1F28
inactive_tab_foreground #727169
color0 #16161D
color1 #C34043
color2 #76946A
color3 #C0A36E
color4 #7E9CD8
color5 #957FB8
color6 #6A9589
color7 #C8C093
color8 #727169
color9 #E82424
color10 #98BB6C
color11 #E6C384
color12 #7FB4CA
color13 #938AA9
color14 #7AA89F
color15 #DCD7BA
color16 #FFA066
color17 #FF5D62
'';
};
};
} }
+42 -48
View File
@@ -1,54 +1,48 @@
{ {
lux.theme = { flake.modules.homeManager.theme =
homeManager = { config, pkgs, ... }:
{ config, pkgs, ... }: let
{ kanagawaThemeSrc = pkgs.fetchFromGitHub {
home.pointerCursor = { owner = "Fausto-Korpsvart";
name = "phinger-cursors-light"; repo = "Kanagawa-GKT-Theme";
package = pkgs.phinger-cursors; rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
size = 24; hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
gtk.enable = true; };
};
gtk = { kanagawaOverride = {
enable = true; version = "unstable-2025-10-23";
gtk3.bookmarks = [ src = kanagawaThemeSrc;
"sftp://orion Orion VPS" };
]; in
theme = { {
name = "Kanagawa-BL-LB"; home.pointerCursor = {
# Package in nixpkgs is outdated name = "phinger-cursors-light";
package = pkgs.kanagawa-gtk-theme.overrideAttrs (oldAttrs: { package = pkgs.phinger-cursors;
version = "unstable-2025-10-23"; size = 24;
src = pkgs.fetchFromGitHub { gtk.enable = true;
owner = "Fausto-Korpsvart"; };
repo = "Kanagawa-GKT-Theme";
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
};
});
};
gtk4.theme = {
inherit (config.gtk.theme) name package;
};
iconTheme = {
name = "Kanagawa";
package = pkgs.kanagawa-icon-theme.overrideAttrs (oldAttrs: {
version = "unstable-2025-10-23";
src = pkgs.fetchFromGitHub {
owner = "Fausto-Korpsvart";
repo = "Kanagawa-GKT-Theme";
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
};
});
};
};
qt = { gtk = {
enable = true; enable = true;
platformTheme.name = "gtk3"; gtk3.bookmarks = [
"sftp://orion Orion VPS"
];
theme = {
name = "Kanagawa-BL-LB";
package = pkgs.kanagawa-gtk-theme.overrideAttrs (_: kanagawaOverride);
};
gtk4.theme = {
inherit (config.gtk.theme) name package;
};
iconTheme = {
name = "Kanagawa";
package = pkgs.kanagawa-icon-theme.overrideAttrs (_: kanagawaOverride);
}; };
}; };
};
qt = {
enable = true;
platformTheme.name = "gtk3";
};
};
} }
+51 -64
View File
@@ -1,73 +1,60 @@
{ inputs, ... }:
{ {
lux.vicinae = { flake.modules.homeManager.vicinae =
homeManager = { pkgs, inputs, ... }:
{ pkgs, ... }: {
{ programs.vicinae = {
programs.vicinae = { enable = true;
enable = true; systemd.enable = true;
systemd.enable = true;
themes = { themes.kanagawa-wave = {
kanagawa-wave = { meta = {
meta = { version = 1;
version = 1; name = "Kanagawa Wave";
name = "Kanagawa Wave"; description = "A dark theme inspired by the colors of the famous painting by Katsushika Hokusai.";
description = "A dark theme inspired by the colors of the famous painting by Katsushika Hokusai."; variant = "dark";
variant = "dark"; inherits = "vicinae-dark";
inherits = "vicinae-dark";
};
colors = {
core = {
background = "#1F1F28";
foreground = "#DCD7BA";
secondary_background = "#16161D";
border = "#2A2A37";
accent = "#7E9CD8";
};
accents = {
blue = "#7E9CD8";
green = "#98BB6C";
magenta = "#D27E99";
orange = "#FFA066";
purple = "#957FB8";
red = "#E82424";
yellow = "#E6C384";
cyan = "#7AA89F";
};
input = {
border_focus = "colors.core.accent";
};
};
};
}; };
colors = {
settings = { core = {
theme = { background = "#1F1F28";
light.name = "kanagawa-wave"; foreground = "#DCD7BA";
dark.name = "kanagawa-wave"; secondary_background = "#16161D";
border = "#2A2A37";
accent = "#7E9CD8";
}; };
accents = {
blue = "#7E9CD8";
green = "#98BB6C";
magenta = "#D27E99";
orange = "#FFA066";
purple = "#957FB8";
red = "#E82424";
yellow = "#E6C384";
cyan = "#7AA89F";
};
input.border_focus = "colors.core.accent";
}; };
extensions = with inputs.vicinae-extensions.packages.${pkgs.stdenv.hostPlatform.system}; [
agenda
#bluetooth
brotab
#dbus
fuzzy-files
github
it-tools
niri
nix
podman
process-manager
pulseaudio
simple-bookmarks
ssh
#systemd
];
}; };
settings.theme = {
light.name = "kanagawa-wave";
dark.name = "kanagawa-wave";
};
extensions = with inputs.vicinae-extensions.packages.${pkgs.stdenv.hostPlatform.system}; [
agenda
brotab
fuzzy-files
github
it-tools
niri
nix
podman
process-manager
pulseaudio
simple-bookmarks
ssh
];
}; };
}; };
} }
+38 -45
View File
@@ -1,52 +1,45 @@
{ {
lux.xdg = { flake.modules.homeManager.xdg =
homeManager = { config, pkgs, ... }:
{ config, pkgs, ... }: let
let homeDir = config.home.homeDirectory;
homeDir = config.home.homeDirectory; localDir = "${homeDir}/.local";
localDir = "${homeDir}/.local"; mediaDir = "${homeDir}/media";
mediaDir = "${homeDir}/media"; in
in {
{ xdg = {
xdg = { enable = true;
cacheHome = "${localDir}/cache";
configHome = "${homeDir}/.config";
dataHome = "${localDir}/share";
stateHome = "${localDir}/state";
userDirs = {
enable = true; enable = true;
createDirectories = true;
setSessionVariables = true;
cacheHome = "${localDir}/cache"; download = "${homeDir}/downloads";
configHome = "${homeDir}/.config"; documents = "${homeDir}/documents";
dataHome = "${localDir}/share"; music = "${mediaDir}/music";
stateHome = "${localDir}/state"; pictures = "${mediaDir}/images";
videos = "${mediaDir}/videos";
userDirs = { desktop = "${localDir}/desktop";
enable = true; publicShare = "${localDir}/public";
createDirectories = true; templates = "${localDir}/templates";
setSessionVariables = true; };
download = "${homeDir}/downloads";
documents = "${homeDir}/documents";
# Organize into media folder
music = "${mediaDir}/music";
pictures = "${mediaDir}/images";
videos = "${mediaDir}/videos";
# Hide these
desktop = "${localDir}/desktop";
publicShare = "${localDir}/public";
templates = "${localDir}/templates";
};
mimeApps = {
enable = true;
defaultApplicationPackages = with pkgs; [
sioyek
imv
vivaldi
neovim
nautilus
];
};
mimeApps = {
enable = true;
defaultApplicationPackages = with pkgs; [
sioyek
imv
vivaldi
neovim
nautilus
];
}; };
}; };
}; };
} }
+36
View File
@@ -0,0 +1,36 @@
{
inputs,
config,
...
}:
let
nixosModules = config.flake.modules.nixos;
in
{
imports = [ inputs.flake-parts.flakeModules.modules ];
systems = [ "x86_64-linux" ];
flake.nixosConfigurations = {
orion = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ nixosModules.orion ];
};
polaris = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ nixosModules.polaris ];
};
zenith = inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; };
modules = [ nixosModules.zenith ];
};
};
perSystem =
{ pkgs, ... }:
{
formatter = pkgs.nixfmt-tree;
};
}
+51
View File
@@ -0,0 +1,51 @@
{ inputs, lib, ... }:
{
imports = [ inputs.disko.nixosModules.disko ];
disko.devices = {
disk.disk1 = {
device = lib.mkDefault "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
};
esp = {
name = "ESP";
size = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
name = "root";
size = "100%";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
lvm_vg.pool = {
type = "lvm_vg";
lvs.root = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [ "defaults" ];
};
};
};
};
}
+22
View File
@@ -0,0 +1,22 @@
{ lib, modulesPath, ... }:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+65 -38
View File
@@ -1,43 +1,70 @@
{ den, lib, lux, ... }: {
inputs,
config,
...
}:
let let
lingerForUsers = den.lib.perHost ( nixosModules = config.flake.modules.nixos;
{ host, ... }:
{
nixos.users.users = lib.mapAttrs (_: _: {
linger = true;
}) host.users;
}
);
in in
{ {
den.aspects.orion = { flake.modules.nixos.orion =
includes = (with lux.services._; [ { pkgs, ... }:
caddy let
openssh host = {
vaultwarden isServer = true;
radicale
actual
gitea
]) ++ [ lingerForUsers ];
nixos =
{ pkgs, ... }:
{
environment.systemPackages = [
pkgs.kitty
];
networking = {
firewall.enable = true;
firewall.allowPing = false;
nftables.enable = true;
};
# Use ssh authorization for sudo instead of password
security.pam = {
sshAgentAuth.enable = true;
services.sudo.sshAgentAuth = true;
};
}; };
}; in
{
_module.args.host = host;
imports = [
inputs.home-manager.nixosModules.home-manager
nixosModules.sopsHost
nixosModules.caddy
nixosModules.openssh
nixosModules.vaultwarden
nixosModules.radicale
nixosModules.actual
nixosModules.gitea
nixosModules.kiri
./_hardware.nix
./_disk.nix
];
system.stateVersion = "24.05";
home-manager = {
useGlobalPkgs = true;
backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; };
};
networking.hostName = "orion";
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
users.users.kiri = {
linger = true;
openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A"
];
};
environment.systemPackages = [
pkgs.kitty
];
networking = {
firewall.enable = true;
firewall.allowPing = false;
nftables.enable = true;
};
security.pam = {
sshAgentAuth.enable = true;
services.sudo.sshAgentAuth = true;
};
};
} }
-63
View File
@@ -1,63 +0,0 @@
{ inputs, ... }:
{
den.aspects.orion = {
nixos =
{ lib, ... }:
{
imports = [ inputs.disko.nixosModules.disko ];
disko.devices = {
disk.disk1 = {
device = lib.mkDefault "/dev/sda";
type = "disk";
content = {
type = "gpt";
partitions = {
boot = {
name = "boot";
size = "1M";
type = "EF02";
};
esp = {
name = "ESP";
size = "500M";
type = "EF00";
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
};
root = {
name = "root";
size = "100%";
content = {
type = "lvm_pv";
vg = "pool";
};
};
};
};
};
lvm_vg = {
pool = {
type = "lvm_vg";
lvs = {
root = {
size = "100%FREE";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/";
mountOptions = [
"defaults"
];
};
};
};
};
};
};
};
};
}
-38
View File
@@ -1,38 +0,0 @@
# Do not modify this file! It was generated by 'nixos-generate-config'
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/system.nix instead.
{ ... }:
{
den.aspects.orion = {
nixos =
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
};
};
}
+44
View File
@@ -0,0 +1,44 @@
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/bda7f8b9-2b3d-4190-8518-baa50490227e";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/26FE-CA37";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
+81 -59
View File
@@ -1,72 +1,94 @@
{ inputs, lux, ... }:
{ {
den.aspects.polaris = { inputs,
includes = [ lux.bundles._.local-session ]; config,
...
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos.polaris =
{
config,
pkgs,
...
}:
let
host = {
isServer = false;
};
in
{
_module.args.host = host;
provides.kiri = { imports = [
includes = with lux; [ nixosModules.desktopBase
bundles._.local-session-user nixosModules.steam
nixosModules.kiri
nixosModules.ergon
./_hardware.nix
]
++ (with inputs.nixos-hardware.nixosModules; [
common-pc
common-pc-ssd
common-cpu-amd
common-gpu-amd
]);
system.stateVersion = "24.05";
networking.hostName = "polaris";
home-manager.users.kiri.imports = with homeModules; [
nix
bitwarden bitwarden
email email
pim pim
mpv mpv
sops-password niri
steam clipboard
localApps
qbittorrentClient
vicinae
xdg
theme
noctalia
]; ];
};
provides.ergon = { home-manager.users.kiri.programs.niri.settings.outputs = {
includes = with lux; [ "LG Electronics LG ULTRAGEAR 103NTYT8R290" = {
sops-password "focus-at-startup" = true;
]; position = {
}; x = 0;
y = 0;
nixos =
{
config,
pkgs,
...
}:
{
imports = with inputs.nixos-hardware.nixosModules; [
common-pc
common-pc-ssd
common-cpu-amd
common-gpu-amd
];
services.hardware.openrgb.enable = true;
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot = {
enable = true;
consoleMode = "auto";
configurationLimit = 5;
# Convert boot entry to a more readable name.
extraInstallCommands = ''
ENTRIES="${config.boot.loader.efi.efiSysMountPoint}/loader/entries"
PROFILES="/nix/var/nix/profiles"
for file in "$ENTRIES"/nixos-generation-*.conf; do
generation=$(${pkgs.coreutils}/bin/basename "$file" | ${pkgs.gnugrep}/bin/grep -o -E '[0-9]+')
timestamp=$(${pkgs.coreutils}/bin/stat -c %y "$PROFILES/system-$generation-link" 2>/dev/null | ${pkgs.coreutils}/bin/cut -d. -f1)
if [ -z "$timestamp" ]; then
timestamp="Unknown Date"
fi
${pkgs.gnused}/bin/sed -i "s/^version .*/version Generation $generation - $timestamp/" "$file"
done
'';
};
}; };
};
tmp.cleanOnBoot = true; "LG Electronics LG ULTRAGEAR 103NTJJ8R332" = {
kernelPackages = pkgs.linuxPackages_latest; position = {
x = 2560;
y = 0;
};
}; };
}; };
};
services.hardware.openrgb.enable = true;
boot.loader.systemd-boot.extraInstallCommands = ''
ENTRIES="${config.boot.loader.efi.efiSysMountPoint}/loader/entries"
PROFILES="/nix/var/nix/profiles"
for file in "$ENTRIES"/nixos-generation-*.conf; do
generation=$(${pkgs.coreutils}/bin/basename "$file" | ${pkgs.gnugrep}/bin/grep -o -E '[0-9]+')
timestamp=$(${pkgs.coreutils}/bin/stat -c %y "$PROFILES/system-$generation-link" 2>/dev/null | ${pkgs.coreutils}/bin/cut -d. -f1)
if [ -z "$timestamp" ]; then
timestamp="Unknown Date"
fi
${pkgs.gnused}/bin/sed -i "s/^version .*/version Generation $generation - $timestamp/" "$file"
done
'';
};
} }
-50
View File
@@ -1,50 +0,0 @@
{
den.aspects.polaris = {
nixos =
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/bda7f8b9-2b3d-4190-8518-baa50490227e";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/26FE-CA37";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
};
};
}
+36
View File
@@ -0,0 +1,36 @@
{ lib, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/6d8f6f33-c9d9-4e90-b496-d5b3ef5e9aeb";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8797-B47E";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+56 -36
View File
@@ -1,48 +1,68 @@
{ inputs, lux, ... }:
{ {
den.aspects.zenith = { inputs,
includes = [ lux.bundles._.local-session ]; config,
...
}:
let
nixosModules = config.flake.modules.nixos;
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos.zenith =
{ ... }:
let
host = {
isServer = false;
};
in
{
_module.args.host = host;
provides.kiri = { imports = [
includes = with lux; [ nixosModules.desktopBase
bundles._.local-session-user nixosModules.kiri
nixosModules.ergon
./_hardware.nix
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu
];
system.stateVersion = "24.05";
networking.hostName = "zenith";
home-manager.users.kiri.imports = with homeModules; [
nix
bitwarden bitwarden
email email
pim pim
mpv mpv
sops-password niri
clipboard
localApps
qbittorrentClient
vicinae
xdg
theme
noctalia
]; ];
};
provides.ergon = { home-manager.users.kiri.programs.niri.settings.outputs = {
includes = with lux; [ "California Institute of Technology 0x1410 Unknown" = {
sops-password "focus-at-startup" = true;
]; position = {
}; x = 0;
y = 0;
nixos = };
{ pkgs, ... }: scale = 1.5;
{ mode = {
imports = [ width = 3072;
inputs.nixos-hardware.nixosModules.lenovo-yoga-7-14ARH7-amdgpu height = 1920;
]; refresh = 120.002;
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot = {
enable = true;
consoleMode = "auto";
configurationLimit = 5;
};
}; };
tmp.cleanOnBoot = true;
kernelPackages = pkgs.linuxPackages_latest;
}; };
hardware.enableRedistributableFirmware = true;
services.fwupd.enable = true;
}; };
};
hardware.enableRedistributableFirmware = true;
services.fwupd.enable = true;
};
} }
-46
View File
@@ -1,46 +0,0 @@
{
den.aspects.zenith = {
nixos =
{
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-amd" ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/6d8f6f33-c9d9-4e90-b496-d5b3ef5e9aeb";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8797-B47E";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
networking.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
};
};
}
-109
View File
@@ -1,109 +0,0 @@
let
serviceDomain = "jelles.net";
adminKeyPath = "/var/lib/sops/keys.txt";
sharedIdentity = {
realName = "Jelle Spreeuwenberg";
authorizedSshKeys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAU2LydkXRTtNFY7oyX8JQURwXLVhB71DeK8XzrXeFX1 openpgp:0xA490D93A"
];
};
kiriAccount = sharedIdentity // {
emails = {
main = {
address = "mail@jelles.net";
primary = true;
kind = "mxrouting";
};
old = {
address = "mail@jellespreeuwenberg.nl";
kind = "mxrouting";
};
uni = {
address = "j.spreeuwenberg@student.tue.nl";
kind = "office365";
};
work = {
address = "jelle.spreeuwenberg@yookr.org";
kind = "office365";
};
};
};
ergonAccount = sharedIdentity // {
emails.work = {
address = "jelle.spreeuwenberg@yookr.org";
primary = true;
kind = "office365";
};
};
in
{
den.hosts.x86_64-linux = {
polaris = {
inherit serviceDomain;
sopsAdminKeyPath = adminKeyPath;
sopsAdminKeyUsers = [
"kiri"
"ergon"
];
displays = {
"LG Electronics LG ULTRAGEAR 103NTYT8R290" = {
primary = true;
position.x = 0;
position.y = 0;
};
"LG Electronics LG ULTRAGEAR 103NTJJ8R332" = {
position.x = 2560;
position.y = 0;
};
};
users = {
kiri = kiriAccount // {
syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
};
ergon = ergonAccount;
};
};
zenith = {
inherit serviceDomain;
sopsAdminKeyPath = adminKeyPath;
sopsAdminKeyUsers = [
"kiri"
"ergon"
];
displays = {
"California Institute of Technology 0x1410 Unknown" = {
primary = true;
position.x = 0;
position.y = 0;
scale = 1.5;
mode = {
width = 3072;
height = 1920;
refresh = 120.002;
};
};
};
users = {
kiri = kiriAccount;
ergon = ergonAccount;
};
};
orion = {
inherit serviceDomain;
requiresSshRecovery = true;
sshRecoveryUsers = [ "kiri" ];
sopsHostSshKeyPath = "/etc/ssh/ssh_host_ed25519_key";
sopsAdminKeyPath = adminKeyPath;
sopsAdminKeyUsers = [ "kiri" ];
users.kiri = kiriAccount // {
syncthingId = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI";
};
};
};
}
-135
View File
@@ -1,135 +0,0 @@
{ lib, ... }:
{
den.schema = {
user =
{ config, ... }:
let
primaryEmailCount = builtins.length (lib.filter (email: email.primary) (builtins.attrValues config.emails));
in
{
options = {
realName = lib.mkOption {
type = lib.types.str;
};
authorizedSshKeys = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
emails = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ ... }:
{
options = {
address = lib.mkOption {
type = lib.types.str;
};
primary = lib.mkOption {
type = lib.types.bool;
default = false;
};
kind = lib.mkOption {
type = lib.types.enum [
"mxrouting"
"office365"
];
};
};
}
)
);
default = { };
};
syncthingId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
};
config = {
assertions = [
{
assertion = primaryEmailCount == 1;
message = "Each user must define exactly one primary email.";
}
];
classes = lib.mkDefault [ "homeManager" ];
};
};
host = {
options = {
serviceDomain = lib.mkOption {
type = lib.types.str;
};
displays = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ ... }:
{
options = {
position = lib.mkOption {
type = lib.types.submodule {
options = {
x = lib.mkOption { type = lib.types.int; };
y = lib.mkOption { type = lib.types.int; };
};
};
};
scale = lib.mkOption {
type = lib.types.nullOr (lib.types.oneOf [
lib.types.int
lib.types.float
]);
default = null;
};
primary = lib.mkOption {
type = lib.types.bool;
default = false;
};
mode = lib.mkOption {
type = lib.types.nullOr (
lib.types.submodule (
{ ... }:
{
options = {
width = lib.mkOption { type = lib.types.int; };
height = lib.mkOption { type = lib.types.int; };
refresh = lib.mkOption {
type = lib.types.nullOr lib.types.float;
default = null;
};
};
}
)
);
default = null;
};
};
}
)
);
default = { };
};
requiresSshRecovery = lib.mkOption {
type = lib.types.bool;
default = false;
};
sshRecoveryUsers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
sopsHostSshKeyPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
sopsAdminKeyPath = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
sopsAdminKeyUsers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
};
};
};
};
}
+48 -75
View File
@@ -1,85 +1,58 @@
{ den, inputs, lib, ... }: {
inputs,
...
}:
let let
sopsReadersGroup = "sops-users"; sopsAdminKeyPath = "/var/lib/sops/keys.txt";
in in
{ {
den.ctx.host.includes = [ flake.modules.nixos.sopsHost =
(den.lib.perHost ( {
{ host, ... }: lib,
let host ? {
missingAdminUsers = lib.filter (userName: !(builtins.hasAttr userName host.users)) host.sopsAdminKeyUsers; isServer = false;
hasSharedAdminKey = host.sopsAdminKeyPath != null && host.sopsAdminKeyUsers != [ ]; },
adminKeyDir = if host.sopsAdminKeyPath == null then null else builtins.dirOf host.sopsAdminKeyPath; ...
in }:
{ let
nixos = { useHostSshKey = host.isServer;
imports = [ inputs.sops-nix.nixosModules.sops ]; useAdminKeyFile = !host.isServer;
adminKeyDir = builtins.dirOf sopsAdminKeyPath;
in
{
imports = [ inputs.sops-nix.nixosModules.sops ];
sops = { sops = {
defaultSopsFile = ./secrets.yaml; defaultSopsFile = ./secrets.yaml;
age = age =
if host.sopsHostSshKeyPath != null then lib.optionalAttrs useHostSshKey {
{ sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sshKeyPaths = [ host.sopsHostSshKeyPath ]; }
} // lib.optionalAttrs useAdminKeyFile {
else keyFile = sopsAdminKeyPath;
{
keyFile = host.sopsAdminKeyPath;
};
}; };
};
users.groups = lib.optionalAttrs hasSharedAdminKey { systemd.tmpfiles.rules = lib.optionals useAdminKeyFile [
${sopsReadersGroup} = { }; "d ${adminKeyDir} 0750 root wheel -"
}; "z ${sopsAdminKeyPath} 0640 root wheel -"
];
};
users.users = lib.genAttrs host.sopsAdminKeyUsers (_: { flake.modules.homeManager.sopsAdmin =
extraGroups = [ sopsReadersGroup ]; {
}); pkgs,
...
}:
{
imports = [ inputs.sops-nix.homeManagerModules.sops ];
systemd.tmpfiles.rules = lib.optionals hasSharedAdminKey [ sops = {
"d ${adminKeyDir} 0750 root ${sopsReadersGroup} -" defaultSopsFile = ./secrets.yaml;
"z ${host.sopsAdminKeyPath} 0640 root ${sopsReadersGroup} -" age.keyFile = sopsAdminKeyPath;
]; };
assertions = [ home.sessionVariables.SOPS_AGE_KEY_FILE = sopsAdminKeyPath;
{ home.packages = [ pkgs.sops ];
assertion = host.sopsAdminKeyUsers == [ ] || host.sopsAdminKeyPath != null; };
message = "Hosts with sopsAdminKeyUsers must set sopsAdminKeyPath.";
}
{
assertion = missingAdminUsers == [ ];
message =
"All sopsAdminKeyUsers must exist on the host. Missing: "
+ lib.concatStringsSep ", " missingAdminUsers;
}
];
};
}
))
];
den.ctx.user.includes = [
(den.lib.perUser (
{ host, user, ... }:
if builtins.elem user.userName host.sopsAdminKeyUsers then
{
homeManager =
{ pkgs, ... }:
{
imports = [ inputs.sops-nix.homeManagerModules.sops ];
sops = {
defaultSopsFile = ./secrets.yaml;
age.keyFile = host.sopsAdminKeyPath;
};
home.sessionVariables.SOPS_AGE_KEY_FILE = host.sopsAdminKeyPath;
home.packages = [ pkgs.sops ];
};
}
else
{ }
))
];
} }
+85
View File
@@ -0,0 +1,85 @@
{ config, ... }:
let
homeModules = config.flake.modules.homeManager;
realName = "Jelle Spreeuwenberg";
accounts = {
kiri = {
homeDirectory = "/home/kiri";
gitEmail = "mail@jelles.net";
vaultEmail = "mail@jelles.net";
extraHomeImports = with homeModules; [ syncthing ];
};
ergon = {
homeDirectory = "/home/ergon";
gitEmail = "jelle.spreeuwenberg@yookr.org";
vaultEmail = "jelle.spreeuwenberg@yookr.org";
extraHomeImports = with homeModules; [ nix ];
};
};
mkUser =
{ accountName }:
{
config,
pkgs,
...
}:
let
account = accounts.${accountName};
in
{
sops.secrets."hashed-password-${accountName}".neededForUsers = true;
programs.zsh.enable = true;
users.users.${accountName} = {
name = accountName;
home = account.homeDirectory;
hashedPasswordFile = config.sops.secrets."hashed-password-${accountName}".path;
isNormalUser = true;
shell = pkgs.zsh;
extraGroups = [
"wheel"
"networkmanager"
];
};
home-manager.users.${accountName} = {
home = {
username = accountName;
homeDirectory = account.homeDirectory;
stateVersion = "24.05";
};
imports =
with homeModules;
[
terminal
shell
neovim
sshClient
sopsAdmin
git
devTools
podman
gemini
]
++ account.extraHomeImports;
programs.git.settings.user = {
name = realName;
email = account.gitEmail;
};
programs.rbw.settings.email = account.vaultEmail;
};
};
in
{
flake.modules.nixos.kiri = mkUser { accountName = "kiri"; };
flake.modules.nixos.ergon = mkUser { accountName = "ergon"; };
}
-19
View File
@@ -1,19 +0,0 @@
{ den, lux, ... }:
{
den.aspects.ergon = {
includes = with lux; [
(den._.user-shell "zsh")
terminal
shell
neovim
ssh
bundles._.development
({ user, ... }: {
nixos.users.users.${user.userName}.extraGroups = [
"wheel"
"networkmanager"
];
})
];
};
}
-15
View File
@@ -1,15 +0,0 @@
{ den, lux, ... }:
{
den.aspects.kiri = {
includes = with lux; [
den._.primary-user
(den._.user-shell "zsh")
syncthing
terminal
shell
neovim
ssh
bundles._.development
];
};
}