Compare commits

..

34 Commits

Author SHA1 Message Date
kiri 9df7bfd825 chore: remove outdated AGENTS.md 2026-06-12 15:46:06 +02:00
kiri 9f565b85db feat: remove global git ignores 2026-06-12 11:33:56 +02:00
kiri 562a65a714 feat: make escape exit menuselect in zsh 2026-06-12 11:33:36 +02:00
kiri beabcabb60 feat: add work repo to trusted codex folders 2026-06-08 10:04:02 +02:00
kiri 709e89c017 fix: nix-wrapper-modules warning 2026-06-08 10:02:36 +02:00
kiri b35c95b4c8 feat: remove uv 2026-06-08 10:02:05 +02:00
kiri 5a1f5a9894 feat: move to limine 2026-06-08 10:01:59 +02:00
kiri d6a3587a89 feat: set notifcation density to compact 2026-06-06 11:35:10 +02:00
kiri ed1c94735c chore: update inputs 2026-06-05 14:54:05 +02:00
kiri 239febf3e0 feat: move notifications to bottom right 2026-05-29 13:15:15 +02:00
kiri e7c0a084a0 chore: update inputs 2026-05-29 10:07:46 +02:00
kiri 30564171f0 chore: update inputs and devenv 2026-05-27 19:23:01 +02:00
kiri 1d591c4f4a feat: add vps-insights to orion 2026-05-07 01:52:25 +02:00
kiri b204e48509 chore: update nix-wrapper-modules call 2026-05-07 00:59:18 +02:00
kiri 86dcf5ce4b fix: transmission failing because of non-existing directory 2026-05-07 00:58:52 +02:00
kiri 8453447f90 feat: switch torrent client to transmission 2026-05-07 00:45:23 +02:00
kiri 2c2276c9b8 feat: always approve nixos mcp requests in codex 2026-05-07 00:37:15 +02:00
kiri c4146eaae0 feat: reduce number of nixpkgs revisions 2026-05-07 00:24:32 +02:00
kiri f193c02f4a feat: better zsh completion 2026-05-06 23:51:54 +02:00
kiri d84fec1a82 feat: enable bitwarden for walker 2026-05-06 22:56:34 +02:00
kiri 1458dd1ae6 feat: use sops for radicale password 2026-05-06 22:56:23 +02:00
kiri c501097e4c feat: enable khal 2026-05-06 22:11:30 +02:00
kiri 4b6e05212c refactor: schema 2026-05-06 21:57:58 +02:00
kiri c01c13aa50 feat: enable walker 2026-05-06 21:21:15 +02:00
kiri e33602e879 refactor: dendritic principles 2026-05-06 19:45:03 +02:00
kiri d6878abc61 refactor default apps and add walker 2026-05-06 19:32:37 +02:00
kiri be1a9b7852 feat: use upstream walker and elephant flakes 2026-05-06 16:03:33 +02:00
kiri 7299f5bb79 fix: walker and gtk4 2026-05-05 21:05:24 +02:00
kiri c2082e942e feat: add walker and general launcher config 2026-05-05 20:56:09 +02:00
kiri fdf6ac5e08 feat: add discord 2026-05-05 17:52:56 +02:00
kiri fdc269483e feat: add phone to syncthing 2026-05-05 16:28:49 +02:00
kiri e8d1f58ed5 chore: update inputs 2026-05-01 18:34:04 +02:00
kiri 5bc37c7009 refactor: niri config 2026-04-29 15:49:32 +02:00
kiri efb0179344 feat: improve config UX 2026-04-29 13:50:20 +02:00
42 changed files with 1566 additions and 1006 deletions
-78
View File
@@ -1,78 +0,0 @@
# AGENTS.md
## Purpose
This repo uses the Dendritic Pattern with `flake-parts`.
Design and change the configuration as a composition of **features**, not as a host-first tree.
For deeper design rationale and pattern descriptions, refer to `.agents/dendritic-design-with-flake-parts.wiki`.
## Core Terms
- **Feature**: a flake-parts module under `modules/` that defines one coherent concern.
- **Aspect**: a reusable module published at `flake.modules.<module class>.<aspect name>`.
- **Module class**: the configuration context of an aspect. This repo primarily uses `nixos` and `homeManager`.
- **Feature module**: the flake-parts module that defines aspects, flake outputs, options, or shared helpers.
In this repo, `flake.nix` imports `./modules` recursively via `inputs.import-tree`. Any non-private `.nix` file under `modules/` is therefore treated as a feature module.
## Design Principles
- Work bottom-up. Define features first; assemble hosts from features.
- Keep semantic ownership local. A feature should contain the configuration for that concern across all relevant module classes.
- Name aspects semantically. The aspect name should usually match the file or directory name that defines it.
- Prefer small, composable aspects. Build larger configurations with `imports`.
- Import aspects unconditionally and only within the same module class.
- Put conditions inside module content with `lib.mkIf` or `lib.mkMerge`, never around `imports`.
- Avoid importing the same aspect multiple times along one import path.
- Keep private helper files next to the feature that uses them and prefix them with `_` so `import-tree` does not import them as feature modules.
- Put shared schemas and constructors in dedicated shared modules, not ad hoc host files.
## Repo Structure
- `modules/capabilities/`: reusable leaf capability features and most aspect definitions.
- `modules/capabilities/services/`: reusable service capabilities, especially hosted daemons and network services.
- `modules/profiles/`: bundle features that assemble capabilities into larger profiles such as `host-base` and `workstation-base`.
- `modules/hosts/<name>/default.nix`: host features that assemble NixOS aspects into `flake.modules.nixos.<name>`.
- `modules/secrets/`: secret-related features shared by hosts.
- `modules/flake-parts.nix`: flake-parts entrypoint; defines systems, formatter, and `flake.nixosConfigurations`.
- `modules/lib/`: shared schemas, constructors, and helpers exposed through `repo.helpers`, especially `mkHost` and `mkCaddyReverseProxy`.
- `modules/data.nix`: canonical shared repo data, including the single `repo.account`, machine inventory, desktop preferences, services, and theme data.
- `modules/lib/schema.nix`: shared metadata schema for `repo.*` and NixOS `meta.machine`.
## How Features Are Applied Here
- Reusable NixOS concerns are published as `flake.modules.nixos.<name>`.
- Reusable Home Manager concerns are published as `flake.modules.homeManager.<name>`.
- Hosts are aspects too. `orion`, `polaris`, and `zenith` are `nixos` aspects assembled from smaller aspects.
- `flake.nixosConfigurations` instantiates every entry in `repo.machines` with `config.repo.helpers.mkHost`.
- Hosts define machine data under `repo.machines.<name>` and host-specific NixOS composition under `flake.modules.nixos.<name>`.
- `mkHost` wires the single `repo.account` into `users.users.<name>` and `home-manager.users.<name>`.
- NixOS modules may read `config.meta.machine`; Home Manager modules should read host facts through `osConfig.meta.machine` and user facts through `config.home` or `repo.account`.
## Preferred Aspect Patterns
- **Simple Aspect**: use for one self-contained concern in one or more module classes.
- **Multi Context Aspect**: use when one concern must configure both `nixos` and `homeManager`.
- **Inheritance Aspect**: use by importing a parent aspect and extending it.
- **Conditional Aspect**: use `lib.mkMerge` plus `lib.mkIf` for conditional content.
Use **Collector Aspect** only when composition through imports or shared library helpers is insufficient.
## Change Rules
- When adding a reusable leaf feature, add or extend aspects under `modules/capabilities/` and let profiles or hosts opt into them explicitly.
- When adding a hosted service or network daemon feature, prefer `modules/capabilities/services/`.
- When adding a bundle of existing capabilities, put it under `modules/profiles/`.
- When adding a host, create `modules/hosts/<name>/default.nix` and keep host-local generated files private as `_hardware.nix`, `_disk.nix`, or similar.
- When a feature needs local data or helper code, keep it inside that feature directory and prefix non-feature files with `_` when they live under `modules/`.
- Do not place arbitrary non-feature `.nix` files under `modules/` unless they are intentionally private and excluded from recursive import.
- If a concern is shared across hosts, it belongs in a reusable feature, not inline in one host unless it is truly host-specific.
## Practical Heuristics
- If you are about to edit a host because of a reusable concern, that concern probably wants its own feature.
- If a Home Manager module needs host facts, prefer `osConfig.meta.machine`; for user facts, prefer `config.home` or `repo.account` instead of duplicating literals.
- If a concern spans system and user space, keep both aspects in one feature so the behavior stays coherent.
- If imports would need to be conditional, redesign the aspect boundary instead.
Generated
+490 -268
View File
File diff suppressed because it is too large Load Diff
+34 -8
View File
@@ -2,21 +2,47 @@
description = "NixOS Configuration"; description = "NixOS Configuration";
inputs = { inputs = {
disko.url = "github:nix-community/disko"; disko = {
url = "github:nix-community/disko";
inputs.nixpkgs.follows = "nixpkgs";
};
devenv.url = "github:cachix/devenv";
flake-parts.follows = "lux-pkgs/flake-parts"; flake-parts.follows = "lux-pkgs/flake-parts";
home-manager.url = "github:nix-community/home-manager"; home-manager = {
url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs";
};
import-tree.url = "github:vic/import-tree"; import-tree.url = "github:vic/import-tree";
llm-agents.url = "github:numtide/llm-agents.nix"; llm-agents = {
url = "github:numtide/llm-agents.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
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";
inputs.nixpkgs.follows = "nixpkgs";
};
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";
noctalia.url = "github:noctalia-dev/noctalia-shell"; noctalia.url = "github:noctalia-dev/noctalia-shell";
sops-nix.url = "github:Mic92/sops-nix"; sops-nix = {
nix-index-database.url = "github:nix-community/nix-index-database"; url = "github:Mic92/sops-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
nix-index-database = {
url = "github:nix-community/nix-index-database";
inputs.nixpkgs.follows = "nixpkgs";
};
#vicinae.url = "github:vicinaehq/vicinae"; elephant = {
vicinae-extensions.url = "github:vicinaehq/extensions"; url = "github:abenz1267/elephant";
inputs.nixpkgs.follows = "nixpkgs";
};
walker = {
url = "github:abenz1267/walker";
inputs.elephant.follows = "elephant";
inputs.nixpkgs.follows = "nixpkgs";
};
lux-pkgs.url = "git+ssh://gitea@orion/kiri/lux-pkgs"; lux-pkgs.url = "git+ssh://gitea@orion/kiri/lux-pkgs";
}; };
+69
View File
@@ -0,0 +1,69 @@
{
cursor = {
name = "phinger-cursors-light";
packagePath = [ "phinger-cursors" ];
size = 24;
};
kanagawa = {
displayName = "Kanagawa Wave";
name = "kanagawa-wave";
gtkThemeName = "Kanagawa-BL-LB";
iconThemeName = "Kanagawa";
owner = "Fausto-Korpsvart";
repo = "Kanagawa-GKT-Theme";
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
version = "unstable-2025-10-23";
palette = {
background = "#1F1F28";
foreground = "#DCD7BA";
secondaryBackground = "#16161D";
border = "#2A2A37";
selectionBackground = "#2D4F67";
selectionForeground = "#C8C093";
url = "#72A7BC";
cursor = "#C8C093";
muted = "#727169";
accents = {
blue = "#7E9CD8";
green = "#98BB6C";
magenta = "#D27E99";
orange = "#FFA066";
purple = "#957FB8";
red = "#E82424";
yellow = "#E6C384";
cyan = "#7AA89F";
};
niri.border = {
active = "#7E9CD8";
inactive = "#54546D";
urgent = "#E82424";
};
terminal = {
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";
};
};
};
}
+8
View File
@@ -1,6 +1,7 @@
{ inputs, config, ... }: { inputs, config, ... }:
let let
account = config.repo.account; account = config.repo.account;
hmModules = config.flake.modules.homeManager;
sharedContext = '' sharedContext = ''
# Global Agent Context # Global Agent Context
@@ -21,6 +22,8 @@ let
in in
{ {
flake.modules.nixos.ai = { flake.modules.nixos.ai = {
home-manager.sharedModules = [ hmModules.ai ];
nixpkgs.overlays = [ inputs.llm-agents.overlays.default ]; nixpkgs.overlays = [ inputs.llm-agents.overlays.default ];
nix.settings = { nix.settings = {
@@ -83,9 +86,14 @@ in
"five-hour-limit" "five-hour-limit"
]; ];
projects.${account.nixosConfigurationPath}.trust_level = "trusted"; projects.${account.nixosConfigurationPath}.trust_level = "trusted";
projects."${config.home.homeDirectory}/work/repos/yookr_data_science".trust_level = "trusted";
sandbox_mode = "workspace-write"; sandbox_mode = "workspace-write";
personality = "pragmatic"; personality = "pragmatic";
features.undo = true; features.undo = true;
mcp_servers.nixos = config.programs.mcp.servers.nixos // {
enabled = true;
default_tools_approval_mode = "approve";
};
}; };
}; };
}; };
+70 -57
View File
@@ -1,63 +1,87 @@
{ ... }: { config, ... }:
let let
mkPrimaryDesktopApplication = homeModules = config.flake.modules.homeManager;
{ vivaldiPackage = pkgs: pkgs.vivaldi;
name, nautilusPackage = pkgs: pkgs.nautilus;
package,
desktopEntryName,
}:
{ pkgs, ... }:
{
meta.desktop.${name} = {
inherit desktopEntryName;
package = package pkgs;
};
};
in in
{ {
flake.modules.homeManager.primary-browser-vivaldi = mkPrimaryDesktopApplication { flake.modules.homeManager.browser-vivaldi =
name = "browser"; { pkgs, ... }:
package = pkgs: pkgs.vivaldi; {
desktopEntryName = "vivaldi-stable"; home.packages = [ (vivaldiPackage pkgs) ];
};
flake.modules.homeManager.primary-browser-vivaldi =
{ lib, pkgs, ... }:
{
imports = [ homeModules.browser-vivaldi ];
facts.desktop.browserCommand = lib.getExe (vivaldiPackage pkgs);
home.sessionVariables.BROWSER = lib.getExe (vivaldiPackage pkgs);
xdg.mimeApps.defaultApplicationPackages = [ (vivaldiPackage pkgs) ];
};
flake.modules.homeManager.file-manager-nautilus =
{ pkgs, ... }:
{
home.packages = [ (nautilusPackage pkgs) ];
};
flake.modules.homeManager.primary-file-manager-nautilus =
{ lib, pkgs, ... }:
{
imports = [ homeModules.file-manager-nautilus ];
xdg.mimeApps.defaultApplicationPackages = [ (nautilusPackage pkgs) ];
};
flake.modules.homeManager.image-viewer-imv = {
programs.imv.enable = true;
}; };
flake.modules.homeManager.primary-file-manager-nautilus = mkPrimaryDesktopApplication { flake.modules.homeManager.default-image-viewer-imv =
name = "fileManager"; { pkgs, ... }:
package = pkgs: pkgs.nautilus; {
desktopEntryName = "org.gnome.Nautilus"; imports = [ homeModules.image-viewer-imv ];
xdg.mimeApps.defaultApplicationPackages = [ pkgs.imv ];
};
flake.modules.homeManager.document-viewer-sioyek = {
programs.sioyek.enable = true;
}; };
flake.modules.homeManager.desktop-defaults = flake.modules.homeManager.default-document-viewer-sioyek =
{ config, pkgs, ... }: { pkgs, ... }:
{
imports = [ homeModules.document-viewer-sioyek ];
xdg.mimeApps.defaultApplicationPackages = [ pkgs.sioyek ];
};
flake.modules.homeManager.workstation-apps =
{ pkgs, ... }:
{
home.packages = with pkgs; [
postman
spotify
calcure
planify
unzip
gimp
dbeaver-bin
];
};
flake.modules.homeManager.xdg =
{ config, ... }:
let let
browser = config.meta.desktop.browser;
fileManager = config.meta.desktop.fileManager;
homeDir = config.home.homeDirectory; homeDir = config.home.homeDirectory;
localDir = "${homeDir}/.local"; localDir = "${homeDir}/.local";
mediaDir = "${homeDir}/media"; mediaDir = "${homeDir}/media";
in in
{ {
home.preferXdgDirectories = true; home.preferXdgDirectories = true;
home.sessionVariables.BROWSER = browser.command;
home.packages =
with pkgs;
[
postman
spotify
calcure
planify
unzip
gimp
dbeaver-bin
]
++ [
browser.package
fileManager.package
];
programs.imv.enable = true;
programs.sioyek.enable = true;
xdg = { xdg = {
enable = true; enable = true;
@@ -85,17 +109,6 @@ in
mimeApps = { mimeApps = {
enable = true; enable = true;
defaultApplicationPackages =
with pkgs;
[
sioyek
imv
neovim
]
++ [
fileManager.package
browser.package
];
}; };
}; };
}; };
+12 -15
View File
@@ -1,22 +1,27 @@
{ inputs, ... }:
{ {
flake.modules.homeManager.dev-tools = flake.modules.homeManager.dev-tools =
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo"; home.sessionVariables.CARGO_HOME = "${config.xdg.dataHome}/cargo";
home.packages = with pkgs; [ home.packages = with pkgs; [
devenv
httpie httpie
bruno bruno
usql usql
posting posting
resterm resterm
inputs.devenv.packages.${pkgs.stdenv.hostPlatform.system}.default
]; ];
programs.direnv = { # programs.direnv = {
enable = true; # enable = true;
enableZshIntegration = true; # enableZshIntegration = true;
nix-direnv.enable = true; # nix-direnv.enable = true;
}; # };
programs.zsh.initContent = ''
eval "$(devenv hook zsh)"
'';
programs.lazygit = { programs.lazygit = {
enable = true; enable = true;
@@ -27,14 +32,6 @@
programs.jq.enable = true; programs.jq.enable = true;
programs.bun.enable = true; programs.bun.enable = true;
programs.ripgrep.enable = true; programs.ripgrep.enable = true;
programs.uv.enable = true; #programs.uv.enable = true;
programs.git.ignores = [
"devenv.*"
".devenv*"
".direnv"
"pre-commit-config.yaml"
".envrc"
];
}; };
} }
+3 -2
View File
@@ -10,7 +10,7 @@ in
... ...
}: }:
let let
machine = osConfig.meta.machine; machine = osConfig.facts.machine;
allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers"; allowedSignersFile = "${config.xdg.configHome}/git/allowed_signers";
mkScope = mkScope =
@@ -19,6 +19,7 @@ in
email = account.emails.${scope}.address; email = account.emails.${scope}.address;
key = lib.attrByPath [ scope ] null machine.sshKeys; key = lib.attrByPath [ scope ] null machine.sshKeys;
hasSigningKey = key != null; hasSigningKey = key != null;
privateKeyPath = key.privateKeyPath or "~/.ssh/id_${scope}";
in in
{ {
allowedSigners = lib.optional hasSigningKey "${email} ${key.publicKey}"; allowedSigners = lib.optional hasSigningKey "${email} ${key.publicKey}";
@@ -28,7 +29,7 @@ in
inherit email; inherit email;
} }
// lib.optionalAttrs hasSigningKey { // lib.optionalAttrs hasSigningKey {
signingKey = "${key.privateKeyPath}.pub"; signingKey = "${privateKeyPath}.pub";
}; };
} }
// lib.optionalAttrs hasSigningKey { // lib.optionalAttrs hasSigningKey {
+75
View File
@@ -0,0 +1,75 @@
{ config, lib, ... }:
let
palette = config.repo.theme.kanagawa.palette;
hex = lib.removePrefix "#";
terminalPalette = palette.terminal;
mkPalette = colors: lib.concatStringsSep ";" (map hex colors);
in
{
flake.modules.nixos.limine =
{ config, lib, ... }:
let
displayValues = builtins.attrValues (config.facts.machine.displays or { });
primaryDisplays = lib.filter (display: display.primary or false) displayValues;
primaryDisplay = if primaryDisplays == [ ] then null else builtins.head primaryDisplays;
interfaceResolution =
if primaryDisplay != null && primaryDisplay ? width && primaryDisplay ? height then
"${toString primaryDisplay.width}x${toString primaryDisplay.height}"
else
null;
in
{
boot.loader = {
efi.canTouchEfiVariables = true;
limine = {
enable = true;
maxGenerations = 10;
resolution = "2560x1440";
style = {
backdrop = hex palette.secondaryBackground;
graphicalTerminal = {
background = "00${hex palette.background}";
foreground = hex palette.foreground;
brightForeground = hex palette.selectionForeground;
brightBackground = hex palette.selectionBackground;
palette = mkPalette [
terminalPalette.color0
terminalPalette.color1
terminalPalette.color2
terminalPalette.color3
terminalPalette.color4
terminalPalette.color5
terminalPalette.color6
terminalPalette.color7
];
brightPalette = mkPalette [
terminalPalette.color8
terminalPalette.color9
terminalPalette.color10
terminalPalette.color11
terminalPalette.color12
terminalPalette.color13
terminalPalette.color14
terminalPalette.color15
];
font = {
scale = "2x2";
spacing = 1;
};
margin = 64;
marginGradient = 24;
};
interface = {
branding = config.networking.hostName;
brandingColor = hex palette.accents.blue;
helpHidden = false;
resolution = interfaceResolution;
};
};
};
};
};
}
+10 -8
View File
@@ -4,6 +4,12 @@ let
repoTheme = config.repo.theme.kanagawa; repoTheme = config.repo.theme.kanagawa;
in in
{ {
flake.modules.homeManager.default-editor-neovim =
{ pkgs, ... }:
{
xdg.mimeApps.defaultApplicationPackages = [ pkgs.neovim ];
};
flake.modules.homeManager.neovim = flake.modules.homeManager.neovim =
{ {
pkgs, pkgs,
@@ -19,13 +25,9 @@ in
}; };
imports = [ imports = [
(inputs.nix-wrapper-modules.lib.mkInstallModule { (inputs.nix-wrapper-modules.lib.getInstallModule {
name = "neovim"; name = "neovim";
value = inputs.nix-wrapper-modules.lib.wrapperModules.neovim; value = inputs.nix-wrapper-modules.lib.wrapperModules.neovim;
loc = [
"home"
"packages"
];
}) })
]; ];
@@ -37,7 +39,7 @@ in
# 2. Runtime Dependencies (from lspsAndRuntimeDeps) # 2. Runtime Dependencies (from lspsAndRuntimeDeps)
# These are added to the PATH of the wrapper # These are added to the PATH of the wrapper
extraPackages = with pkgs; [ runtimePkgs = with pkgs; [
# Tools # Tools
universal-ctags universal-ctags
ripgrep ripgrep
@@ -154,8 +156,8 @@ in
# Hostname/ConfigDir needed for nixd # Hostname/ConfigDir needed for nixd
nixdExtras = { nixdExtras = {
nixpkgs = "import ${pkgs.path} {}"; nixpkgs = "import ${pkgs.path} {}";
nixos_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.meta.machine.name}.options''; nixos_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.facts.machine.name}.options'';
home_manager_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.meta.machine.name}.options.home-manager.users.type.getSubOptions []''; home_manager_options = ''(builtins.getFlake "path://${account.nixosConfigurationPath}").nixosConfigurations.${osConfig.facts.machine.name}.options.home-manager.users.type.getSubOptions []'';
}; };
themeSetup = import ./_kanagawa-theme.nix { themeSetup = import ./_kanagawa-theme.nix {
+92 -47
View File
@@ -1,8 +1,11 @@
{ {
browserCommand, browserCommand,
launcherCommand,
shortcutCommands,
terminalCommand, terminalCommand,
}: }:
{ {
# Application and utility launchers
"Mod+Return" = { "Mod+Return" = {
action.spawn = terminalCommand; action.spawn = terminalCommand;
hotkey-overlay.title = "Terminal"; hotkey-overlay.title = "Terminal";
@@ -13,13 +16,36 @@
}; };
"Mod+Space" = { "Mod+Space" = {
repeat = false; repeat = false;
action.spawn = [ action.spawn = launcherCommand;
"vicinae"
"toggle"
];
hotkey-overlay.title = "App Launcher"; hotkey-overlay.title = "App Launcher";
}; };
"Mod+E" = {
repeat = false;
action.spawn = shortcutCommands.neovimProjects;
hotkey-overlay.title = "Neovim Projects";
};
"Mod+Ctrl+Return" = {
repeat = false;
action.spawn = shortcutCommands.nixosTerminal;
hotkey-overlay.title = "NixOS Config Terminal";
};
"Mod+Ctrl+Shift+Return" = {
repeat = false;
action.spawn = shortcutCommands.nixosSwitch;
hotkey-overlay.title = "NixOS Switch";
};
"Mod+Ctrl+E" = {
repeat = false;
action.spawn = shortcutCommands.editSecrets;
hotkey-overlay.title = "Edit Secrets";
};
"Mod+Ctrl+C" = {
repeat = false;
action.spawn = shortcutCommands.pickColor;
hotkey-overlay.title = "Pick Color";
};
# Hardware media, volume, and brightness keys
"XF86AudioPlay" = { "XF86AudioPlay" = {
action.spawn-sh = "playerctl play-pause"; action.spawn-sh = "playerctl play-pause";
allow-when-locked = true; allow-when-locked = true;
@@ -61,23 +87,26 @@
allow-when-locked = true; allow-when-locked = true;
}; };
# Screenshots
"Mod+S".action.screenshot = [ ]; "Mod+S".action.screenshot = [ ];
"Mod+Ctrl+S".action.screenshot-screen = [ ]; "Mod+Ctrl+S".action.screenshot-screen = [ ];
"Mod+Alt+S".action.screenshot-window = [ ]; "Mod+Alt+S".action.screenshot-window = [ ];
# Session and compositor controls
"Mod+Shift+Slash".action.show-hotkey-overlay = [ ]; "Mod+Shift+Slash".action.show-hotkey-overlay = [ ];
"Mod+Escape" = { "Mod+Escape" = {
action.toggle-keyboard-shortcuts-inhibit = [ ]; action.toggle-keyboard-shortcuts-inhibit = [ ];
allow-inhibiting = false; allow-inhibiting = false;
}; };
"Mod+Alt+L" = { "Mod+Ctrl+L" = {
action.spawn-sh = "loginctl lock-session"; action.spawn-sh = "loginctl lock-session";
hotkey-overlay.title = "Lock Screen"; hotkey-overlay.title = "Lock Screen";
}; };
"Mod+Shift+E".action.quit = [ ]; "Mod+Ctrl+Shift+Q".action.quit = [ ];
"Ctrl+Alt+Delete".action.quit = [ ]; "Ctrl+Alt+Delete".action.quit = [ ];
"Mod+Shift+P".action.power-off-monitors = [ ]; "Mod+Shift+P".action.power-off-monitors = [ ];
# Overview and window close
"Mod+O" = { "Mod+O" = {
action.toggle-overview = [ ]; action.toggle-overview = [ ];
repeat = false; repeat = false;
@@ -87,58 +116,66 @@
repeat = false; repeat = false;
}; };
# Keyboard focus movement
"Mod+Left".action.focus-column-or-monitor-left = [ ];
"Mod+Down".action.focus-window-down = [ ];
"Mod+Up".action.focus-window-up = [ ];
"Mod+Right".action.focus-column-or-monitor-right = [ ];
"Mod+H".action.focus-column-or-monitor-left = [ ]; "Mod+H".action.focus-column-or-monitor-left = [ ];
"Mod+J".action.focus-window-down = [ ]; "Mod+J".action.focus-window-down = [ ];
"Mod+K".action.focus-window-up = [ ]; "Mod+K".action.focus-window-up = [ ];
"Mod+L".action.focus-column-or-monitor-right = [ ]; "Mod+L".action.focus-column-or-monitor-right = [ ];
"Mod+Ctrl+Left".action.move-column-left = [ ]; # Keyboard window and column movement
"Mod+Ctrl+Down".action.move-window-down = [ ]; "Mod+Alt+Left".action.move-column-left-or-to-monitor-left = [ ];
"Mod+Ctrl+Up".action.move-window-up = [ ]; "Mod+Alt+Down".action.move-window-down-or-to-workspace-down = [ ];
"Mod+Ctrl+Right".action.move-column-right = [ ]; "Mod+Alt+Up".action.move-window-up-or-to-workspace-up = [ ];
"Mod+Ctrl+H".action.move-column-left = [ ]; "Mod+Alt+Right".action.move-column-right-or-to-monitor-right = [ ];
"Mod+Ctrl+J".action.move-window-down = [ ]; "Mod+Alt+H".action.move-column-left-or-to-monitor-left = [ ];
"Mod+Ctrl+K".action.move-window-up = [ ]; "Mod+Alt+J".action.move-window-down-or-to-workspace-down = [ ];
"Mod+Ctrl+L".action.move-column-right = [ ]; "Mod+Alt+K".action.move-window-up-or-to-workspace-up = [ ];
"Mod+Alt+L".action.move-column-right-or-to-monitor-right = [ ];
# First and last column navigation
"Mod+Home".action.focus-column-first = [ ]; "Mod+Home".action.focus-column-first = [ ];
"Mod+End".action.focus-column-last = [ ]; "Mod+End".action.focus-column-last = [ ];
"Mod+Ctrl+Home".action.move-column-to-first = [ ]; "Mod+Alt+Home".action.move-column-to-first = [ ];
"Mod+Ctrl+End".action.move-column-to-last = [ ]; "Mod+Alt+End".action.move-column-to-last = [ ];
# Move focus, columns, and workspaces across monitors
"Mod+Tab".action.focus-monitor-next = [ ];
"Mod+A" = {
repeat = false;
action.spawn = shortcutCommands.swapMonitorWorkspaces;
hotkey-overlay.title = "Swap Monitor Workspaces";
};
"Mod+Alt+Tab".action.move-column-to-monitor-next = [ ];
"Mod+Shift+Tab".action.move-workspace-to-monitor-next = [ ];
"Mod+Shift+Left".action.focus-monitor-left = [ ]; "Mod+Shift+Left".action.focus-monitor-left = [ ];
"Mod+Shift+Down".action.focus-monitor-down = [ ]; "Mod+Shift+Down".action.focus-monitor-down = [ ];
"Mod+Shift+Up".action.focus-monitor-up = [ ]; "Mod+Shift+Up".action.focus-monitor-up = [ ];
"Mod+Shift+Right".action.focus-monitor-right = [ ]; "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 = [ ];
# Linear workspace navigation
"Mod+Page_Down".action.focus-workspace-down = [ ]; "Mod+Page_Down".action.focus-workspace-down = [ ];
"Mod+Page_Up".action.focus-workspace-up = [ ]; "Mod+Page_Up".action.focus-workspace-up = [ ];
"Mod+U".action.focus-workspace-down = [ ]; "Mod+U".action.focus-workspace-down = [ ];
"Mod+I".action.focus-workspace-up = [ ]; "Mod+I".action.focus-workspace-up = [ ];
"Mod+Ctrl+Page_Down".action.move-column-to-workspace-down = [ ]; # Move columns between adjacent workspaces
"Mod+Ctrl+Page_Up".action.move-column-to-workspace-up = [ ]; "Mod+Alt+Page_Down".action.move-column-to-workspace-down = [ ];
"Mod+Ctrl+U".action.move-column-to-workspace-down = [ ]; "Mod+Alt+Page_Up".action.move-column-to-workspace-up = [ ];
"Mod+Ctrl+I".action.move-column-to-workspace-up = [ ]; "Mod+Alt+U".action.move-column-to-workspace-down = [ ];
"Mod+Alt+I".action.move-column-to-workspace-up = [ ];
# Reorder workspaces
"Mod+Shift+Page_Down".action.move-workspace-down = [ ]; "Mod+Shift+Page_Down".action.move-workspace-down = [ ];
"Mod+Shift+Page_Up".action.move-workspace-up = [ ]; "Mod+Shift+Page_Up".action.move-workspace-up = [ ];
"Mod+Shift+U".action.move-workspace-down = [ ]; "Mod+Shift+U".action.move-workspace-down = [ ];
"Mod+Shift+I".action.move-workspace-up = [ ]; "Mod+Shift+I".action.move-workspace-up = [ ];
# Mouse workspace navigation
"Mod+WheelScrollDown" = { "Mod+WheelScrollDown" = {
action.focus-workspace-down = [ ]; action.focus-workspace-down = [ ];
cooldown-ms = 150; cooldown-ms = 150;
@@ -147,24 +184,24 @@
action.focus-workspace-up = [ ]; action.focus-workspace-up = [ ];
cooldown-ms = 150; cooldown-ms = 150;
}; };
"Mod+Ctrl+WheelScrollDown" = { "Mod+Alt+WheelScrollDown" = {
action.move-column-to-workspace-down = [ ]; action.move-column-to-workspace-down = [ ];
cooldown-ms = 150; cooldown-ms = 150;
}; };
"Mod+Ctrl+WheelScrollUp" = { "Mod+Alt+WheelScrollUp" = {
action.move-column-to-workspace-up = [ ]; action.move-column-to-workspace-up = [ ];
cooldown-ms = 150; cooldown-ms = 150;
}; };
"Mod+WheelScrollRight".action.focus-column-right = [ ]; # Mouse column navigation and movement
"Mod+WheelScrollLeft".action.focus-column-left = [ ]; "Mod+WheelScrollRight".action.focus-column-or-monitor-right = [ ];
"Mod+Ctrl+WheelScrollRight".action.move-column-right = [ ]; "Mod+WheelScrollLeft".action.focus-column-or-monitor-left = [ ];
"Mod+Ctrl+WheelScrollLeft".action.move-column-left = [ ]; "Mod+Alt+WheelScrollRight".action.move-column-right-or-to-monitor-right = [ ];
"Mod+Shift+WheelScrollDown".action.focus-column-right = [ ]; "Mod+Alt+WheelScrollLeft".action.move-column-left-or-to-monitor-left = [ ];
"Mod+Shift+WheelScrollUp".action.focus-column-left = [ ]; "Mod+Shift+WheelScrollDown".action.focus-column-or-monitor-right = [ ];
"Mod+Ctrl+Shift+WheelScrollDown".action.move-column-right = [ ]; "Mod+Shift+WheelScrollUp".action.focus-column-or-monitor-left = [ ];
"Mod+Ctrl+Shift+WheelScrollUp".action.move-column-left = [ ];
# Direct workspace focus
"Mod+1".action.focus-workspace = 1; "Mod+1".action.focus-workspace = 1;
"Mod+2".action.focus-workspace = 2; "Mod+2".action.focus-workspace = 2;
"Mod+3".action.focus-workspace = 3; "Mod+3".action.focus-workspace = 3;
@@ -175,6 +212,7 @@
"Mod+8".action.focus-workspace = 8; "Mod+8".action.focus-workspace = 8;
"Mod+9".action.focus-workspace = 9; "Mod+9".action.focus-workspace = 9;
# Move columns to numbered workspaces
"Mod+Ctrl+1".action.move-column-to-workspace = 1; "Mod+Ctrl+1".action.move-column-to-workspace = 1;
"Mod+Ctrl+2".action.move-column-to-workspace = 2; "Mod+Ctrl+2".action.move-column-to-workspace = 2;
"Mod+Ctrl+3".action.move-column-to-workspace = 3; "Mod+Ctrl+3".action.move-column-to-workspace = 3;
@@ -185,27 +223,34 @@
"Mod+Ctrl+8".action.move-column-to-workspace = 8; "Mod+Ctrl+8".action.move-column-to-workspace = 8;
"Mod+Ctrl+9".action.move-column-to-workspace = 9; "Mod+Ctrl+9".action.move-column-to-workspace = 9;
# Add and remove windows from columns
"Mod+BracketLeft".action.consume-or-expel-window-left = [ ]; "Mod+BracketLeft".action.consume-or-expel-window-left = [ ];
"Mod+BracketRight".action.consume-or-expel-window-right = [ ]; "Mod+BracketRight".action.consume-or-expel-window-right = [ ];
"Mod+Comma".action.consume-window-into-column = [ ]; "Mod+Comma".action.consume-window-into-column = [ ];
"Mod+Period".action.expel-window-from-column = [ ]; "Mod+Period".action.expel-window-from-column = [ ];
# Column and window presentation modes
"Mod+R".action.switch-preset-column-width = [ ]; "Mod+R".action.switch-preset-column-width = [ ];
"Mod+Shift+R".action.switch-preset-window-height = [ ]; "Mod+Shift+R".action.switch-preset-column-width-back = [ ];
"Mod+Ctrl+R".action.reset-window-height = [ ]; "Mod+Ctrl+R".action.reset-window-height = [ ];
"Mod+Ctrl+Shift+R".action.switch-preset-window-height = [ ];
"Mod+F".action.maximize-column = [ ]; "Mod+F".action.maximize-column = [ ];
"Mod+Shift+F".action.fullscreen-window = [ ]; "Mod+Shift+F".action.fullscreen-window = [ ];
"Mod+M".action.maximize-window-to-edges = [ ]; "Mod+M".action.maximize-window-to-edges = [ ];
"Mod+Ctrl+F".action.expand-column-to-available-width = [ ];
"Mod+C".action.center-column = [ ]; "Mod+C".action.center-column = [ ];
"Mod+Ctrl+C".action.center-visible-columns = [ ];
# Manual column width and window height adjustments
"Mod+Shift+H".action.set-column-width = "-10%";
"Mod+Shift+L".action.set-column-width = "+10%";
"Mod+Shift+J".action.set-window-height = "+10%";
"Mod+Shift+K".action.set-window-height = "-10%";
"Mod+Minus".action.set-column-width = "-10%"; "Mod+Minus".action.set-column-width = "-10%";
"Mod+Equal".action.set-column-width = "+10%"; "Mod+Equal".action.set-column-width = "+10%";
"Mod+Shift+Minus".action.set-window-height = "-10%"; "Mod+Shift+Minus".action.set-window-height = "-10%";
"Mod+Shift+Equal".action.set-window-height = "+10%"; "Mod+Shift+Equal".action.set-window-height = "+10%";
"Mod+V".action.toggle-window-floating = [ ]; # Floating and tabbed layout toggles
"Mod+Alt+V".action.toggle-window-floating = [ ];
"Mod+Shift+V".action.switch-focus-between-floating-and-tiling = [ ]; "Mod+Shift+V".action.switch-focus-between-floating-and-tiling = [ ];
"Mod+W".action.toggle-column-tabbed-display = [ ]; "Mod+W".action.toggle-column-tabbed-display = [ ];
} }
+146
View File
@@ -0,0 +1,146 @@
{
config,
lib,
pkgs,
repo,
}:
let
nixosConfigDir = repo.account.nixosConfigurationPath;
mkTerminalScript =
{
name,
workdir ? nixosConfigDir,
command ? null,
runtimeInputs ? [ ],
}:
let
args = lib.optionals (command != null) [
"--"
"${pkgs.bash}/bin/bash"
"-lc"
command
];
argString = lib.concatMapStringsSep " " lib.escapeShellArg args;
in
pkgs.writeShellApplication {
inherit name runtimeInputs;
checkPhase = "";
text = lib.concatStringsSep "\n" [
"# shellcheck disable=SC2016"
"cd ${lib.escapeShellArg workdir}"
"exec ${lib.escapeShellArg config.facts.desktop.terminalCommand} ${argString}"
];
};
in
rec {
scripts = {
nixosTerminal = mkTerminalScript {
name = "niri-shortcut-nixos-terminal";
};
nixosSwitch = mkTerminalScript {
name = "niri-shortcut-nixos-switch";
runtimeInputs = [
pkgs.coreutils
pkgs.nh
];
command = ''
set -o pipefail
log_dir="''${XDG_STATE_HOME:-$HOME/.local/state}/nixos-switch"
mkdir -p "$log_dir"
log="$log_dir/$(date +%Y%m%d-%H%M%S).log"
status_file="$(mktemp)"
printf 'Running nh os switch in %s\n\n' ${lib.escapeShellArg nixosConfigDir}
(
cd ${lib.escapeShellArg nixosConfigDir}
nh os switch
printf '%s' "$?" > "$status_file"
) 2>&1 | tee "$log"
status="$(cat "$status_file")"
rm -f "$status_file"
printf '\nLog: %s\n' "$log"
if [ "$status" -eq 0 ]; then
printf 'NixOS switch completed successfully.\n'
else
printf 'NixOS switch failed with exit code %s.\n' "$status"
fi
printf 'Press Enter to close...'
read -r _
exit "$status"
'';
};
editSecrets = mkTerminalScript {
name = "niri-shortcut-edit-secrets";
runtimeInputs = [ pkgs.sops ];
command = ''
sops edit ${lib.escapeShellArg "${nixosConfigDir}/modules/secrets/secrets.yaml"}
'';
};
neovimProjects = mkTerminalScript {
name = "niri-shortcut-neovim-projects";
command = ''
nvim -c 'Telescope projects'
'';
};
pickColor = pkgs.writeShellApplication {
name = "niri-shortcut-pick-color";
runtimeInputs = [
pkgs.libnotify
pkgs.niri
pkgs.wl-clipboard
];
text = ''
color="$(niri msg pick-color)"
printf '%s' "$color" | wl-copy
notify-send 'Color picked' "$color"
'';
};
swapMonitorWorkspaces = pkgs.writeShellApplication {
name = "niri-shortcut-swap-monitor-workspaces";
runtimeInputs = [
pkgs.jq
pkgs.niri
];
text = ''
focused_output="$(niri msg --json focused-output | jq -r '.name // empty')"
if [ -z "$focused_output" ]; then
exit 0
fi
niri msg action focus-monitor-next
target_output="$(niri msg --json focused-output | jq -r '.name // empty')"
if [ -z "$target_output" ] || [ "$target_output" = "$focused_output" ]; then
exit 0
fi
target_workspace_idx="$(
niri msg --json workspaces \
| jq -r --arg output "$target_output" '
first(.[] | select(.output == $output and .is_active) | .idx) // empty
'
)"
if [ -z "$target_workspace_idx" ]; then
niri msg action focus-monitor "$focused_output"
exit 0
fi
niri msg action focus-monitor "$focused_output"
niri msg action move-workspace-to-monitor "$target_output"
niri msg action focus-workspace "$target_workspace_idx"
niri msg action move-workspace-to-monitor "$focused_output"
'';
};
};
commands = lib.mapAttrs (_: lib.getExe) scripts;
}
+80 -63
View File
@@ -5,20 +5,31 @@
}: }:
let let
repo = config.repo; repo = config.repo;
hmModules = config.flake.modules.homeManager;
in in
{ {
flake.modules.nixos.niri = flake.modules.nixos.niri =
{ pkgs, ... }: { pkgs, ... }:
{ {
imports = [ inputs.niri.nixosModules.niri ]; imports = [ inputs.niri.nixosModules.niri ];
home-manager.sharedModules = [ hmModules.niri ];
nixpkgs.overlays = [ inputs.niri.overlays.niri ]; nixpkgs.overlays = [ inputs.niri.overlays.niri ];
programs.niri.enable = true; programs = {
programs.niri.package = pkgs.niri-unstable; dconf.enable = true;
programs.dconf.enable = true; niri = {
enable = true;
package = pkgs.niri-unstable;
};
};
services = {
gvfs.enable = true;
udisks2.enable = true;
};
services.gvfs.enable = true;
services.udisks2.enable = true;
xdg.portal.enable = true; xdg.portal.enable = true;
}; };
@@ -31,55 +42,64 @@ in
... ...
}: }:
let let
repoTheme = repo.theme.kanagawa; borderPalette = repo.theme.kanagawa.palette.niri.border;
browserCommand = config.meta.desktop.browser.command; shortcuts = import ./_shortcuts.nix {
fileManagerPackage = config.meta.desktop.fileManager.package; inherit
terminalCommand = config.meta.desktop.terminal.command; config
outputs = lib.mapAttrs ( lib
_: display: pkgs
{ repo
position = { ;
x = display.x; };
y = display.y; machine = osConfig.facts.machine;
};
}
// lib.optionalAttrs (display.primary or false) {
"focus-at-startup" = true;
}
// lib.optionalAttrs (display.scale != null) {
inherit (display) scale;
}
// lib.optionalAttrs (display.width != null && display.height != null && display.refresh != null) {
mode = {
inherit (display)
width
height
refresh
;
};
}
) osConfig.meta.machine.displays;
in in
{ {
home.sessionVariables.NIXOS_OZONE_WL = "1"; home = {
sessionVariables.NIXOS_OZONE_WL = "1";
dconf.settings = { packages =
"org/gnome/desktop/interface" = { with pkgs;
color-scheme = "prefer-dark"; [
}; playerctl
brightnessctl
xwayland-satellite
]
++ lib.attrValues shortcuts.scripts;
}; };
home.packages = dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark";
with pkgs;
[
playerctl
brightnessctl
xwayland-satellite
]
++ [ fileManagerPackage ];
programs.niri.settings = { programs.niri.settings = {
inherit outputs; outputs = lib.mapAttrs (
_: display:
let
scale = display.scale or null;
width = display.width or null;
height = display.height or null;
refresh = display.refresh or null;
in
{
position = {
x = display.x or 0;
y = display.y or 0;
};
}
// lib.optionalAttrs (display.primary or false) {
"focus-at-startup" = true;
}
// lib.optionalAttrs (scale != null) {
inherit scale;
}
// lib.optionalAttrs (width != null && height != null && refresh != null) {
mode = {
inherit
width
height
refresh
;
};
}
) (machine.displays or { });
environment.DISPLAY = ":0"; environment.DISPLAY = ":0";
spawn-at-startup = [ spawn-at-startup = [
{ command = [ "xwayland-satellite" ]; } { command = [ "xwayland-satellite" ]; }
@@ -91,9 +111,9 @@ in
animations.slowdown = 0.6; animations.slowdown = 0.6;
cursor = with config.home.pointerCursor; { cursor = {
size = size; inherit (config.home.pointerCursor) size;
theme = name; theme = config.home.pointerCursor.name;
hide-after-inactive-ms = 3000; hide-after-inactive-ms = 3000;
hide-when-typing = true; hide-when-typing = true;
}; };
@@ -102,15 +122,14 @@ in
always-center-single-column = true; always-center-single-column = true;
gaps = 14; gaps = 14;
focus-ring.enable = false; focus-ring.enable = false;
default-column-width.proportion = 1. / 2.; default-column-width.proportion = 1. / 2.;
border = { border = {
enable = true; enable = true;
width = 3; width = 3;
active.color = repoTheme.palette.niri.border.active; active.color = borderPalette.active;
inactive.color = repoTheme.palette.niri.border.inactive; inactive.color = borderPalette.inactive;
urgent.color = repoTheme.palette.niri.border.urgent; urgent.color = borderPalette.urgent;
}; };
}; };
@@ -131,6 +150,7 @@ in
]; ];
debug.honor-xdg-activation-with-invalid-serial = true; debug.honor-xdg-activation-with-invalid-serial = true;
gestures.hot-corners.enable = false;
input = { input = {
focus-follows-mouse.enable = true; focus-follows-mouse.enable = true;
@@ -140,17 +160,14 @@ in
repeat-rate = 50; repeat-rate = 50;
xkb.options = "caps:escape"; xkb.options = "caps:escape";
}; };
touchpad.dwt = true;
touchpad = {
dwt = true;
};
}; };
binds = import ./_bindings.nix { binds = import ./_bindings.nix {
inherit browserCommand = config.facts.desktop.browserCommand;
browserCommand launcherCommand = config.facts.desktop.launcherCommand;
terminalCommand terminalCommand = config.facts.desktop.terminalCommand;
; shortcutCommands = shortcuts.commands;
}; };
}; };
}; };
@@ -458,9 +458,9 @@
notifications = { notifications = {
enabled = true; enabled = true;
enableMarkdown = false; enableMarkdown = false;
density = "default"; density = "compact";
monitors = [ ]; monitors = [ ];
location = "top_right"; location = "bottom_right";
overlayLayer = true; overlayLayer = true;
backgroundOpacity = 1; backgroundOpacity = 1;
respectExpireTimeout = false; respectExpireTimeout = false;
+1 -1
View File
@@ -71,7 +71,7 @@ in
terminalCommand = lib.getExe pkgs.xdg-terminal-exec; terminalCommand = lib.getExe pkgs.xdg-terminal-exec;
}; };
settings = settings =
if baseSettings == { } || !osConfig.meta.machine.portable then if baseSettings == { } || !(osConfig.facts.machine.portable or false) then
baseSettings baseSettings
else else
mkPortableSettings baseSettings; mkPortableSettings baseSettings;
+5 -13
View File
@@ -5,31 +5,23 @@
let let
repo = config.repo; repo = config.repo;
account = repo.account; account = repo.account;
homeModules = config.flake.modules.homeManager;
in in
{ {
flake.modules.homeManager.pinentry =
{ pkgs, ... }:
{
meta.pinentry.package = pkgs.pinentry-gnome3;
};
flake.modules.homeManager.passwords = flake.modules.homeManager.passwords =
{ {
config, pkgs,
... ...
}: }:
let
pinentryPackage = pkgs.pinentry-gnome3;
in
{ {
imports = [
homeModules.pinentry
];
programs.rbw = { programs.rbw = {
enable = true; enable = true;
settings = { settings = {
base_url = repo.services.vaultwarden.url; base_url = repo.services.vaultwarden.url;
email = account.primaryEmail.address; email = account.primaryEmail.address;
pinentry = config.meta.pinentry.package; pinentry = pinentryPackage;
}; };
}; };
}; };
+8 -6
View File
@@ -17,7 +17,7 @@ in
mkOffice365Account = mkOffice365Account =
{ {
address, address,
primary, primary ? false,
... ...
}: }:
{ {
@@ -37,7 +37,7 @@ in
mkMxrouteAccount = mkMxrouteAccount =
{ {
address, address,
primary, primary ? false,
... ...
}: }:
{ {
@@ -93,6 +93,7 @@ in
flake.modules.homeManager.calendar-tasks = flake.modules.homeManager.calendar-tasks =
{ {
config, config,
pkgs,
... ...
}: }:
let let
@@ -102,8 +103,10 @@ in
programs.pimsync.enable = true; programs.pimsync.enable = true;
services.pimsync.enable = true; services.pimsync.enable = true;
sops.secrets."radicale-pass" = { };
programs.khal = { programs.khal = {
enable = false; enable = true;
locale = { locale = {
timeformat = "%H:%M"; timeformat = "%H:%M";
dateformat = "$m-$d"; dateformat = "$m-$d";
@@ -139,9 +142,8 @@ in
type = "caldav"; type = "caldav";
userName = config.home.username; userName = config.home.username;
passwordCommand = [ passwordCommand = [
"rbw" "${pkgs.coreutils}/bin/cat"
"get" config.sops.secrets."radicale-pass".path
"Radicale"
]; ];
}; };
@@ -1,22 +0,0 @@
{
flake.modules.nixos.qbittorrent-client = {
networking.firewall = {
allowedTCPPorts = [ 43864 ];
allowedUDPPorts = [ 43864 ];
};
};
flake.modules.homeManager.qbittorrent-client =
{
lib,
pkgs,
...
}:
{
home.packages = [ pkgs.qbittorrent ];
programs.niri.settings.spawn-at-startup = lib.mkAfter [
{ command = [ "qbittorrent" ]; }
];
};
}
+7
View File
@@ -5,6 +5,13 @@ let
service = repo.services.actual; service = repo.services.actual;
in in
{ {
repo.services.actual = {
domain = "finance.jelles.net";
host = "127.0.0.1";
port = 3000;
url = "https://finance.jelles.net";
};
flake.modules.nixos.actual = flake.modules.nixos.actual =
{ lib, ... }: { lib, ... }:
lib.mkMerge [ lib.mkMerge [
+7
View File
@@ -5,6 +5,13 @@ let
service = repo.services.gitea; service = repo.services.gitea;
in in
{ {
repo.services.gitea = {
domain = "git.jelles.net";
host = "127.0.0.1";
port = 3001;
url = "https://git.jelles.net/";
};
flake.modules.nixos.gitea = flake.modules.nixos.gitea =
{ lib, ... }: { lib, ... }:
lib.mkMerge [ lib.mkMerge [
+2 -2
View File
@@ -3,8 +3,8 @@ let
account = config.repo.account; account = config.repo.account;
personalPublicKeys = personalPublicKeys =
machines: machines:
map (machine: machine.sshKeys.personal.publicKey) ( map (machine: (machine.sshKeys or { }).personal.publicKey) (
lib.filter (machine: machine.sshKeys ? personal) (builtins.attrValues machines) lib.filter (machine: (machine.sshKeys or { }) ? personal) (builtins.attrValues machines)
); );
in in
{ {
@@ -5,6 +5,13 @@ let
service = repo.services.radicale; service = repo.services.radicale;
in in
{ {
repo.services.radicale = {
domain = "radicale.jelles.net";
host = "127.0.0.1";
port = 5232;
url = "https://radicale.jelles.net/";
};
flake.modules.nixos.radicale = flake.modules.nixos.radicale =
{ lib, ... }: { lib, ... }:
lib.mkMerge [ lib.mkMerge [
@@ -0,0 +1,28 @@
{ config, ... }:
let
account = config.repo.account;
in
{
flake.modules.nixos.transmission =
{ config, pkgs, ... }:
{
services.transmission = {
enable = true;
package = pkgs.transmission_4;
openPeerPorts = true;
downloadDirPermissions = "775";
settings = {
download-dir = "${account.homeDirectory}/torrents";
incomplete-dir = "${account.homeDirectory}/torrents/.incomplete";
peer-port = 43864;
umask = "002";
};
};
# NOTE: Upstream bug?
systemd.services.transmission-setup.requiredBy = [ "transmission.service" ];
users.users.${account.name}.extraGroups = [ config.services.transmission.group ];
};
}
@@ -5,6 +5,13 @@ let
service = repo.services.vaultwarden; service = repo.services.vaultwarden;
in in
{ {
repo.services.vaultwarden = {
domain = "vault.jelles.net";
host = "127.0.0.1";
port = 8100;
url = "https://vault.jelles.net";
};
flake.modules.nixos.vaultwarden = flake.modules.nixos.vaultwarden =
{ lib, ... }: { lib, ... }:
lib.mkMerge [ lib.mkMerge [
@@ -0,0 +1,215 @@
{ ... }:
{
flake.modules.nixos.vps-insights =
{ config, pkgs, ... }:
let
localAddress = "127.0.0.1";
grafanaDataDir = config.services.grafana.dataDir;
lokiDataDir = config.services.loki.dataDir;
lokiUrl = "http://${localAddress}:3100";
prometheusUrl = "http://${localAddress}:9090";
in
{
environment = {
etc."alloy/config.alloy".text = ''
loki.relabel "journal" {
forward_to = []
rule {
source_labels = ["__journal__systemd_unit"]
target_label = "unit"
}
rule {
source_labels = ["__journal_syslog_identifier"]
target_label = "syslog_identifier"
}
rule {
source_labels = ["__journal_priority_keyword"]
target_label = "level"
}
}
loki.source.journal "system" {
forward_to = [loki.write.local.receiver]
relabel_rules = loki.relabel.journal.rules
max_age = "24h"
labels = {
host = "${config.networking.hostName}",
}
}
loki.write "local" {
endpoint {
url = "${lokiUrl}/loki/api/v1/push"
}
}
'';
systemPackages = with pkgs; [
goaccess
lynis
];
};
services = {
# Keep local system logs available for Loki and manual inspection.
journald.extraConfig = ''
Storage=persistent
SystemMaxUse=1G
MaxRetentionSec=30day
'';
# Detect and block common attacks against SSH and Caddy.
crowdsec = {
enable = true;
hub.collections = [
"crowdsecurity/linux"
"crowdsecurity/caddy"
];
localConfig.acquisitions = [
{
source = "journalctl";
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
labels.type = "syslog";
}
{
filenames = [ "/var/log/caddy/*.log" ];
labels.type = "caddy";
}
];
};
crowdsec-firewall-bouncer = {
enable = true;
registerBouncer.bouncerName = "${config.networking.hostName}-firewall-bouncer";
};
# Grafana defaults to 127.0.0.1:3000; add secrets and datasources only.
grafana = {
enable = true;
settings = {
analytics.reporting_enabled = false;
security = {
admin_password = "$__file{${grafanaDataDir}/admin-password}";
secret_key = "$__file{${grafanaDataDir}/secret-key}";
};
};
provision.datasources.settings = {
prune = true;
datasources = [
{
name = "Prometheus";
type = "prometheus";
uid = "prometheus";
url = prometheusUrl;
isDefault = true;
}
{
name = "Loki";
type = "loki";
uid = "loki";
url = lokiUrl;
}
];
};
};
# Store local logs in Loki and feed them from journald through Alloy.
loki = {
enable = true;
configuration = {
analytics.reporting_enabled = false;
auth_enabled = false;
server = {
http_listen_address = localAddress;
http_listen_port = 3100;
grpc_listen_address = localAddress;
grpc_listen_port = 9096;
};
common = {
path_prefix = lokiDataDir;
replication_factor = 1;
instance_interface_names = [ "lo" ];
ring = {
instance_addr = localAddress;
kvstore.store = "inmemory";
};
};
schema_config.configs = [
{
from = "2025-01-01";
store = "tsdb";
object_store = "filesystem";
schema = "v13";
index = {
prefix = "index_";
period = "24h";
};
}
];
storage_config.filesystem.directory = "${lokiDataDir}/chunks";
compactor = {
working_directory = "${lokiDataDir}/compactor";
retention_enabled = true;
delete_request_store = "filesystem";
};
limits_config.retention_period = "720h";
};
};
alloy = {
enable = true;
extraFlags = [ "--server.http.listen-addr=${localAddress}:12345" ];
};
# Collect basic VPS health metrics for Grafana.
prometheus = {
enable = true;
listenAddress = localAddress;
retentionTime = "30d";
scrapeConfigs = [
{
job_name = "prometheus";
static_configs = [
{
targets = [ "${localAddress}:9090" ];
}
];
}
{
job_name = "node";
static_configs = [
{
targets = [ "${localAddress}:9100" ];
}
];
}
];
exporters.node = {
enable = true;
listenAddress = localAddress;
};
};
};
systemd.services.grafana.preStart = ''
umask 077
if [ ! -s ${grafanaDataDir}/admin-password ]; then
${pkgs.openssl}/bin/openssl rand -base64 32 > ${grafanaDataDir}/admin-password
fi
if [ ! -s ${grafanaDataDir}/secret-key ]; then
${pkgs.openssl}/bin/openssl rand -hex 32 > ${grafanaDataDir}/secret-key
fi
'';
};
}
+10 -1
View File
@@ -65,12 +65,21 @@
bindkey -v bindkey -v
export KEYTIMEOUT=1 export KEYTIMEOUT=1
setopt MENU_COMPLETE
zmodload zsh/complist
autoload -U history-search-end autoload -U history-search-end
zle -N history-beginning-search-backward-end history-search-end zle -N history-beginning-search-backward-end history-search-end
zle -N history-beginning-search-forward-end history-search-end zle -N history-beginning-search-forward-end history-search-end
bindkey "^[OA" history-beginning-search-backward-end bindkey "^[OA" history-beginning-search-backward-end
bindkey "^[OB" history-beginning-search-forward-end bindkey "^[OB" history-beginning-search-forward-end
if [[ -n "''${terminfo[kcbt]}" ]]; then
bindkey "''${terminfo[kcbt]}" reverse-menu-complete
bindkey -M menuselect "''${terminfo[kcbt]}" reverse-menu-complete
fi
bindkey "^[[Z" reverse-menu-complete
bindkey -M menuselect "^[[Z" reverse-menu-complete
bindkey -M menuselect "^[" send-break
zstyle ':completion:*' completer _extensions _complete _approximate zstyle ':completion:*' completer _extensions _complete _approximate
zstyle ':completion:*' use-cache on zstyle ':completion:*' use-cache on
@@ -79,7 +88,7 @@
zstyle ':completion:*' complete-options true zstyle ':completion:*' complete-options true
zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*' zstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'
zstyle ':completion:*' keep-prefix true zstyle ':completion:*' keep-prefix true
zstyle ':completion:*' menu select zstyle ':completion:*' menu yes select=1
zstyle ':completion:*' list-grouped false zstyle ':completion:*' list-grouped false
zstyle ':completion:*' list-separator ''' zstyle ':completion:*' list-separator '''
zstyle ':completion:*' group-name ''' zstyle ':completion:*' group-name '''
+30 -16
View File
@@ -4,23 +4,37 @@
... ...
}: }:
let let
syncthingMesh = lib.listToAttrs ( syncMachines = lib.listToAttrs (
lib.concatMap ( lib.concatLists (
machine: lib.mapAttrsToList (
lib.optional (machine.syncthingId != null) ( machineName: machine:
let let
name = "${config.repo.account.name}@${machine.name}"; syncthingId = machine.syncthingId or null;
in in
{ lib.optional (syncthingId != null) (
inherit name; let
value = { name = "${config.repo.account.name}@${machineName}";
in
{
inherit name; inherit name;
id = machine.syncthingId; value = {
}; inherit name;
} id = syncthingId;
) };
) (builtins.attrValues config.repo.machines) }
)
) config.repo.machines
)
); );
syncPhones = {
"pixel-10" = {
name = "pixel-10";
id = "MTJHEHA-UMZDQZ7-BTMRRLQ-Y7BFPUJ-ZTY6LZX-PDXV3IS-XVJCU7B-EPETBQZ";
};
};
syncDevices = syncMachines // syncPhones;
in in
{ {
flake.modules.homeManager.syncthing = flake.modules.homeManager.syncthing =
@@ -37,15 +51,15 @@ in
sync = { sync = {
path = "~/sync"; path = "~/sync";
label = "sync"; label = "sync";
devices = builtins.attrNames syncthingMesh; devices = builtins.attrNames syncDevices;
}; };
calibre = { calibre = {
path = "~/calibre"; path = "~/calibre";
label = "calibre"; label = "calibre";
devices = builtins.attrNames syncthingMesh; devices = builtins.attrNames syncMachines;
}; };
}; };
devices = syncthingMesh; devices = syncDevices;
}; };
}; };
}; };
+24 -34
View File
@@ -19,30 +19,6 @@ let
''; '';
}; };
mkTerminal =
{
desktopEntryName,
packageFor,
terminalModule,
}:
{ config, pkgs, ... }:
let
package = packageFor pkgs;
in
{
imports = [ terminalModule ];
config = {
meta.desktop.terminal = {
inherit desktopEntryName package;
};
xdg.terminal-exec = {
enable = true;
settings.default = [ config.meta.desktop.terminal.desktopId ];
};
};
};
in in
{ {
flake.modules.homeManager.terminal-foot = flake.modules.homeManager.terminal-foot =
@@ -194,15 +170,29 @@ in
}; };
}; };
flake.modules.homeManager.primary-terminal-foot = mkTerminal { flake.modules.homeManager.primary-terminal-foot =
desktopEntryName = "foot"; { lib, pkgs, ... }:
packageFor = pkgs: pkgs.foot; {
terminalModule = config.flake.modules.homeManager.terminal-foot; imports = [ config.flake.modules.homeManager.terminal-foot ];
};
flake.modules.homeManager.primary-terminal-kitty = mkTerminal { facts.desktop.terminalCommand = lib.getExe pkgs.foot;
desktopEntryName = "kitty";
packageFor = pkgs: kittySingleInstance pkgs; xdg.terminal-exec = {
terminalModule = config.flake.modules.homeManager.terminal-kitty; enable = true;
}; settings.default = [ "foot.desktop" ];
};
};
flake.modules.homeManager.primary-terminal-kitty =
{ lib, pkgs, ... }:
{
imports = [ config.flake.modules.homeManager.terminal-kitty ];
facts.desktop.terminalCommand = lib.getExe (kittySingleInstance pkgs);
xdg.terminal-exec = {
enable = true;
settings.default = [ "kitty.desktop" ];
};
};
} }
+6 -3
View File
@@ -5,8 +5,11 @@
let let
repo = config.repo; repo = config.repo;
repoHelpers = repo.helpers; repoHelpers = repo.helpers;
hmModules = config.flake.modules.homeManager;
in in
{ {
repo.theme = import ./_theme.nix;
flake.modules.nixos.theme = flake.modules.nixos.theme =
{ {
pkgs, pkgs,
@@ -22,6 +25,8 @@ in
}; };
in in
{ {
home-manager.sharedModules = [ hmModules.theme ];
environment.systemPackages = [ cursorTheme.package ]; environment.systemPackages = [ cursorTheme.package ];
services.displayManager.sddm.settings = { services.displayManager.sddm.settings = {
@@ -77,9 +82,7 @@ in
name = repoTheme.kanagawa.gtkThemeName; name = repoTheme.kanagawa.gtkThemeName;
package = pkgs.kanagawa-gtk-theme.overrideAttrs (_: kanagawaOverride); package = pkgs.kanagawa-gtk-theme.overrideAttrs (_: kanagawaOverride);
}; };
gtk4.theme = { gtk4.theme = null;
inherit (config.gtk.theme) name package;
};
iconTheme = { iconTheme = {
name = repoTheme.kanagawa.iconThemeName; name = repoTheme.kanagawa.iconThemeName;
package = pkgs.kanagawa-icon-theme.overrideAttrs (_: kanagawaOverride); package = pkgs.kanagawa-icon-theme.overrideAttrs (_: kanagawaOverride);
+4
View File
@@ -5,8 +5,10 @@ in
{ {
flake.modules.homeManager.vicinae = flake.modules.homeManager.vicinae =
{ {
config,
pkgs, pkgs,
inputs, inputs,
lib,
... ...
}: }:
let let
@@ -70,5 +72,7 @@ in
ssh ssh
]; ];
}; };
facts.desktop.launcherCommand = lib.getExe config.programs.vicinae.package;
}; };
} }
+47
View File
@@ -0,0 +1,47 @@
{ config, inputs, ... }:
let
homeModules = config.flake.modules.homeManager;
in
{
flake.modules.nixos.walker-cache = {
nix.settings = {
extra-substituters = [
"https://walker.cachix.org"
"https://walker-git.cachix.org"
];
extra-trusted-public-keys = [
"walker.cachix.org-1:fG8q+uAaMqhsMxWjwvk0IMb4mFPFLqHjuvfwQxE4oJM="
"walker-git.cachix.org-1:vmC0ocfPWh0S/vRAQGtChuiZBTAe4wiKDeyyXM0/7pM="
];
};
};
flake.modules.homeManager.walker-base =
{
config,
...
}:
{
imports = [ inputs.walker.homeManagerModules.default ];
programs.walker = {
enable = true;
runAsService = true;
config.providers.prefixes = [
{
provider = "bitwarden";
prefix = "?";
}
];
};
};
flake.modules.homeManager.primary-launcher-walker =
{ config, lib, ... }:
{
imports = [ homeModules.walker-base ];
facts.desktop.launcherCommand = lib.getExe config.programs.walker.package;
};
}
+5 -100
View File
@@ -1,8 +1,11 @@
{ {
repo = { repo = {
account = { account = rec {
name = "kiri"; name = "kiri";
realName = "Jelle Spreeuwenberg"; realName = "Jelle Spreeuwenberg";
homeDirectory = "/home/${name}";
nixosConfigurationPath = "${homeDirectory}/.config/nixos";
emails = { emails = {
personal = { personal = {
address = "mail@jelles.net"; address = "mail@jelles.net";
@@ -22,106 +25,8 @@
type = "office365"; type = "office365";
}; };
}; };
};
services = { primaryEmail = emails.personal;
actual = {
domain = "finance.jelles.net";
host = "127.0.0.1";
port = 3000;
url = "https://finance.jelles.net";
};
gitea = {
domain = "git.jelles.net";
host = "127.0.0.1";
port = 3001;
url = "https://git.jelles.net/";
};
radicale = {
domain = "radicale.jelles.net";
host = "127.0.0.1";
port = 5232;
url = "https://radicale.jelles.net/";
};
vaultwarden = {
domain = "vault.jelles.net";
host = "127.0.0.1";
port = 8100;
url = "https://vault.jelles.net";
};
};
theme = {
cursor = {
name = "phinger-cursors-light";
packagePath = [ "phinger-cursors" ];
size = 24;
};
kanagawa = {
displayName = "Kanagawa Wave";
name = "kanagawa-wave";
gtkThemeName = "Kanagawa-BL-LB";
iconThemeName = "Kanagawa";
owner = "Fausto-Korpsvart";
repo = "Kanagawa-GKT-Theme";
rev = "55ca4ba249eba21f861b9866b71ab41bb8930318";
hash = "sha256-UdMoMx2DoovcxSp/zBZ3PRv/Qpj+prd0uPm1gmdak2E=";
version = "unstable-2025-10-23";
palette = {
background = "#1F1F28";
foreground = "#DCD7BA";
secondaryBackground = "#16161D";
border = "#2A2A37";
selectionBackground = "#2D4F67";
selectionForeground = "#C8C093";
url = "#72A7BC";
cursor = "#C8C093";
muted = "#727169";
accents = {
blue = "#7E9CD8";
green = "#98BB6C";
magenta = "#D27E99";
orange = "#FFA066";
purple = "#957FB8";
red = "#E82424";
yellow = "#E6C384";
cyan = "#7AA89F";
};
niri.border = {
active = "#7E9CD8";
inactive = "#54546D";
urgent = "#E82424";
};
terminal = {
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";
};
};
};
}; };
}; };
} }
+2 -2
View File
@@ -12,10 +12,10 @@
systems = [ "x86_64-linux" ]; systems = [ "x86_64-linux" ];
flake.nixosConfigurations = builtins.mapAttrs ( flake.nixosConfigurations = builtins.mapAttrs (
_: machine: name: machine:
inputs.nixpkgs.lib.nixosSystem { inputs.nixpkgs.lib.nixosSystem {
specialArgs = { inherit inputs; }; specialArgs = { inherit inputs; };
modules = [ (config.repo.helpers.mkHost machine) ]; modules = [ (config.repo.helpers.mkHost name machine) ];
} }
) config.repo.machines; ) config.repo.machines;
+1 -1
View File
@@ -12,7 +12,6 @@ in
syncthingId = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI"; syncthingId = "NNRNQKZ-OWPHSVA-B6KKBHE-SDYLSTV-7SVHGPR-NEWLKPL-4MWNJG4-G5FHUAI";
stateVersion = "24.05"; stateVersion = "24.05";
hmStateVersion = "24.05";
}; };
flake.modules.nixos.orion = flake.modules.nixos.orion =
@@ -26,6 +25,7 @@ in
nixosModules.caddy nixosModules.caddy
nixosModules.server-firewall nixosModules.server-firewall
nixosModules.sudo-ssh-agent-auth nixosModules.sudo-ssh-agent-auth
nixosModules.vps-insights
nixosModules.vaultwarden nixosModules.vaultwarden
nixosModules.radicale nixosModules.radicale
nixosModules.actual nixosModules.actual
+1 -2
View File
@@ -16,7 +16,6 @@ in
syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3"; syncthingId = "6HBAKXB-DB3B4H2-BODCAXF-KD23H5W-6X5LGLC-ZJHZHLG-7U7YMGO-BB6IXQ3";
stateVersion = "24.05"; stateVersion = "24.05";
hmStateVersion = "24.05";
displays = { displays = {
"LG Electronics LG ULTRAGEAR 103NTYT8R290" = { "LG Electronics LG ULTRAGEAR 103NTYT8R290" = {
@@ -37,7 +36,7 @@ in
{ {
imports = [ imports = [
nixosModules.workstation-base nixosModules.workstation-base
nixosModules.qbittorrent-client nixosModules.transmission
nixosModules.steam nixosModules.steam
./_hardware.nix ./_hardware.nix
] ]
+1 -2
View File
@@ -28,7 +28,6 @@ in
}; };
stateVersion = "24.05"; stateVersion = "24.05";
hmStateVersion = "24.05";
}; };
flake.modules.nixos.zenith = flake.modules.nixos.zenith =
@@ -36,7 +35,7 @@ in
{ {
imports = [ imports = [
nixosModules.workstation-base nixosModules.workstation-base
nixosModules.qbittorrent-client nixosModules.transmission
nixosModules.laptop-power nixosModules.laptop-power
{ {
hardware.enableRedistributableFirmware = true; hardware.enableRedistributableFirmware = true;
+16 -13
View File
@@ -37,26 +37,35 @@ let
}; };
mkHost = mkHost =
machine: name: machine:
{ pkgs, ... }: { pkgs, ... }:
let let
account = config.repo.account; account = config.repo.account;
accountHome = account.homeDirectory or "/home/${account.name}";
normalizedMachine = machine // {
inherit name;
displays = machine.displays or { };
hmStateVersion = machine.hmStateVersion or machine.stateVersion;
portable = machine.portable or false;
sshKeys = machine.sshKeys or { };
syncthingId = machine.syncthingId or null;
};
in in
{ {
imports = [ imports = [
nixosModules.${machine.name} nixosModules.${name}
]; ];
meta.machine = machine; facts.machine = normalizedMachine;
networking.hostName = machine.name; networking.hostName = name;
system.stateVersion = machine.stateVersion; system.stateVersion = machine.stateVersion;
programs.zsh.enable = true; programs.zsh.enable = true;
users.users.${account.name} = { users.users.${account.name} = {
isNormalUser = true; isNormalUser = true;
home = account.homeDirectory; home = accountHome;
extraGroups = [ extraGroups = [
"wheel" "wheel"
"networkmanager" "networkmanager"
@@ -67,19 +76,13 @@ let
home-manager.users.${account.name} = { home-manager.users.${account.name} = {
home = { home = {
username = account.name; username = account.name;
homeDirectory = account.homeDirectory; homeDirectory = accountHome;
stateVersion = machine.hmStateVersion; stateVersion = normalizedMachine.hmStateVersion;
}; };
}; };
}; };
in in
{ {
options.repo.helpers = lib.mkOption {
type = lib.types.attrsOf lib.types.raw;
internal = true;
readOnly = true;
};
config.repo.helpers = { config.repo.helpers = {
inherit inherit
mkCaddyReverseProxy mkCaddyReverseProxy
+19 -230
View File
@@ -1,244 +1,33 @@
{ lib, ... }: { lib, ... }:
let
emailProviderType = lib.types.enum [
"mxrouting"
"office365"
];
emailType = lib.types.submodule (
{ ... }:
{
options = {
address = lib.mkOption {
type = lib.types.str;
};
primary = lib.mkOption {
type = lib.types.bool;
default = false;
};
type = lib.mkOption {
type = emailProviderType;
};
};
}
);
sshKeyType = lib.types.submodule (
{ name, ... }:
{
options = {
publicKey = lib.mkOption {
type = lib.types.str;
};
privateKeyPath = lib.mkOption {
type = lib.types.str;
default = "~/.ssh/id_${name}";
};
};
}
);
accountType = lib.types.submodule (
{ config, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
};
realName = lib.mkOption {
type = lib.types.str;
};
homeDirectory = lib.mkOption {
type = lib.types.str;
default = "/home/${config.name}";
};
nixosConfigurationPath = lib.mkOption {
type = lib.types.str;
default = "${config.homeDirectory}/.config/nixos";
};
emails = lib.mkOption {
type = lib.types.attrsOf emailType;
default = { };
};
primaryEmail = lib.mkOption {
type = lib.types.nullOr emailType;
description = "Derived primary email entry for this user.";
default =
let
emails = builtins.attrValues config.emails;
in
lib.findFirst (email: email.primary) null emails;
};
};
}
);
desktopApplicationType = lib.types.submodule (
{ config, ... }:
{
options = {
package = lib.mkOption {
type = lib.types.package;
};
command = lib.mkOption {
type = lib.types.str;
default = lib.getExe config.package;
defaultText = lib.literalExpression "lib.getExe config.package";
};
desktopEntryName = lib.mkOption {
type = lib.types.str;
};
desktopId = lib.mkOption {
type = lib.types.str;
default = "${config.desktopEntryName}.desktop";
defaultText = lib.literalExpression ''"${config.desktopEntryName}.desktop"'';
};
};
}
);
displayType = lib.types.submodule (
{ ... }:
{
options = {
primary = lib.mkOption {
type = lib.types.bool;
default = false;
};
x = lib.mkOption {
type = lib.types.int;
default = 0;
};
y = lib.mkOption {
type = lib.types.int;
default = 0;
};
scale = lib.mkOption {
type = lib.types.nullOr lib.types.float;
default = null;
};
width = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
};
height = lib.mkOption {
type = lib.types.nullOr lib.types.int;
default = null;
};
refresh = lib.mkOption {
type = lib.types.nullOr lib.types.float;
default = null;
};
};
}
);
machineType = lib.types.submodule (
{ name, config, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
default = name;
};
stateVersion = lib.mkOption {
type = lib.types.str;
};
hmStateVersion = lib.mkOption {
type = lib.types.str;
default = config.stateVersion;
};
displays = lib.mkOption {
type = lib.types.attrsOf displayType;
default = { };
};
sshKeys = lib.mkOption {
type = lib.types.attrsOf sshKeyType;
default = { };
};
syncthingId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
};
portable = lib.mkOption {
type = lib.types.bool;
default = false;
};
};
}
);
in
{ {
options.repo = { options.repo = lib.mkOption {
account = lib.mkOption { type = lib.types.submodule {
type = accountType; freeformType = lib.types.attrsOf lib.types.anything;
};
machines = lib.mkOption { options.helpers = lib.mkOption {
type = lib.types.attrsOf machineType; type = lib.types.attrsOf lib.types.raw;
default = { }; default = { };
}; internal = true;
};
services = lib.mkOption {
type = lib.types.raw;
default = { };
};
theme = lib.mkOption {
type = lib.types.raw;
default = { };
}; };
default = { };
}; };
config.flake.modules.nixos.meta = config.flake.modules.nixos.facts =
{ ... }: { lib, ... }:
{ {
options.meta.machine = lib.mkOption { options.facts.machine = lib.mkOption {
type = machineType; type = lib.types.attrsOf lib.types.anything;
default = { };
}; };
}; };
config.flake.modules.homeManager.meta = config.flake.modules.homeManager.facts =
{ ... }: { lib, ... }:
{ {
options.meta.desktop.browser = lib.mkOption { options.facts.desktop = lib.mkOption {
type = desktopApplicationType; type = lib.types.attrsOf lib.types.anything;
}; default = { };
options.meta.desktop.fileManager = lib.mkOption {
type = desktopApplicationType;
};
options.meta.desktop.terminal = lib.mkOption {
type = desktopApplicationType;
};
options.meta.pinentry.package = lib.mkOption {
type = lib.types.package;
}; };
}; };
} }
+2 -2
View File
@@ -10,7 +10,7 @@ in
{ {
flake.modules.nixos.host-base = { flake.modules.nixos.host-base = {
imports = [ imports = [
nixosModules.meta nixosModules.facts
inputs.home-manager.nixosModules.home-manager inputs.home-manager.nixosModules.home-manager
nixosModules.nix nixosModules.nix
nixosModules.locale-nl nixosModules.locale-nl
@@ -22,7 +22,7 @@ in
backupFileExtension = "bak"; backupFileExtension = "bak";
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = { inherit inputs; };
sharedModules = [ sharedModules = [
hmModules.meta hmModules.facts
hmModules.syncthing hmModules.syncthing
hmModules.shell hmModules.shell
hmModules.neovim hmModules.neovim
+14 -8
View File
@@ -20,10 +20,11 @@ in
nixosModules.printing nixosModules.printing
nixosModules.sddm nixosModules.sddm
nixosModules.sops-admin-key-file nixosModules.sops-admin-key-file
nixosModules.systemd-boot nixosModules.limine
nixosModules.theme nixosModules.theme
nixosModules.ai nixosModules.ai
nixosModules.hidraw-access nixosModules.hidraw-access
nixosModules.walker-cache
]; ];
services.dbus.implementation = "broker"; services.dbus.implementation = "broker";
@@ -38,28 +39,33 @@ in
flake.modules.homeManager.workstation-base = { flake.modules.homeManager.workstation-base = {
imports = [ imports = [
homeModules.ai
homeModules.passwords homeModules.passwords
homeModules.clipboard homeModules.clipboard
homeModules.dev-tools homeModules.dev-tools
homeModules.xdg
homeModules.workstation-apps
homeModules.primary-browser-vivaldi homeModules.primary-browser-vivaldi
homeModules.primary-file-manager-nautilus homeModules.primary-file-manager-nautilus
homeModules.desktop-defaults homeModules.primary-launcher-walker
homeModules.default-image-viewer-imv
homeModules.default-document-viewer-sioyek
homeModules.default-editor-neovim
homeModules.email homeModules.email
homeModules.mpv homeModules.mpv
homeModules.niri
homeModules.nix homeModules.nix
homeModules.calendar-tasks homeModules.calendar-tasks
homeModules.podman homeModules.podman
homeModules.qbittorrent-client
homeModules.sops
homeModules.git homeModules.git
homeModules.ssh-client homeModules.ssh-client
homeModules.primary-terminal-kitty homeModules.primary-terminal-kitty
homeModules.terminal-foot homeModules.terminal-foot
homeModules.theme
homeModules.vicinae
homeModules.noctalia homeModules.noctalia
{
programs.discord = {
enable = true;
settings.SKIP_HOST_UPDATE = true;
};
}
]; ];
}; };
} }
+3
View File
@@ -1,11 +1,14 @@
{ config, ... }: { config, ... }:
let let
account = config.repo.account; account = config.repo.account;
nixosModules = config.flake.modules.nixos;
in in
{ {
flake.modules.nixos.sops-password = flake.modules.nixos.sops-password =
{ config, ... }: { config, ... }:
{ {
imports = [ nixosModules.sops ];
sops.secrets.hashed-password.neededForUsers = true; sops.secrets.hashed-password.neededForUsers = true;
users.users.${account.name}.hashedPasswordFile = config.sops.secrets.hashed-password.path; users.users.${account.name}.hashedPasswordFile = config.sops.secrets.hashed-password.path;
+3
View File
@@ -5,6 +5,7 @@
}: }:
let let
nixosModules = config.flake.modules.nixos; nixosModules = config.flake.modules.nixos;
hmModules = config.flake.modules.homeManager;
sopsAdminKeyPath = "/var/lib/sops/keys.txt"; sopsAdminKeyPath = "/var/lib/sops/keys.txt";
in in
{ {
@@ -22,6 +23,8 @@ in
{ {
imports = [ nixosModules.sops ]; imports = [ nixosModules.sops ];
home-manager.sharedModules = [ hmModules.sops ];
sops.age.keyFile = sopsAdminKeyPath; sops.age.keyFile = sopsAdminKeyPath;
systemd.tmpfiles.rules = [ systemd.tmpfiles.rules = [