Compare commits

...

165 Commits

Author SHA1 Message Date
53cd519fa3 feat: add nfc module (and use it on 'astyanax') 2026-02-05 18:48:40 +01:00
1681a246de Fix: Simplify git hooks to just define in Nix, install with nix flake check 2026-02-05 18:36:43 +01:00
0d860d4a4f Fix: Remove git-hooks service from hosts (cleanup duplicate definitions) 2026-02-05 18:09:50 +01:00
67d7313691 Simplify: Git hooks via nix flake check (no systemd, no activation, deleted module) 2026-02-05 18:01:26 +01:00
03baf67e79 Phase1: Git hooks implementation (statix, deadnix, nix flake check, all hosts) 2026-02-05 17:29:17 +01:00
e5c8fb3d48 Fix: Use nix flake check for hooks, simplify module, remove apps 2026-02-05 17:26:54 +01:00
4ac16cedc4 test 2026-02-05 16:04:00 +01:00
53cf49f158 test mirroring 2026-02-05 14:07:39 +01:00
bbdd83f9f6 flake.lock: Update
Flake lock file updates:

• Updated input 'firefox-addons':
    'gitlab:rycee/nur-expressions/4f827ff035c6ddc58d04c45abe5b777d356b926a?dir=pkgs/firefox-addons&narHash=sha256-9Sqq/hxq8ZDLRSzu%2Bedn0OfWG%2BFAPWFpwMKaJobeLec%3D' (2026-02-03)
  → 'gitlab:rycee/nur-expressions/c7794d3f46304de5234008c31b5b28a9d5709184?dir=pkgs/firefox-addons&narHash=sha256-0iGDl/ct3rW%2Bh6%2BsLq4RZaze/U/aQo2L5sLLuyjuVTk%3D' (2026-02-04)
• Updated input 'home-manager':
    'github:nix-community/home-manager/984708c34d3495a518e6ab6b8633469bbca2f77a?narHash=sha256-gj1yP3spUb1vGtaF5qPhshd2j0cg4xf51pklDsIm19Q%3D' (2026-02-01)
  → 'github:nix-community/home-manager/04e5203db66417d548ae1ff188a9f591836dfaa7?narHash=sha256-R1WFtIvp38hS9x63dnijdJw1KyIiy30KGea6e6N7LHs%3D' (2026-02-05)
• Updated input 'nixpkgs':
    'github:nixos/nixpkgs/cb369ef2efd432b3cdf8622b0ffc0a97a02f3137?narHash=sha256-VKS4ZLNx4PNrABoB0L8KUpc1fE7CLpQXQs985tGfaCU%3D' (2026-02-02)
  → 'github:nixos/nixpkgs/00c21e4c93d963c50d4c0c89bfa84ed6e0694df2?narHash=sha256-AYqlWrX09%2BHvGs8zM6ebZ1pwUqjkfpnv8mewYwAo%2BiM%3D' (2026-02-04)
• Updated input 'nvim':
    'path:./dots/.config/nvim'
  → 'path:./dots/.config/nvim'
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/f990b0a334e96d3ef9ca09d4bd92778b42fd84f9?narHash=sha256-NUVGVtYBTC96WhPh4Y3SVM7vf0o1z5W4uqRBn9v1pfo%3D' (2026-02-03)
  → 'github:Mic92/sops-nix/17eea6f3816ba6568b8c81db8a4e6ca438b30b7c?narHash=sha256-ktjWTq%2BD5MTXQcL9N6cDZXUf9kX8JBLLBLT0ZyOTSYY%3D' (2026-02-03)
2026-02-05 12:36:38 +01:00
4cf601df84 fix: remove wlsunset spawn (replaced by gammastep service) 2026-02-05 12:21:09 +01:00
c8e4337a14 fix: remove duplicate waybar spawn in niri config (already managed by systemd) 2026-02-05 12:20:19 +01:00
49de518ad1 chore: update lockfile
Flake lock file updates:

• Updated input 'nvim':
    'path:./dots/.config/nvim'
  → 'path:./dots/.config/nvim'
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/1e89149dcfc229e7e2ae24a8030f124a31e4f24f?narHash=sha256-twBMKGQvaztZQxFxbZnkg7y/50BW9yjtCBWwdjtOZew%3D' (2026-02-01)
  → 'github:Mic92/sops-nix/f990b0a334e96d3ef9ca09d4bd92778b42fd84f9?narHash=sha256-NUVGVtYBTC96WhPh4Y3SVM7vf0o1z5W4uqRBn9v1pfo%3D' (2026-02-03)
2026-02-03 23:02:45 +01:00
6c9312f509 feat: mute 'astyanax' speakers when disconnecting AC 2026-02-03 23:02:41 +01:00
3359426c48 fix: integrate keepassxc browser on all firefox-based browsers 2026-02-03 23:02:41 +01:00
0f0f038f5a feat: set up restic backups for 'andromache' and 'astyanax' 2026-02-03 23:02:41 +01:00
ab31842e58 feat: set up syncthing (with e-reader) 2026-02-03 22:59:30 +01:00
ea88fff4a4 feat: set up 'paperless-ngx' (behind nginx reverse proxy) 2026-02-02 22:11:45 +01:00
b3ab7dcb1c fix: smarten 'buildOnTarget' by using tags 2026-02-02 22:11:26 +01:00
adb1265800 fix: add python dependency to 'taskwarrior' home module 2026-02-02 20:51:08 +01:00
40b2c821c8 fix: enable 'eetion' firewall 2026-02-02 19:43:07 +01:00
b59eb6889a fix: allow 'astyanax' to cross-compile to ARM (e.g. for eetion) 2026-02-02 18:37:01 +01:00
c538c5ad08 fix: add public hostname to ssh config and refactor 2026-02-02 18:37:01 +01:00
4236aa1def feat: host 'ActualBudget' on 'eetion' host 2026-02-02 18:37:01 +01:00
9ea3a7c984 fix(colmena): add hostname to 'hecuba' host 2026-02-02 18:37:01 +01:00
f57cabb186 feat: add 'k8s' home module 2026-02-02 16:54:22 +01:00
0778b12305 feat: add 'docker' home module to 'work' host 2026-02-02 16:54:17 +01:00
d9c3cb9889 fix: add 'dconf2nix' package to 'dconf' module 2026-02-02 14:30:09 +01:00
9d22c210e3 refactor: clean up packages 2026-02-02 14:29:22 +01:00
eb54ade226 refactor: clean up 'flake.nix' and 'deploy/colmena.nix' 2026-02-01 23:55:27 +01:00
1d5c1a7c2a fix(ssh): harden ARM SD installer image SSH 2026-02-01 22:57:08 +01:00
0f7f9585b3 feat(host): add 'eetion' host (as a test for Orange Pi Zero2 H616) 2026-02-01 22:56:12 +01:00
ed24f55d15 fix(deploy): add colmena to 'builder' hosts 2026-02-01 22:48:57 +01:00
f5a490d452 refactor: move disko module out of 'common' module 2026-02-01 22:47:24 +01:00
88969087fe fix: use cross-compilation from x86 to ARM for SD card image 2026-01-31 22:59:25 +01:00
b14e2e5a39 feat: add SD card image for ARM 2026-01-31 22:47:04 +01:00
02f28ab1df feat(phone): set up 'nix-on-droid' 2026-01-31 10:18:06 +01:00
c048eb73c0 fix: only use 'nvim' flake as home manager module 2026-01-31 10:17:55 +01:00
b22c5bc935 feat: add 'taskopen' to 'taskwarrior' module 2026-01-30 16:10:46 +01:00
7c46bae3e2 feat: add 'comms' module 2026-01-30 16:10:46 +01:00
8a1f51873e chore: temporarily disable wireguard VPN module 2026-01-30 16:10:46 +01:00
e03c77cdbc feat: add CLI tools to git module 2026-01-30 16:10:46 +01:00
a64d153004 feat: add 'azure' cloud option (and generalized module) 2026-01-30 16:10:46 +01:00
a78af6529c fix: update 'ai-tools' module and add to 'astyanax' host 2026-01-27 21:36:17 +01:00
c460bebb2d feat: add 'ai-tools' home module 2026-01-27 16:35:20 +01:00
b84944543a chore: update nvim flake dependencies 2026-01-27 16:30:17 +01:00
63f4c82c76 chore: update flake lockfiles 2026-01-27 16:22:13 +01:00
677b1b6666 fix: declare contents of 'setup-gnome' 2026-01-27 16:19:34 +01:00
b827b518cd refactor(statix): resolve 'statix check' issues 2026-01-27 07:34:37 +01:00
68eecd01c7 chore: update lockfile 2026-01-26 21:59:30 +01:00
8fc4e23d3b fix(nixd): properly configure 'nixd' nvim lsp 2026-01-26 21:58:09 +01:00
cf381042d0 feat: add 'gammastep' to niri deskopt 2026-01-26 21:21:49 +01:00
2303988b74 feat: add '3d' and 'photography' modules to andromache 2026-01-26 21:21:26 +01:00
791d90b703 fix: update hardware config 2026-01-26 18:47:43 +01:00
29137a8cdd chore: update lockfile 2026-01-25 15:32:53 +01:00
dd175e99b8 refactor: migrate vim.cmd to lua API in init.lua 2026-01-23 15:22:55 +01:00
3a5f1cf47e fix: remove conflicting light background setting
The bg=light setting was immediately overridden by vim.opt.background = "dark" later in the file.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 15:22:55 +01:00
755f1f4a06 refactor: remove duplicate 'paq-setup' require 2026-01-23 15:22:55 +01:00
1cfc049326 chore(nvim): remove redundant unused config 2026-01-23 15:22:55 +01:00
09d2832948 fix(vim.keymap): resolve duplicate 'fzf' keymap 2026-01-23 15:22:55 +01:00
85ab23eb5d fix(tmux): update tmux config 2026-01-23 15:22:55 +01:00
76a31b3051 refactor: deduplicate firefox/librewolf config 2026-01-23 15:22:55 +01:00
8e5cbe6350 fix: use 'nixGL' for kitty when available 2026-01-23 15:22:55 +01:00
e75fc95b27 feat: add 'tmux' to 'shell' module 2026-01-23 15:22:55 +01:00
24ed3f03cd refactor: extract 'dotsPath' for 'dots' path 2026-01-23 15:22:55 +01:00
b6453330bf refactor: centralize kitty config 2026-01-23 15:22:55 +01:00
bd008cde04 fix: remove 'edit_editor_config' alias 2026-01-23 15:22:55 +01:00
ffff1cfda1 refactor: modularize 'nvim' for home manager hosts 2026-01-23 15:22:55 +01:00
0f369bdf6c feat: set up colmena with hetzner stuff 2026-01-22 20:26:11 +01:00
600e55de1f feat: configure auto suspend 2026-01-22 20:25:06 +01:00
a390428ca9 feat: set up opencode (with automated API key) 2026-01-22 20:25:05 +01:00
a5aeddc5c2 feat: add 'hcloud' module 2026-01-22 20:24:36 +01:00
e9748b0236 chore: update Nix 'work' host 2026-01-22 20:22:19 +01:00
3902e2da67 chore: update lockfile 2026-01-22 20:20:30 +01:00
42af1badc4 refactor: modularize 'nvim' for home manager hosts 2026-01-19 10:12:02 +01:00
1eca0c995d feat: use shell module on work host 2026-01-19 10:03:05 +01:00
92389f7048 feat: modularize (and extend) kitty config 2026-01-19 09:45:22 +01:00
d6459d0d84 feat: add 'hcloud' module 2026-01-18 10:02:20 +01:00
00e5c92c1e fix: add 'hetzner' module 2026-01-18 09:43:45 +01:00
c19afff26a chore: update lockfile 2026-01-17 20:01:31 +01:00
8ea03f0a66 feat: automate optimising store, garbage collection and upgrades 2026-01-17 20:00:21 +01:00
8f3f6ec66d refactor(nixfmt): format 2026-01-17 19:58:27 +01:00
3401ed7424 chore: add 'andromache' ssh public keys 2026-01-17 19:50:21 +01:00
bb6a380599 refactor: simplify hosts files 2026-01-17 19:37:05 +01:00
35fd4e61e2 fix: remove xdg config 2026-01-17 18:02:17 +01:00
01542dda96 feat: replace 'sddm' with 'ly' 2026-01-17 17:51:26 +01:00
8464884fdb feat: automate SSH config ('known_hosts', 'authorized_keys' ...) 2026-01-17 17:37:37 +01:00
33b022c659 chore(nixfmt): format 2026-01-17 17:35:38 +01:00
a8f3f222b1 fix: merge 'astyanax' services configuration 2026-01-17 16:35:38 +01:00
bf9ea37280 fix: disable 'throttled' service 2026-01-17 16:34:14 +01:00
724c5c176b fix: improve niri desktop 2026-01-17 16:33:30 +01:00
49e99e9de2 fix: add anki to 'astyanax' host 2026-01-17 16:31:37 +01:00
ce0af2988a fix: move kitty tab bar to bottom 2026-01-17 15:10:28 +01:00
5a7afbfe82 fix: update font configuration 2026-01-17 15:09:57 +01:00
87afec8955 chore: update lockfile 2026-01-17 15:09:14 +01:00
2a1512f85b fix: disable 'nixos-hardware' module for astyanax (caused boot to hang on 'loading module i915') 2026-01-17 14:56:03 +01:00
313e623ec4 feat(home): add shell module 2026-01-16 15:25:29 +01:00
4f7ab88634 fix(anki): make sops optional for standalone home-manager 2026-01-16 15:25:27 +01:00
a8851e5a91 feat(home): migrate bash config to shell module 2026-01-16 15:25:25 +01:00
629f25c795 feat(nixos): pass inputs to home-manager via extraSpecialArgs 2026-01-16 15:25:23 +01:00
b52d87d30b chore(git): add .claude/ to gitignore 2026-01-16 15:25:20 +01:00
54114f99ab fix: make taskwarrior available on both NixOS and standalone home-manager 2026-01-14 22:57:27 +01:00
2fcde8ddd1 chore: update NixOS 2026-01-14 20:55:59 +01:00
a952136be1 fix: remove descriptions from 'browser' module 2026-01-14 16:45:56 +01:00
7773d2a7a0 fix: resolve nvim treesitter errors 2026-01-14 11:50:28 +01:00
c86a52e435 fix: add 'stylelint' to neovim flake 2026-01-14 11:22:01 +01:00
c99738c210 refactor(browser): create single browser module 2026-01-12 18:10:52 +01:00
8321d5e2ef chore: update Nix 'work' host 2026-01-08 11:59:54 +01:00
46477cce25 chore: update lockfile 2025-12-29 09:35:08 +01:00
4765527fa6 feat(nvim): add typescript-language-server to runtime dependencies 2025-12-24 14:46:40 +01:00
67f5aefc82 fix(nvim): ensure codecompanion config structure exists before mcphub extension loads 2025-12-24 14:43:29 +01:00
89c398a957 chore: update flake.lock with nvim mcp-hub input
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 14:14:38 +01:00
d1fc192d26 feat(nvim): add mcp-hub, fd, and delta dependencies
- add mcp-hub flake input for MCP integration
- create system-aware dependency overlays
- add mcp-hub, fd, delta to lspsAndRuntimeDeps
- remove duplicate tailwind-fold.lua file

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-24 14:14:10 +01:00
bc2790c7fb feat: set up 'claude-code.nvim' plugin 2025-12-18 16:01:31 +01:00
e3f55a1fbd chore: add TODO for unique 'networking.hostId' 2025-12-18 13:40:26 +01:00
c66cd0e28c refactor: use username variable consistently
Replaced hardcoded "h" username references with variables:
- hosts/vm: use username variable for secrets.username
- home configs: use username variable in bash initExtra paths
- keepassxc: update comment to use $HOME instead of /home/h

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 13:39:43 +01:00
d5d395ed56 fix(firefox): merge duplicate policies declarations
Second policies declaration was overwriting the first, causing
DefaultDownloadDirectory setting to be lost. Merged both into single
policies block.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-18 13:39:43 +01:00
e15f9a51cb fix: format rust using 'rustfmt' 2025-12-15 18:18:20 +01:00
acafbf9a6a refactor: decouple 'andromache' home config from 'astyanax' 2025-12-15 12:19:38 +01:00
4952ea0634 chore: update neovim flake (and main flake) 2025-12-15 12:01:19 +01:00
6e2f28d601 refactor: import shikane 'desktop/niri' instead of directly 2025-12-15 11:57:22 +01:00
143d31433f feat: add plain 'mako' service for notifications 2025-12-14 23:45:58 +01:00
a176c744f8 feat: declare anki config 2025-12-14 22:44:45 +01:00
2fa0b1f36a fix: migrate 'r5rs' script to neovim 2025-12-14 22:11:14 +01:00
520cd476fc fix: ignore directories that contain '.nobackup' in 'save-home' 2025-12-14 22:11:14 +01:00
f985df8e61 chore: format using 'black' 2025-12-14 22:11:14 +01:00
ec750ebb17 chore: clean up 'astyanax' packages 2025-12-09 23:43:56 +01:00
f3fd842692 feat: add 'fail2ban' to 'hecuba' host 2025-12-09 23:10:24 +01:00
6ff168caeb refactor: use environment variable for zettelkasten path 2025-12-09 12:43:07 +01:00
0863445dab feat: add 'rustfmt' for rust formatting 2025-12-08 20:16:18 +01:00
989a9626b3 chore: relock flake 2025-12-07 23:04:06 +01:00
7fa58a0421 feat: add 'figet.nvim' to 'nvim' flake 2025-12-07 22:59:05 +01:00
a477b2c5c3 test(nvim): try out 'm_taskwarrior_d.nvim' plugin 2025-12-07 19:16:07 +01:00
d2999ab763 fix: resolve 'nix flake check' errors 2025-12-07 17:42:18 +01:00
5d7b8d520a feat: use 'rustaceanvim' instead for rust development 2025-12-07 17:36:33 +01:00
edbbd3efd5 feat: add 'wl-clipboard' to niri desktop 2025-12-07 14:32:33 +01:00
de0b4852bf fix: work around throttled error 2025-12-07 00:13:59 +01:00
3e66197dd8 fix: declare graphics config for 'astyanax' host 2025-12-07 00:06:22 +01:00
495befc8c0 fix: resolve treesitter errors on NixOS 2025-12-07 00:05:46 +01:00
c4ccfc3a92 chore: ignore breaking changes warning for 'codecompanion.nvim' 2025-12-07 00:04:56 +01:00
02869d267a enable 'shikane' on 'astyanax' (and add 'wdisplays') 2025-12-06 23:51:50 +01:00
1e03157838 feat(nvim): set up rust lsp config 2025-12-06 23:49:29 +01:00
bc3caec6ba refactor: enable firewall explicitely for 'hecuba' host 2025-12-04 12:48:55 +01:00
2d9e1fd875 fix: remove common '.nix' suffix 2025-12-04 12:48:55 +01:00
63ef553d6b fix: update waybar to match polybar config (for the most part) 2025-12-04 12:48:55 +01:00
11ed160935 refactor: move 'wlsunset' package into home manager module 2025-12-04 12:48:55 +01:00
Hektor Misplon
7256c82b91 chore: update 'nvim' flake 2025-12-04 02:24:28 +01:00
Hektor Misplon
fcdb9d19fc fix: don't autoinstall treesitter grammars when using 'nixCats' 2025-12-04 02:21:30 +01:00
cec89af852 fix: declare 'fuzzel' config and add it to 'niri' desktop 2025-12-03 23:49:58 +01:00
8de9913ecf feat: track (currently unused) k3s module 2025-12-03 23:45:55 +01:00
d71e7d0e5d refactor: use 'default.nix' for all modules 2025-12-03 23:43:43 +01:00
e643d22eda fix: declare 'waybar' config and add it to 'niri' desktop 2025-12-03 23:36:33 +01:00
c141508203 fix: declare niri config 2025-12-03 23:36:33 +01:00
8ee1913d93 fix: try 'writeShellApplication' for 'astyanax' WOL script 2025-12-03 22:35:21 +01:00
ac4619f1a4 fix: declare 'andromache' 'eno1' interface MAC address 2025-12-03 21:40:44 +01:00
d178a03b43 feat: add 'hecuba' host config 2025-12-03 19:28:03 +01:00
063f142ae5 fix: further harden 'hardened-openssh' module 2025-12-03 17:14:08 +01:00
c90127e212 fix: replace 'gnome' desktop with 'niri' 2025-12-03 15:56:09 +01:00
f317f9409e fix: declare KeePassXC browser integration 2025-12-03 15:56:06 +01:00
c13de26ee1 chore(pkgs): add 'signal-desktop' package 2025-12-03 15:54:33 +01:00
ac5b97dba4 fix: disable kitty tab shortcut for now 2025-12-03 15:54:33 +01:00
4e2c3473e4 update bluetooth config 2025-12-03 15:54:33 +01:00
8434ceb45a refactor: move bootloader into 'modules/boot' 2025-12-03 15:54:33 +01:00
b2d1ef4bb1 refactor: move 'disko' modules into 'modules/disko' 2025-12-03 15:54:33 +01:00
c6ec0a5d1d resolve NixOS build warnings 2025-12-03 15:54:33 +01:00
d9ea9d1d27 Merge pull request 'update' (#1) from claude-code-test into main
Reviewed-on: #1
2025-12-03 15:53:43 +01:00
143 changed files with 4802 additions and 718 deletions

13
.editorconfig Normal file
View File

@@ -0,0 +1,13 @@
root = true
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
max_line_length = 120
trim_trailing_whitespace = true
[**.{md,rst}]
indent_size = 2
max_line_length = 80

21
.github/workflows/flake-check.yaml vendored Normal file
View File

@@ -0,0 +1,21 @@
name: "Nix flake check"
on:
workflow_call:
pull_request:
push:
jobs:
tests:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31
with:
nix_path: nixpkgs=channel:nixos-unstable
- name: Check formatting with nixfmt
run: nix run nixpkgs#nixfmt-rfc-style --check .
- name: Lint with statix
run: nix run nixpkgs#statix check
- name: Find dead code with deadnix
run: nix run nixpkgs#deadnix
- name: Run flake check
run: nix flake check --accept-flake-config

6
.gitignore vendored
View File

@@ -1,8 +1,10 @@
#
.claude/
home/hosts/work/packages.local.nix
# ---> Nix # ---> Nix
# Ignore build outputs from performing a nix-build or `nix build` command # Ignore build outputs from performing a nix-build or `nix build` command
result result
result-* result-*
nixos-efi-vars.fd nixos-efi-vars.fd
home/hosts/work/packages.local.nix

1
.mirroring-test Normal file
View File

@@ -0,0 +1 @@
test-1770296859

View File

@@ -0,0 +1,149 @@
# Migration Plan: Move books and papers to flat directory
## Current State
- **Books location:** `/data/desk/home.h.doc/books`
- **Papers location:** `/data/desk/home.h.doc/papers`
- **Current syncthing path:** `~/doc/readings``/home/h/doc/readings`
- **Zotero:** Currently active, will be kept during/after migration
- **Future Papis:** Will use same files once consolidated
## Decision Summary
- **Target path:** `/data/desk/home.h.doc/readings` (single flat directory)
- **Organization:** Completely flat (no subdirectories) - use Papis/Zotero tags for categorization
- **Zotero:** Keep active during/after migration
- **Rebuild timing:** After files are moved (safer - syncthing won't sync while moving)
---
## Implementation Steps
### Step 1: Update syncthing config (andromache)
**File:** `hosts/andromache/default.nix`
Change the syncthing folder path from:
```nix
path = "/home/h/doc/readings";
```
To:
```nix
path = "/data/desk/home.h.doc/readings";
```
### Step 2: Rebuild andromache
```bash
sudo nixos-rebuild switch --flake /home/h/nix
```
This applies the new syncthing configuration.
### Step 3: Prepare target directory
```bash
# Create the target directory (in case it doesn't exist)
mkdir -p /data/desk/home.h.doc/readings
```
### Step 4: Move files (EXECUTE THIS MANUALLY)
Choose one method:
**Method A: Move (removes original directories)**
```bash
mv /data/desk/home.h.doc/books/* /data/desk/home.h.doc/readings/
mv /data/desk/home.h.doc/papers/* /data/desk/home.h.doc/readings/
rmdir /data/desk/home.h.doc/books /data/desk/home.h.doc/papers
```
**Method B: Copy (keeps original directories as backup)**
```bash
cp -r /data/desk/home.h.doc/books/* /data/desk/home.h.doc/readings/
cp -r /data/desk/home.h.doc/papers/* /data/desk/home.h.doc/readings/
```
### Step 5: Configure Boox to sync new path
On your Boox device, update the Syncthing folder to sync:
- Path: Choose where you want the files (e.g., `/sdcard/Books/readings` or `/sdcard/Documents/readings`)
- Accept connection from andromache when prompted
---
## Post-Migration Verification
### 1. Verify syncthing on andromache
- Open http://localhost:8384
- Confirm `readings` folder points to `/data/desk/home.h.doc/readings`
- Check that files are being synced to Boox
### 2. Verify Boox receives files
- Check that files from new directory appear on Boox
- Confirm `readings` folder is active on Boox
### 3. Verify Zotero
- Ensure Zotero can still access files at new location
- Check that tags/categorization still work
- Verify PDFs open correctly from Zotero library
---
## Future Work: Papis Migration
When ready to migrate to Papis:
1. Install Papis: `nix-shell -p papis`
2. Configure Papis to use: `/data/desk/home.h.doc/readings`
3. Import from Zotero or start fresh
4. Both Zotero and Papis can coexist during transition
5. Gradually migrate to Papis, then retire Zotero
---
## Rollback Plan
If anything goes wrong:
### Option 1: Revert syncthing config
```bash
# In hosts/andromache/default.nix, change back to:
path = "/home/h/doc/readings";
# Rebuild:
sudo nixos-rebuild switch --flake /home/h/nix
```
### Option 2: Restore original directories
If Method A (move) was used:
```bash
mkdir -p /data/desk/home.h.doc/books /data/desk/home.h.doc/papers
# You'll need to manually move files back from readings/
```
If Method B (copy) was used:
```bash
# Original directories still exist as backups at:
/data/desk/home.h.doc/books
/data/desk/home.h.doc/papers
```
---
## Session Checklist
- [ ] Update syncthing config in andromache
- [ ] Rebuild andromache
- [ ] Create target directory
- [ ] Move files (choose method: move or copy)
- [ ] Configure Boox folder path
- [ ] Verify syncthing sync
- [ ] Verify Zotero access
- [ ] (Future) Install and configure Papis
---
## Notes
- **File conflicts:** If books and papers have files with the same name, the moved file will overwrite (from `books/` processed first, then `papers/`). Consider checking beforehand.
- **Zotero database:** No changes needed - Zotero tracks files by absolute path, which won't change.
- **Boox folder naming:** The Boox folder name can be anything you want (doesn't have to be "readings"). Use something descriptive for your device like "E-reader" or "Boox".

189
CI_HOOKS_SUMMARY.md Normal file
View File

@@ -0,0 +1,189 @@
# Declarative CI and Git Hooks - Summary
## What's New
### 1. GitHub Actions CI ✅
`.github/workflows/flake-check.yaml`
- Runs `nixfmt --check` on every push/PR
- Runs `nix flake check`
- Blocks merging if checks fail
### 2. Nix-Native Git Hooks ✅
`modules/git-hooks/default.nix`
- Hooks defined in `flake.nix` (pure Nix)
- Install automatically on `nixos-rebuild switch`
- Run on every git commit
## Usage
### Install Hooks (One-time per host)
```nix
# Add to hosts/<hostname>/default.nix
{
imports = [
# ... other modules
../../modules/git-hooks
];
services.git-hooks = {
enable = true;
# flake-path = /home/h/nix; # Optional, default
};
}
```
### Rebuild
```bash
sudo nixos-rebuild switch --flake .#andromache
# Output:
# 🪝 Installing git hooks...
# ✅ Done
```
### Now Hooks Work Automatically
```bash
git add .
git commit -m "changes" # Hooks run automatically
```
## Files
| File | Purpose |
|------|---------|
| `.github/workflows/flake-check.yaml` | CI pipeline |
| `modules/git-hooks/default.nix` | Auto-install module |
| `flake.nix` | Hook definitions |
| `.editorconfig` | Code style |
## Enable on Other Hosts
```nix
# hosts/<hostname>/default.nix
imports = [
# ... existing modules
../../modules/git-hooks # Add this
];
services.git-hooks.enable = true;
```
## Add More Hooks
Edit `flake.nix`:
```nix
checks.${system}.pre-commit-check.hooks = {
nixfmt-rfc-style.enable = true; # ✅ Already done
statix.enable = true; # ✅ Already done
deadnix.enable = true; # ✅ Already done
};
```
All Phase 1 hooks are now enabled!
## Testing
```bash
# 1. Rebuild to install hooks
sudo nixos-rebuild switch --flake .#andromache
# 2. Test hooks
git commit -m "test"
# 3. Test CI locally
nix run nixpkgs#nixfmt --check .
nix flake check
```
## Documentation
- `CI_HOOKS_SUMMARY.md` - This file
- `DRUPOL_INFRA_ANALYSIS.md` - Reference patterns
- `AWESOME_NIX_PLAN.md` - Future improvements
- `OPENCODE.md` - Tracking document
## Currently Enabled
| Host | Status | Config File |
|------|--------|--------------|
| andromache | ✅ Enabled | `hosts/andromache/default.nix` |
| astyanax | ✅ Enabled | `hosts/astyanax/default.nix` |
| hecuba | ✅ Enabled | `hosts/hecuba/default.nix` |
| eetion | ✅ Enabled | `hosts/eetion/default.nix` |
| vm | ✅ Enabled | `hosts/vm/default.nix` |
## Clean Slate Test (Astyanax)
```bash
# 1. Remove existing git hooks
rm -rf /home/h/nix/.git/hooks/*
ls -la /home/h/nix/.git/hooks/
# 2. Rebuild astyanax (installs hooks)
sudo nixos-rebuild switch --flake .#astyanax
# Expected output:
# 🪝 Installing git hooks...
# ✅ Done
# 3. Verify hooks were installed
ls -la /home/h/nix/.git/hooks/
# 4. Test hooks work
echo "broken { }" > /home/h/nix/test.nix
git add test.nix
git commit -m "test" # Should fail with nixfmt error
# 5. Clean up
rm /home/h/nix/test.nix
```
## Future Enhancements
### High Priority
- [x] Add statix hook (lint for antipatterns) ✅ Done
- [x] Add deadnix hook (find dead code) ✅ Done
- [x] Enable git-hooks on all hosts ✅ Done
- [ ] Add CI caching (speed up builds)
### Medium Priority
- [ ] Add automated flake.lock updates
- [ ] Add per-host CI checks
- [ ] Add nixos-rebuild tests in CI
## References
- [git-hooks.nix](https://github.com/cachix/git-hooks.nix)
- [nixfmt-rfc-style](https://github.com/NixOS/nixfmt)
- [drupol/infra analysis](DRUPOL_INFRA_ANALYSIS.md)
- [awesome-nix plan](AWESOME_NIX_PLAN.md)
- [OpenCode documentation](OPENCODE.md)
## Quick Reference
```bash
# Rebuild (installs hooks automatically)
sudo nixos-rebuild switch --flake .#<host>
# Verify hooks
ls -la /home/h/nix/.git/hooks/
# Test formatting
nixfmt .
# Check CI status
# https://github.com/hektor/nix/actions
```
## Key Points
**Fully declarative** - Hooks install on every rebuild
**No manual setup** - No `nix develop` needed
**No devShell** - Pure NixOS activation
**Reproducible** - Managed by flake.lock
**Host-aware** - Per-host configuration
**Idempotent** - Checks before installing

70
CLOUD_BACKUP_PLAN.md Normal file
View File

@@ -0,0 +1,70 @@
# Cloud Host Backup Plan
## Security Architecture
### Current Setup
- **astyanax** (local): `b2:lmd005` - single repo, all hosts mixed
- **andromache** (cloud): manual backup via script to `b2:lmd005:desktop-arch`
### Recommended Setup
#### 1. Repository Isolation
Each host gets its own restic repository in a separate subdirectory:
```
b2:lmd005:astyanax/ # restic repo for astyanax
b2:lmd005:andromache/ # restic repo for andromache
b2:lmd005:<hostname>/ # restic repo for each host
```
**Benefits:**
- Cryptographic isolation (different restic keys per repo)
- Can't accidentally prune/delete other hosts' backups
- Easier to restore/manage individual hosts
- Can use B2 lifecycle rules per subdirectory
#### 2. Credential Isolation
Each host gets its own B2 Application Key restricted to its subdirectory:
```
B2 Key for astyanax: access to `lmd005:astyanax/*`
B2 Key for andromache: access to `lmd005:andromache/*`
```
**Security benefits:**
- If host is compromised, attacker only accesses that host's backups
- Cannot delete/read other hosts' backups
- Principle of least privilege
#### 3. Cloud Host Strategy (No B2 credentials on cloud hosts)
For cloud hosts like andromache:
```
andromache (cloud) --[SFTP]--> astyanax (local) --[B2]--> b2:lmd005:andromache/
```
- **andromache**: SSH access only, no B2 credentials
- **astyanax**: Pulls backups via SFTP from andromache, pushes to B2
- **B2 credentials**: Only stored on trusted local machine (astyanax)
## Implementation Plan
### ✅ Phase 1: Update astyanax backup
- Change repository from `b2:lmd005` to `b2:lmd005:astyanax/`
- Create new restic repo
- Migrate old snapshots if needed
- Update to use host-specific B2 key (when available)
### ✅ Phase 2: Implement cloud host backups
- Use SFTP-based module to pull from andromache ✅
- Store in `b2:lmd005:andromache/`
- No B2 credentials on andromache ✅
- Daily automated backups ✅
### Phase 3: Cleanup old backups
- Clean up old `desktop-arch` snapshots
- Remove old mixed repo (once migration complete)
## Questions
1. Do you want to migrate existing astyanax snapshots to the new subdirectory, or start fresh?
2. Should astyanax have a master/admin B2 key to manage all backups, or just its own?

217
DOCKER_UPDATE_PLAN.md Normal file
View File

@@ -0,0 +1,217 @@
# Docker Container Update Automation Plan
## Current State
- Hecuba (Hetzner cloud host) runs Docker containers
- WUD (Watchtower) is already running as a docker container
- No declarative docker configuration in NixOS
- Manual container management currently
## Goals
Automate docker container updates on hecuba with proper declarative management
## Evaluation: Update Approaches
### Option 1: WUD (Watchtower)
**Pros:**
- Already deployed and working
- Simple, single-purpose tool
- Good monitoring capabilities via web UI
- Can schedule update windows
- Supports multiple strategies (always, weekly, etc.)
**Cons:**
- Not declarative
- Requires manual docker-compose or container management
- No NixOS integration
### Option 2: Watchtower (original)
**Pros:**
- More popular and battle-tested
- Simpler configuration
- Wide community support
**Cons:**
- Same as WUD - not declarative
### Option 3: NixOS Virtualisation.OCI-Containers
**Pros:**
- Fully declarative
- Reproducible builds
- Integrated with NixOS system
- Automatic rollback capability
- Can be managed via colmena
**Cons:**
- More complex setup
- Learning curve for OCI containers syntax
- Update automation still needs to be handled separately
### Option 4: NixOS + Auto-Update
**Pros:**
- Declarative containers
- Automatic system updates can trigger container updates
- Full NixOS ecosystem integration
**Cons:**
- Most complex approach
- Overkill for simple use case
## Implementation Plan
### Phase 1: Inventory Current Setup
- [ ] Document all existing docker containers on hecuba
- [ ] Document current WUD configuration
- [ ] Document update schedules and preferences
- [ ] Identify containers that should NOT auto-update
- [ ] Map container dependencies
### Phase 2: Choose Strategy
- [ ] Evaluate trade-offs between WUD vs declarative approach
- [ ] Decision: Hybrid approach (declarative + WUD) OR full NixOS
#### Option A: Hybrid (Recommended Short-term)
- Keep WUD for automation
- Add OCI containers to NixOS for declarative config
- Gradually migrate containers one by one
#### Option B: Full NixOS
- Replace WUD with declarative containers
- Use systemd timers for update schedules
- More complex but fully reproducible
### Phase 3: Implementation (Hybrid Approach)
#### Step 1: Create Docker Module
Create `modules/docker/containers.nix`:
```nix
{ config, lib, ... }:
{
virtualisation.oci-containers = {
backend = "docker";
containers = {
# Container definitions here
};
};
}
```
#### Step 2: Define Containers
- [ ] Add WUD container to declarative config
- [ ] Add other existing containers to declarative config
- [ ] Configure container restart policies
- [ ] Set up container-specific networks if needed
#### Step 3: Persistent Storage
- [ ] Document volumes for each container
- [ ] Add volume management to NixOS config
- [ ] Ensure backup processes cover container data
#### Step 4: WUD Configuration
- [ ] Add WUD config to NixOS module
- [ ] Configure watch intervals
- [ ] Set up notifications
- [ ] Configure containers to exclude from auto-update
#### Step 5: Deployment
- [ ] Test configuration locally first
- [ ] Deploy to hecuba via colmena
- [ ] Monitor container restarts
- [ ] Verify WUD still works
### Phase 4: Maintenance & Monitoring
- [ ] Set up container health checks
- [ ] Configure alerts for failed updates
- [ ] Document rollback procedure
- [ ] Schedule regular container audits
## Container Inventory Template
```
Container Name:
Purpose:
Image:
Exposed Ports:
Volumes:
Network:
Auto-Update: yes/no
Restart Policy:
Notes:
```
## Example NixOS OCI Container Definition
```nix
# modules/docker/containers.nix
{ config, lib, pkgs, ... }:
{
virtualisation.oci-containers = {
backend = "docker";
containers = {
wud = {
image = "containrrr/watchtower:latest";
ports = [ "8080:8080" ];
volumes = [
"/var/run/docker.sock:/var/run/docker.sock"
];
environment = {
WATCHTOWER_CLEANUP = "true";
WATCHTOWER_SCHEDULE = "0 2 * * *";
};
};
# Add other containers here
};
};
}
```
## Migration Strategy
1. **Document First**: Before changing anything, document current state
2. **Test Locally**: Use colmena's local deployment if possible
3. **Migrate One by One**: Move containers individually to minimize risk
4. **Monitor Closely**: Watch logs after each migration
5. **Keep Backups**: Ensure data is backed up before major changes
## WUD vs Watchtower Clarification
There are two different tools:
- **Watchtower**: Original tool, more popular
- **WUD**: Different implementation with web UI
Since you already have WUD running, we should:
1. Document its current configuration
2. Either keep it and make it declarative, OR
3. Switch to Watchtower if it better fits your needs
## Next Steps
1. **Immediate**: Document all current containers and their configs
2. **Decision**: Choose between hybrid or full NixOS approach
3. **Implementation**: Create docker containers module
4. **Testing**: Deploy to hecuba and verify
## Questions to Answer
- Which containers are currently running?
- How critical is uptime for each container?
- Any containers that should NEVER auto-update?
- Preferred update schedule (daily, weekly)?
- How should update failures be handled (retry, notify, manual)?
- Do you have backups of container data currently?
## Risk Considerations
- Auto-updates can break applications
- Need to test updates before production (maybe staging)
- Some containers have configuration changes between versions
- Data loss risk if volumes are misconfigured
- Network disruption during updates
## Monitoring Setup
Consider adding monitoring for:
- Container health status
- Update success/failure rates
- Disk space usage
- Resource consumption
- Backup verification

226
IMPLEMENTATION_PLAN.md Normal file
View File

@@ -0,0 +1,226 @@
# Implementation Plan - Nix Flake Improvements
## Overview
Consolidated plan from:
- [AWESOME_NIX_PLAN.md](AWESOME_NIX_PLAN.md) - Awesome-nix integration
- [DRUPOL_INFRA_ANALYSIS.md](DRUPOL_INFRA_ANALYSIS.md) - Reference patterns
- [OPENCODE.md](OPENCODE.md) - Tracking document
## ✅ Completed
### Code Quality
- ✅ GitHub Actions CI (`.github/workflows/flake-check.yaml`)
- ✅ Nix-native git hooks (`modules/git-hooks/default.nix`)
- ✅ nixfmt integration (runs on commit and CI)
- ✅ .editorconfig (unified code style)
### Declarative Setup
- ✅ Git hooks auto-install on `nixos-rebuild switch`
- ✅ No devShell (fully NixOS activation-based)
- ✅ Hooks enabled on andromache and astyanax
## 📋 Pending Implementation
### Phase 1: Enhanced Code Quality (Week 1)
**Priority: HIGH** ✅ Complete
| # | Task | Effort | Impact | Details | Status |
|---|-------|--------|---------|----------|--------|
| 1.1 | Add statix hook | Low | High | Lint for Nix antipatterns | ✅ Done |
| 1.2 | Add deadnix hook | Low | High | Find dead code in Nix files | ✅ Done |
| 1.3 | Enable git-hooks on all hosts | Very Low | Medium | Add to hecuba, eetion, vm | ✅ Done |
| 1.4 | Fix activation script | Low | High | Use `nix flake check` | ✅ Done |
| 1.5 | Fix module syntax errors | Low | High | Correct brace closing | ✅ Done |
| # | Task | Effort | Impact | Details | Status |
|---|-------|--------|---------|----------|--------|
| 1.1 | Add statix hook | Low | High | Lint for Nix antipatterns | ✅ Done |
| 1.2 | Add deadnix hook | Low | High | Find dead code in Nix files | ✅ Done |
| 1.3 | Enable git-hooks on all hosts | Very Low | Medium | Add to hecuba, eetion, vm | ✅ Done |
**Implementation:**
```nix
# flake.nix
checks.${system}.pre-commit-check.hooks = {
nixfmt-rfc-style.enable = true; # ✅ Already done
statix.enable = true; # Add this
deadnix.enable = true; # Add this
};
```
### Phase 2: CI/CD Enhancements (Week 2)
**Priority: HIGH**
| # | Task | Effort | Impact | Details |
|---|-------|--------|---------|
| 2.1 | Add CI caching | Medium | High | Speed up GitHub Actions builds |
| 2.2 | Add automated flake.lock updates | Medium | Medium | Weekly scheduled updates |
| 2.3 | Add per-host CI checks | Medium | Medium | Test specific NixOS configs in CI |
**2.1 CI Caching:**
```yaml
# .github/workflows/flake-check.yaml
- uses: actions/cache@v4
with:
path: /nix/store
key: ${{ runner.os }}-nix-${{ hashFiles('**') }}
```
**2.2 Automated Updates:**
```yaml
# .github/workflows/update-flake-lock.yaml
name: "Auto update flake lock"
on:
schedule:
- cron: "0 12 * * 0" # Weekly
jobs:
update:
steps:
- uses: actions/checkout@v6
- uses: cachix/install-nix-action@v31
- run: nix flake update
- uses: peter-evans/create-pull-request@v6
```
### Phase 3: Developer Experience (Week 3)
**Priority: MEDIUM**
| # | Task | Effort | Impact | Details |
|---|-------|--------|---------|
| 3.1 | Add nil/nixd LSP | Low | Medium | Autocompletion, error highlighting |
| 3.2 | Add nix-index + comma | Low | Medium | Run any binary without `nix run` |
| 3.3 | Add nh | Low | Medium | Better CLI output for nix commands |
**3.1 LSP Setup:**
```nix
# Add to nvim config or home-manager
services.lsp.servers.nil = {
enable = true;
package = pkgs.nil;
};
```
**3.2 nix-index:**
```bash
nix-index
git clone https://github.com/nix-community/nix-index
```
### Phase 4: Utility Tools (Week 4)
**Priority: LOW**
| # | Task | Effort | Impact | Details |
|---|-------|--------|---------|
| 4.1 | Add nix-tree | Very Low | Low | Browse dependency graph |
| 4.2 | Add nix-du | Very Low | Low | Visualize GC roots |
| 4.3 | Add nix-init | Low | Low | Generate packages from URLs |
| 4.4 | Add nix-update | Low | Low | Update package versions |
### Phase 5: Structural Improvements (Future)
**Priority: LOW-MEDIUM**
| # | Task | Effort | Impact | Details |
|---|-------|--------|---------|
| 5.1 | Migrate to flake-parts | Medium-High | High | Automatic module discovery |
| 5.2 | Add treefmt-nix | Medium | Medium | Unified project formatting |
| 5.3 | Add nix-direnv | Low | Medium | Auto-load dev environments |
## 📊 Implementation Status
### Code Quality
| Feature | Status | File |
|---------|--------|-------|
| CI (GitHub Actions) | ✅ Done | `.github/workflows/flake-check.yaml` |
| Git hooks (Nix-native) | ✅ Done | `modules/git-hooks/default.nix` |
| nixfmt | ✅ Done | Enabled in hooks |
| statix | ✅ Done | Phase 1.1 complete |
| deadnix | ✅ Done | Phase 1.2 complete |
| All hosts enabled | ✅ Done | Phase 1.3 complete |
| CI caching | ⏳ Pending | Phase 2.1 |
| Auto flake updates | ⏳ Pending | Phase 2.2 |
### Hosts with Git Hooks
| Host | Status | Config |
|------|--------|--------|
| andromache | ✅ Enabled | `hosts/andromache/default.nix` |
| astyanax | ✅ Enabled | `hosts/astyanax/default.nix` |
| hecuba | ✅ Enabled | `hosts/hecuba/default.nix` |
| eetion | ✅ Enabled | `hosts/eetion/default.nix` |
| vm | ✅ Enabled | `hosts/vm/default.nix` |
### Developer Tools
| Tool | Status | Phase |
|------|--------|--------|
| nil/nixd | ⏳ Pending | 3.1 |
| nix-index | ⏳ Pending | 3.2 |
| nh | ⏳ Pending | 3.3 |
| nix-tree | ⏳ Pending | 4.1 |
| nix-du | ⏳ Pending | 4.2 |
| nix-init | ⏳ Pending | 4.3 |
| nix-update | ⏳ Pending | 4.4 |
### Structure
| Feature | Status | Phase |
|---------|--------|--------|
| flake-parts | ⏳ Pending | 5.1 |
| treefmt-nix | ⏳ Pending | 5.2 |
| nix-direnv | ⏳ Pending | 5.3 |
| .editorconfig | ✅ Done | Already added |
## 🎯 Quick Wins (Day 1)
If you want immediate value, start with:
### 1. Enable git-hooks on remaining hosts (5 minutes)
```nix
# Add to hosts/hecuba/default.nix, eetion/default.nix, vm/default.nix
imports = [
# ... existing modules
../../modules/git-hooks
];
services.git-hooks.enable = true;
```
### 2. Add statix hook (10 minutes)
```nix
# Edit flake.nix
checks.${system}.pre-commit-check.hooks = {
nixfmt-rfc-style.enable = true;
statix.enable = true; # Add this
};
```
### 3. Add deadnix hook (10 minutes)
```nix
# Edit flake.nix
checks.${system}.pre-commit-check.hooks = {
nixfmt-rfc-style.enable = true;
statix.enable = true;
deadnix.enable = true; # Add this
};
```
## 📚 References
- [CI_HOOKS_SUMMARY.md](CI_HOOKS_SUMMARY.md) - Current CI/hooks setup
- [AWESOME_NIX_PLAN.md](AWESOME_NIX_PLAN.md) - Awesome-nix integration
- [DRUPOL_INFRA_ANALYSIS.md](DRUPOL_INFRA_ANALYSIS.md) - Reference patterns
- [OPENCODE.md](OPENCODE.md) - Original tracking
## 🚀 Implementation Order
**Recommended sequence:**
1. **Phase 1** (Week 1) - Enhanced code quality
2. **Phase 2** (Week 2) - CI/CD improvements
3. **Phase 3** (Week 3) - Developer experience
4. **Phase 4** (Week 4) - Utility tools
5. **Phase 5** (Future) - Structural changes
## 🔄 Updates
As items are completed, update the status in this document and check off in:
- [AWESOME_NIX_PLAN.md](AWESOME_NIX_PLAN.md)
- [OPENCODE.md](OPENCODE.md)
- [CI_HOOKS_SUMMARY.md](CI_HOOKS_SUMMARY.md)

67
OPENCODE.md Normal file
View File

@@ -0,0 +1,67 @@
# OpenCode: Future Nix Flake Improvements
This document tracks potential improvements to the Nix flake configuration.
## 📋 Status Overview
| Category | Status |
|---------|--------|
| Code Quality | 🟡 In Progress |
| CI/CD | ✅ Baseline Done |
| Developer Experience | ⏸ Not Started |
| Utilities | ⏸ Not Started |
| Structure | ⏸ Not Started |
## ✅ Completed
### CI and Git Hooks
-**GitHub Actions CI** - `.github/workflows/flake-check.yaml`
-**Nix-native git hooks** - `modules/git-hooks/default.nix`
-**Declarative hook installation** - Auto-installs on rebuild
-**nixfmt integration** - Runs on commit and CI
-**statix integration** - Lints for Nix antipatterns
-**deadnix integration** - Finds dead code
-**.editorconfig** - Unified code style
-**Git hooks on all hosts** - Enabled on andromache, astyanax, hecuba, eetion, vm
### Deduplication
-**Created `mkNixOS` helper** - Centralized system configuration
## 📋 Pending Improvements
See [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for detailed implementation phases.
### Quick Reference
| Priority | Task | Phase |
|----------|-------|--------|
| HIGH | Add statix hook | 1.1 |
| HIGH | Add deadnix hook | 1.2 |
| HIGH | Enable git-hooks on all hosts | 1.3 |
| HIGH | Add CI caching | 2.1 |
| MEDIUM | Add automated flake.lock updates | 2.2 |
| MEDIUM | Add nil/nixd LSP | 3.1 |
| MEDIUM | Add nix-index + comma | 3.2 |
| MEDIUM | Add nh | 3.3 |
| LOW | Add utility tools (nix-tree, etc.) | 4.x |
| LOW | Migrate to flake-parts | 5.1 |
## 🎯 Next Steps
1. Review [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) for complete roadmap
2. Start with Phase 1 (Enhanced Code Quality)
3. Update this document as items are completed
## 📚 Documentation
| Document | Purpose |
|----------|---------|
| [IMPLEMENTATION_PLAN.md](IMPLEMENTATION_PLAN.md) | ✅ **Main plan** - Consolidated roadmap |
| [CI_HOOKS_SUMMARY.md](CI_HOOKS_SUMMARY.md) | Current CI/hooks setup |
| [AWESOME_NIX_PLAN.md](AWESOME_NIX_PLAN.md) | Awesome-nix integration details |
| [DRUPOL_INFRA_ANALYSIS.md](DRUPOL_INFRA_ANALYSIS.md) | Reference patterns |
## 🔗 Links
- [awesome-nix](https://github.com/nix-community/awesome-nix)
- [git-hooks.nix](https://github.com/cachix/git-hooks.nix)
- [drupol/infra](https://github.com/drupol/infra)

130
SIMPLE_HOOKS.md Normal file
View File

@@ -0,0 +1,130 @@
# Git Hooks - Simple Declarative Setup
## Concept
Hooks are defined in Nix (`flake.nix`) and installed by running `nix flake check` once.
**No systemd services, no activation scripts, no complexity.**
## How It Works
### 1. Hooks Defined in Nix
`flake.nix`:
```nix
checks.${system}.pre-commit-check = git-hooks.lib.${system}.run {
src = ./.;
hooks = {
nixfmt.enable = true;
statix.enable = true;
deadnix.enable = true;
};
};
```
### 2. Installation
Run once on each host:
```bash
nix flake check
```
This installs the hooks and creates `.git/hooks/pre-commit`.
### 3. Automatic
- ✅ Hooks run on every `git commit`
- ✅ CI runs `nix flake check` automatically
- ✅ Hooks checked on every push/PR
## Usage
### Install Hooks (One-Time Per Host)
```bash
# From the flake directory
nix flake check
# You should see hooks installing
```
### Verify Installation
```bash
ls -la .git/hooks/
```
Should show `pre-commit` (and potentially other hooks).
### Test Hooks
```bash
# Create a file with bad formatting
echo "broken { }" > test.nix
# Try to commit (should fail)
git add test.nix
git commit -m "test"
# Clean up
rm test.nix
```
## What's Declarative
| Aspect | Status |
|---------|--------|
| Hook definitions | ✅ Yes - in `flake.nix` |
| Hook installation | ✅ Yes - via `nix flake check` |
| CI integration | ✅ Yes - via `nix flake check` in workflows |
| Local git hooks | ✅ Yes - run automatically on commit |
| No systemd services | ✅ Removed - too complex |
| No activation scripts | ✅ Removed - unnecessary |
| One-time setup | ✅ Yes - run `nix flake check` once per host |
## Files
| File | Status |
|------|--------|
| `flake.nix` | ✅ Hook definitions |
| `.github/workflows/flake-check.yaml` | ✅ CI uses `nix flake check` |
| `.editorconfig` | ✅ Code style |
| `modules/git-hooks/default.nix` | ❌ **DELETED** - Not needed |
| `hosts/*/default.nix` | ✅ **CLEANED** - Removed git-hooks |
## Next Steps
1. Test locally:
```bash
nix flake check
ls -la .git/hooks/
echo "broken { }" > test.nix
git add test.nix
git commit -m "test" # Should fail
rm test.nix
```
2. Commit changes:
```bash
git add .
git commit -m "Simplify: Git hooks via nix flake check (no systemd, no activation)"
git push
```
3. Run `nix flake check` on each host when you next rebuild
## This Is The Right Approach Because
| Issue | Overcomplicated Solution | Simple Solution |
|-------|----------------------|----------------|
| Declarative | ❌ Systemd service is separate from Nix | ✅ Hooks in `flake.nix`, install via `nix flake check` |
| Simple | ❌ Multiple layers (activation, systemd) | ✅ One command: `nix flake check` |
| Idempotent | ❌ Runs on every rebuild | ✅ Idempotent - run once per host |
| Reproducible | ❌ Depends on systemd state | ✅ Pure Nix |
## Summary
**The simplest declarative approach:**
1. Define hooks in `flake.nix` ✅ Already done
2. Run `nix flake check` once per host ✅ To do
3. That's it! Hooks work automatically ✅ Declarative
No systemd services. No activation scripts. No complexity.

9
deploy/README.md Normal file
View File

@@ -0,0 +1,9 @@
# `colmena` deployments
* tags: `local`, `cloud`
* deployments can be made from `astyanax` and `andromache` hosts
## References
- [docs: `colmena`](https://colmena.cli.rs/)
- [repo: `colmena`](https://github.com/zhaofengli/colmena)

32
deploy/colmena.nix Normal file
View File

@@ -0,0 +1,32 @@
{
self,
inputs,
}:
let
mkNode = hostname: tags: {
imports = [ ../hosts/${hostname} ];
deployment = {
targetHost = self.nixosConfigurations.${hostname}.config.ssh.publicHostname;
targetUser = self.nixosConfigurations.${hostname}.config.ssh.username;
buildOnTarget = builtins.any (t: t != "local") tags;
inherit tags;
};
};
in
inputs.colmena.lib.makeHive {
meta = {
nixpkgs = import inputs.nixpkgs {
system = "x86_64-linux";
};
nodeNixpkgs = builtins.mapAttrs (_: v: v.pkgs) self.nixosConfigurations;
nodeSpecialArgs = builtins.mapAttrs (_: v: v._module.specialArgs or { }) self.nixosConfigurations;
};
astyanax = mkNode "astyanax" [ "local" ];
andromache = mkNode "andromache" [ "local" ];
vm = mkNode "vm" [ "local" ];
hecuba = mkNode "hecuba" [ "cloud" ];
eetion = mkNode "eetion" [ "arm" ];
}

View File

@@ -4,16 +4,3 @@
# Set NeoVim as default editor # Set NeoVim as default editor
export EDITOR=nvim export EDITOR=nvim
export SUDO_EDITOR="$EDITOR" export SUDO_EDITOR="$EDITOR"
declare -A -r EDITOR_CONFIGS=(
["nvim"]="$HOME/.config/nvim/init.lua"
["vim"]="$HOME/.vimrc"
)
edit_editor_config() {
for editor in "${!EDITOR_CONFIGS[@]}"; do
if [ "$EDITOR" = "$editor" ]; then
$EDITOR "${EDITOR_CONFIGS[$editor]}"
fi
done
}

View File

@@ -8,19 +8,24 @@ Pomodoro timer
- Notification on break finish - Notification on break finish
""" """
import os
import atexit import atexit
import os
from argparse import ArgumentParser from argparse import ArgumentParser
from time import sleep from time import sleep
from plyer import notification from plyer import notification
POMO_PATH = os.path.join(os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")), "pomo") POMO_PATH = os.path.join(
os.getenv("XDG_DATA_HOME", os.path.expanduser("~/.local/share")), "pomo"
)
@atexit.register @atexit.register
def clear(): def clear():
if os.path.exists(POMO_PATH): if os.path.exists(POMO_PATH):
os.remove(POMO_PATH) os.remove(POMO_PATH)
def format_mins_secs(mins, secs): def format_mins_secs(mins, secs):
return f"{mins:02d}:{secs:02d}" return f"{mins:02d}:{secs:02d}"
@@ -34,6 +39,7 @@ def make_countdown():
os.system(f'echo -n "{time_str}" > {POMO_PATH}') os.system(f'echo -n "{time_str}" > {POMO_PATH}')
sleep(1) sleep(1)
duration -= 1 duration -= 1
return countdown return countdown
@@ -58,21 +64,23 @@ def main(args):
def handle_signal(signal, frame): def handle_signal(signal, frame):
# Wait for clear to finish # Wait for clear to finish
clear() clear()
print('Exiting') print("Exiting")
exit(0) exit(0)
if __name__ == '__main__': if __name__ == "__main__":
parser = ArgumentParser() parser = ArgumentParser()
parser.add_argument('-w', '--work-duration', type=int, parser.add_argument(
help='Session duration', default=25) "-w", "--work-duration", type=int, help="Session duration", default=25
parser.add_argument('-b', '--break-duration', type=int, )
help='Break duration', default=5) parser.add_argument(
parser.add_argument('-r', '--repeats', type=int, "-b", "--break-duration", type=int, help="Break duration", default=5
help='Numer of sessions', default=1) )
parser.add_argument('-c', '--clear', action='store_true', parser.add_argument(
help='Clear timer') "-r", "--repeats", type=int, help="Numer of sessions", default=1
)
parser.add_argument("-c", "--clear", action="store_true", help="Clear timer")
args = parser.parse_args() args = parser.parse_args()

View File

@@ -2,8 +2,8 @@
session="r5rs" session="r5rs"
tmux attach-session -t $session || tmux new-session -s $session \; \ tmux attach-session -t "$session" || tmux new-session -s "$session" \; \
split-window -h -t $session \; \ split-window -h -t $session \; \
send-keys -t 0 "vim" C-m \; \ send-keys -t 1 "nvim -c \"set ft=scheme\"" C-m \; \
send-keys -t 1 "plt-r5rs --no-prim" C-m \; \ send-keys -t 2 "plt-r5rs --no-prim" C-m \; \
select-pane -t 0 select-pane -t 1

View File

@@ -22,4 +22,5 @@ restic -r "$RESTIC_REPOSITORY:$HOSTNAME" backup \
--one-file-system \ --one-file-system \
--files-from="$HOME/.resticinclude" \ --files-from="$HOME/.resticinclude" \
--exclude-file="$HOME/.resticexclude" \ --exclude-file="$HOME/.resticexclude" \
--exclude-if-present=".nobackup" \
--verbose=3 --verbose=3

View File

@@ -1,12 +1,12 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys
import subprocess import subprocess
import sys
DEFAULT_TEMPERATURE = 3500 DEFAULT_TEMPERATURE = 3500
try: try:
with open('/tmp/temperature', 'r') as temp_file: with open("/tmp/temperature", "r") as temp_file:
current_temperature = int(temp_file.read()) current_temperature = int(temp_file.read())
except FileNotFoundError: except FileNotFoundError:
current_temperature = DEFAULT_TEMPERATURE current_temperature = DEFAULT_TEMPERATURE
@@ -16,7 +16,8 @@ if len(sys.argv) == 1:
print(current_temperature) print(current_temperature)
sys.exit(0) sys.exit(0)
elif len(sys.argv) != 2: elif len(sys.argv) != 2:
print(""" print(
"""
Usage: Usage:
screen-temperature screen-temperature
@@ -27,7 +28,8 @@ Usage:
screen-temperature <+|-><temperature> screen-temperature <+|-><temperature>
increase or decrease screen temperature by <temperature> increase or decrease screen temperature by <temperature>
""") """
)
sys.exit(1) sys.exit(1)
temperature_change = sys.argv[1] temperature_change = sys.argv[1]
@@ -41,11 +43,10 @@ else:
try: try:
subprocess.run(["redshift", "-O", str(new_temperature), "-P"], check=True) subprocess.run(["redshift", "-O", str(new_temperature), "-P"], check=True)
with open('/tmp/temperature', 'w') as temp_file: with open("/tmp/temperature", "w") as temp_file:
temp_file.write(str(new_temperature) + '\n') temp_file.write(str(new_temperature) + "\n")
# Send notification # Send notification
subprocess.run( subprocess.run(["notify-send", str(new_temperature) + "K"])
["notify-send", str(new_temperature) + "K"])
except subprocess.CalledProcessError: except subprocess.CalledProcessError:
print("Error: could not set screen temperature.") print("Error: could not set screen temperature.")
sys.exit(1) sys.exit(1)

View File

@@ -1,37 +0,0 @@
#!/usr/bin/env bash
gsettings set org.gnome.desktop.background primary-color "#555555"
gsettings set org.gnome.desktop.wm.preferences workspace-names "['sh', 'www', 'dev', 'info', 'etc']"
gsettings set org.gnome.desktop.wm.keybindings close "['<Shift><Super>Delete']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications "['<Super>j']"
gsettings set org.gnome.desktop.wm.keybindings switch-applications-backward "['<Super>k']"
gsettings set org.gnome.shell.keybindings toggle-application-view "['<Super>p']"
gsettings set org.gnome.mutter center-new-windows true
gsettings set org.gnome.shell.keybindings toggle-quick-settings []
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-1 "['<Super>a']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-2 "['<Super>s']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-3 "['<Super>d']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-4 "['<Super>f']"
gsettings set org.gnome.desktop.wm.keybindings switch-to-workspace-5 "['<Super>g']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-1 "['<Super><Shift>a']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-2 "['<Super><Shift>s']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-3 "['<Super><Shift>d']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-4 "['<Super><Shift>f']"
gsettings set org.gnome.desktop.wm.keybindings move-to-workspace-5 "['<Super><Shift>g']"
gsettings set org.gnome.settings-daemon.plugins.media-keys custom-keybindings "['/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/']"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ name "Kitty"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ command "kitty"
gsettings set org.gnome.settings-daemon.plugins.media-keys.custom-keybinding:/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/ binding "<Shift><Super>Return"
gsettings set org.gnome.shell.keybindings screenshot "['Print']"
gsettings set org.gnome.desktop.wm.preferences num-workspaces "5"
gsettings set org.gnome.mutter dynamic-workspaces "false"
gsettings set org.gnome.shell.extensions.window-list display-all-workspaces "true"
gsettings set org.gnome.shell.app-switcher current-workspace-only "true"
gsettings set org.gnome.login-screen logo ''
gsettings set org.gnome.shell favorite-apps "['firefox-developer-edition.desktop']"

View File

@@ -1,7 +1,9 @@
#!/usr/bin/env bash #!/usr/bin/env bash
current_zettel_path="$ZK_PATH/$(cat "$ZK_PATH/current-zettel.txt")"
if [ "$TERM_PROGRAM" = tmux ]; then if [ "$TERM_PROGRAM" = tmux ]; then
cd ~/.zk && $EDITOR "$(cat ~/.zk/current-zettel.txt)" cd "$ZK_PATH" && $EDITOR "$current_zettel_path"
else else
echo 'Not in tmux' echo 'Not in tmux'
echo 'Choose an option:' echo 'Choose an option:'
@@ -18,12 +20,12 @@ else
else else
# Create session with a window named 'zk' and start nvim # Create session with a window named 'zk' and start nvim
tmux new-session -s zk -n zk -d tmux new-session -s zk -n zk -d
tmux send-keys -t zk:zk "cd ~/.zk && $EDITOR \"\$(cat ~/.zk/current-zettel.txt)\"" Enter tmux send-keys -t zk:zk "cd $ZK_PATH && $EDITOR $current_zettel_path" Enter
tmux attach -t zk tmux attach -t zk
fi fi
;; ;;
2) 2)
cd ~/.zk && $EDITOR "$(cat ~/.zk/current-zettel.txt)" cd "$ZK_PATH" && $EDITOR "$current_zettel_path"
;; ;;
*) *)
echo 'Not opening Zettelkasten' echo 'Not opening Zettelkasten'

View File

@@ -56,7 +56,7 @@ hide_window_decorations yes
#: Tab bar {{{ #: Tab bar {{{
tab_bar_edge top tab_bar_edge bottom
tab_bar_style powerline tab_bar_style powerline
tab_bar_min_tabs 1 tab_bar_min_tabs 1
tab_powerline_style slanted tab_powerline_style slanted
@@ -136,7 +136,7 @@ map f5 goto_tab 5
map f6 goto_tab 6 map f6 goto_tab 6
map f7 goto_tab 7 map f7 goto_tab 7
map f8 goto_tab 8 map f8 goto_tab 8
map kitty_mod+c new_tab # map kitty_mod+c new_tab # FIXME: conflict with 'copy'
map cmd+t map cmd+t
map kitty_mod+q map kitty_mod+q
map cmd+w map cmd+w

View File

@@ -0,0 +1,61 @@
require("claude-code").setup({
-- Terminal window settings
window = {
split_ratio = 0.3, -- Percentage of screen for the terminal window (height for horizontal, width for vertical splits)
position = "vertical", -- Position of the window: "botright", "topleft", "vertical", "float", etc.
enter_insert = true, -- Whether to enter insert mode when opening Claude Code
hide_numbers = true, -- Hide line numbers in the terminal window
hide_signcolumn = true, -- Hide the sign column in the terminal window
-- Floating window configuration (only applies when position = "float")
float = {
width = "80%", -- Width: number of columns or percentage string
height = "80%", -- Height: number of rows or percentage string
row = "center", -- Row position: number, "center", or percentage string
col = "center", -- Column position: number, "center", or percentage string
relative = "editor", -- Relative to: "editor" or "cursor"
border = "rounded", -- Border style: "none", "single", "double", "rounded", "solid", "shadow"
},
},
-- File refresh settings
refresh = {
enable = true, -- Enable file change detection
updatetime = 100, -- updatetime when Claude Code is active (milliseconds)
timer_interval = 1000, -- How often to check for file changes (milliseconds)
show_notifications = true, -- Show notification when files are reloaded
},
-- Git project settings
git = {
use_git_root = true, -- Set CWD to git root when opening Claude Code (if in git project)
},
-- Shell-specific settings
shell = {
separator = "&&", -- Command separator used in shell commands
pushd_cmd = "pushd", -- Command to push directory onto stack (e.g., 'pushd' for bash/zsh, 'enter' for nushell)
popd_cmd = "popd", -- Command to pop directory from stack (e.g., 'popd' for bash/zsh, 'exit' for nushell)
},
-- Command settings
command = "claude", -- Command used to launch Claude Code
-- Command variants
command_variants = {
-- Conversation management
continue = "--continue", -- Resume the most recent conversation
resume = "--resume", -- Display an interactive conversation picker
-- Output options
verbose = "--verbose", -- Enable verbose logging with full turn-by-turn output
},
-- Keymaps
keymaps = {
toggle = {
normal = "<C-,>", -- Normal mode keymap for toggling Claude Code, false to disable
terminal = "<C-,>", -- Terminal mode keymap for toggling Claude Code, false to disable
variants = {
continue = "<leader>cC", -- Normal mode keymap for Claude Code with continue flag
verbose = "<leader>cV", -- Normal mode keymap for Claude Code with verbose flag
},
},
window_navigation = true, -- Enable window navigation keymaps (<C-h/j/k/l>)
scrolling = true, -- Enable scrolling keymaps (<C-f/b>) for page up/down
},
})

View File

@@ -1,16 +1,22 @@
require("codecompanion").setup({ require("codecompanion").setup({
extensions = { ignore_warnings = true,
mcphub = {
callback = "mcphub.extensions.codecompanion",
opts = {
make_vars = true,
make_slash_commands = true,
show_result_in_chat = true
}
}
},
strategies = { strategies = {
chat = { adapter = "openai" }, chat = { adapter = "openai" },
inline = { adapter = "openai" }, inline = { adapter = "openai" },
}, },
}) })
-- Load mcphub extension after codecompanion is initialized
-- and ensure the config structure exists
local ok, cc_config = pcall(require, "codecompanion.config")
if ok then
cc_config.interactions = cc_config.interactions or {}
cc_config.interactions.chat = cc_config.interactions.chat or {}
cc_config.interactions.chat.tools = cc_config.interactions.chat.tools or {}
require("mcphub.extensions.codecompanion").setup({
make_vars = true,
make_slash_commands = true,
show_result_in_chat = true,
})
end

View File

@@ -13,14 +13,15 @@ require("conform").setup({
gdscript = { "gdformat" }, gdscript = { "gdformat" },
haskell = { "ormolu" }, haskell = { "ormolu" },
html = { "prettierd", "prettier", stop_after_first = true }, html = { "prettierd", "prettier", stop_after_first = true },
lua = { "stylua" }, -- configured in stylua.toml
markdown = { "prettierd", "prettier", stop_after_first = true },
nix = { "nixfmt" },
javascript = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true }, javascript = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true },
javascriptreact = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true }, javascriptreact = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true },
json = { "prettierd", "prettier", stop_after_first = true }, json = { "prettierd", "prettier", stop_after_first = true },
jsonc = { "prettierd", "prettier", stop_after_first = true }, jsonc = { "prettierd", "prettier", stop_after_first = true },
lua = { "stylua" }, -- configured in stylua.toml
markdown = { "prettierd", "prettier", stop_after_first = true },
nix = { "nixfmt" },
python = { "isort", "black" }, python = { "isort", "black" },
rust = { "rustfmt", lsp_fallback = "fallback" },
svelte = { "eslint_d", "prettierd", "prettier", stop_after_first = true }, svelte = { "eslint_d", "prettierd", "prettier", stop_after_first = true },
typescript = { "eslint_d", "prettierd", "prettier", stop_after_first = true }, typescript = { "eslint_d", "prettierd", "prettier", stop_after_first = true },
typescriptreact = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true }, typescriptreact = { "eslint_d", "eslint", "prettierd", "prettier", stop_after_first = true },

View File

@@ -0,0 +1 @@
require("fidget").setup()

View File

@@ -11,6 +11,6 @@ vim.keymap.set("n", "<leader>fd", fzf.diagnostics_workspace)
vim.keymap.set("n", "<leader>fhe", fzf.help_tags) vim.keymap.set("n", "<leader>fhe", fzf.help_tags)
vim.keymap.set("n", "<leader>fhi", fzf.search_history) vim.keymap.set("n", "<leader>fhi", fzf.search_history)
vim.keymap.set("n", "<leader>fma", fzf.marks) vim.keymap.set("n", "<leader>fma", fzf.marks)
vim.keymap.set("n", "<leader>fma", fzf.man_pages) vim.keymap.set("n", "<leader>fmp", fzf.man_pages)
vim.keymap.set("i", "<c-f>", fzf.complete_path) vim.keymap.set("i", "<c-f>", fzf.complete_path)

View File

@@ -1,8 +1,5 @@
require("neodev").setup() -- should setup before lspconfig require("neodev").setup() -- should setup before lspconfig
-- vim.g.coq_settings = { auto_start = 'shut-up' }
-- local capabilities = coq.lsp_ensure_capabilities()
local cmp_nvim_lsp = require("cmp_nvim_lsp") local cmp_nvim_lsp = require("cmp_nvim_lsp")
local capabilities = cmp_nvim_lsp.default_capabilities() local capabilities = cmp_nvim_lsp.default_capabilities()
@@ -64,8 +61,30 @@ local servers = {
Lua = {}, Lua = {},
}, },
}, },
-- marksman = {}, nixd = {
nixd = {}, settings = {
nixd = {
nixpkgs = {
expr = "import <nixpkgs> { }",
expr = 'import (builtins.getFlake ("git+file://" + toString ../../../../../.)).inputs.nixpkgs { }',
},
},
options = {
nixos = {
expr = '(builtins.getFlake ("git+file://" + toString ../../../../../.)).nixosConfigurations."'
.. vim.fn.hostname()
.. '".options',
},
home_manager = {
expr = '(builtins.getFlake ("git+file://" + toString ../../../../../.)).homeConfigurations."'
.. vim.fn.expand("$USER")
.. "@"
.. vim.fn.hostname()
.. '".options',
},
},
},
},
pyright = {}, pyright = {},
-- tsserver = {}, -- tsserver = {},
svelte = { svelte = {

View File

@@ -0,0 +1,9 @@
require("m_taskwarrior_d").setup()
vim.api.nvim_create_autocmd({ "BufEnter", "BufWritePost" }, {
group = vim.api.nvim_create_augroup("TWTask", { clear = true }),
pattern = "*.md",
callback = function()
vim.cmd("TWSyncTasks")
end,
})

View File

@@ -2,12 +2,15 @@ local ts = require("treesj")
local vim = vim local vim = vim
local keymap = vim.keymap local keymap = vim.keymap
local opt = vim.opt local opt = vim.opt
local treesitter_configs = require("nvim-treesitter.configs") local treesitter = require("nvim-treesitter")
treesitter_configs.setup({ local nixCatsUtils = require("nixCatsUtils")
local is_nix = nixCatsUtils.isNixCats
treesitter.setup({
-- Basically added what I might need from the docs -- Basically added what I might need from the docs
-- <https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#supported-languages> -- <https://github.com/nvim-treesitter/nvim-treesitter?tab=readme-ov-file#supported-languages>
ensure_installed = { ensure_installed = is_nix and {} or {
"awk", "awk",
"bash", "bash",
"bibtex", "bibtex",
@@ -86,7 +89,7 @@ treesitter_configs.setup({
enable = true, enable = true,
}, },
sync_install = false, sync_install = false,
auto_install = true, auto_install = not is_nix,
ignore_install = {}, ignore_install = {},
modules = {}, modules = {},
textobjects = { textobjects = {

View File

@@ -1,12 +1,52 @@
{ {
"nodes": { "nodes": {
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"mcp-hub",
"nixpkgs"
]
},
"locked": {
"lastModified": 1743550720,
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"mcp-hub": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1755841689,
"narHash": "sha256-KakvXZf0vjdqzyT+LsAKHEr4GLICGXPmxl1hZ3tI7Yg=",
"owner": "ravitemer",
"repo": "mcp-hub",
"rev": "9c7670a4c341ed3cf738a6242c0fde1cea40bccf",
"type": "github"
},
"original": {
"owner": "ravitemer",
"repo": "mcp-hub",
"type": "github"
}
},
"nixCats": { "nixCats": {
"locked": { "locked": {
"lastModified": 1763330129, "lastModified": 1769578476,
"narHash": "sha256-KbOeWIF52SV53BOeETGO2C5ewaV2Ex9iaXH7G72gOr8=", "narHash": "sha256-4+KbiBcC6hQ3sh0UbPXjy6TOfLh9yhskRlfPzyZ2FH4=",
"owner": "BirdeeHub", "owner": "BirdeeHub",
"repo": "nixCats-nvim", "repo": "nixCats-nvim",
"rev": "c81551ed87db2aefab30a12cf7425ff94dc0ad64", "rev": "48f8be4bdafccfa19ceaaf08071a15eca36fdb1d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -17,11 +57,27 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1763464769, "lastModified": 1743689281,
"narHash": "sha256-AJHrsT7VoeQzErpBRlLJM1SODcaayp0joAoEA35yiwM=", "narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2bfc080955153be0be56724be6fa5477b4eefabb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1769740369,
"narHash": "sha256-xKPyJoMoXfXpDM5DFDZDsi9PHArf2k5BJjvReYXoFpM=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6f374686605df381de8541c072038472a5ea2e2d", "rev": "6308c3b21396534d8aaeac46179c14c439a89b8a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -47,30 +103,14 @@
"type": "github" "type": "github"
} }
}, },
"plugins-crazy-node-movement": {
"flake": false,
"locked": {
"lastModified": 1693654676,
"narHash": "sha256-hQcQEp39zFN2zphMfcr97yRVcuHhBsSkzKO7XNloDpQ=",
"owner": "theHamsta",
"repo": "crazy-node-movement",
"rev": "d5cf01cc44c5715501d3d6fe439af7c8b7fa5df2",
"type": "github"
},
"original": {
"owner": "theHamsta",
"repo": "crazy-node-movement",
"type": "github"
}
},
"plugins-helm-ls-nvim": { "plugins-helm-ls-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1761915179, "lastModified": 1768584652,
"narHash": "sha256-W9NRa84l5Cs62OsDeqb+LMxk8oYjhVBCB3o3UmE9a0I=", "narHash": "sha256-jnMc87OjURNcqsva0npYgVyUrWc5C6L7yHpNvt9eSmg=",
"owner": "qvalentin", "owner": "qvalentin",
"repo": "helm-ls.nvim", "repo": "helm-ls.nvim",
"rev": "d6f3a8d4ad59b4f54cd734267dfb5411679ea608", "rev": "f0b9a1723890971a6d84890b50dbf5f40974ea1b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -79,14 +119,30 @@
"type": "github" "type": "github"
} }
}, },
"plugins-m-taskwarrior-d-nvim": {
"flake": false,
"locked": {
"lastModified": 1767960157,
"narHash": "sha256-ov0qi4LhIlwqrBzSbTJ6APC5qjl2d/vlKWJfW5ZiDrg=",
"owner": "huantrinh1802",
"repo": "m_taskwarrior_d.nvim",
"rev": "107247387cd81823046bc2b8e71150c8edf041d3",
"type": "github"
},
"original": {
"owner": "huantrinh1802",
"repo": "m_taskwarrior_d.nvim",
"type": "github"
}
},
"plugins-mcphub-nvim": { "plugins-mcphub-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1759035242, "lastModified": 1768730387,
"narHash": "sha256-I6EbgY/2sAdtrxtmH0qbAAQvMCHhOsfolJfblV0fXOk=", "narHash": "sha256-g9tPvjThz6EUk7zcY7lL+YH4lrT4x3FJ6jrNMHA8PAE=",
"owner": "ravitemer", "owner": "ravitemer",
"repo": "mcphub.nvim", "repo": "mcphub.nvim",
"rev": "8ff40b5edc649959bb7e89d25ae18e055554859a", "rev": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -130,11 +186,11 @@
"plugins-tailwind-fold-nvim": { "plugins-tailwind-fold-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1752559116, "lastModified": 1766077142,
"narHash": "sha256-8uefZIVsn9USEd6FyiO3m3TRKAS/vigU4t9Tk5ijd3c=", "narHash": "sha256-SwcDLlygXUSV/dytPXA5Y45OpUhjnExc8SZg5a8MZ2k=",
"owner": "razak17", "owner": "razak17",
"repo": "tailwind-fold.nvim", "repo": "tailwind-fold.nvim",
"rev": "d9e7ca11691d252b35795726dff087bf013b2ebf", "rev": "e2ba5ee1ca9b74208709fe9d7314b8aa753b26a7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -145,11 +201,12 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"mcp-hub": "mcp-hub",
"nixCats": "nixCats", "nixCats": "nixCats",
"nixpkgs": "nixpkgs", "nixpkgs": "nixpkgs_2",
"plugins-beancount-nvim": "plugins-beancount-nvim", "plugins-beancount-nvim": "plugins-beancount-nvim",
"plugins-crazy-node-movement": "plugins-crazy-node-movement",
"plugins-helm-ls-nvim": "plugins-helm-ls-nvim", "plugins-helm-ls-nvim": "plugins-helm-ls-nvim",
"plugins-m-taskwarrior-d-nvim": "plugins-m-taskwarrior-d-nvim",
"plugins-mcphub-nvim": "plugins-mcphub-nvim", "plugins-mcphub-nvim": "plugins-mcphub-nvim",
"plugins-nvimkit-nvim": "plugins-nvimkit-nvim", "plugins-nvimkit-nvim": "plugins-nvimkit-nvim",
"plugins-shipwright-nvim": "plugins-shipwright-nvim", "plugins-shipwright-nvim": "plugins-shipwright-nvim",

View File

@@ -2,13 +2,14 @@
inputs = { inputs = {
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixCats.url = "github:BirdeeHub/nixCats-nvim"; nixCats.url = "github:BirdeeHub/nixCats-nvim";
mcp-hub.url = "github:ravitemer/mcp-hub";
plugins-shipwright-nvim = { plugins-shipwright-nvim = {
url = "github:rktjmp/shipwright.nvim"; url = "github:rktjmp/shipwright.nvim";
flake = false; flake = false;
}; };
plugins-crazy-node-movement = { plugins-m-taskwarrior-d-nvim = {
url = "github:theHamsta/crazy-node-movement"; url = "github:huantrinh1802/m_taskwarrior_d.nvim";
flake = false; flake = false;
}; };
plugins-beancount-nvim = { plugins-beancount-nvim = {
@@ -47,8 +48,11 @@
forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all; forEachSystem = utils.eachSystem nixpkgs.lib.platforms.all;
extra_pkg_config = { }; extra_pkg_config = { };
dependencyOverlays = [ mkDependencyOverlays = system: [
(utils.standardPluginOverlay inputs) (utils.standardPluginOverlay inputs)
(final: prev: {
mcp-hub = inputs.mcp-hub.packages.${system}.default;
})
]; ];
categoryDefinitions = categoryDefinitions =
@@ -62,18 +66,33 @@
black black
clang clang
clang-tools clang-tools
delta
emmet-language-server
eslint_d
fd
gawk gawk
gdtoolkit_4 gdtoolkit_4
hadolint
helm-ls
isort isort
tree-sitter lua-language-server
ormolu mcp-hub
nodePackages.prettier
nixd nixd
nixfmt nixfmt
nodePackages.prettier
nodePackages.typescript-language-server
ormolu
prettierd prettierd
rust-analyzer
rustfmt
shellcheck-minimal shellcheck-minimal
stylelint
stylua stylua
tree-sitter
vscode-langservers-extracted vscode-langservers-extracted
vtsls
yaml-language-server
yamllint
]; ];
}; };
@@ -123,7 +142,6 @@
pkgs.neovimPlugins.shipwright-nvim pkgs.neovimPlugins.shipwright-nvim
lush-nvim lush-nvim
zenbones-nvim zenbones-nvim
pkgs.neovimPlugins.crazy-node-movement
nvim-treesitter.withAllGrammars nvim-treesitter.withAllGrammars
nvim-treesitter-textobjects nvim-treesitter-textobjects
# nvim-treesitter-context # nvim-treesitter-context
@@ -143,7 +161,11 @@
copilot-lua copilot-lua
copilot-cmp copilot-cmp
pkgs.neovimPlugins.helm-ls-nvim pkgs.neovimPlugins.helm-ls-nvim
pkgs.vimPlugins.kitty-scrollback-nvim kitty-scrollback-nvim
fidget-nvim
rustaceanvim
pkgs.neovimPlugins.m-taskwarrior-d-nvim
claude-code-nvim
]; ];
}; };
@@ -160,9 +182,7 @@
}; };
packageDefinitions = { packageDefinitions = {
nvim = nvim = _: {
{ ... }:
{
settings = { settings = {
suffix-path = true; suffix-path = true;
suffix-LD = true; suffix-LD = true;
@@ -180,6 +200,7 @@
forEachSystem ( forEachSystem (
system: system:
let let
dependencyOverlays = mkDependencyOverlays system;
nixCatsBuilder = utils.baseBuilder luaPath { nixCatsBuilder = utils.baseBuilder luaPath {
inherit inherit
nixpkgs nixpkgs
@@ -199,7 +220,7 @@
name = defaultPackageName; name = defaultPackageName;
packages = [ defaultPackage ]; packages = [ defaultPackage ];
inputsFrom = [ ]; inputsFrom = [ ];
shellHook = ''''; shellHook = "";
}; };
}; };
@@ -211,31 +232,32 @@
moduleNamespace = [ defaultPackageName ]; moduleNamespace = [ defaultPackageName ];
inherit inherit
defaultPackageName defaultPackageName
dependencyOverlays
luaPath luaPath
categoryDefinitions categoryDefinitions
packageDefinitions packageDefinitions
extra_pkg_config extra_pkg_config
nixpkgs nixpkgs
; ;
dependencyOverlays = mkDependencyOverlays;
}; };
homeModule = utils.mkHomeModules { homeModule = utils.mkHomeModules {
moduleNamespace = [ defaultPackageName ]; moduleNamespace = [ defaultPackageName ];
inherit inherit
defaultPackageName defaultPackageName
dependencyOverlays
luaPath luaPath
categoryDefinitions categoryDefinitions
packageDefinitions packageDefinitions
extra_pkg_config extra_pkg_config
nixpkgs nixpkgs
; ;
dependencyOverlays = mkDependencyOverlays;
}; };
in in
{ {
overlays = utils.makeOverlays luaPath { overlays = utils.makeOverlays luaPath {
inherit nixpkgs dependencyOverlays extra_pkg_config; inherit nixpkgs extra_pkg_config;
dependencyOverlays = mkDependencyOverlays;
} categoryDefinitions packageDefinitions defaultPackageName; } categoryDefinitions packageDefinitions defaultPackageName;
nixosModules.default = nixosModule; nixosModules.default = nixosModule;

View File

@@ -1,10 +1,7 @@
require("nixCatsUtils").setup({ non_nix_value = true }) -- https://github.com/BirdeeHub/nixCats-nvim/blob/77dffad8235eb77684fcb7599487c8e9f23d5b8f/templates/example/init.lua require("nixCatsUtils").setup({ non_nix_value = true }) -- https://github.com/BirdeeHub/nixCats-nvim/blob/77dffad8235eb77684fcb7599487c8e9f23d5b8f/templates/example/init.lua
vim.cmd([[ vim.opt.termguicolors = true
set termguicolors vim.api.nvim_set_hl(0, "Normal", { ctermbg = "NONE", bg = "NONE" })
set bg=light
hi Normal ctermbg=none guibg=NONE
]])
require("base") require("base")
require("cursor") require("cursor")
@@ -22,7 +19,5 @@ require("utils")
require("zk") require("zk")
require("reload") require("reload")
require("paq-setup") -- when not on nixCats
vim.opt.background = "dark" vim.opt.background = "dark"
vim.opt.laststatus = 3 vim.opt.laststatus = 3

View File

@@ -43,4 +43,5 @@ require("nixCatsUtils.catPacker").setup({
{ "zbirenbaum/copilot-cmp" }, { "zbirenbaum/copilot-cmp" },
{ "qvalentin/helm-ls.nvim", ft = "helm" }, { "qvalentin/helm-ls.nvim", ft = "helm" },
{ "mikesmithgh/kitty-scrollback.nvim" }, { "mikesmithgh/kitty-scrollback.nvim" },
{ "greggh/claude-code.nvim" },
}) })

View File

@@ -39,10 +39,22 @@ bind-key -T root F7 select-window -t 7
bind-key -T root F8 select-window -t 8 bind-key -T root F8 select-window -t 8
bind-key -T root F9 select-window -t 9 bind-key -T root F9 select-window -t 9
# bind-key j command-prompt -p "join pane from:" "join-pane -s '%%'"
# bind-key s command-prompt -p "send pane to:" "join-pane -t '%%'"
bind-key -T root S-F1 join-pane -s :1
bind-key -T root S-F2 join-pane -s :2
bind-key -T root S-F3 join-pane -s :3
bind-key -T root S-F4 join-pane -s :4
bind-key -T root S-F5 join-pane -s :5
bind-key -T root S-F6 join-pane -s :6
bind-key -T root S-F7 join-pane -s :7
bind-key -T root S-F8 join-pane -s :8
bind-key -T root S-F9 join-pane -s :9
# 1-based indexing makes most sense for keyboard layouts (where number row start at 1) # 1-based indexing makes most sense for keyboard layouts (where number row start at 1)
set -g base-index 1 set -g base-index 1
set -g pane-base-index 1 set -g pane-base-index 1
setw -g automatic-rename
# statusbar # statusbar
set -g status-position top set -g status-position top
@@ -53,7 +65,7 @@ set -g status-left "#[bg=colour235,fg=colour255] #S #[fg=colour235,bg=default]
set -g status-right "" set -g status-right ""
%else %else
set -g status-left '#h ' set -g status-left '#h '
set -g status-right '#(uptime | cut -f 4-5 -d " " | cut -f 1 -d ",") %a%l:%M:%S %p %Y-%m-%d' set -g status-right '#(uptime | cut -f 4-5 -d " " | cut -f 1 -d ",") %a %l:%M:%S %p %Y-%m-%d'
%endif %endif
# theming # theming
@@ -75,3 +87,5 @@ set-hook -g after-new-session 'if -F "#{==:#{session_name},ssh}" "source ${XDG_C
if-shell "test '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -ge 4 \)'" 'bind-key -Tcopy-mode-vi v send -X begin-selection; bind-key -Tcopy-mode-vi y send -X copy-selection-and-cancel' if-shell "test '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -ge 4 \)'" 'bind-key -Tcopy-mode-vi v send -X begin-selection; bind-key -Tcopy-mode-vi y send -X copy-selection-and-cancel'
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 4\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'bind-key -t vi-copy v begin-selection; bind-key -t vi-copy y copy-selection' if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 4\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'bind-key -t vi-copy v begin-selection; bind-key -t vi-copy y copy-selection'
if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 2\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'set-option -g status-utf8 on' if-shell '\( #{$TMUX_VERSION_MAJOR} -eq 2 -a #{$TMUX_VERSION_MINOR} -lt 2\) -o #{$TMUX_VERSION_MAJOR} -le 1' 'set-option -g status-utf8 on'
set -g allow-passthrough on

467
flake.lock generated
View File

@@ -1,5 +1,29 @@
{ {
"nodes": { "nodes": {
"colmena": {
"inputs": {
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nix-github-actions": "nix-github-actions",
"nixpkgs": [
"nixpkgs"
],
"stable": "stable"
},
"locked": {
"lastModified": 1762034856,
"narHash": "sha256-QVey3iP3UEoiFVXgypyjTvCrsIlA4ecx6Acaz5C8/PQ=",
"owner": "zhaofengli",
"repo": "colmena",
"rev": "349b035a5027f23d88eeb3bc41085d7ee29f18ed",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "colmena",
"type": "github"
}
},
"disko": { "disko": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -7,11 +31,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1746728054, "lastModified": 1768920986,
"narHash": "sha256-eDoSOhxGEm2PykZFa/x9QG5eTH0MJdiJ9aR00VAofXE=", "narHash": "sha256-CNzzBsRhq7gg4BMBuTDObiWDH/rFYHEuDRVOwCcwXw4=",
"owner": "nix-community", "owner": "nix-community",
"repo": "disko", "repo": "disko",
"rev": "ff442f5d1425feb86344c028298548024f21256d", "rev": "de5708739256238fb912c62f03988815db89ec9a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -29,11 +53,11 @@
}, },
"locked": { "locked": {
"dir": "pkgs/firefox-addons", "dir": "pkgs/firefox-addons",
"lastModified": 1764561884, "lastModified": 1770177820,
"narHash": "sha256-vQ3iFPPhxsLqV3c5kgmYP53mVD6id6gsP0tN+oTmqok=", "narHash": "sha256-0iGDl/ct3rW+h6+sLq4RZaze/U/aQo2L5sLLuyjuVTk=",
"owner": "rycee", "owner": "rycee",
"repo": "nur-expressions", "repo": "nur-expressions",
"rev": "aba4621459aec251d90d6452e3495b58a8a5e185", "rev": "c7794d3f46304de5234008c31b5b28a9d5709184",
"type": "gitlab" "type": "gitlab"
}, },
"original": { "original": {
@@ -43,7 +67,76 @@
"type": "gitlab" "type": "gitlab"
} }
}, },
"flake-compat": {
"flake": false,
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"locked": {
"lastModified": 1767039857,
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
"owner": "NixOS",
"repo": "flake-compat",
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "flake-compat",
"type": "github"
}
},
"flake-parts": {
"inputs": {
"nixpkgs-lib": [
"nvim",
"mcp-hub",
"nixpkgs"
]
},
"locked": {
"lastModified": 1743550720,
"narHash": "sha256-hIshGgKZCgWh6AYJpJmRgFdR3WUbkY04o82X05xqQiY=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "c621e8422220273271f52058f618c94e405bb0f5",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
}, },
@@ -61,6 +154,49 @@
"type": "github" "type": "github"
} }
}, },
"git-hooks": {
"inputs": {
"flake-compat": "flake-compat_2",
"gitignore": "gitignore",
"nixpkgs": [
"nixpkgs"
]
},
"locked": {
"lastModified": 1769939035,
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
"type": "github"
},
"original": {
"owner": "cachix",
"repo": "git-hooks.nix",
"type": "github"
}
},
"gitignore": {
"inputs": {
"nixpkgs": [
"git-hooks",
"nixpkgs"
]
},
"locked": {
"lastModified": 1709087332,
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
"owner": "hercules-ci",
"repo": "gitignore.nix",
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "gitignore.nix",
"type": "github"
}
},
"home-manager": { "home-manager": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -68,11 +204,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1764544324, "lastModified": 1770263241,
"narHash": "sha256-GVBGjO7UsmzLrlOJV8NlKSxukHaHencrJqWkCA6FkqI=", "narHash": "sha256-R1WFtIvp38hS9x63dnijdJw1KyIiy30KGea6e6N7LHs=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "e4e25a8c310fa45f2a8339c7972dc43d2845a612", "rev": "04e5203db66417d548ae1ff188a9f591836dfaa7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -81,13 +217,104 @@
"type": "github" "type": "github"
} }
}, },
"mcp-hub": {
"inputs": {
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1755841689,
"narHash": "sha256-KakvXZf0vjdqzyT+LsAKHEr4GLICGXPmxl1hZ3tI7Yg=",
"owner": "ravitemer",
"repo": "mcp-hub",
"rev": "9c7670a4c341ed3cf738a6242c0fde1cea40bccf",
"type": "github"
},
"original": {
"owner": "ravitemer",
"repo": "mcp-hub",
"type": "github"
}
},
"nix-formatter-pack": {
"inputs": {
"nixpkgs": [
"nix-on-droid",
"nixpkgs"
],
"nmd": "nmd",
"nmt": "nmt"
},
"locked": {
"lastModified": 1705252799,
"narHash": "sha256-HgSTREh7VoXjGgNDwKQUYcYo13rPkltW7IitHrTPA5c=",
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"rev": "2de39dedd79aab14c01b9e2934842051a160ffa5",
"type": "github"
},
"original": {
"owner": "Gerschtli",
"repo": "nix-formatter-pack",
"type": "github"
}
},
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"colmena",
"nixpkgs"
]
},
"locked": {
"lastModified": 1729742964,
"narHash": "sha256-B4mzTcQ0FZHdpeWcpDYPERtyjJd/NIuaQ9+BV1h+MpA=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "e04df33f62cdcf93d73e9a04142464753a16db67",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nix-on-droid": {
"inputs": {
"home-manager": [
"home-manager"
],
"nix-formatter-pack": "nix-formatter-pack",
"nixpkgs": [
"nixpkgs"
],
"nixpkgs-docs": "nixpkgs-docs",
"nixpkgs-for-bootstrap": "nixpkgs-for-bootstrap",
"nmd": "nmd_2"
},
"locked": {
"lastModified": 1720396533,
"narHash": "sha256-UFzk/hZWO1VkciIO5UPaSpJN8s765wsngUSvtJM6d5Q=",
"owner": "nix-community",
"repo": "nix-on-droid",
"rev": "f3d3b8294039f2f9a8fb7ea82c320f29c6b0fe25",
"type": "github"
},
"original": {
"owner": "nix-community",
"ref": "release-24.05",
"repo": "nix-on-droid",
"type": "github"
}
},
"nix-secrets": { "nix-secrets": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1764371082, "lastModified": 1770135527,
"narHash": "sha256-yxFxEKXFuXFyFIDZY1gla2OyuqcIE3uT8KDDgTmm3cE=", "narHash": "sha256-Fup9LiyL6bDID3x+rAB2nP99Xv2o9Is5NkTDbmIy6o0=",
"ref": "main", "ref": "main",
"rev": "b9c2ce32cc4c95d7ff01372faea2668407ef8d27", "rev": "521d144f8a8ff9fca8ccf492d7fbdd05d9a5fe37",
"shallow": true, "shallow": true,
"type": "git", "type": "git",
"url": "ssh://git@github.com/hektor/nix-secrets" "url": "ssh://git@github.com/hektor/nix-secrets"
@@ -101,11 +328,11 @@
}, },
"nixCats": { "nixCats": {
"locked": { "locked": {
"lastModified": 1764009888, "lastModified": 1769578476,
"narHash": "sha256-hJekfTiW1792txgRSM4LcHnz1lDSY87LYbsJEn2V378=", "narHash": "sha256-4+KbiBcC6hQ3sh0UbPXjy6TOfLh9yhskRlfPzyZ2FH4=",
"owner": "BirdeeHub", "owner": "BirdeeHub",
"repo": "nixCats-nvim", "repo": "nixCats-nvim",
"rev": "16ac3281f322ea15d39843829e42a44d22da3715", "rev": "48f8be4bdafccfa19ceaaf08071a15eca36fdb1d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -116,7 +343,7 @@
}, },
"nixgl": { "nixgl": {
"inputs": { "inputs": {
"flake-utils": "flake-utils", "flake-utils": "flake-utils_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
] ]
@@ -137,11 +364,11 @@
}, },
"nixos-hardware": { "nixos-hardware": {
"locked": { "locked": {
"lastModified": 1764440730, "lastModified": 1769302137,
"narHash": "sha256-ZlJTNLUKQRANlLDomuRWLBCH5792x+6XUJ4YdFRjtO4=", "narHash": "sha256-QEDtctEkOsbx8nlFh4yqPEOtr4tif6KTqWwJ37IM2ds=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixos-hardware", "repo": "nixos-hardware",
"rev": "9154f4569b6cdfd3c595851a6ba51bfaa472d9f3", "rev": "a351494b0e35fd7c0b7a1aae82f0afddf4907aa8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -153,11 +380,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1764517877, "lastModified": 1770197578,
"narHash": "sha256-pp3uT4hHijIC8JUK5MEqeAWmParJrgBVzHLNfJDZxg4=", "narHash": "sha256-AYqlWrX09+HvGs8zM6ebZ1pwUqjkfpnv8mewYwAo+iM=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2d293cbfa5a793b4c50d17c05ef9e385b90edf6c", "rev": "00c21e4c93d963c50d4c0c89bfa84ed6e0694df2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -167,15 +394,118 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-docs": {
"locked": {
"lastModified": 1705957679,
"narHash": "sha256-Q8LJaVZGJ9wo33wBafvZSzapYsjOaNjP/pOnSiKVGHY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "9a333eaa80901efe01df07eade2c16d183761fa3",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-for-bootstrap": {
"locked": {
"lastModified": 1720244366,
"narHash": "sha256-WrDV0FPMVd2Sq9hkR5LNHudS3OSMmUrs90JUTN+MXpA=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "49ee0e94463abada1de470c9c07bfc12b36dcf40",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "49ee0e94463abada1de470c9c07bfc12b36dcf40",
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1743689281,
"narHash": "sha256-y7Hg5lwWhEOgflEHRfzSH96BOt26LaYfrYWzZ+VoVdg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2bfc080955153be0be56724be6fa5477b4eefabb",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nmd": {
"flake": false,
"locked": {
"lastModified": 1666190571,
"narHash": "sha256-Z1hc7M9X6L+H83o9vOprijpzhTfOBjd0KmUTnpHAVjA=",
"owner": "rycee",
"repo": "nmd",
"rev": "b75d312b4f33bd3294cd8ae5c2ca8c6da2afc169",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmd",
"type": "gitlab"
}
},
"nmd_2": {
"inputs": {
"nixpkgs": [
"nix-on-droid",
"nixpkgs-docs"
],
"scss-reset": "scss-reset"
},
"locked": {
"lastModified": 1705050560,
"narHash": "sha256-x3zzcdvhJpodsmdjqB4t5mkVW22V3wqHLOun0KRBzUI=",
"owner": "~rycee",
"repo": "nmd",
"rev": "66d9334933119c36f91a78d565c152a4fdc8d3d3",
"type": "sourcehut"
},
"original": {
"owner": "~rycee",
"repo": "nmd",
"type": "sourcehut"
}
},
"nmt": {
"flake": false,
"locked": {
"lastModified": 1648075362,
"narHash": "sha256-u36WgzoA84dMVsGXzml4wZ5ckGgfnvS0ryzo/3zn/Pc=",
"owner": "rycee",
"repo": "nmt",
"rev": "d83601002c99b78c89ea80e5e6ba21addcfe12ae",
"type": "gitlab"
},
"original": {
"owner": "rycee",
"repo": "nmt",
"type": "gitlab"
}
},
"nvim": { "nvim": {
"inputs": { "inputs": {
"mcp-hub": "mcp-hub",
"nixCats": "nixCats", "nixCats": "nixCats",
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"plugins-beancount-nvim": "plugins-beancount-nvim", "plugins-beancount-nvim": "plugins-beancount-nvim",
"plugins-crazy-node-movement": "plugins-crazy-node-movement",
"plugins-helm-ls-nvim": "plugins-helm-ls-nvim", "plugins-helm-ls-nvim": "plugins-helm-ls-nvim",
"plugins-m-taskwarrior-d-nvim": "plugins-m-taskwarrior-d-nvim",
"plugins-mcphub-nvim": "plugins-mcphub-nvim", "plugins-mcphub-nvim": "plugins-mcphub-nvim",
"plugins-nvimkit-nvim": "plugins-nvimkit-nvim", "plugins-nvimkit-nvim": "plugins-nvimkit-nvim",
"plugins-shipwright-nvim": "plugins-shipwright-nvim", "plugins-shipwright-nvim": "plugins-shipwright-nvim",
@@ -207,30 +537,14 @@
"type": "github" "type": "github"
} }
}, },
"plugins-crazy-node-movement": {
"flake": false,
"locked": {
"lastModified": 1693654676,
"narHash": "sha256-hQcQEp39zFN2zphMfcr97yRVcuHhBsSkzKO7XNloDpQ=",
"owner": "theHamsta",
"repo": "crazy-node-movement",
"rev": "d5cf01cc44c5715501d3d6fe439af7c8b7fa5df2",
"type": "github"
},
"original": {
"owner": "theHamsta",
"repo": "crazy-node-movement",
"type": "github"
}
},
"plugins-helm-ls-nvim": { "plugins-helm-ls-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1761915179, "lastModified": 1768584652,
"narHash": "sha256-W9NRa84l5Cs62OsDeqb+LMxk8oYjhVBCB3o3UmE9a0I=", "narHash": "sha256-jnMc87OjURNcqsva0npYgVyUrWc5C6L7yHpNvt9eSmg=",
"owner": "qvalentin", "owner": "qvalentin",
"repo": "helm-ls.nvim", "repo": "helm-ls.nvim",
"rev": "d6f3a8d4ad59b4f54cd734267dfb5411679ea608", "rev": "f0b9a1723890971a6d84890b50dbf5f40974ea1b",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -239,14 +553,30 @@
"type": "github" "type": "github"
} }
}, },
"plugins-m-taskwarrior-d-nvim": {
"flake": false,
"locked": {
"lastModified": 1767960157,
"narHash": "sha256-ov0qi4LhIlwqrBzSbTJ6APC5qjl2d/vlKWJfW5ZiDrg=",
"owner": "huantrinh1802",
"repo": "m_taskwarrior_d.nvim",
"rev": "107247387cd81823046bc2b8e71150c8edf041d3",
"type": "github"
},
"original": {
"owner": "huantrinh1802",
"repo": "m_taskwarrior_d.nvim",
"type": "github"
}
},
"plugins-mcphub-nvim": { "plugins-mcphub-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1759035242, "lastModified": 1768730387,
"narHash": "sha256-I6EbgY/2sAdtrxtmH0qbAAQvMCHhOsfolJfblV0fXOk=", "narHash": "sha256-g9tPvjThz6EUk7zcY7lL+YH4lrT4x3FJ6jrNMHA8PAE=",
"owner": "ravitemer", "owner": "ravitemer",
"repo": "mcphub.nvim", "repo": "mcphub.nvim",
"rev": "8ff40b5edc649959bb7e89d25ae18e055554859a", "rev": "7cd5db330f41b7bae02b2d6202218a061c3ebc1f",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -290,11 +620,11 @@
"plugins-tailwind-fold-nvim": { "plugins-tailwind-fold-nvim": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1752559116, "lastModified": 1766077142,
"narHash": "sha256-8uefZIVsn9USEd6FyiO3m3TRKAS/vigU4t9Tk5ijd3c=", "narHash": "sha256-SwcDLlygXUSV/dytPXA5Y45OpUhjnExc8SZg5a8MZ2k=",
"owner": "razak17", "owner": "razak17",
"repo": "tailwind-fold.nvim", "repo": "tailwind-fold.nvim",
"rev": "d9e7ca11691d252b35795726dff087bf013b2ebf", "rev": "e2ba5ee1ca9b74208709fe9d7314b8aa753b26a7",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -305,9 +635,12 @@
}, },
"root": { "root": {
"inputs": { "inputs": {
"colmena": "colmena",
"disko": "disko", "disko": "disko",
"firefox-addons": "firefox-addons", "firefox-addons": "firefox-addons",
"git-hooks": "git-hooks",
"home-manager": "home-manager", "home-manager": "home-manager",
"nix-on-droid": "nix-on-droid",
"nix-secrets": "nix-secrets", "nix-secrets": "nix-secrets",
"nixgl": "nixgl", "nixgl": "nixgl",
"nixos-hardware": "nixos-hardware", "nixos-hardware": "nixos-hardware",
@@ -316,6 +649,22 @@
"sops-nix": "sops-nix" "sops-nix": "sops-nix"
} }
}, },
"scss-reset": {
"flake": false,
"locked": {
"lastModified": 1631450058,
"narHash": "sha256-muDlZJPtXDIGevSEWkicPP0HQ6VtucbkMNygpGlBEUM=",
"owner": "andreymatin",
"repo": "scss-reset",
"rev": "0cf50e27a4e95e9bb5b1715eedf9c54dee1a5a91",
"type": "github"
},
"original": {
"owner": "andreymatin",
"repo": "scss-reset",
"type": "github"
}
},
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": [ "nixpkgs": [
@@ -323,11 +672,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1764483358, "lastModified": 1770145881,
"narHash": "sha256-EyyvCzXoHrbL467YSsQBTWWg4sR96MH1sPpKoSOelB4=", "narHash": "sha256-ktjWTq+D5MTXQcL9N6cDZXUf9kX8JBLLBLT0ZyOTSYY=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "5aca6ff67264321d47856a2ed183729271107c9c", "rev": "17eea6f3816ba6568b8c81db8a4e6ca438b30b7c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -336,6 +685,22 @@
"type": "github" "type": "github"
} }
}, },
"stable": {
"locked": {
"lastModified": 1750133334,
"narHash": "sha256-urV51uWH7fVnhIvsZIELIYalMYsyr2FCalvlRTzqWRw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "36ab78dab7da2e4e27911007033713bab534187b",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-25.05",
"repo": "nixpkgs",
"type": "github"
}
},
"systems": { "systems": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,

109
flake.nix
View File

@@ -5,7 +5,6 @@
}; };
nixos-hardware = { nixos-hardware = {
url = "github:NixOS/nixos-hardware/master"; url = "github:NixOS/nixos-hardware/master";
inputs.nixpkgs.follows = "nixpkgs";
}; };
disko = { disko = {
url = "github:nix-community/disko/latest"; url = "github:nix-community/disko/latest";
@@ -23,6 +22,11 @@
url = "github:nix-community/home-manager"; url = "github:nix-community/home-manager";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nix-on-droid = {
url = "github:nix-community/nix-on-droid/release-24.05";
inputs.nixpkgs.follows = "nixpkgs";
inputs.home-manager.follows = "home-manager";
};
nixgl = { nixgl = {
url = "github:nix-community/nixGL"; url = "github:nix-community/nixGL";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -35,48 +39,117 @@
url = "path:./dots/.config/nvim"; url = "path:./dots/.config/nvim";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
colmena = {
url = "github:zhaofengli/colmena";
inputs.nixpkgs.follows = "nixpkgs";
};
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
}; };
outputs = outputs =
{ {
self, self,
nixpkgs, nixpkgs,
nixos-hardware,
disko,
sops-nix,
nix-secrets,
home-manager, home-manager,
nix-on-droid,
nixgl, nixgl,
firefox-addons, git-hooks,
nvim, ...
}@inputs: }@inputs:
let let
lib = inputs.nixpkgs.lib; inherit (self) outputs;
inherit (inputs.nixpkgs) lib;
utils = import ./utils { inherit lib; }; utils = import ./utils { inherit lib; };
hostDirNames = utils.dirNames ./hosts; hostDirNames = utils.dirNames ./hosts;
system = "x86_64-linux"; system = "x86_64-linux";
pkgs = import nixpkgs { dotsPath = ./dots;
inherit system; pkgs = import nixpkgs { inherit system; };
overlays = [ nixgl.overlay ];
};
in in
{ {
nix.nixPath = [ nix.nixPath = [
"nixpkgs=${inputs.nixpkgs}" "nixpkgs=${inputs.nixpkgs}"
]; # <https://github.com/nix-community/nixd/blob/main/nixd/docs/configuration.md> ];
nixosConfigurations = lib.genAttrs hostDirNames (
nixosConfigurations =
(lib.genAttrs hostDirNames (
host: host:
nixpkgs.lib.nixosSystem { nixpkgs.lib.nixosSystem {
system = import ./hosts/${host}/system.nix;
modules = [ ./hosts/${host} ]; modules = [ ./hosts/${host} ];
specialArgs = { inherit inputs; }; specialArgs = {
inherit
inputs
outputs
dotsPath
self
;
};
} }
); ))
// {
sd-image-aarch64 = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
"${nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
./images/sd-image-aarch64.nix
{
nixpkgs.crossSystem = {
system = "aarch64-linux";
};
}
];
specialArgs = {
inherit inputs outputs dotsPath;
};
};
};
homeConfigurations = { homeConfigurations = {
work = home-manager.lib.homeManagerConfiguration { work = home-manager.lib.homeManagerConfiguration {
inherit pkgs; pkgs = import nixpkgs {
inherit system;
overlays = [ nixgl.overlay ];
};
modules = [ ./home/hosts/work ]; modules = [ ./home/hosts/work ];
extraSpecialArgs = { inherit inputs; }; extraSpecialArgs = {
inherit inputs outputs dotsPath;
}; };
}; };
}; };
nixOnDroidConfigurations = {
pixel = nix-on-droid.lib.nixOnDroidConfiguration {
modules = [ ./phone ];
extraSpecialArgs = {
inherit inputs outputs dotsPath;
};
pkgs = import nixpkgs {
system = "aarch64-linux";
overlays = [ nix-on-droid.overlays.default ];
};
home-manager-path = home-manager.outPath;
};
};
colmenaHive = import ./deploy/colmena.nix {
inherit
self
inputs
;
};
checks.${system}.pre-commit-check = git-hooks.lib.${system}.run {
src = ./.;
hooks = {
nixfmt.enable = true;
statix.enable = true;
deadnix.enable = true;
};
};
images.sd-image-aarch64 = self.nixosConfigurations.sd-image-aarch64.config.system.build.sdImage;
};
} }

View File

@@ -6,14 +6,51 @@
... ...
}: }:
let
username = "h";
in
{ {
imports = [ imports = [
(import ../astyanax { ../../modules/cloud
inherit inputs; ../../modules/comms
inherit config; ../../modules/desktop/niri
inherit pkgs; ../../modules/3d
}) ../../modules/git
../../modules/k8s/k9s.nix
../../modules/kitty.nix
../../modules/nvim.nix
../../modules/ssh.nix
../../modules/taskwarrior.nix
../../modules/keepassxc.nix
../../modules/anki.nix
../../modules/photography
../../modules/browser
../../modules/shell
]; ];
programs.taskwarrior.config.recurrence = lib.mkForce "on"; home = {
stateVersion = "25.05";
inherit username;
homeDirectory = "/home/${username}";
};
xdg.userDirs.createDirectories = false;
xdg.userDirs.download = "${config.home.homeDirectory}/dl";
browser.primary = "librewolf";
cloud.hetzner.enable = true;
comms.signal.enable = true;
github.enable = true;
shell.bash = {
enable = true;
aliases.lang-js = true;
};
programs = {
home-manager.enable = true;
taskwarrior.config.recurrence = lib.mkForce "on";
};
home.packages = import ../packages.nix { inherit pkgs; };
} }

View File

@@ -1,5 +1,4 @@
{ {
inputs,
config, config,
pkgs, pkgs,
... ...
@@ -10,68 +9,49 @@ let
in in
{ {
imports = [ imports = [
../../modules/dconf.nix # TODO: Only enable when on Gnome? ../../modules/ai-tools.nix
../../modules/git.nix ../../modules/anki.nix
../../modules/k9s.nix ../../modules/cloud
(import ../../modules/taskwarrior.nix { ../../modules/comms
inherit config; ../../modules/desktop/niri
inherit pkgs; ../../modules/git
}) ../../modules/k8s/k9s.nix
../../modules/kitty.nix
../../modules/nfc
../../modules/nvim.nix
../../modules/ssh.nix
../../modules/taskwarrior.nix
../../modules/keepassxc.nix
../../modules/browser
../../modules/shell
]; ];
home.stateVersion = "25.05"; home = {
home.username = username; stateVersion = "25.05";
home.homeDirectory = "/home/${username}"; inherit username;
homeDirectory = "/home/${username}";
};
xdg.userDirs.createDirectories = false; xdg.userDirs.createDirectories = false;
xdg.userDirs.download = "${config.home.homeDirectory}/dl"; xdg.userDirs.download = "${config.home.homeDirectory}/dl";
browser.primary = "librewolf";
cloud.hetzner.enable = true;
comms.signal.enable = true;
github.enable = true;
nfc.proxmark3.enable = true;
shell.bash = {
enable = true;
aliases.lang-js = true;
};
programs = { programs = {
bash = {
enable = true;
enableCompletion = true;
initExtra = ''
for f in /home/h/.bashrc.d/*; do
[ -f "$f" ] && source "$f"
done
source /home/h/.bash_aliases/all
source /home/h/.bash_aliases/lang-js
# host-specific config goes here
# ...
export PATH=${../../../dots/.bin}:$PATH
'';
};
firefox = import ../../modules/firefox.nix {
inherit inputs;
inherit pkgs;
inherit config;
};
fzf = {
enable = true;
enableBashIntegration = true;
};
home-manager.enable = true; home-manager.enable = true;
keepassxc = import ../../modules/keepassxc.nix;
}; };
home.packages = import ./packages.nix { home.packages = import ../packages.nix {
inherit pkgs; inherit pkgs;
inherit config; inherit config;
}; };
home.file = {
".inputrc".source = ../../../dots/.inputrc;
".bashrc.d/prompt".source = ../../../dots/.bashrc.d/prompt;
".bashrc.d/editor".source = ../../../dots/.bashrc.d/editor;
".bash_aliases/all".source = ../../../dots/.bash_aliases/all;
".bash_aliases/lang-js".source = ../../../dots/.bash_aliases/lang-js;
".config/kitty/kitty.conf".source = ../../../dots/.config/kitty/kitty.conf;
".config/kitty/themes/zenwritten_light.conf".source =
../../../dots/.config/kitty/themes/zenwritten_light.conf;
".config/kitty/themes/zenwritten_dark.conf".source =
../../../dots/.config/kitty/themes/zenwritten_dark.conf;
};
} }

View File

@@ -1,52 +0,0 @@
{ pkgs, ... }:
with pkgs;
[
bash-completion
bash-language-server
bat
brightnessctl
entr
eslint_d
feh
fzf
gh
git
haskell-language-server
haskellPackages.pandoc-crossref
haskellPackages.hadolint
htop
jq
kitty
lua-language-server
nixfmt-rfc-style
nmap
nodejs_24
nvimpager
ormolu
pandoc
parallel
pass
pnpm
ripgrep
silver-searcher
sops
sshfs
stylelint
svelte-language-server
tailwindcss-language-server
tldr
tmux
tmuxp
tree
tree-sitter
typescript-language-server
unzip
vim-language-server
vimPlugins.vim-plug
vtsls
wget
xbanish
xclip
yaml-language-server
]

29
home/hosts/packages.nix Normal file
View File

@@ -0,0 +1,29 @@
{ pkgs, ... }:
with pkgs;
[
bat
entr
feh
fzf
haskellPackages.pandoc-crossref
htop
jq
nixfmt-rfc-style
nmap
nodejs_24
nvimpager
pandoc
parallel
pass
pnpm
ripgrep
silver-searcher
sops
sshfs
tldr
tree
unzip
vimPlugins.vim-plug
wget
]

View File

@@ -10,35 +10,80 @@ let
in in
{ {
imports = [ imports = [
inputs.sops-nix.homeManagerModules.sops
../../modules/ai-tools.nix
../../modules/cloud
../../modules/comms
../../modules/dconf.nix ../../modules/dconf.nix
../../modules/git.nix ../../modules/docker
../../modules/git
../../modules/k8s
../../modules/k9s.nix ../../modules/k9s.nix
../../modules/keepassxc.nix
../../modules/kitty.nix
../../modules/nvim.nix
../../modules/browser
../../modules/shell
../../modules/taskwarrior.nix
]; ];
sops = {
age.keyFile = "${config.home.homeDirectory}/.config/sops/age/keys.txt";
defaultSopsFile = "${inputs.nix-secrets}/secrets.yaml";
secrets = {
taskwarrior_sync_server_url = { };
taskwarrior_sync_server_client_id = { };
taskwarrior_sync_encryption_secret = { };
anki_sync_user = { };
anki_sync_key = { };
};
templates."taskrc.d/sync" = {
content = ''
sync.server.url=${config.sops.placeholder.taskwarrior_sync_server_url}
sync.server.client_id=${config.sops.placeholder.taskwarrior_sync_server_client_id}
sync.encryption_secret=${config.sops.placeholder.taskwarrior_sync_encryption_secret}
'';
};
};
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
home.stateVersion = "25.05"; home = {
home.username = username; stateVersion = "25.05";
home.homeDirectory = "/home/${username}"; inherit username;
homeDirectory = "/home/${username}";
};
targets.genericLinux.nixGL = { targets.genericLinux.nixGL = {
packages = inputs.nixgl.packages; inherit (inputs.nixgl) packages;
defaultWrapper = "mesa"; defaultWrapper = "mesa";
}; };
browser.primary = "firefox";
browser.secondary = "chromium";
cloud.azure.enable = true;
comms.signal.enable = true;
comms.teams.enable = true;
github.enable = true;
gitlab.enable = true;
shell.bash.enable = true;
starship.enable = true;
programs = { programs = {
# editorconfig.enable = true;
firefox = import ../../modules/firefox.nix {
inherit inputs;
inherit pkgs;
inherit config;
};
gh.enable = true; gh.enable = true;
keepassxc = import ../../modules/keepassxc.nix;
kubecolor.enable = true; kubecolor.enable = true;
}; };
home.packages = import ./packages.nix { home.packages =
import ./packages.nix {
inherit inputs;
inherit config;
inherit pkgs;
}
++ import ../packages.nix {
inherit inputs; inherit inputs;
inherit config; inherit config;
inherit pkgs; inherit pkgs;

View File

@@ -13,7 +13,4 @@ let
[ ]; [ ];
in in
(with pkgs; [ localPackages
inputs.nvim.packages.x86_64-linux.nvim
])
++ localPackages

View File

@@ -0,0 +1,11 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
bambu-studio
blender
openscad-lsp
openscad-unstable
orca-slicer
];
}

40
home/modules/ai-tools.nix Normal file
View File

@@ -0,0 +1,40 @@
{
pkgs,
...
}:
{
config = {
home.packages = with pkgs; [
aider-chat
(pkgs.stdenv.mkDerivation {
name = "ccline";
src = pkgs.fetchurl {
url = "https://github.com/Haleclipse/CCometixLine/releases/download/v1.0.8/ccline-linux-x64.tar.gz";
hash = "sha256-Joe3Dd6uSMGi66QT6xr2oY/Tz8rA5RuKa6ckBVJIzI0=";
};
unpackPhase = ''
tar xzf $src
'';
installPhase = ''
mkdir -p $out/bin
cp ccline $out/bin/
chmod +x $out/bin/ccline
'';
meta = with pkgs.lib; {
description = "CCometixLine Linux x64 CLI (Claude Code statusline)";
homepage = "https://github.com/Haleclipse/CCometixLine";
license = licenses.mit;
platforms = [ "x86_64-linux" ];
};
})
# claude-code
# (config.lib.nixGL.wrap code-cursor)
# github-copilot-cli
mcp-nixos
opencode
];
};
}

View File

@@ -1,6 +1,33 @@
{ {
config,
lib,
pkgs,
osConfig ? null,
...
}:
let
hmSopsAvailable = config ? sops && config.sops ? secrets;
osSopsAvailable = osConfig != null && osConfig ? sops && osConfig.sops ? secrets;
sopsAvailable = hmSopsAvailable || osSopsAvailable;
sopsSecrets = if hmSopsAvailable then config.sops.secrets else osConfig.sops.secrets;
in
{
warnings = lib.optional (
!sopsAvailable && config.programs.anki.enable
) "anki is enabled but sops secrets are not available. anki sync will not be configured.";
programs.anki = {
enable = true; enable = true;
# sync = { addons = with pkgs.ankiAddons; [
# username = config.sops.secrets."email/personal".path; anki-connect
# }; puppy-reinforcement
review-heatmap
];
sync = lib.mkIf sopsAvailable {
usernameFile = "${sopsSecrets."anki_sync_user".path}";
keyFile = "${sopsSecrets."anki_sync_key".path}";
};
};
} }

View File

@@ -0,0 +1,19 @@
{
nixos = {
name = "NixOS";
bookmarks = [
{
name = "wiki";
url = "https://wiki.nixos.org/wiki/NixOS_Wiki";
}
{
name = "packages";
url = "https://search.nixos.org/packages";
}
{
name = "options";
url = "https://search.nixos.org/options";
}
];
};
}

View File

@@ -0,0 +1,12 @@
{
config,
lib,
pkgs,
...
}:
{
config = lib.mkIf (config.browser.primary == "chromium" || config.browser.secondary == "chromium") {
home.packages = [ pkgs.chromium ];
};
}

View File

@@ -0,0 +1,31 @@
{ lib, ... }:
{
options.browser = {
primary = lib.mkOption {
type = lib.types.enum [
"firefox"
"chromium"
"librewolf"
];
default = "firefox";
};
secondary = lib.mkOption {
type = lib.types.nullOr (
lib.types.enum [
"firefox"
"chromium"
"librewolf"
]
);
default = null;
};
};
imports = [
./firefox.nix
./librewolf.nix
./chromium.nix
];
}

View File

@@ -1,19 +1,26 @@
{ inputs, pkgs, ... }: {
config,
inputs,
pkgs,
}:
let
bookmarks = import ./bookmarks.nix;
in
{ {
enable = true; nativeMessagingHosts =
nativeMessagingHosts = with pkgs; [ with pkgs;
[
tridactyl-native tridactyl-native
]; ]
policies = { ++ lib.optionals config.programs.keepassxc.enable [ keepassxc ];
DefaultDownloadDirectory = "\${home}/dl";
};
profiles = { profiles = {
default = { default = {
settings = { settings = {
"signon.rememberSignons" = false; "signon.rememberSignons" = false;
"findbar.highlightAll" = true; "findbar.highlightAll" = true;
"extensions.autoDisableScopes" = 0; # Enable extensions by default <https://nix-community.github.io/home-manager/options.xhtml#opt-programs.firefox.profiles._name_.extensions.packages> "extensions.autoDisableScopes" = 0;
}; };
extensions = { extensions = {
packages = with inputs.firefox-addons.packages.${pkgs.system}; [ packages = with inputs.firefox-addons.packages.${pkgs.system}; [
@@ -33,23 +40,7 @@
{ {
toolbar = true; toolbar = true;
bookmarks = [ bookmarks = [
{ bookmarks.nixos
name = "NixOS";
bookmarks = [
{
name = "wiki";
url = "https://wiki.nixos.org/wiki/NixOS_Wiki";
}
{
name = "packages";
url = "https://search.nixos.org/packages";
}
{
name = "options";
url = "https://search.nixos.org/options";
}
];
}
]; ];
} }
]; ];
@@ -57,6 +48,7 @@
}; };
}; };
policies = { policies = {
DefaultDownloadDirectory = "\${home}/dl";
ExtensionSettings = { ExtensionSettings = {
"jid1-ZAdIEUB7XOzOJw@jetpack" = { "jid1-ZAdIEUB7XOzOJw@jetpack" = {
default_area = "navbar"; default_area = "navbar";

View File

@@ -0,0 +1,16 @@
{
config,
lib,
inputs,
pkgs,
...
}:
{
config = lib.mkIf (config.browser.primary == "firefox" || config.browser.secondary == "firefox") {
programs.firefox = {
enable = true;
}
// (import ./firefox-base.nix { inherit config inputs pkgs; });
};
}

View File

@@ -0,0 +1,18 @@
{
config,
lib,
inputs,
pkgs,
...
}:
{
config =
lib.mkIf (config.browser.primary == "librewolf" || config.browser.secondary == "librewolf")
{
programs.librewolf = {
enable = true;
}
// (import ./firefox-base.nix { inherit config inputs pkgs; });
};
}

View File

@@ -0,0 +1,12 @@
{
config,
lib,
pkgs,
...
}:
{
config = lib.mkIf config.cloud.azure.enable {
home.packages = with pkgs; [ azure-cli ];
};
}

View File

@@ -0,0 +1,17 @@
{ lib, ... }:
{
options.cloud = {
azure = {
enable = lib.mkEnableOption "azure CLI";
};
hetzner = {
enable = lib.mkEnableOption "hetzner CLI";
};
};
imports = [
./azure.nix
./hetzner.nix
];
}

View File

@@ -0,0 +1,21 @@
{
config,
lib,
pkgs,
osConfig ? null,
...
}:
let
isNixOS = osConfig != null;
in
{
config = lib.mkIf config.cloud.hetzner.enable {
warnings =
lib.optional (!isNixOS)
"hcloud module requires NixOS host configuration. This module will not work with standalone home-manager.";
home = {
packages = with pkgs; [ hcloud ];
};
};
}

View File

@@ -0,0 +1,17 @@
{ lib, ... }:
{
options.comms = {
signal = {
enable = lib.mkEnableOption "signal";
};
teams = {
enable = lib.mkEnableOption "teams";
};
};
imports = [
./signal.nix
./teams.nix
];
}

View File

@@ -0,0 +1,13 @@
{
config,
lib,
pkgs,
...
}:
{
config = lib.mkIf config.comms.signal.enable {
home.packages = with pkgs; [
(if config.lib ? nixGL then config.lib.nixGL.wrap signal-desktop else signal-desktop)
];
};
}

View File

@@ -0,0 +1,14 @@
{
config,
lib,
pkgs,
...
}:
{
config = lib.mkIf config.comms.teams.enable {
home.packages = with pkgs; [
(if config.lib ? nixGL then config.lib.nixGL.wrap teams-for-linux else teams-for-linux)
];
};
}

View File

@@ -1,21 +1,13 @@
{ config, pkgs, ... }:
let
terminal = "kitty";
browser = config.browser.primary;
in
{ {
dconf.settings = { dconf.settings = {
"org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = true;
night-light-schedule-automatic = true;
};
"org/gnome/desktop/interface" = {
color-scheme = "prefer-dark";
};
"org/gnome/desktop/applications/terminal" = {
exec = "kitty";
exec-arg = "";
};
"org/gnome/desktop/background" = { "org/gnome/desktop/background" = {
color-shading-type = "solid"; color-shading-type = "solid";
picture-opacity = 100;
picture-options = "zoom"; picture-options = "zoom";
picture-uri = "none"; picture-uri = "none";
picture-uri-dark = "none"; picture-uri-dark = "none";
@@ -24,55 +16,54 @@
show-desktop-icons = false; show-desktop-icons = false;
}; };
# "org/gnome/desktop/input-sources" = { "org/gnome/desktop/default-applications/office/calendar" = {
# sources = [ exec = "${browser} https://calendar.proton.me";
# (mkTuple [ needs-term = false;
# "xkb" };
# "us"
# ]) "org/gnome/desktop/default-applications/office/tasks" = {
# ]; exec = "task";
# xkb-options = [ "caps:none" ]; needs-term = true;
# }; };
"org/gnome/desktop/default-applications/terminal" = {
exec = terminal;
exec-arg = "";
};
"org/gnome/desktop/input-sources" = {
xkb-options = [ "caps:none" ];
};
"org/gnome/desktop/interface" = {
clock-format = "24h";
clock-show-weekday = true;
color-scheme = "prefer-dark";
enable-hot-corners = false;
font-name = "Iosevka Term SS08 12";
locate-pointer = true;
monospace-font-name = "Iosevka Term SS08 12";
};
"org/gnome/desktop/wm/keybindings" = { "org/gnome/desktop/wm/keybindings" = {
close = [ "<Shift><Super>Delete" ]; close = [ "<Shift><Super>Delete" ];
cycle-group = [ ]; minimize = [ "<Super>h" ];
cycle-group-backward = [ ]; move-to-monitor-down = [ "<Super><Shift>Down" ];
cycle-panels = [ ]; move-to-monitor-left = [ "<Super><Shift>Left" ];
cycle-panels-backward = [ ]; move-to-monitor-right = [ "<Super><Shift>Right" ];
cycle-windows = [ ]; move-to-monitor-up = [ "<Super><Shift>Up" ];
cycle-windows-backward = [ ];
maximize = [ "<Super> " ];
minimize = [ ];
move-to-workspace-1 = [ "<Super><Shift>a" ]; move-to-workspace-1 = [ "<Super><Shift>a" ];
move-to-workspace-2 = [ "<Super><Shift>s" ]; move-to-workspace-2 = [ "<Super><Shift>s" ];
move-to-workspace-3 = [ "<Super><Shift>d" ]; move-to-workspace-3 = [ "<Super><Shift>d" ];
move-to-workspace-4 = [ "<Super><Shift>f" ]; move-to-workspace-4 = [ "<Super><Shift>f" ];
move-to-workspace-5 = [ "<Super><Shift>g" ]; move-to-workspace-5 = [ "<Super><Shift>g" ];
move-to-workspace-last = [ ];
move-to-workspace-left = [ "<Super><Shift>h" ];
move-to-workspace-right = [ "<Super><Shift>l" ];
panel-run-dialog = [ ];
switch-applications = [ "<Super>j" ]; switch-applications = [ "<Super>j" ];
switch-applications-backward = [ "<Super>k" ]; switch-applications-backward = [ "<Super>k" ];
switch-group = [ ];
switch-group-backward = [ ];
switch-input-source = [ ];
switch-input-source-backward = [ ];
switch-panels = [ ];
switch-panels-backward = [ ];
switch-to-workspace-1 = [ "<Super>a" ]; switch-to-workspace-1 = [ "<Super>a" ];
switch-to-workspace-2 = [ "<Super>s" ]; switch-to-workspace-2 = [ "<Super>s" ];
switch-to-workspace-3 = [ "<Super>d" ]; switch-to-workspace-3 = [ "<Super>d" ];
switch-to-workspace-4 = [ "<Super>f" ]; switch-to-workspace-4 = [ "<Super>f" ];
switch-to-workspace-5 = [ "<Super>g" ]; switch-to-workspace-5 = [ "<Super>g" ];
switch-to-workspace-last = [ ];
switch-to-workspace-left = [ "<Super>h" ];
switch-to-workspace-right = [ "<Super>l" ];
switch-windows = [ ];
switch-windows-backward = [ ];
toggle-maximized = [ "<Super>space" ];
unmaximize = [ ];
}; };
"org/gnome/desktop/wm/preferences" = { "org/gnome/desktop/wm/preferences" = {
@@ -86,8 +77,19 @@
]; ];
}; };
"org/gnome/mutter" = {
center-new-windows = true;
dynamic-workspaces = false;
};
"org/gnome/settings-daemon/plugins/color" = {
night-light-enabled = true;
night-light-schedule-automatic = true;
};
"org/gnome/settings-daemon/plugins/media-keys" = { "org/gnome/settings-daemon/plugins/media-keys" = {
custom-keybindings = [ custom-keybindings = [
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/"
"/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/" "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/"
]; ];
}; };
@@ -100,14 +102,23 @@
"org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1" = { "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1" = {
binding = "<Super>Return"; binding = "<Super>Return";
command = "kitty"; command = terminal;
name = "Kitty"; name = "Kitty";
}; };
"org/gnome/settings-daemon/plugins/power" = {
power-button-action = "suspend";
};
"org/gnome/shell/app-switcher" = {
current-workspace-only = true;
};
"org/gnome/shell/keybindings" = { "org/gnome/shell/keybindings" = {
screenshot = [ "Print" ];
toggle-application-view = [ "<Super>p" ]; toggle-application-view = [ "<Super>p" ];
toggle-quick-settings = [ ]; toggle-quick-settings = [ ];
}; };
}; };
home.packages = with pkgs; [ dconf2nix ];
} }

View File

@@ -0,0 +1,182 @@
input {
touchpad {
tap
natural-scroll
}
mouse {
accel-profile "flat"
}
}
// NOTE: monitors are managed using `shikane` instead, as I assume this to be
// too limited for multiple multimonitor configurations. Below is an example
// for a simple, fixed, vertical dual monitor setup
// output "eDP-1" {
// position x=0 y=1440
// }
//
// output "DP-5" {
// position x=0 y=0
// }
layout {
gaps 4
struts {}
center-focused-column "never"
preset-column-widths {
proportion 0.382
proportion 0.618
proportion 1.0
}
default-column-width { }
focus-ring {
off
}
border {
width 2
active-color "#555555"
inactive-color "#55555511"
urgent-color "#ff0000"
}
shadow {
on
softness 32
spread 4
offset x=0 y=0
color "#0007"
}
}
hotkey-overlay {
skip-at-startup
}
prefer-no-csd
screenshot-path "~/doc/screenshots/%Y-%m-%d %H-%M-%S.png"
// https://yalter.github.io/niri/Configuration:-Animations
animations {
slowdown 0.66
}
window-rule {
match app-id=r#"firefox$"# title="^Picture-in-Picture$"
open-floating true
}
window-rule {
match app-id=r#"^org\.keepassxc\.KeePassXC$"#
block-out-from "screen-capture"
}
window-rule {
geometry-corner-radius 0
clip-to-geometry true
}
gestures {
hot-corners {
off
}
}
binds {
Mod+Slash { show-hotkey-overlay; }
Mod+Return hotkey-overlay-title="Open a Terminal: kitty" { spawn "kitty"; }
Mod+P hotkey-overlay-title="Run an Application: fuzzel" { spawn "fuzzel"; }
Super+Alt+L hotkey-overlay-title="Lock the Screen: swaylock" { spawn "swaylock"; }
XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1+"; }
XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 0.1-"; }
XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; }
XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; }
Mod+Shift+XF86Display { power-off-monitors; }
XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "+10%"; }
XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "--class=backlight" "set" "10%-"; }
Mod+O repeat=false { toggle-overview; }
Mod+Delete repeat=false { close-window; }
Mod+H { focus-column-left; }
Mod+J { focus-window-or-workspace-down; }
Mod+K { focus-window-or-workspace-up; }
Mod+L { focus-column-right; }
Mod+Shift+H { move-column-left; }
Mod+Shift+J { move-window-down-or-to-workspace-down; }
Mod+Shift+K { move-window-up-or-to-workspace-up; }
Mod+Shift+L { move-column-right; }
Mod+Home { focus-column-first; }
Mod+End { focus-column-last; }
Mod+Ctrl+Home { move-column-to-first; }
Mod+Ctrl+End { move-column-to-last; }
Mod+Left { focus-monitor-left; }
Mod+Down { focus-monitor-down; }
Mod+Up { focus-monitor-up; }
Mod+Right { focus-monitor-right; }
Mod+Shift+Left { move-column-to-monitor-left; }
Mod+Shift+Down { move-column-to-monitor-down; }
Mod+Shift+Up { move-column-to-monitor-up; }
Mod+Shift+Right { move-column-to-monitor-right; }
Mod+Ctrl+Up { move-workspace-down; }
Mod+Ctrl+Down { move-workspace-up; }
// Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; }
// Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; }
// Mod+Shift+WheelScrollDown cooldown-ms=150 { move-window-down-or-to-workspace-down; }
// Mod+Shift+WheelScrollUp cooldown-ms=150 { move-window-up-or-to-workspace-up; }
// Mod+A { focus-workspace 1; }
// Mod+S { focus-workspace 2; }
// Mod+D { focus-workspace 3; }
// Mod+F { focus-workspace 4; }
// Mod+Shift+A { move-column-to-workspace 1; }
// Mod+Shift+S { move-column-to-workspace 2; }
// Mod+Shift+D { move-column-to-workspace 3; }
// Mod+Shift+F { move-column-to-workspace 4; }
Mod+Tab { focus-workspace-previous; }
Mod+BracketLeft { consume-or-expel-window-left; }
Mod+BracketRight { consume-or-expel-window-right; }
Mod+Comma { consume-window-into-column; }
Mod+Period { expel-window-from-column; }
Mod+N { switch-preset-column-width; }
Mod+Shift+N { switch-preset-window-height; }
Mod+Ctrl+R { reset-window-height; }
Mod+Space { maximize-column; }
Mod+Shift+Space { fullscreen-window; }
Mod+Escape { toggle-window-floating; }
Mod+Shift+Escape { switch-focus-between-floating-and-tiling; }
Mod+Ctrl+F { expand-column-to-available-width; }
Mod+C { center-column; }
Mod+Ctrl+C { center-visible-columns; }
Mod+Minus { set-column-width "-10%"; }
Mod+Equal { set-column-width "+10%"; }
Mod+Shift+Minus { set-window-height "-10%"; }
Mod+Shift+Equal { set-window-height "+10%"; }
Mod+W { toggle-column-tabbed-display; }
Print { screenshot; }
Ctrl+Print { screenshot-screen; }
Alt+Print { screenshot-window; }
Mod+Shift+Delete { quit; }
}

View File

@@ -0,0 +1,25 @@
{ pkgs, ... }:
{
imports = [
../../fuzzel
../../mako
../../shikane
../../waybar
];
home = {
file.".config/niri/config.kdl".source = ./config.kdl;
packages = with pkgs; [
wl-clipboard
wlsunset
];
};
services.gammastep = {
enable = true;
provider = "manual";
latitude = 51.05;
longitude = 3.71667;
};
}

View File

@@ -0,0 +1,9 @@
{ pkgs, ... }:
{
config = {
home.packages = with pkgs; [
dive
];
};
}

View File

@@ -0,0 +1,28 @@
{
programs.fuzzel = {
enable = true;
settings = {
main = {
font = "Iosevka Term SS08";
horizontal-pad = 0;
vertical-pad = 0;
};
colors = {
background = "ccccccff";
text = "111111ff";
prompt = "ccccccff";
placeholder = "aaaaaaff";
input = "111111ff";
selection = "eeeeeeff";
selection-text = "111111ff";
selection-match = "333333ff";
counter = "111111ff";
border = "111111ff";
};
border = {
width = 2;
radius = 0;
};
};
};
}

View File

@@ -1,8 +0,0 @@
{
programs.git.enable = true;
home.file = {
".gitconfig".source = ../../dots/.gitconfig;
".gitconfig.work".source = ../../dots/.gitconfig.work;
".gitignore".source = ../../dots/.gitignore;
};
}

View File

@@ -0,0 +1,26 @@
{
config,
lib,
pkgs,
dotsPath,
...
}:
{
options = {
github.enable = lib.mkEnableOption "Github CLI";
gitlab.enable = lib.mkEnableOption "Gitlab CLI";
};
config = {
programs.git.enable = true;
home.file = {
".gitconfig".source = dotsPath + "/.gitconfig";
".gitconfig.work".source = dotsPath + "/.gitconfig.work";
".gitignore".source = dotsPath + "/.gitignore";
};
programs.gh.enable = config.github.enable;
home.packages = with pkgs; lib.optionals (config.gitlab.enable) [ glab ];
};
}

View File

@@ -0,0 +1,18 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
argocd
fluxcd
k3d
kubectl
kubernetes
kubernetes-helm
kustomize
minikube
opentofu
upbound
];
imports = [ ./k9s.nix ];
}

View File

@@ -1,4 +1,10 @@
{ pkgs, ... }:
{ {
programs.keepassxc = {
enable = true; enable = true;
# TODO: https://mynixos.com/home-manager/option/programs.keepassxc.settings settings = {
Browser.Enabled = true;
};
};
} }

23
home/modules/kitty.nix Normal file
View File

@@ -0,0 +1,23 @@
{ pkgs, config, lib, dotsPath, ... }:
{
config = {
home.packages = [
(if config.lib ? nixGL
then config.lib.nixGL.wrap pkgs.kitty
else pkgs.kitty)
];
programs.bash.shellAliases = {
icat = "kitty +kitten icat";
};
home.file = {
".config/kitty/kitty.conf".source = dotsPath + "/.config/kitty/kitty.conf";
".config/kitty/nvim.conf".source = dotsPath + "/.config/kitty/nvim.conf";
".config/kitty/themes/zenwritten_light.conf".source =
dotsPath + "/.config/kitty/themes/zenwritten_light.conf";
".config/kitty/themes/zenwritten_dark.conf".source =
dotsPath + "/.config/kitty/themes/zenwritten_dark.conf";
};
};
}

View File

@@ -0,0 +1,5 @@
{
services.mako = {
enable = true;
};
}

View File

@@ -0,0 +1,5 @@
{
imports = [
./proxmark3.nix
];
}

View File

@@ -0,0 +1,21 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.nfc.proxmark3;
in
{
options.nfc.proxmark3 = {
enable = lib.mkEnableOption "proxmark3 (iceman fork)";
};
config = lib.mkIf cfg.enable {
home.packages = [
pkgs.proxmark3
];
};
}

9
home/modules/nvim.nix Normal file
View File

@@ -0,0 +1,9 @@
{ pkgs, inputs, ... }:
{
config = {
home.packages = [
inputs.nvim.packages.${pkgs.system}.nvim
];
};
}

View File

@@ -0,0 +1,7 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [
darktable
];
}

View File

@@ -0,0 +1,74 @@
{
config,
lib,
pkgs,
dotsPath,
...
}:
let
cfg = config.shell.bash;
inherit (config.home) username;
in
{
options.shell.bash = {
enable = lib.mkEnableOption "bash configuration";
aliases = {
all = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Enable common aliases";
};
lang-js = lib.mkOption {
type = lib.types.bool;
default = false;
description = "Enable JavaScript/Node.js aliases";
};
};
addBinToPath = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Add dots .bin directory to PATH";
};
extraInit = lib.mkOption {
type = lib.types.lines;
default = "";
description = "Additional bash initialization";
};
};
config = lib.mkIf cfg.enable {
shell-utils.enable = lib.mkDefault true;
programs.bash = {
enable = true;
enableCompletion = true;
initExtra = ''
for f in /home/${username}/.bashrc.d/*; do
[ -f "$f" ] && source "$f"
done
${lib.optionalString cfg.aliases.all "source /home/${username}/.bash_aliases/all"}
${lib.optionalString cfg.aliases.lang-js "source /home/${username}/.bash_aliases/lang-js"}
${lib.optionalString cfg.addBinToPath "export PATH=${dotsPath}/.bin:$PATH"}
${cfg.extraInit}
'';
};
home.file = {
".inputrc".source = dotsPath + "/.inputrc";
".bashrc.d/prompt".source = dotsPath + "/.bashrc.d/prompt";
".bashrc.d/editor".source = dotsPath + "/.bashrc.d/editor";
}
// lib.optionalAttrs cfg.aliases.all {
".bash_aliases/all".source = dotsPath + "/.bash_aliases/all";
}
// lib.optionalAttrs cfg.aliases.lang-js {
".bash_aliases/lang-js".source = dotsPath + "/.bash_aliases/lang-js";
};
};
}

View File

@@ -0,0 +1,8 @@
{
imports = [
./bash.nix
./utils.nix
./prompt.nix
../tmux.nix
];
}

View File

@@ -0,0 +1,17 @@
{
config,
lib,
pkgs,
...
}:
{
options.starship = {
enable = lib.mkEnableOption "starship prompt";
};
config = lib.mkIf config.starship.enable {
programs.starship = {
enable = true;
};
};
}

View File

@@ -0,0 +1,26 @@
{
config,
lib,
pkgs,
...
}:
{
options.shell-utils = {
enable = lib.mkEnableOption "shell utilities";
};
config = lib.mkIf config.shell-utils.enable {
programs.fzf = {
enable = true;
enableBashIntegration = lib.mkDefault true;
};
home.packages = with pkgs; [
ripgrep
bat
jq
entr
parallel
];
};
}

View File

@@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = with pkgs; [ wdisplays ];
services.shikane.enable = true;
}

37
home/modules/ssh.nix Normal file
View File

@@ -0,0 +1,37 @@
{
outputs,
lib,
...
}:
let
nixosConfigs = builtins.attrNames outputs.nixosConfigurations;
homeConfigs = map (n: lib.last (lib.splitString "@" n)) (
builtins.attrNames outputs.homeConfigurations
);
allHosts = lib.unique (homeConfigs ++ nixosConfigs);
hostsWithKeys = lib.filter (
hostname: builtins.pathExists ../../hosts/${hostname}/ssh_host.pub
) allHosts;
in
{
programs.ssh = {
enable = true;
enableDefaultConfig = false;
matchBlocks = lib.genAttrs hostsWithKeys (
hostname:
let
hostConfig = outputs.nixosConfigurations.${hostname}.config;
publicHostname = hostConfig.ssh.publicHostname;
targetUser = hostConfig.ssh.username;
in
{
host = hostname;
user = targetUser;
}
// lib.optionalAttrs (publicHostname != "") {
hostname = publicHostname;
}
);
};
}

View File

@@ -1,31 +1,46 @@
{ {
config, config,
lib,
pkgs, pkgs,
dotsPath,
osConfig ? null,
... ...
}: }:
let
hmSopsAvailable = config ? sops && config.sops ? templates;
osSopsAvailable = osConfig != null && osConfig ? sops && osConfig.sops ? templates;
sopsAvailable = hmSopsAvailable || osSopsAvailable;
sopsTemplates = if hmSopsAvailable then config.sops.templates else osConfig.sops.templates;
in
{ {
warnings =
lib.optional (!sopsAvailable && config.programs.taskwarrior.enable)
"taskwarrior is enabled, but sops templates are not available. taskwarrior sync will not be configured.";
home.packages = with pkgs; [ home.packages = with pkgs; [
python314
libnotify libnotify
taskopen
python3
]; ];
home.file = { home.file = {
".config/task/taskrc" = { ".config/task/taskrc" = {
force = true; # overwrite when present force = true; # overwrite when present
source = ../../dots/.config/task/taskrc; source = dotsPath + "/.config/task/taskrc";
}; };
".config/task/taskrc.d/aliases".source = ../../dots/.config/task/taskrc.d/aliases; ".config/task/taskrc.d/aliases".source = dotsPath + "/.config/task/taskrc.d/aliases";
".config/task/taskrc.d/colors".source = ../../dots/.config/task/taskrc.d/colors; ".config/task/taskrc.d/colors".source = dotsPath + "/.config/task/taskrc.d/colors";
".config/task/taskrc.d/contexts".source = ../../dots/.config/task/taskrc.d/contexts; ".config/task/taskrc.d/contexts".source = dotsPath + "/.config/task/taskrc.d/contexts";
".config/task/taskrc.d/reports".source = ../../dots/.config/task/taskrc.d/reports; ".config/task/taskrc.d/reports".source = dotsPath + "/.config/task/taskrc.d/reports";
".config/task/taskrc.d/udas".source = ../../dots/.config/task/taskrc.d/udas; ".config/task/taskrc.d/udas".source = dotsPath + "/.config/task/taskrc.d/udas";
".config/task/taskrc.d/urgency".source = ../../dots/.config/task/taskrc.d/urgency; ".config/task/taskrc.d/urgency".source = dotsPath + "/.config/task/taskrc.d/urgency";
".local/share/task/hooks/on-exit.sync.py" = { ".local/share/task/hooks/on-exit.sync.py" = {
source = ../../dots/.local/share/task/hooks/on-exit.sync.py; source = dotsPath + "/.local/share/task/hooks/on-exit.sync.py";
}; };
".local/share/task/scripts/sync-and-notify.sh" = { ".local/share/task/scripts/sync-and-notify.sh" = {
source = ../../dots/.local/share/task/scripts/sync-and-notify.sh; source = dotsPath + "/.local/share/task/scripts/sync-and-notify.sh";
executable = true; executable = true;
}; };
}; };
@@ -35,17 +50,10 @@
package = taskwarrior3; package = taskwarrior3;
colorTheme = "dark-256"; colorTheme = "dark-256";
config = { config = {
# sync = {
# server.url = "${builtins.readFile config.sops.secrets."taskwarrior_sync_server_url".path}";
# server.client_id = "${builtins.readFile
# config.sops.secrets."taskwarrior_sync_server_client_id".path
# }";
# encryption_secret = "${builtins.readFile
# config.sops.secrets."taskwarrior_sync_encryption_secret".path
# }";
# };
recurrence = "off"; recurrence = "off";
}; };
extraConfig = "include ${config.sops.templates."taskrc.d/sync".path}"; extraConfig = lib.optionalString sopsAvailable ''
include ${sopsTemplates."taskrc.d/sync".path}
'';
}; };
} }

25
home/modules/tmux.nix Normal file
View File

@@ -0,0 +1,25 @@
{
pkgs,
dotsPath,
...
}:
{
config = {
home.packages = with pkgs; [
tmux
tmuxp
reptyr
];
home.file = {
".config/tmux/tmux.conf".source = dotsPath + "/.config/tmux/tmux.conf";
".config/tmux/tmux.regular.conf".source = dotsPath + "/.config/tmux/tmux.regular.conf";
".config/tmux/themes/zenwritten_light.tmux".source =
dotsPath + "/.config/tmux/themes/zenwritten_light.tmux";
".config/tmux/themes/zenwritten_dark.tmux".source =
dotsPath + "/.config/tmux/themes/zenwritten_dark.tmux";
".config/tmux/hooks/tmux.ssh.conf".source = dotsPath + "/.config/tmux/hooks/tmux.ssh.conf";
".config/tmux/hooks/tmux.regular.conf".source = dotsPath + "/.config/tmux/hooks/tmux.regular.conf";
};
};
}

View File

@@ -0,0 +1,57 @@
[
{
"height": 16,
"spacing": 4,
"modules-left": ["niri/workspaces"],
"modules-right": [
"pulseaudio",
"memory",
"cpu",
"network",
"clock",
"battery",
],
"clock": {
"format": "W{:%V %d %b %H:%M}",
"tooltip-format": "{calendar}",
"format-alt": "{:%Y-%m-%d %H:%M:%S}",
},
"battery": {
"bat": "BAT0",
"adapter": "ADP1",
"interval": 5,
"full-at": 99,
"states": {
"good": 80,
"warning": 20,
"critical": 10,
},
"format": "{capacity}%--",
"format-charging": "{capacity}%++",
"format-plugged": "{capacity}%",
"format-alt": "{time} {power}W",
},
"pulseaudio": {
"format": "VOL {volume}%",
"format-muted": "muted",
"on-click": "pavucontrol",
},
"memory": {
"interval": 2,
"format": "RAM {percentage}%",
"format-alt": "RAM {used:0.1f}G/{total:0.1f}G",
},
"cpu": {
"interval": 2,
"format": "CPU {usage}%",
"format-alt": "CPU {avg_frequency}GHz",
},
"network": {
"interval": 5,
"format-wifi": "{ifname} {ipaddr} {essid}",
"format-ethernet": "{ifname} {ipaddr}",
"format-disconnected": "{ifname} disconnected",
"tooltip-format": "{ifname}: {ipaddr}/{cidr}",
},
},
]

View File

@@ -0,0 +1,8 @@
{
programs.waybar = {
enable = true;
};
home.file.".config/waybar/config.jsonc".source = ./config.jsonc;
home.file.".config/waybar/style.css".source = ./style.css;
}

View File

@@ -0,0 +1,56 @@
* {
font-family:
Iosevka Term SS08,
monospace;
font-size: 12px;
border-radius: 0px;
}
.modules-left,
.modules-center,
.modules-right {
margin: 4px;
margin-bottom: 0;
}
window#waybar {
background-color: transparent;
}
window#waybar.hidden {
opacity: 0.2;
}
#workspaces button {
padding: 0;
background-color: transparent;
}
#workspaces button:hover {
background: #000000;
}
#workspaces button.focused,
#workspaces button.active {
background-color: #111111;
}
#workspaces button.urgent {
background-color: #eb4d4b;
}
#clock,
#battery,
#pulseaudio,
#memory,
#cpu,
#network {
padding: 0 4px;
color: #ffffff;
background-color: #111111;
}
#window,
#workspaces {
margin: 0;
}

View File

@@ -1,47 +1,65 @@
{ {
lib, lib,
inputs, inputs,
outputs,
self,
config, config,
pkgs, pkgs,
... ...
}: }:
let let
username = "h"; username = "h";
hostName = "andromache";
wolInterfaces = import ./wol-interfaces.nix;
in in
{ {
imports = [ imports = [
../../modules/common.nix
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
inputs.sops-nix.nixosModules.sops ../../modules/common
inputs.home-manager.nixosModules.default
./hard.nix ./hard.nix
../../modules/bootloader.nix inputs.nixos-hardware.nixosModules.common-cpu-intel
(import ../../modules/disko.zfs-encrypted-root.nix { inputs.nixos-hardware.nixosModules.common-pc
inputs.nixos-hardware.nixosModules.common-pc-ssd
inputs.sops-nix.nixosModules.sops
../../modules/boot/bootloader.nix
(import ../../modules/disko/zfs-encrypted-root.nix {
inherit lib config;
device = "/dev/nvme1n1"; device = "/dev/nvme1n1";
inherit lib;
inherit config;
}) })
../../modules/gnome.nix ../../modules/desktops/niri
../../modules/bluetooth.nix ../../modules/backups
../../modules/keyboard ../../modules/bluetooth
(import ../../modules/networking.nix { hostName = "andromache"; }) ../../modules/## modules/keyboard
../../modules/users.nix (import ../../modules/networking { inherit hostName; })
../../modules/audio.nix ../../modules/users
../../modules/localization.nix ../../modules/audio
../../modules/localization
../../modules/fonts ../../modules/fonts
../../modules/ssh/hardened-openssh.nix ../../modules/ssh/hardened-openssh.nix
(import ../../modules/secrets { (import ../../modules/secrets { inherit lib inputs config; })
inherit lib; ../../modules/docker
inherit inputs; ../../modules/syncthing
inherit config;
})
../../modules/docker.nix
]; ];
home-manager.users.${username} = import ../../home/hosts/andromache {
inherit
inputs
config
pkgs
lib
;
};
networking.hostName = hostName;
ssh.username = username;
ssh.authorizedHosts = [ "astyanax" ];
secrets.username = username; secrets.username = username;
docker.user = username; docker.user = username;
nix.settings.secret-key-files = [ config.sops.secrets.nix_signing_key_andromache.path ];
disko.devices = { disko.devices = {
disk.data = { disk.data = {
type = "disk"; type = "disk";
@@ -75,57 +93,125 @@ in
}; };
}; };
environment.systemPackages = [ inputs.nvim.packages.x86_64-linux.nvim ]; boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
home-manager = { environment.systemPackages = [
useGlobalPkgs = true; inputs.colmena.packages.${pkgs.system}.colmena
useUserPackages = true; ];
users.${username} = import ../../home/hosts/andromache {
inherit lib;
inherit inputs;
inherit config;
inherit pkgs;
};
};
networking = { services = {
hostId = "80eef97e"; xserver = {
};
services.xserver = {
videoDrivers = [ "nvidia" ]; videoDrivers = [ "nvidia" ];
}; };
services.openssh = { openssh = {
enable = true; enable = true;
harden = true; harden = true;
}; };
services.syncthing = { locate = {
enable = true;
openDefaultPorts = true;
folders = {
"/home/${username}/sync" = {
id = "sync";
devices = [ ];
};
};
devices = {
# "device1" = {
# id = "DEVICE-ID-GOES-HERE";
# };
};
};
services.locate = {
enable = true; enable = true;
package = pkgs.plocate; package = pkgs.plocate;
}; };
};
networking.hostName = hostName;
ssh.username = username;
ssh.authorizedHosts = [ "astyanax" ];
secrets.username = username;
docker.user = username;
nix.settings.secret-key-files = [ config.sops.secrets.nix_signing_key_andromache.path ];
disko.devices = {
disk.data = {
type = "disk";
device = "/dev/nvme0n1";
content = {
type = "gpt";
partitions = {
data = {
size = "100%";
content = {
type = "filesystem";
format = "ext4";
mountpoint = "/data";
};
};
};
};
};
};
hardware = {
cpu.intel.updateMicrocode = true;
graphics.enable = true;
nvidia = {
modesetting.enable = true;
powerManagement.enable = true;
powerManagement.finegrained = false;
open = true;
nvidiaSettings = true;
package = config.boot.kernelPackages.nvidiaPackages.stable;
};
};
boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
environment.systemPackages = [
inputs.colmena.packages.${pkgs.system}.colmena
];
services = {
git-hooks = {
enable = true;
};
xserver = {
videoDrivers = [ "nvidia" ];
};
openssh = {
enable = true;
harden = true;
};
locate = {
enable = true;
package = pkgs.plocate;
};
};
# my.syncthing = {
# enable = true;
# deviceNames = [
# "boox"
# "astyanax"
# ];
# folders = {
# readings = {
# path = "/home/h/doc/readings";
# id = "readings";
# devices = [
# {
# device = "boox";
# type = "receiveonly";
# }
# "astyanax"
# ];
# };
# };
# };
networking = { networking = {
# TODO: generate unique hostId on actual host with: head -c 8 /etc/machine-id
hostId = "80eef97e";
interfaces = { interfaces = {
eno1 = { eno1 = {
wakeOnLan.enable = true; wakeOnLan.enable = true;
inherit (wolInterfaces.eno1) macAddress;
}; };
}; };
firewall = { firewall = {

View File

@@ -14,7 +14,8 @@
(modulesPath + "/installer/scan/not-detected.nix") (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = [ boot = {
initrd.availableKernelModules = [
"vmd" "vmd"
"xhci_pci" "xhci_pci"
"ahci" "ahci"
@@ -24,9 +25,10 @@
"uas" "uas"
"sd_mod" "sd_mod"
]; ];
boot.initrd.kernelModules = [ ]; initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; extraModulePackages = [ ];
};
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's # (the default) this is the recommended approach. When using systemd-networkd it's

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIG7TMnKO4EqISk2s/xy+3P2xn8XcMOuzZrSiYTZT+8m2 root@andromache

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOOXPEhdKOVnb6mkeLLUcFGt+mnUR5pMie17JtjrxwgO h@andromache

View File

@@ -0,0 +1 @@
"x86_64-linux"

View File

@@ -0,0 +1,3 @@
{
eno1.macAddress = "02:68:b3:29:da:98";
}

View File

@@ -1,87 +1,114 @@
{ {
lib, lib,
inputs, inputs,
outputs,
self,
config, config,
pkgs, pkgs,
... ...
}: }:
let let
username = "h"; username = "h";
hostName = "astyanax"; hostName = "astyanax";
wolInterfaces = import ../andromache/wol-interfaces.nix;
in in
{ {
imports = [ imports = [
../../modules/common.nix
inputs.nixos-hardware.nixosModules.lenovo-thinkpad-e14-intel
inputs.disko.nixosModules.disko inputs.disko.nixosModules.disko
inputs.sops-nix.nixosModules.sops ../../modules/common
inputs.home-manager.nixosModules.default
./hard.nix ./hard.nix
../../modules/bootloader.nix inputs.nixos-hardware.nixosModules.common-pc
(import ../../modules/disko.zfs-encrypted-root.nix { inputs.nixos-hardware.nixosModules.common-pc-ssd
inherit lib; # inputs.nixos-hardware.nixosModules.lenovo-thinkpad-e14-intel-gen7 (not available yet?)
inherit config; inputs.sops-nix.nixosModules.sops
../../modules/boot/bootloader.nix
(import ../../modules/disko/zfs-encrypted-root.nix {
inherit lib config;
device = "/dev/nvme0n1"; device = "/dev/nvme0n1";
}) })
../../modules/gnome.nix ../../modules/desktops/niri
../../modules/bluetooth.nix ../../modules/audio
../../modules/audio-automation
../../modules/backups
../../modules/bluetooth
../../modules/keyboard ../../modules/keyboard
(import ../../modules/networking.nix { hostName = hostName; }) (import ../../modules/networking { inherit hostName; })
../../modules/users.nix ../../modules/users
../../modules/audio.nix ../../modules/localization
../../modules/localization.nix
../../modules/fonts ../../modules/fonts
../../modules/ssh/hardened-openssh.nix ../../modules/ssh/hardened-openssh.nix
(import ../../modules/secrets { # ../../modules/vpn/wireguard.nix
inherit lib; (import ../../modules/secrets { inherit lib inputs config; })
inherit inputs; ../../modules/docker
inherit config; ../../modules/syncthing
inherit username; ];
home-manager.users.${username} = import ../../home/hosts/astyanax {
inherit
inputs
config
pkgs
lib
;
};
networking.hostName = hostName;
ssh.username = username;
ssh.authorizedHosts = [ "andromache" ];
secrets.username = username;
docker.user = username;
nix.settings.secret-key-files = [ config.sops.secrets.nix_signing_key_astyanax.path ];
hardware = {
cpu.intel.updateMicrocode = true;
# https://wiki.nixos.org/wiki/Intel_Graphics
graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver
vpl-gpu-rt
];
};
};
# https://wiki.nixos.org/wiki/Intel_Graphics
environment.sessionVariables = {
LIBVA_DRIVER_NAME = "iHD";
};
environment.systemPackages = [
inputs.colmena.packages.${pkgs.system}.colmena
(pkgs.writeShellApplication {
name = "wol-andromache";
runtimeInputs = [ pkgs.wakeonlan ];
text = ''
wakeonlan ${wolInterfaces.eno1.macAddress}
'';
}) })
]; ];
secrets.username = username;
environment.systemPackages = [ inputs.nvim.packages.x86_64-linux.nvim ];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
users.${username} = import ../../home/hosts/astyanax {
inherit inputs;
inherit config;
inherit pkgs;
};
};
networking = { networking = {
# TODO: generate unique hostId on actual host with: head -c 8 /etc/machine-id
hostId = "80eef97e"; hostId = "80eef97e";
}; };
services.openssh = { boot.binfmt.emulatedSystems = [ "aarch64-linux" ];
services = {
git-hooks = {
enable = true;
};
fwupd.enable = true;
openssh = {
enable = true; enable = true;
harden = true; harden = true;
}; };
locate = {
services.syncthing = {
enable = true;
openDefaultPorts = true;
folders = {
"/home/h/sync" = {
id = "sync";
devices = [ ];
};
};
devices = {
# "device1" = {
# id = "DEVICE-ID-GOES-HERE";
# };
};
};
services.locate = {
enable = true; enable = true;
package = pkgs.plocate; package = pkgs.plocate;
}; };
};
} }

View File

@@ -14,16 +14,18 @@
(modulesPath + "/installer/scan/not-detected.nix") (modulesPath + "/installer/scan/not-detected.nix")
]; ];
boot.initrd.availableKernelModules = [ boot = {
initrd.availableKernelModules = [
"xhci_pci" "xhci_pci"
"thunderbolt" "thunderbolt"
"nvme" "nvme"
"uas" "uas"
"sd_mod" "sd_mod"
]; ];
boot.initrd.kernelModules = [ ]; initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ]; kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; extraModulePackages = [ ];
};
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking # Enables DHCP on each ethernet and wireless interface. In case of scripted networking
# (the default) this is the recommended approach. When using systemd-networkd it's # (the default) this is the recommended approach. When using systemd-networkd it's

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO8+UOyZbvQeHfFfYox3SQi42KJ0S3RZj79iswSsZeFy root@nixos

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIzP1PjIDb1tN9nhPOK88HYDtTNk9SN9ZpEem2id49Fa h@astyanax

View File

@@ -0,0 +1 @@
"x86_64-linux"

130
hosts/eetion/default.nix Normal file
View File

@@ -0,0 +1,130 @@
{ pkgs, ... }:
# Orange Pi Zero2 H616
# See <https://nixos.wiki/wiki/NixOS_on_ARM/Orange_Pi_Zero2_H616>
let
username = "h";
hostName = "eetion";
in
{
imports = [
./hard.nix
../../modules/ssh/hardened-openssh.nix
];
ssh.username = username;
ssh.publicHostname = "eetion";
ssh.authorizedHosts = [
"andromache"
"astyanax"
];
ssh.username = username;
ssh.publicHostname = "eetion";
ssh.authorizedHosts = [
"andromache"
"astyanax"
];
boot.loader = {
grub.enable = false;
generic-extlinux-compatible.enable = true;
};
networking.hostName = hostName;
networking.networkmanager.enable = true;
networking.firewall = {
enable = true;
allowedTCPPorts = [
80
443
];
};
users.users = {
root.hashedPassword = "!";
${username} = {
isNormalUser = true;
extraGroups = [ "wheel" ];
};
};
security.sudo.wheelNeedsPassword = false;
services.openssh = {
enable = true;
harden = true;
};
environment.etc."paperless-admin-pass".text = "admin";
services.paperless = {
enable = true;
passwordFile = "/etc/paperless-admin-pass";
settings = {
PAPERLESS_URL = "http://paperless.eetion";
};
};
# added (OPNSense) domain override to make this work on LAN
#
# host: eetion
# domain: <domain (e.g. lan)>
# ip address: <eetion-ip>
#
# host: paperless
# domain: eetion
# ip address: <eetion-ip>
services.nginx = {
enable = true;
recommendedGzipSettings = true;
recommendedOptimisation = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
virtualHosts = {
"eetion" = {
default = true;
locations."/" = {
proxyPass = "http://127.0.0.1:5006";
};
};
"paperless.eetion" = {
locations."/" = {
proxyPass = "http://127.0.0.1:28981";
};
};
};
};
virtualisation = {
podman.enable = true;
oci-containers = {
backend = "podman";
containers.actualbudget = {
image = "docker.io/actualbudget/actual-server:latest-alpine";
ports = [ "5006:5006" ];
volumes = [ "/var/lib/actualbudget:/data" ];
};
};
};
environment.systemPackages = with pkgs; [
vim
git
];
nix.settings = {
experimental-features = [
"nix-command"
"flakes"
];
trusted-users = [
"root"
"@wheel"
];
};
system.stateVersion = "26.05";
}

22
hosts/eetion/hard.nix Normal file
View File

@@ -0,0 +1,22 @@
{ lib, modulesPath, ... }:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [ ];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-label/NIXOS_SD";
fsType = "ext4";
options = [ "noatime" ];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux";
}

1
hosts/eetion/system.nix Normal file
View File

@@ -0,0 +1 @@
"aarch64-linux"

View File

@@ -0,0 +1,71 @@
# Hecuba uptime server plan
## Current State
- Hecuba is a Hetzner cloud host running NixOS
- Docker is enabled for user `username`
- Firewall allows ports 80 and 443
- No existing uptime monitoring
## Goals
Monitor docker containers on hecuba with a self-hosted uptime dashboard
## Uptime Monitoring Options
### Option 1: Uptime Kuma (Recommended)
- Easy to use web dashboard
- Docker-based (fits existing setup)
- HTTP/TCP/Ping monitoring
- Status pages
- Notifications (email, Telegram, etc.)
## Implementation Plan
### Phase 1: Evaluate & Choose
- [ ] Research uptime monitoring solutions $id{11c06cf8-bea2-4858-9c7f-a293c3e8fba5}
- [ ] Decide on solution (Uptime Kuma likely best fit) $id{f87debaa-312e-424e-80e0-b624f0768774}
### Phase 2: Docker Setup
- [ ] Add uptime monitoring container to hecuba $id{7d8c5bf4-3d49-4f4c-87f1-1f34c5a4dbec}
- [ ] Configure persistent storage $id{9568b276-2885-4ae7-b5ca-5a9d7efb6a69}
- [ ] Set up reverse proxy (ports 80/443 already open) $id{c2f6ea85-f5e3-465d-95ba-62738a97da80}
- [ ] Configure SSL certificate $id{95c257e2-931b-44da-b0b1-a3e088956800}
### Phase 3: Configuration
- [ ] Add docker containers to monitor $id{4670deda-70d2-4c37-8121-2035aa7d57fb}
- [ ] Set up alert thresholds $id{da6acf90-0b62-4451-bb11-4f74c5c5dd27}
- [ ] Configure notifications (email/Telegram) $id{0b188adf-9a27-4499-9a19-b1ebd081bd21}
- [ ] Test monitoring $id{dd0df63f-5da2-4ba0-a386-45162a2bb642}
### Phase 4: Maintenance
- [ ] Add to backup routine $id{33a2c381-94cb-460e-b600-67cb503826d7}
- [ ] Document monitoring setup $id{f3bf7b85-737f-4511-8d3e-a270044abea3}
- [ ] Review and adjust alerts $id{32e46c53-dd9d-48a8-aef2-985ebaadd8da}
## Technical Details
### Storage Location
`/var/lib/uptime-kuma` or similar persistent volume
### Docker Compose Structure
```yaml
services:
uptime-kuma:
image: louislam/uptime-kuma:1
volumes:
- /var/lib/uptime-kuma:/app/data
ports:
- 3001:3001
restart: always
```
### NixOS Integration
- Consider using `virtualisation.oci-containers` for declarative setup
- Or keep docker-compose file (more flexible for updates)
## Next Steps
1. Pick uptime monitoring solution
2. Decide on deployment method (NixOS declarative vs docker-compose)
3. Implement

Some files were not shown because too many files have changed in this diff Show More