Author SHA1 Message Date
moons-14 ec3770502d Add central Nix builder and binary cache 2026-08-31 08:07:48 +09:00
moons-14 fda29cd08d update 2026-08-30 06:48:50 +09:00
moons-14 db0a440da4 update Python to 3.14 2026-08-30 05:52:30 +09:00
moons-14 76f5dce9c0 update CodexBar to 0.56.0 2026-08-30 05:52:23 +09:00
moons-14 3b61457718 remove obsolete Codex skill alias 2026-08-30 05:52:16 +09:00
moons-14 c9f1584797 replace Codex Desktop with ChatGPT 2026-08-30 05:52:06 +09:00
moons-14 d51948c307 hugging face 2026-08-29 16:29:42 +09:00
moons-14 9a38e9f614 gpu settings 2026-08-29 16:14:32 +09:00
moons-14 2cb7e76ca1 nix s9 camera 2026-08-27 12:09:55 +09:00
moons-14 749410e032 fix 2026-08-26 21:35:17 +09:00
moons-14 d43f19c20a nix builder 2026-08-26 17:28:09 +09:00
moons-14 32a3067cb0 hardware configuration 2026-08-26 15:53:44 +09:00
moons-14 6e60bd8886 add nix-builder 2026-08-26 13:21:37 +09:00
moons-14 bcf7ef56cf update 2026-08-25 09:24:58 +09:00
moons-14 63e2008423 chrome video play 2026-08-24 02:14:30 +09:00
moons-14 3b8147ff46 codex setting 2026-08-23 14:06:05 +09:00
moons-14 c84f257149 ffmpeg and yt-dlp 2026-08-23 14:04:36 +09:00
moons-14 6347292c1d projects 2026-08-21 05:44:16 +09:00
moons-14 2a82433754 fix(vesktop): restrict WebRTC to public default interface (#67) 2026-08-21 05:31:13 +09:00
moons-14 847ee17b29 linuxPackages 2026-08-21 05:08:30 +09:00
moons-14 95f74aabcd feat 2026-08-21 05:08:30 +09:00
moons-14 717572ae24 feat 2026-08-21 05:08:30 +09:00
moons-14 8086c9a7f3 fix(vesktop): avoid DTLS stalls with multiple interfaces (#66)
* fix(vesktop): add WebRTC IP handling support

* fix(vesktop): constrain WebRTC interface selection
2026-08-21 04:31:24 +09:00
moons-14 eba23455d4 noctalia 2026-08-21 02:32:23 +09:00
moons-14 b3b1031364 fix 2026-08-20 06:18:23 +09:00
moons-14 366ff54403 allow suspend 2026-08-18 10:19:12 +09:00
moons-14 456e9946f4 flake update 2026-08-18 06:56:34 +09:00
moons-14 c104404e5b remove handy 2026-08-18 06:56:28 +09:00
moons-14 cb41932fec add installer keys 2026-08-18 06:29:01 +09:00
moons-14 fa4b7ca404 codex mutable config 2026-08-18 06:25:46 +09:00
moons-14 847d33e83b simplify codex home configuration 2026-08-18 06:12:20 +09:00
moons-14 b2c700e1e4 remove niri window overview bindings 2026-08-18 06:10:56 +09:00
moons-14 c1540d8764 remove noctalia patches 2026-08-18 06:10:43 +09:00
moons-14 5b8c3b1415 remove labwc patch 2026-08-18 06:10:29 +09:00
moons-14 6743569789 remove window-overview 2026-08-18 06:09:11 +09:00
moons-14 70253fc451 evremap 2026-08-18 05:16:18 +09:00
moons-14 5107b80173 feat(ssh): use available SSH agent socket 2026-08-18 05:00:21 +09:00
moons-14 2bdea522cb feat(niri): toggle floating windows with middle click 2026-08-18 05:00:13 +09:00
moons-14 c113d0d46d feat(x1g9): remap VXE mouse buttons 2026-08-18 05:00:05 +09:00
moons-14 fa50be8feb vicinae chrome integuration 2026-08-18 04:41:31 +09:00
moons-14 33ebef4a1e niri keybind 2026-08-18 04:21:16 +09:00
moons-14 94048ef8d5 wallpaper 2026-08-18 04:20:59 +09:00
moons-14 c7627fa1b0 darwin: add stable Xcode and iOS simulator shell (#65)
* darwin: add xcode ios simulator shell

* docs: add iOS simulator setup
2026-08-14 20:35:13 +09:00
moons-14 d68da620ac oh my openagent 2026-08-10 03:25:01 +09:00
moons-14 5f0df47775 codex 2026-08-09 19:54:35 +09:00
moons-14 119342e564 codex 2026-08-09 19:12:02 +09:00
moons-14 1f066e8937 codex 2026-08-09 18:51:09 +09:00
moons-14 0a440e3da8 update codex session usage 2026-08-09 18:13:03 +09:00
moons-14 bdf93ac6bb codex agents prompt 2026-08-09 15:58:40 +09:00
moons-14 9ae5da4d30 zed docker file extension 2026-08-09 15:40:11 +09:00
moons-14 872436b170 skill 2026-08-08 13:14:29 +09:00
moons-14 c14325e29c Update flake.lock 2026-08-08 06:46:59 +09:00
moons-14 45bc66e25f codex prompt 2026-08-08 06:45:22 +09:00
moons-14 78ee2d41ec codex usage vicinae 2026-08-08 05:51:40 +09:00
moons-14 0b1ae13048 window-overview 2026-08-08 04:15:35 +09:00
moons-14 458b0a2cdb galleria tailscale 2026-08-08 00:16:33 +09:00
moons-14 01179f3dc6 desktop: disable system sleep 2026-08-07 22:00:03 +09:00
moons-14 42949fc06c zed: enable Copilot edit predictions 2026-08-07 21:59:57 +09:00
moons-14 a7f514c0f9 opencode: install package through Home Manager 2026-08-07 21:59:47 +09:00
moons-14 9bed1c3e25 zed: add vim keymaps 2026-08-07 21:58:25 +09:00
moons-14 791b6baa83 mod + v toggle 2026-08-07 20:33:44 +09:00
moons-14 349f49e496 fix 2026-08-07 20:33:33 +09:00
moons-14 3166c12448 codex 2026-08-07 18:34:49 +09:00
moons-14 4c459e4aa7 codex back vesion 2026-08-07 18:34:17 +09:00
moons-14 9b9141dd84 lock codex version 2026-08-07 17:30:50 +09:00
moons-14 16e3fda275 ghostty single instance 2026-08-07 14:44:48 +09:00
moons-14 ca36b07839 Display OFF 2026-08-07 06:28:27 +09:00
moons-14 5ebcbb4abf labwc 2026-08-06 17:22:00 +09:00
moons-14 f8fd8a3d99 wallpaper engine 2026-08-06 17:13:02 +09:00
moons-14 16742d2fd7 window overlay 2026-08-05 06:21:26 +09:00
moons-14 15da7affaa window-overview 2026-08-05 05:53:23 +09:00
moons-14 548647fec7 window switch 2026-08-05 05:27:40 +09:00
moons-14 bcbd08c225 wallpaper vicinae 2026-08-05 05:04:22 +09:00
moons-14 a0ae83d24e feat 2026-08-05 04:37:32 +09:00
moons-14 33e09f8e93 normcap-translate 2026-08-05 03:56:16 +09:00
moons-14 eff32fddcd background-opacity 2026-08-05 03:56:16 +09:00
moons-14 8ce3a6082a dns 2026-08-05 03:56:16 +09:00
moons-14 a8246261ad noctalia: add taskbar overview command hook (#61) 2026-08-05 03:54:14 +09:00
moons-14 8b51b5c55f noctalia taskbar 2026-08-05 02:55:46 +09:00
moons-14 e24d85da56 echo cancel 2026-08-05 02:10:48 +09:00
moons-14 01ead9a385 labwc suspend 2026-08-05 02:10:36 +09:00
moons-14 328f11d0ed screencast 2026-08-05 01:40:35 +09:00
moons-14 d877ffc76c nh 2026-08-05 01:40:18 +09:00
moons-14 fe40adaeee activity watch 2026-08-05 00:59:32 +09:00
moons-14 991dde5305 noctalia patch 2026-08-05 00:40:02 +09:00
moons-14 96ce4d768c nani wayland 2026-08-05 00:16:12 +09:00
moons-14 30b1480e50 hazkey 2026-08-04 23:06:25 +09:00
moons-14 71011d7bd1 thunderbird 2026-08-04 23:06:11 +09:00
moons-14 9cced59e58 thunderbird 2026-08-04 23:06:01 +09:00
moons-14 20a601402e rate 2026-08-04 17:03:03 +09:00
moons-14 1b4a5fa5a2 wallpaper engine 2026-08-04 16:58:40 +09:00
moons-14 5fb55f2e6a open ghostty 2026-08-04 16:49:56 +09:00
moons-14 2a3f7ee6ff nani 2026-08-04 16:16:32 +09:00
moons-14 247db71f2d nani 2026-08-04 16:04:44 +09:00
moons-14 a44a83a587 handy 2026-08-04 15:43:12 +09:00
moons-14 1f1d46ea2a find-cursor 2026-08-04 15:26:43 +09:00
moons-14 29c4815b88 screenshot 2026-08-04 14:59:21 +09:00
moons-14 28a46d9990 skill 2026-08-04 14:42:31 +09:00
moons-14 403971eef6 vesktop
CI: NixOS / Check all NixOS configurations (push) Canceled after 0s
2026-08-04 01:22:34 +09:00
moons-14 c62468396d chrome 2026-08-03 23:35:42 +09:00
moons-14 9145b36412 wallpaper 2026-08-03 23:16:21 +09:00
moons-14 f574b1d1e7 obs 2026-08-03 23:16:14 +09:00
moons-14 cf088a6998 labwc 2026-08-03 22:56:44 +09:00
moons-14 e4eb1802d7 screen shot 2026-08-03 22:29:39 +09:00
moons-14 a7c6a1507c ghostty 2026-08-03 22:27:58 +09:00
moons-14 49141e3478 kanshi 2026-08-03 21:45:35 +09:00
moons-14 cc91ad88b0 noctalia doc 2026-08-03 21:44:02 +09:00
moons-14 bb1f81a598 codex bar 2026-08-03 21:42:33 +09:00
moons-14 c0fdd9b4ef vscode 2026-08-03 21:35:44 +09:00
moons-14 aafcc1555d vicinae 2026-08-03 21:31:30 +09:00
moons-14 245f22e094 hash 2026-08-03 20:07:54 +09:00
moons-14 15ca59e43c suspend 2026-08-03 19:59:45 +09:00
moons-14 3627587bc7 niri 2026-08-03 18:17:42 +09:00
moons-14 d90aed6903 vicinae 2026-08-03 17:45:24 +09:00
moons-14 3e57b6c4c1 Keyring 2026-08-03 15:52:28 +09:00
moons-14 bdca6fb2fb lock screen 2026-08-03 15:28:52 +09:00
moons-14 98397cf152 polkit-gnome 2026-08-03 15:11:58 +09:00
moons-14 3162bc0eba neovim 2026-08-03 15:10:03 +09:00
moons-14 c3bb2f4d43 mac dock 2026-08-03 15:08:41 +09:00
moons-14 5edbc6cbb4 zsh 2026-08-03 14:50:42 +09:00
moons-14 bf28275b40 zoom 2026-08-03 14:46:57 +09:00
moons-14 92b4bc7b8d yazi 2026-08-03 14:33:31 +09:00
moons-14 9bbef37010 vscode 2026-08-03 14:33:25 +09:00
moons-14 e708ceee26 nh 2026-08-03 14:32:59 +09:00
moons-14 7604dfb0e3 vlc 2026-08-03 14:04:42 +09:00
moons-14 02f97f73df vicinae 2026-08-03 14:02:41 +09:00
moons-14 cde17e6a68 tealdeer 2026-08-03 13:40:02 +09:00
moons-14 64fe5020d0 ssh 2026-08-03 13:34:02 +09:00
moons-14 843dd0cbf4 slack 2026-08-03 13:32:27 +09:00
moons-14 0060fdae15 gnome app 2026-08-03 13:27:35 +09:00
moons-14 6402cdcf3a nautilus right click 2026-08-03 13:27:23 +09:00
moons-14 118d91f1d5 nautilus 2026-08-03 13:05:38 +09:00
moons-14 b261f4aec7 remote desktop 2026-08-03 13:05:34 +09:00
moons-14 b146081ba8 minecraft 2026-08-03 13:05:24 +09:00
moons-14 6f19ea8f23 prismlauncher 2026-08-03 12:47:45 +09:00
moons-14 aaa4542f25 mangohud 2026-08-03 12:33:25 +09:00
moons-14 d3ce44ff63 loupe 2026-08-03 12:32:10 +09:00
moons-14 fb3254daa1 playerctl 2026-08-03 12:28:50 +09:00
moons-14 e69203ce4c keybind 2026-08-03 12:24:38 +09:00
moons-14 e84fa82710 niri 2026-08-03 11:44:27 +09:00
moons-14 d5e4c90710 fcitx5 on labwc 2026-08-03 11:44:15 +09:00
moons-14 d67d53644e fcitx5 2026-08-03 09:59:01 +09:00
moons-14 f1dd96945a vscode 2026-08-03 09:50:43 +09:00
moons-14 aceb3d4808 labwc 2026-08-02 23:53:38 +09:00
moons-14 ac874a849e grok 2026-08-02 22:06:39 +09:00
moons-14 519f7dd54d gnone apps 2026-08-02 22:04:46 +09:00
moons-14 233ba91309 ghostty 2026-08-02 21:57:19 +09:00
moons-14 e6c80ad5d6 gamemode 2026-08-02 21:48:44 +09:00
moons-14 847d7ee6dd nix-index 2026-08-02 21:48:38 +09:00
moons-14 5e12c1d953 fxitx5 2026-08-02 21:35:35 +09:00
moons-14 dfc4dc79d6 easyeffects 2026-08-02 20:39:24 +09:00
moons-14 5deab38d3c drawio 2026-08-02 20:35:08 +09:00
moons-14 3c674e34c1 docker 2026-08-02 20:33:19 +09:00
moons-14 506602d7e1 vesktop 2026-08-02 20:25:18 +09:00
moons-14 6b4253e1d4 direnv 2026-08-02 20:17:14 +09:00
moons-14 a3660b5733 chatgpt 2026-08-02 20:14:08 +09:00
moons-14 894b18bd10 chrome 2026-08-02 19:57:32 +09:00
moons-14 08effb9e29 celluloid 2026-08-02 19:52:47 +09:00
moons-14 605e63acdb home file 2026-08-02 19:40:54 +09:00
moons-14 12c9d5241b galleria fingerprint 2026-08-02 19:11:42 +09:00
moons-14 ac44bdf22f baobab 2026-08-02 19:07:23 +09:00
moons-14 421ede5d57 atuin 2026-08-02 19:03:25 +09:00
moons-14 7204e3e8f6 1password 2026-08-02 19:00:34 +09:00
moons-14 f696ed6b93 remove pear-desktop 2026-08-02 18:56:37 +09:00
moons-14 d1891382ea 1password 2026-08-02 18:54:40 +09:00
moons-14 4a7516939c galleria disk uuid 2026-08-02 18:28:13 +09:00
moons-14 176cd60d68 feat 2026-08-02 17:54:30 +09:00
moons-14 7c66c15da5 Replace Parsec with Sunshine and Moonlight 2026-07-31 23:56:43 +09:00
moons-14 dddb7e07ab galleria chrome beta 2026-07-31 23:40:25 +09:00
moons-14 9ede34fcfd fix 2026-07-31 23:07:22 +09:00
moons-14 855b8c55cf luncher 2026-07-31 22:49:18 +09:00
moons-14 a51e9584b0 apps 2026-07-31 22:06:53 +09:00
moons-14 3dae1d26ef noctalia 2026-07-31 22:02:52 +09:00
moons-14 06cd9516b3 side folder 2026-07-31 21:24:40 +09:00
moons-14 f3098f2674 feat 2026-07-31 15:29:21 +09:00
moons-14 2f9c8f3d33 text editor 2026-07-31 14:39:43 +09:00
moons-14 82d00fb574 systemd 2026-07-31 14:39:33 +09:00
moons-14 ad6dff2f6a ly 2026-07-31 14:19:55 +09:00
moons-14 54b84c0544 noctalia workspace 2026-07-31 13:58:24 +09:00
moons-14 c3dbcda528 display 2026-07-31 13:58:09 +09:00
moons-14 480a1c3194 display 2026-07-31 13:40:16 +09:00
moons-14 37d4a4a7c5 kmscon 2026-07-31 13:40:08 +09:00
moons-14 e68e2f536f remove app list 2026-07-31 13:26:27 +09:00
moons-14 36f01a084f galleria host 2026-07-31 12:24:17 +09:00
moons-14 e9ab8c2caa sops add host 2026-07-31 12:23:05 +09:00
moons-14 7ef25c5e63 galleria hardware 2026-07-31 12:02:52 +09:00
moons-14 d6026a5bfc update 2026-07-30 18:02:00 +09:00
moons-14 b477446f5c galleria 2026-07-30 16:46:44 +09:00
moons-14 ee9ce66d55 mozc 2026-07-30 16:45:45 +09:00
moons-14 ecabb8b630 nwg-drawer 2026-07-30 16:16:41 +09:00
moons-14 831ae7bbc2 labwc 2026-07-30 15:56:46 +09:00
moons-14 8dc9452d95 labwc 2026-07-30 15:24:55 +09:00
moons-14 c566f426ec zoom 2026-07-30 02:05:35 +09:00
moons-14 e56af06b04 display 2026-07-30 02:05:29 +09:00
moons-14 acb5ed3449 zoom 2026-07-30 01:33:43 +09:00
moons-14 9f40aadab3 vscode 2026-07-30 01:32:32 +09:00
moons-14 55e1e0b5b4 minecraft mac 2026-07-30 01:06:13 +09:00
moons-14 aef1338d79 minecraft 2026-07-29 14:30:22 +09:00
moons-14 5bbf1d42e9 ci 2026-07-29 10:19:59 +09:00
moons-14 f02eeac2a3 parsec 2026-07-29 10:14:22 +09:00
moons-14 e23e0058bd privact 2026-07-29 09:52:32 +09:00
moons-14 e474c38aff parsec 2026-07-29 09:33:54 +09:00
moons-14 04e4bdaeff windows codex update error 2026-07-29 04:57:38 +09:00
moons-14 c02d6936fa windows 2026-07-29 04:54:08 +09:00
moons-14 3f35a54e0a windows 2026-07-29 04:01:25 +09:00
moons-14 601c94a5d8 niri 2026-07-28 01:33:30 +09:00
moons-14 7e8bd33c89 mac 2026-07-28 01:01:21 +09:00
moons-14 6f4f048f4c mac keyboard 2026-07-28 00:45:32 +09:00
moons-14 c2a5e174b9 mac dock 2026-07-28 00:30:46 +09:00
moons-14 b1954ba5be add hosts 2026-07-28 00:19:14 +09:00
moons-14 09a4fd83a7 noctalia 2026-07-28 00:07:48 +09:00
moons-14 1f4ec6b8cd x1g13 2026-07-27 23:45:54 +09:00
moons-14 5132a1af1b vicinae 2026-07-27 23:16:30 +09:00
moons-14 2a02beda38 mac 2026-07-27 22:27:49 +09:00
moons-14 ee0bd37915 mac 2026-07-27 22:04:11 +09:00
moons-14 a8113633db oxker test 2026-07-27 21:29:20 +09:00
moons-14 91bb7e80db feat hosts 2026-07-27 21:18:00 +09:00
moons-14 9bb95535cf fingerprint 2026-07-27 20:57:15 +09:00
moons-14 fcd0d75537 feat 2026-07-27 20:55:05 +09:00
moons-14 a8e9a4dce5 update flake.nix 2026-07-27 20:34:27 +09:00
moons-14 72ff60fb16 x1g9 2026-07-27 19:58:07 +09:00
moons-14 f65318b765 mac 2026-07-27 19:43:42 +09:00
moons-14 0257b2e2fd mac 2026-07-27 19:43:31 +09:00
moons-14 8fec0494ec feat 2026-07-27 19:31:25 +09:00
moons-14 89eeb23d1c add docs 2026-07-27 18:41:42 +09:00
moons-14 bf94d1183f add profiles 2026-07-27 18:31:50 +09:00
moons-14 6bd05887db add systems 2026-07-27 18:02:48 +09:00
moons-14 3e32c9874b add apps 2026-07-27 16:49:48 +09:00
moons-14 684acef46c add apps 2026-07-27 16:10:17 +09:00
moons-14 9061825c63 add apps 2026-07-27 16:10:03 +09:00
moons-14 e703e1b31c add vim, vscode, zed, zellij, zsh 2026-07-27 15:24:37 +09:00
moons-14 79cc69045f add gtk, niri, noctalia, ssh, swaylock 2026-07-27 15:10:46 +09:00
moons-14 5c2ff3cbcf add nix-index, ly 2026-07-27 14:32:59 +09:00
moons-14 c5d4de5a9d add fcitx5, ghostty, git 2026-07-27 14:06:13 +09:00
moons-14 c58bdd30c3 x1g9 2026-07-27 12:34:20 +09:00
moons-14 9771a85e3f x1g9 2026-07-27 11:26:27 +09:00
moons-14 5b1bde7d90 nix registory 2026-07-27 10:58:24 +09:00
moons-14 1d82ab92b6 feat 2026-07-27 10:05:55 +09:00
moons-14 19bc309b8b add document 2026-07-27 06:18:24 +09:00
moons-14 e477c6bee8 init files 2026-07-27 06:13:53 +09:00
moons-14 0171582307 delete 2026-07-27 05:51:17 +09:00
moons-14 dd40b978dd fix 2026-07-27 01:52:41 +09:00
533 changed files with 10531 additions and 6683 deletions
+27
View File
@@ -0,0 +1,27 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/nix-build.yaml
name: Check NixOS configurations
description: Build every NixOS configuration and the Registry tests
runs:
using: composite
steps:
- name: Build every NixOS configuration
shell: bash
run: |
set -euo pipefail
mapfile -t hosts < <(
nix eval --raw .#nixosConfigurations \
--apply 'configs: builtins.concatStringsSep "\n" (builtins.attrNames configs)'
)
installables=(.#checks.x86_64-linux.registry)
for host in "${hosts[@]}"; do
installables+=(".#nixosConfigurations.${host}.config.system.build.toplevel")
done
nix build \
--keep-going \
--no-link \
--print-build-logs \
--show-trace \
"${installables[@]}"
+22
View File
@@ -0,0 +1,22 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/actions/setup-nix/action.yaml
name: Setup Nix
description: Install Nix and cache the Nix store
runs:
using: composite
steps:
- name: Allow unprivileged user namespaces
if: runner.os == 'Linux'
shell: bash
run: sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 2>/dev/null || true
- name: Install Nix
uses: nixbuild/nix-quick-install-action@9f63be77f412a248c9d9a65a4c82cf066cdf8f0c # v35
with:
nix_conf: |
accept-flake-config = true
max-jobs = auto
- name: Cache Nix store
uses: nix-community/cache-nix-action@7df957e333c1e5da7721f60227dbba6d06080569 # v7.0.2
with:
primary-key: nix-${{ runner.os }}-${{ runner.arch }}-${{ hashFiles('flake.lock') }}
restore-prefixes-first-match: nix-${{ runner.os }}-${{ runner.arch }}-
gc-max-store-size-linux: 4G
@@ -1,260 +0,0 @@
name: Update Flake Input
description: Update one GitHub-backed Nix flake input and create a pull request
inputs:
input-name:
description: Name of the flake input to update
required: true
github-token:
description: Token used to query GitHub, push the update branch, and manage the pull request
required: true
base-branch:
description: Branch targeted by the pull request
required: false
default: main
minimum-release-age-days:
description: Minimum age of the target commit in days
required: false
default: "3"
skip-delay:
description: Update to the latest revision without applying the minimum age
required: false
default: "false"
auto-merge:
description: Enable squash auto-merge on the pull request
required: false
default: "true"
pr-labels:
description: Comma-separated labels to add when they already exist in the repository
required: false
default: dependencies,automated
outputs:
updated:
description: Whether flake.lock changed
value: ${{ steps.update.outputs.updated }}
current-version:
description: Previous locked revision
value: ${{ steps.update.outputs.current_version }}
new-version:
description: New locked revision
value: ${{ steps.update.outputs.new_version }}
pr-url:
description: URL of the created or updated pull request
value: ${{ steps.pull-request.outputs.pr_url }}
runs:
using: composite
steps:
- name: Update flake input
id: update
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
INPUT_NAME: ${{ inputs.input-name }}
MINIMUM_RELEASE_AGE_DAYS: ${{ inputs.minimum-release-age-days }}
SKIP_DELAY: ${{ inputs.skip-delay }}
run: |
set -euo pipefail
if [[ ! "$MINIMUM_RELEASE_AGE_DAYS" =~ ^[0-9]+$ ]]; then
echo "::error::minimum-release-age-days must be a non-negative integer"
exit 1
fi
node_key="$(
jq -er --arg input "$INPUT_NAME" '
.nodes.root.inputs[$input]
| if type == "array" then .[0] else . end
' flake.lock
)"
input_type="$(jq -r --arg node "$node_key" '.nodes[$node].locked.type // ""' flake.lock)"
input_owner="$(jq -r --arg node "$node_key" '.nodes[$node].locked.owner // ""' flake.lock)"
input_repo="$(jq -r --arg node "$node_key" '.nodes[$node].locked.repo // ""' flake.lock)"
input_ref="$(jq -r --arg node "$node_key" '.nodes[$node].original.ref // ""' flake.lock)"
current_rev="$(jq -er --arg node "$node_key" '.nodes[$node].locked.rev' flake.lock)"
if [ "$input_type" != "github" ] || [ -z "$input_owner" ] || [ -z "$input_repo" ]; then
echo "::error::${INPUT_NAME} is not a GitHub-backed flake input"
exit 1
fi
echo "Input: $INPUT_NAME"
echo "Repository: ${input_owner}/${input_repo}"
echo "Current revision: $current_rev"
if [ "$SKIP_DELAY" = "true" ]; then
nix flake update "$INPUT_NAME"
else
cutoff="$(date --utc --date="${MINIMUM_RELEASE_AGE_DAYS} days ago" +%Y-%m-%dT%H:%M:%SZ)"
api_args=(
--method GET
"repos/${input_owner}/${input_repo}/commits"
-f "until=$cutoff"
-f per_page=1
)
if [ -n "$input_ref" ]; then
api_args+=(-f "sha=$input_ref")
fi
echo "Selecting the newest commit no later than $cutoff"
target_data="$(gh api "${api_args[@]}" --jq '.[0] | {sha: .sha, date: .commit.committer.date}')"
target_rev="$(jq -er '.sha' <<< "$target_data")"
target_date="$(jq -er '.date' <<< "$target_data")"
if [ "$target_rev" = "$current_rev" ]; then
echo "The input is already at the newest eligible revision"
{
echo "updated=false"
echo "current_version=$current_rev"
echo "new_version=$current_rev"
} >> "$GITHUB_OUTPUT"
exit 0
fi
current_date="$(
gh api "repos/${input_owner}/${input_repo}/commits/${current_rev}" \
--jq '.commit.committer.date'
)"
current_timestamp="$(date --date="$current_date" +%s)"
target_timestamp="$(date --date="$target_date" +%s)"
if [ "$target_timestamp" -lt "$current_timestamp" ]; then
echo "The newest eligible revision is older than the current revision; skipping"
{
echo "updated=false"
echo "current_version=$current_rev"
echo "new_version=$current_rev"
} >> "$GITHUB_OUTPUT"
exit 0
fi
nix flake update "$INPUT_NAME" \
--override-input "$INPUT_NAME" "github:${input_owner}/${input_repo}/${target_rev}"
fi
if git diff --quiet -- flake.lock; then
echo "No lock file changes were produced"
{
echo "updated=false"
echo "current_version=$current_rev"
echo "new_version=$current_rev"
} >> "$GITHUB_OUTPUT"
exit 0
fi
new_node_key="$(
jq -er --arg input "$INPUT_NAME" '
.nodes.root.inputs[$input]
| if type == "array" then .[0] else . end
' flake.lock
)"
new_rev="$(jq -er --arg node "$new_node_key" '.nodes[$node].locked.rev' flake.lock)"
echo "New revision: $new_rev"
{
echo "updated=true"
echo "current_version=$current_rev"
echo "new_version=$new_rev"
echo "input_owner=$input_owner"
echo "input_repo=$input_repo"
} >> "$GITHUB_OUTPUT"
- name: Create or update pull request
id: pull-request
if: steps.update.outputs.updated == 'true'
shell: bash
env:
GH_TOKEN: ${{ inputs.github-token }}
INPUT_NAME: ${{ inputs.input-name }}
BASE_BRANCH: ${{ inputs.base-branch }}
CURRENT_REV: ${{ steps.update.outputs.current_version }}
NEW_REV: ${{ steps.update.outputs.new_version }}
INPUT_OWNER: ${{ steps.update.outputs.input_owner }}
INPUT_REPO: ${{ steps.update.outputs.input_repo }}
MINIMUM_RELEASE_AGE_DAYS: ${{ inputs.minimum-release-age-days }}
SKIP_DELAY: ${{ inputs.skip-delay }}
AUTO_MERGE: ${{ inputs.auto-merge }}
PR_LABELS: ${{ inputs.pr-labels }}
run: |
set -euo pipefail
branch_suffix="$(tr -c 'A-Za-z0-9._-' '-' <<< "$INPUT_NAME" | sed 's/-$//')"
branch="update-flake-${branch_suffix}"
current_short="${CURRENT_REV:0:8}"
new_short="${NEW_REV:0:8}"
title="chore(nix): update ${INPUT_NAME} to ${new_short}"
if [ "$SKIP_DELAY" = "true" ]; then
age_note="The minimum release age check was skipped for this manually requested update."
else
age_note="The target commit is at least ${MINIMUM_RELEASE_AGE_DAYS} days old."
fi
body="$(
printf '%s\n' \
"Automated update of the \`${INPUT_NAME}\` flake input." \
"" \
"- Previous revision: [\`${current_short}\`](https://github.com/${INPUT_OWNER}/${INPUT_REPO}/commit/${CURRENT_REV})" \
"- New revision: [\`${new_short}\`](https://github.com/${INPUT_OWNER}/${INPUT_REPO}/commit/${NEW_REV})" \
"- Changes: [compare](https://github.com/${INPUT_OWNER}/${INPUT_REPO}/compare/${CURRENT_REV}...${NEW_REV})" \
"" \
"$age_note"
)"
git config user.name "github-actions[bot]"
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git add flake.lock
git switch -C "$branch"
git commit -m "$title"
git fetch origin "refs/heads/${branch}:refs/remotes/origin/${branch}" || true
git push --force-with-lease origin "HEAD:refs/heads/${branch}"
label_args=()
available_labels="$(gh label list --limit 100 --json name --jq '.[].name')"
IFS=',' read -ra requested_labels <<< "$PR_LABELS"
for label in "${requested_labels[@]}"; do
label="$(xargs <<< "$label")"
if [ -n "$label" ] && grep -Fxq "$label" <<< "$available_labels"; then
label_args+=(--add-label "$label")
elif [ -n "$label" ]; then
echo "::warning::Skipping missing pull request label: $label"
fi
done
pr_number="$(
gh pr list \
--state open \
--head "$branch" \
--json number \
--jq '.[0].number // empty'
)"
if [ -n "$pr_number" ]; then
gh pr edit "$pr_number" \
--title "$title" \
--body "$body" \
"${label_args[@]}"
else
gh pr create \
--base "$BASE_BRANCH" \
--head "$branch" \
--title "$title" \
--body "$body"
pr_number="$(
gh pr list \
--state open \
--head "$branch" \
--json number \
--jq '.[0].number'
)"
if [ "${#label_args[@]}" -gt 0 ]; then
gh pr edit "$pr_number" "${label_args[@]}"
fi
fi
if [ "$AUTO_MERGE" = "true" ]; then
gh pr merge "$pr_number" --auto --squash ||
echo "::warning::Auto-merge could not be enabled; check the repository merge settings"
fi
pr_url="$(gh pr view "$pr_number" --json url --jq '.url')"
echo "pr_url=$pr_url" >> "$GITHUB_OUTPUT"
echo "Pull request: $pr_url"
-150
View File
@@ -1,150 +0,0 @@
name: NixOS CI
on:
pull_request:
branches:
- main
push:
branches:
- main
workflow_dispatch:
permissions:
contents: read
concurrency:
group: nixos-ci-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
jobs:
validate:
name: Validate flake
runs-on: ubuntu-latest
timeout-minutes: 30
outputs:
hosts: ${{ steps.hosts.outputs.hosts }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ github.token }}
- name: Check flake and evaluate all outputs
run: nix flake check --all-systems --no-build --show-trace
- name: Discover NixOS hosts
id: hosts
run: |
hosts=$(nix eval --json '.#nixosConfigurations' --apply 'configs: builtins.attrNames configs')
echo "hosts=$hosts" >> "$GITHUB_OUTPUT"
echo "Discovered hosts: $hosts"
build:
name: Build ${{ matrix.host }}
needs: validate
if: ${{ needs.validate.outputs.hosts != '[]' }}
runs-on: ubuntu-latest
timeout-minutes: 120
strategy:
fail-fast: false
matrix:
host: ${{ fromJSON(needs.validate.outputs.hosts) }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ github.token }}
- name: Build NixOS system
run: |
nix build ".#nixosConfigurations.${{ matrix.host }}.config.system.build.toplevel" \
--no-link \
--print-build-logs \
--show-trace
report-main-status:
name: Report main status
needs:
- validate
- build
if: ${{ always() && !cancelled() && github.event_name == 'push' && github.ref == 'refs/heads/main' }}
runs-on: ubuntu-latest
timeout-minutes: 5
permissions:
contents: read
issues: write
env:
CI_FAILED: ${{ needs.validate.result == 'failure' || needs.build.result == 'failure' }}
JOB_RESULTS: ${{ toJSON(needs) }}
steps:
- name: Create or resolve failure issue
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9
with:
script: |
const owner = context.repo.owner;
const repo = context.repo.repo;
const title = "NixOS CI is failing on main";
const marker = "<!-- nixos-ci-main-failure -->";
const failed = process.env.CI_FAILED === "true";
const jobs = JSON.parse(process.env.JOB_RESULTS);
const failedJobs = Object.entries(jobs)
.filter(([, job]) => job.result === "failure")
.map(([name]) => `\`${name}\``)
.join(", ");
const runUrl = `${context.serverUrl}/${owner}/${repo}/actions/runs/${context.runId}`;
const commitUrl = `${context.serverUrl}/${owner}/${repo}/commit/${context.sha}`;
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner,
repo,
state: "open",
per_page: 100,
});
const existing = issues.find(
(issue) => !issue.pull_request && issue.title === title && issue.body?.includes(marker),
);
if (failed) {
const body = [
marker,
"The NixOS CI workflow failed after a push to `main`.",
"",
`- Failed jobs: ${failedJobs || "unknown"}`,
`- Commit: [\`${context.sha.slice(0, 7)}\`](${commitUrl})`,
`- Workflow run: [${context.runId}](${runUrl})`,
"",
"This issue is updated on subsequent failures and closed automatically after CI recovers.",
].join("\n");
if (existing) {
await github.rest.issues.update({
owner,
repo,
issue_number: existing.number,
body,
});
} else {
await github.rest.issues.create({ owner, repo, title, body });
}
return;
}
if (existing) {
await github.rest.issues.createComment({
owner,
repo,
issue_number: existing.number,
body: `CI recovered in [workflow run ${context.runId}](${runUrl}).`,
});
await github.rest.issues.update({
owner,
repo,
issue_number: existing.number,
state: "closed",
state_reason: "completed",
});
}
+51
View File
@@ -0,0 +1,51 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/nix-build.yaml
name: "CI: NixOS"
on:
push:
branches:
- main
paths:
- flake.nix
- flake.lock
- "flake/**"
- "hosts/**"
- "libs/**"
- "modules/**"
- "overlays/**"
- "shells/**"
- "tests/**"
- ".github/actions/check-nixos/**"
- ".github/actions/setup-nix/**"
- ".github/workflows/nixos.yaml"
pull_request:
paths:
- flake.nix
- flake.lock
- "flake/**"
- "hosts/**"
- "libs/**"
- "modules/**"
- "overlays/**"
- "shells/**"
- "tests/**"
- ".github/actions/check-nixos/**"
- ".github/actions/setup-nix/**"
- ".github/workflows/nixos.yaml"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
check:
name: Check all NixOS configurations
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup Nix
uses: ./.github/actions/setup-nix
- name: Check NixOS configurations
uses: ./.github/actions/check-nixos
-31
View File
@@ -1,31 +0,0 @@
name: Renovate
on:
schedule:
# Every day at 03:00 JST (18:00 UTC on the previous day).
- cron: "0 18 * * *"
workflow_dispatch:
permissions:
contents: read
concurrency:
group: renovate
cancel-in-progress: false
jobs:
renovate:
name: Update GitHub Actions dependencies
runs-on: ubuntu-latest
timeout-minutes: 60
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
# Use a PAT or GitHub App token so Renovate PRs trigger the other workflows.
- name: Run Renovate
uses: renovatebot/github-action@3064367f740a1a91cca218698a63902689cce200 # v46.1.20
with:
renovate-version: 43.262.1
token: ${{ secrets.RENOVATE_TOKEN }}
env:
LOG_LEVEL: info
RENOVATE_PLATFORM: github
RENOVATE_REPOSITORIES: ${{ github.repository }}
-106
View File
@@ -1,106 +0,0 @@
name: Update Flake Inputs
on:
schedule:
# Every day at 03:30 JST (18:30 UTC on the previous day).
- cron: "30 18 * * *"
workflow_dispatch:
inputs:
input:
description: Update only this flake input (empty updates all inputs)
required: false
type: string
skip-delay:
description: Update to the latest revision without the three-day delay
required: false
default: false
type: boolean
auto-merge:
description: Enable auto-merge after required checks pass
required: false
default: true
type: boolean
permissions:
contents: write
pull-requests: write
concurrency:
group: update-flake-inputs
cancel-in-progress: false
jobs:
discover:
name: Discover flake inputs
runs-on: ubuntu-latest
timeout-minutes: 5
outputs:
matrix: ${{ steps.inputs.outputs.matrix }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Build update matrix
id: inputs
env:
REQUESTED_INPUT: ${{ inputs.input }}
run: |
set -euo pipefail
github_inputs="$(
jq -c '
. as $lock
| [
$lock.nodes.root.inputs
| to_entries[]
| .key as $name
| (
.value
| if type == "array" then .[0] else . end
) as $node
| select($lock.nodes[$node].locked.type == "github")
| $name
]
| sort
' flake.lock
)"
if [ -n "$REQUESTED_INPUT" ]; then
if ! jq -e --arg input "$REQUESTED_INPUT" 'index($input) != null' <<< "$github_inputs" >/dev/null; then
echo "::error::Unknown or unsupported flake input: $REQUESTED_INPUT"
exit 1
fi
matrix="$(jq -cn --arg input "$REQUESTED_INPUT" '{input: [$input]}')"
else
matrix="$(jq -cn --argjson inputs "$github_inputs" '{input: $inputs}')"
fi
echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
echo "Update matrix: $matrix"
update:
name: Update ${{ matrix.input }}
needs: discover
if: ${{ needs.discover.outputs.matrix != '{"input":[]}' }}
runs-on: ubuntu-latest
timeout-minutes: 30
strategy:
fail-fast: false
max-parallel: 4
matrix: ${{ fromJSON(needs.discover.outputs.matrix) }}
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
token: ${{ secrets.RENOVATE_TOKEN }}
- name: Install Nix
uses: cachix/install-nix-action@630ae543ea3a38a9a4166f03376c02c50f408342 # v31.11.0
with:
extra_nix_config: |
experimental-features = nix-command flakes
accept-flake-config = true
access-tokens = github.com=${{ secrets.RENOVATE_TOKEN }}
- name: Update input
uses: ./.github/actions/update-flake-input
with:
input-name: ${{ matrix.input }}
github-token: ${{ secrets.RENOVATE_TOKEN }}
skip-delay: ${{ github.event_name == 'workflow_dispatch' && inputs.skip-delay }}
auto-merge: ${{ github.event_name != 'workflow_dispatch' || inputs.auto-merge }}
+48
View File
@@ -0,0 +1,48 @@
# Reference: https://github.com/ryoppippi/dotfiles/blob/main/.github/workflows/update-flake.yaml
name: "Bot: Update flake inputs"
on:
schedule:
- cron: "0 6 * * *"
workflow_dispatch:
concurrency:
group: ${{ github.workflow }}
cancel-in-progress: false
permissions:
contents: write
pull-requests: write
jobs:
update:
name: Update and validate flake inputs
runs-on: ubuntu-latest
timeout-minutes: 120
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
- name: Setup Nix
uses: ./.github/actions/setup-nix
- name: Update flake inputs
id: update
run: |
nix flake update
if git diff --quiet -- flake.lock; then
echo 'changed=false' >> "$GITHUB_OUTPUT"
else
echo 'changed=true' >> "$GITHUB_OUTPUT"
fi
- name: Check updated NixOS configurations
if: steps.update.outputs.changed == 'true'
uses: ./.github/actions/check-nixos
- name: Create update pull request
if: steps.update.outputs.changed == 'true'
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
with:
token: ${{ secrets.GITHUB_TOKEN }}
add-paths: flake.lock
branch: automation/update-flake-lock
delete-branch: true
commit-message: "flake: update inputs"
title: "flake: update inputs"
body: |
Automated update of `flake.lock`.
The updated inputs passed the Registry tests and a build of every NixOS configuration.
+15 -10
View File
@@ -4,6 +4,7 @@
!README.md !README.md
!LICENSE !LICENSE
!AGENTS.md !AGENTS.md
!/docs/
!.github/ !.github/
!.gitea/ !.gitea/
@@ -14,15 +15,19 @@
!/flake.nix !/flake.nix
!/flake.lock !/flake.lock
!/renovate.json
!shells/
!hosts/
!overlays/
!profiles/
!modules/
!docs/
!images/
!secrets/
!/shells/
!/flake/ !/flake/
!/overlays/
!/images/
!/secrets/
!/windows/
!/hosts/
!/libs/
!/modules/
!/tests/
!/skills/
+2
View File
@@ -3,6 +3,7 @@ keys:
- &host_x1g13 age12g85cuvg4kjfr79lqf5fx2k0d82tchrgv88xgkt7ukk2cfcsw98s2rjyat - &host_x1g13 age12g85cuvg4kjfr79lqf5fx2k0d82tchrgv88xgkt7ukk2cfcsw98s2rjyat
- &host_ops age18rtm2dq2r62zvnhwdq0gkm24hu85r7zyleyk3jqv22zpdtw064eq7ay7dl - &host_ops age18rtm2dq2r62zvnhwdq0gkm24hu85r7zyleyk3jqv22zpdtw064eq7ay7dl
- &host_internal-app-01 age1mcp5gma7y0k59equhzqfsnn0ed335ljjtn0k08ua77htlxf0x54qsravch - &host_internal-app-01 age1mcp5gma7y0k59equhzqfsnn0ed335ljjtn0k08ua77htlxf0x54qsravch
- &host_galleria age1wh7r9wnvyrgt5efjvg2324khsf4w6e9atpmz2udr4uw7frhnvvwquzcu72
creation_rules: creation_rules:
- path_regex: ^secrets/common/[^/]+\.ya?ml$ - path_regex: ^secrets/common/[^/]+\.ya?ml$
key_groups: key_groups:
@@ -11,6 +12,7 @@ creation_rules:
- *host_x1g13 - *host_x1g13
- *host_ops - *host_ops
- *host_internal-app-01 - *host_internal-app-01
- *host_galleria
- path_regex: ^secrets/hosts/x1g13/[^/]+\.ya?ml$ - path_regex: ^secrets/hosts/x1g13/[^/]+\.ya?ml$
key_groups: key_groups:
- age: - age:
+776 -350
View File
File diff suppressed because it is too large Load Diff
+2 -190
View File
@@ -1,191 +1,3 @@
# dotfiles # moons14 dotfiles
My NixOS + Home Manager configurations built with flake-parts. My NixOS + Home Manager configurations build with flake.
## Overview
- **OS**: NixOS 26.05 (stable) + nixpkgs-unstable
- **Window Manager**: Niri (Wayland)
- **Shell**: Zsh
- **Terminal**: Ghostty
- **Editor**: Neovim (nixvim), VSCode
- **Launcher**: Vicinae
- **Theme**: Stylix (Dracula)
- **Secrets**: sops-nix + age + YubiKey
## Hosts
| Host | Description | Profiles |
| ------------- | --------------- | -------------------------------------------- |
| `x1g13` | ThinkPad laptop | gui, thinkpad, dev, personal, secure-storage |
| `nix-example` | VM | cli-interactive, vm, dev, remote |
| `installer` | NixOS installer | (standalone) |
## Directory Structure
```
.
├── flake.nix # Flake inputs and outputs
├── flake/
│ ├── formatter.nix # treefmt configuration (nixfmt, deadnix, statix, etc.)
│ └── git-hooks.nix # pre-commit hooks
├── hosts/
│ ├── default.nix # mkSystem helper and host definitions
│ ├── x1g13/ # ThinkPad host config
│ ├── nix-example/ # VM host config
│ └── installer/ # Installer ISO config
├── modules/
│ ├── applications/ # Application configs (NixOS + Home Manager)
│ │ ├── niri/ # Wayland compositor
│ │ ├── ghostty/ # Terminal emulator
│ │ ├── vim/ # Neovim (nixvim)
│ │ ├── vscode/ # VSCode
│ │ ├── zsh/ # Shell
│ │ ├── zellij/ # Terminal multiplexer
│ │ ├── git/ # Git config
│ │ ├── docker.nix # Container runtime
│ │ ├── tailscale.nix # VPN
│ │ ├── claude/ # Claude Code
│ │ ├── opencode.nix # OpenCode
│ │ └── ... # chrome, discord, zoom, slack, etc.
│ ├── system/ # NixOS system configs
│ │ ├── audio.nix # PipeWire
│ │ ├── boot/ # Bootloader (systemd-boot, lanzaboote)
│ │ ├── disko.nix # Disk partitioning
│ │ ├── fonts.nix # Fonts
│ │ ├── network/ # Networking
│ │ ├── sops.nix # Secrets management
│ │ ├── user/ # User accounts
│ │ └── ...
│ ├── features/ # Feature bundles (abstraction layer)
│ │ ├── application/ # browser, communication
│ │ ├── boot/ # UEFI
│ │ ├── cli/ # base, interactive, shell
│ │ ├── connect/ # WiFi, Bluetooth
│ │ ├── dev/ # agent, nix, python, bun, java, arduino
│ │ ├── gui/ # desktop, terminal, audio, editor, capture
│ │ ├── identity/ # SSH key, fingerprint
│ │ ├── network/ # Tailscale
│ │ ├── services/ # container, KDE
│ │ └── storage/ # disko
│ ├── drivers/ # Hardware drivers (Intel)
│ └── integrations/ # Home Manager integration
├── profiles/
│ ├── interfaces/ # cli-minimal, cli-interactive, gui
│ ├── platforms/ # desktop, laptop, thinkpad, vm
│ └── workloads/ # dev, personal, srv, remote, secure-storage
├── overlays/ # nixpkgs overlays
├── shells/ # devShells (pre-commit hooks, sops, age)
├── secrets/ # Encrypted secrets (sops)
└── docs/ # Documentation
```
## Architecture
```
profile (enable features)
→ features (bundle applications/system + add packages)
→ applications (system.nix + home.nix)
→ system (NixOS config)
```
### Module Patterns
**Simple Module** — Single file for NixOS-only or Home Manager-only configs:
```nix
{ lib, config, ... }:
let cfg = config.my.system.audio;
in {
options.my.system.audio.enable = lib.mkEnableOption "Audio";
config = lib.mkIf cfg.enable { ... };
}
```
**Complex Module** — Directory with `default.nix`, `system.nix`, `home.nix`:
```
modules/applications/<app>/
├── default.nix # Master enable + imports
├── system.nix # NixOS config
└── home.nix # Home Manager config (sharedModules)
```
**Feature Module** — Bundles multiple applications/system modules:
```nix
{ lib, config, ... }:
let cfg = config.my.features.gui.desktop;
in {
options.my.features.gui.desktop.enable = lib.mkEnableOption "Desktop";
config = lib.mkIf cfg.enable {
my.applications = { niri.enable = true; gtk.enable = true; ... };
};
}
```
**Profile** — Thin layer that only enables features:
```nix
{
my.features = {
gui.desktop.enable = true;
dev.agent.enable = true;
};
}
```
## Packages
### CLI
- **Shell**: Zsh with zoxide, direnv
- **Terminal multiplexer**: Zellij
- **Editor**: Neovim (nixvim)
- **Tools**: ripgrep, curl, wget, htop, btop, fastfetch, unzip, unrar
### GUI
- **Compositor**: Niri
- **Terminal**: Ghostty, Alacritty
- **Editor**: VSCode
- **Browser**: Chrome
- **Launcher**: Vicinae
- **File manager**: Nautilus
- **Communication**: Discord, Zoom, Slack
### Development
- **AI agents**: Claude Code, Codex, OpenCode, Grok
- **Languages**: Python, Bun (JavaScript/TypeScript), Java, Arduino
- **Container**: Docker
- **Nix**: nh, nixfmt, deadnix, statix
### System
- **VPN**: Tailscale
- **Secrets**: sops-nix, age
- **Boot**: systemd-boot, lanzaboote (Secure Boot)
- **Disk**: disko
- **Theme**: Stylix
## Commands
```sh
nix flake update # Update flake inputs
nix fmt # Format code
nix develop .#dotnix # Enter dev shell
sudo nixos-rebuild switch --flake .#<host> # Apply config
sudo nixos-rebuild build --flake .#<host> # Build without applying
```
## Inspired
- [Zaney/zaneyos](https://gitlab.com/Zaney/zaneyos)
- [fa0311/.zshrc](https://gist.github.com/fa0311/d37d53ff39c73c54c883379e8e3732df)
- [AsianLovesLinux/Niri](https://github.com/AsianLovesLinux/Niri)
- [natsukium/dotfiles](https://github.com/natsukium/dotfiles)
- [dracula](https://github.com/dracula)
- [akazdayo/nix-configs](https://github.com/akazdayo/nix-configs)
- [yutakobayashidev/dotnix](https://github.com/yutakobayashidev/dotnix)
- [kawaemon/dotfiles](https://github.com/kawaemon/dotfiles)
+119
View File
@@ -0,0 +1,119 @@
# iOS Simulator 初期セットアップ
この手順は `m2` の macOS 環境で、stable Xcode と最新の stable iOS Simulator Runtime を使える状態にするためのもの。
## 前提
- `m2` が `workload.development` profile を有効にしていること
- Mac App Store に Apple Account でサインイン済みであること
- dotfiles を最新化していること
Xcode 本体は `applications.xcode` が Mac App Store 版を管理する。Simulator Runtime は Apple が管理する mutable state のため、Nix store には入れず専用 dev shell から導入する。
## 1. macOS 設定を反映する
リポジトリ直下で nix-darwin の設定を反映する。
```bash
sudo darwin-rebuild switch --flake .#m2
```
これにより `/Applications/Xcode.app` に stable Xcode がインストールされる。
Xcode のインストールで Mac App Store の認証エラーになる場合は、App Store を一度開いてサインイン状態を確認してから再実行する。
## 2. iOS Simulator Runtime を導入する
初回セットアップは次の1コマンドで行う。
```bash
nix develop .#ios -c ios-simulator-install
```
`ios-simulator-install` は次を順に実行する。
1. `/Applications/Xcode.app` が存在することを確認
2. `xcode-select` の Developer Directory を stable Xcode に切り替え
3. Xcode の first-launch components を導入
4. 利用可能な新しい hardware support components を確認
5. 選択中の Xcode に対応する最新の iOS Simulator Runtime をダウンロードしてインストール
6. Xcode のバージョンとインストール済み Simulator Runtime を表示
途中で `sudo` の認証を求められる場合がある。
## 3. インストールを確認する
```bash
xcodebuild -version
xcode-select -p
xcrun simctl list runtimes
xcrun simctl list devices available
```
`xcode-select -p` は次を指していること。
```text
/Applications/Xcode.app/Contents/Developer
```
`xcrun simctl list runtimes` に iOS runtime が表示されればセットアップ完了。
## 4. Simulator を起動する
```bash
open -a Simulator
```
Simulator の Device メニューから、インストール済み runtime で利用可能な iPhone を選択する。
## Runtime の更新
Xcode を stable の新しいバージョンへ更新した後は、同じコマンドを再実行する。
```bash
nix develop .#ios -c ios-simulator-install
```
Xcode の選択、first-launch components、hardware support、iOS Simulator Runtime の状態をまとめて更新できる。
## トラブルシューティング
### Xcode が見つからない
次のエラーが出る場合、先に nix-darwin の設定を反映する。
```text
Xcode is not installed at /Applications/Xcode.app.
```
```bash
sudo darwin-rebuild switch --flake .#m2
```
### Simulator Runtime が見えない
まず runtime 一覧を確認する。
```bash
xcrun simctl list runtimes
```
iOS runtime がない場合は再度インストーラーを実行する。
```bash
nix develop .#ios -c ios-simulator-install
```
### Command Line Tools 側を参照している
```bash
xcode-select -p
```
が `/Library/Developer/CommandLineTools` を指している場合でも、`ios-simulator-install` が `/Applications/Xcode.app/Contents/Developer` へ切り替える。
手動で直す場合は次を実行する。
```bash
sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer
```
Generated
+891 -272
View File
File diff suppressed because it is too large Load Diff
+31 -12
View File
@@ -11,6 +11,11 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nix-darwin = {
url = "github:nix-darwin/nix-darwin/nix-darwin-26.05";
inputs.nixpkgs.follows = "nixpkgs";
};
# Hardware / Platform # Hardware / Platform
nixos-hardware.url = "github:NixOS/nixos-hardware/master"; nixos-hardware.url = "github:NixOS/nixos-hardware/master";
nixos-wsl.url = "github:nix-community/NixOS-WSL"; nixos-wsl.url = "github:nix-community/NixOS-WSL";
@@ -18,6 +23,11 @@
# Desktop # Desktop
niri-flake.url = "github:sodiboo/niri-flake"; niri-flake.url = "github:sodiboo/niri-flake";
nix-hazkey = {
url = "github:aster-void/nix-hazkey";
inputs.nixpkgs.follows = "nixpkgs";
};
stylix = { stylix = {
url = "github:nix-community/stylix"; url = "github:nix-community/stylix";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
@@ -25,7 +35,7 @@
# Terminal # Terminal
ghostty = { ghostty = {
url = "github:moons-14/ghostty"; url = "github:ghostty-org/ghostty";
}; };
# Shell / Launcher # Shell / Launcher
@@ -36,10 +46,7 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
noctalia = { noctalia.url = "github:noctalia-dev/noctalia/cachix";
url = "github:noctalia-dev/noctalia";
inputs.nixpkgs.follows = "nixpkgs";
};
# Editor # Editor
nixvim = { nixvim = {
@@ -53,6 +60,11 @@
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
deploy-rs = {
url = "github:serokell/deploy-rs";
inputs.nixpkgs.follows = "nixpkgs";
};
# Disk management # Disk management
disko = { disko = {
url = "github:nix-community/disko"; url = "github:nix-community/disko";
@@ -84,6 +96,13 @@
url = "github:ilysenko/codex-desktop-linux"; url = "github:ilysenko/codex-desktop-linux";
}; };
codex-session-usage.url = "github:moons-14/codex-session-usage";
skills = {
url = "github:mattpocock/skills";
flake = false;
};
# Index / Search # Index / Search
nix-index-database = { nix-index-database = {
url = "github:nix-community/nix-index-database"; url = "github:nix-community/nix-index-database";
@@ -91,13 +110,15 @@
}; };
# Systems # Systems
systems.url = "github:nix-systems/default-linux"; systems.url = "github:nix-systems/default";
# Japanese Input Method browser-previews = {
nix-hazkey = { url = "github:nix-community/browser-previews";
url = "github:aster-void/nix-hazkey";
inputs.nixpkgs.follows = "nixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
}; };
nani-translate-linux.url = "git+https://github.com/zunoser/nani-translate-linux.git";
}; };
outputs = outputs =
@@ -111,10 +132,8 @@
imports = [ imports = [
./overlays ./overlays
./hosts
./shells ./shells
./flake/formatter.nix ./flake
./flake/git-hooks.nix
]; ];
}; };
} }
+8
View File
@@ -0,0 +1,8 @@
{
imports = [
./deploy.nix
./formatter.nix
./git-hooks.nix
./registry.nix
];
}
+28
View File
@@ -0,0 +1,28 @@
{
inputs,
self,
...
}:
{
flake.deploy = {
nodes.nix-builder = {
hostname = "nix-builder";
sshUser = "moons";
user = "root";
interactiveSudo = true;
remoteBuild = true;
autoRollback = true;
magicRollback = true;
profiles.system.path = inputs.deploy-rs.lib.x86_64-linux.activate.nixos self.nixosConfigurations.nix-builder;
};
};
perSystem =
{ system, ... }:
{
apps.deploy = inputs.deploy-rs.apps.${system}.default;
checks = inputs.deploy-rs.lib.${system}.deployChecks self.deploy;
};
}
+54
View File
@@ -0,0 +1,54 @@
{
inputs,
lib,
...
}:
let
dotfilesLib = import ../libs {
inherit inputs lib;
root = ../.;
};
hostSpecsPath = ../hosts/default.nix;
hostSpecs =
if builtins.pathExists hostSpecsPath then
let
value = import hostSpecsPath;
in
if builtins.isFunction value then
value (
builtins.intersectAttrs (builtins.functionArgs value) {
inherit inputs lib;
}
)
else
value
else
{ };
configurations = dotfilesLib.hosts.mkConfigurations hostSpecs;
in
{
flake = {
inherit (configurations) darwinConfigurations nixosConfigurations;
lib = dotfilesLib;
};
perSystem =
{ pkgs, system, ... }:
let
nixosChecks =
lib.mapAttrs' (name: nixos: lib.nameValuePair "nixos-${name}" nixos.config.system.build.toplevel)
(
lib.filterAttrs (
_: nixos: nixos.pkgs.stdenv.hostPlatform.system == system
) configurations.nixosConfigurations
);
in
{
checks = {
registry = import ../tests/registry.nix {
inherit inputs lib pkgs;
};
}
// nixosChecks;
};
}
+106 -107
View File
@@ -1,113 +1,112 @@
{ {
inputs, nix-builder = {
config, system = "x86_64-linux";
lib, stateVersion = "26.05";
... user = "moons";
}: path = ./nix-builder;
let
inherit (inputs.nixpkgs.lib) nixosSystem;
username = "moons"; profiles = [
"base"
mkSystem = "interface.cli"
{ "networking.tailscale-client"
host, "platform.vm"
system, "workload.nix-builder"
profiles ? [ ], "workload.remote-access"
extraModules ? [ ], ];
}:
let
unstable = import inputs.nixpkgs-unstable {
inherit system;
config = {
allowUnfree = true;
};
};
in
assert lib.assertMsg (lib.elem system config.systems)
"mkSystem: system '${system}' not in valid systems: ${lib.generators.toPretty { } config.systems}";
nixosSystem {
inherit system;
modules = [
{
nixpkgs.config.allowUnfree = true;
nixpkgs.overlays = builtins.attrValues inputs.self.overlays;
}
../modules
./${host}/default.nix
]
++ map (p: ../profiles/${p}.nix) profiles
++ extraModules;
specialArgs = {
inherit
inputs
username
unstable
host
;
};
};
nixosConfigurations = {
nix-example = mkSystem {
host = "nix-example";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/dev"
"workloads/remote"
];
};
ops = mkSystem {
host = "ops";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/remote"
];
};
internal-app-01 = mkSystem {
host = "internal-app-01";
system = "x86_64-linux";
profiles = [
"interfaces/cli-interactive"
"platforms/vm"
"workloads/srv"
];
};
x1g13 = mkSystem {
host = "x1g13";
system = "x86_64-linux";
profiles = [
"interfaces/gui"
"platforms/thinkpad"
"workloads/dev"
"workloads/personal"
"workloads/secure-storage"
"workloads/tailscale/client"
];
};
installer = nixosSystem {
system = "x86_64-linux";
modules = [
./installer/default.nix
];
specialArgs = {
inherit inputs;
};
};
}; };
in
{
flake = {
inherit nixosConfigurations;
checks.x86_64-linux = lib.mapAttrs' ( installer = {
name: nixos: lib.nameValuePair "nixos-${name}" nixos.config.system.build.toplevel system = "x86_64-linux";
) nixosConfigurations; stateVersion = "26.05";
user = "moons";
path = ./installer;
homeManager = false;
profiles = [ "base" ];
};
x1g9 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./x1g9;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"platform.thinkpad-x1"
"security.fingerprint"
# "security.secrets"
"workload.personal"
];
};
x1g13 = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./x1g13;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"networking.tailscale-client"
"platform.thinkpad-x1"
"security.fingerprint"
"security.secrets"
"security.secure-boot"
"security.tpm-storage"
"workload.development"
"workload.game"
"workload.personal"
];
};
galleria = {
system = "x86_64-linux";
stateVersion = "26.05";
user = "moons";
path = ./galleria;
profiles = [
"base"
"interface.cli"
"interface.labwc"
"interface.niri"
"networking.tailscale-client"
"platform.intel-nvidia-desktop"
"security.secrets"
"security.secure-boot"
"security.tpm-storage"
"security.fingerprint"
"workload.development"
"workload.game"
"workload.machine-learning"
"workload.personal"
"workload.camera"
];
};
m2 = {
system = "aarch64-darwin";
stateVersion = "26.05";
user = "moons";
path = ./m2;
profiles = [
"base"
"interface.cli"
"interface.macos"
"security.fingerprint"
# "security.secrets"
"workload.development"
"workload.game"
"workload.personal"
];
}; };
} }
+91
View File
@@ -0,0 +1,91 @@
_:
let
espPart = "/dev/disk/by-partuuid/008b04ef-9c06-4049-bffb-3906f5c3a9c1";
nixosPart = "/dev/disk/by-partuuid/04295552-cbb8-4511-ac1e-1171ec20f8d1";
btrfsMountOptions = [
"compress=zstd"
"noatime"
"ssd"
"space_cache=v2"
];
in
{
disko.enableConfig = true;
# These are deliberately partition paths, not the whole Windows disk. Disko
# must never own or destroy the disk's GPT or any Windows partition.
disko.devices.disk = {
esp = {
type = "disk";
device = espPart;
destroy = false;
content = {
type = "filesystem";
format = "vfat";
mountpoint = "/boot";
mountOptions = [ "umask=0077" ];
};
};
nixos = {
type = "disk";
device = nixosPart;
destroy = false;
content = {
type = "luks";
name = "cryptroot";
askPassword = true;
settings.allowDiscards = true;
extraFormatArgs = [
"--type"
"luks2"
"--pbkdf"
"argon2id"
"--label"
"NixOS-LUKS"
];
content = {
type = "btrfs";
extraArgs = [
"-f"
"-L"
"NixOS"
];
subvolumes = {
"@root" = {
mountpoint = "/";
mountOptions = btrfsMountOptions;
};
"@home" = {
mountpoint = "/home";
mountOptions = btrfsMountOptions;
};
"@nix" = {
mountpoint = "/nix";
mountOptions = btrfsMountOptions;
};
"@log" = {
mountpoint = "/var/log";
mountOptions = btrfsMountOptions;
};
"@swap" = {
mountpoint = "/.swapvol";
mountOptions = [ "noatime" ];
swap.swapfile.size = "32G";
};
};
};
};
};
};
}
+30
View File
@@ -0,0 +1,30 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"ahci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
+51
View File
@@ -0,0 +1,51 @@
{
lib,
config,
...
}:
{
# This desktop is permanently connected to AC power.
systemd.user.services.swayidle.Service.Environment = [
"SWAYIDLE_ASSUME_AC=1"
];
services.kanshi = {
enable = true;
settings = [
{
profile = {
name = "galleria";
outputs = [
{
criteria = "HDMI-A-1";
status = "enable";
position = "0,0";
scale = 1.5;
}
{
criteria = "DP-1";
status = "enable";
position = "2560,0";
}
{
criteria = "DP-2";
status = "enable";
position = "5120,0";
scale = 1.5;
}
];
};
}
];
};
home.file.".wallpapers" = {
source = lib.mkForce (
config.lib.file.mkOutOfStoreSymlink "${config.home.homeDirectory}/Pictures/wallpapers"
);
recursive = lib.mkForce false;
};
}
+21
View File
@@ -0,0 +1,21 @@
{ inputs, pkgs, ... }:
{
imports = [
./hardware-configuration.nix
./disko.nix
];
boot.initrd.luks.devices.cryptroot.device =
"/dev/disk/by-partuuid/04295552-cbb8-4511-ac1e-1171ec20f8d1";
# Keep Windows data and recovery partitions out of UDisks-based file
# managers. The shared EFI System Partition stays available as /boot.
services.udev.extraRules = ''
ENV{ID_PART_ENTRY_UUID}=="0480f887-d1f9-489d-b8fe-78549ced1938", ENV{UDISKS_IGNORE}="1"
ENV{ID_PART_ENTRY_UUID}=="6c70041b-3f65-4eb1-8b08-18ed20001877", ENV{UDISKS_IGNORE}="1"
'';
environment.systemPackages = with inputs.browser-previews.packages.${pkgs.system}; [
google-chrome-beta
];
}
@@ -5,9 +5,7 @@
... ...
}: }:
{ {
imports = [ imports = [ "${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix" ];
"${modulesPath}/installer/cd-dvd/installation-cd-minimal.nix"
];
boot.zfs.forceImportRoot = false; boot.zfs.forceImportRoot = false;
@@ -33,26 +31,32 @@
users.users.root.openssh.authorizedKeys.keys = [ users.users.root.openssh.authorizedKeys.keys = [
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com" "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIKhxDkucmeCor6CKoXAua7DgDSzuXrZOtpdkyzQxz5+aAAAABHNzaDo= moons@moons14.com"
"sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com" "sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIN6hZJyng/5LgFKPjR6uZAd/00UkO0vN0uQOoIvfSELdAAAABHNzaDo= moons@moons14.com"
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLwReAiwhXoO34S2+MrvqUhi8IWp4IzUq4OSp3niJdq"
]; ];
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
git # Clone dotfiles repository git
disko # Disk partitioning disko
sops # Secrets management sops
age # Age encryption age
ssh-to-age # Convert SSH keys to age ssh-to-age
age-plugin-yubikey # YubiKey support age-plugin-yubikey
yubikey-manager # YubiKey management yubikey-manager
pcsc-tools # Smart card tools pcsc-tools
mkpasswd # Password hash generation mkpasswd
rsync # File synchronization rsync
vim # Text editor vim
wget # Download files wget
curl # HTTP client curl
jq # JSON processor jq
parted # Partition tools parted
cryptsetup # LUKS encryption cryptsetup
btrfs-progs # Btrfs filesystem tools btrfs-progs
efibootmgr
pciutils
sbctl
tpm2-tools
util-linux
]; ];
services.pcscd.enable = true; services.pcscd.enable = true;
@@ -188,6 +192,4 @@
}; };
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
system.stateVersion = "26.05";
} }
+10
View File
@@ -0,0 +1,10 @@
{ hostName, ... }:
{
# networking.hostName and networking.localHostName are derived from the
# registry name; computerName controls the user-visible macOS name.
networking.computerName = hostName;
# Keep this value stable after the first activation. It is independent of
# the Home Manager stateVersion in hosts/default.nix.
system.stateVersion = 7;
}
+101
View File
@@ -0,0 +1,101 @@
# nix-builder bootstrap
The host configuration can be built before its cache signing secret exists.
Harmonia's socket remains stopped until SOPS installs the signing key at
`/run/secrets/harmonia/signing-key`.
## Proxmox storage layout
The host configuration expects three filesystems. Keep the build scratch space
separate from the store so a large build cannot fill the root filesystem.
| Mount point | Suggested size | Contents |
| -------------------- | -------------- | ------------------------------- |
| `/` | 48 GiB | NixOS and mutable system state |
| `/var/lib/nix-build` | 192 GiB | Disposable build scratch space |
| `/nix/store` | 1 TiB | Fleet closures and binary cache |
The build-server policy starts emergency store GC below 64 GiB free and aims
for 128 GiB free. Persistent roots under `/var/lib/nix-fleet/roots` protect the
latest fleet builds from that GC. It also limits Nix to two concurrent
derivations while allowing each derivation to use every vCPU assigned to the
VM.
For the two dedicated ext4 data filesystems, remove the default root-reserved
blocks once after formatting; keep the root filesystem's reserve intact:
```bash
sudo tune2fs -m 0 /dev/disk/by-label/nix-build
sudo tune2fs -m 0 /dev/disk/by-label/nix-store
```
## Initial deployment
Once the VM is reachable as `moons@nix-builder`, deploy it from the repository:
```bash
nix run .#deploy -- .#nix-builder
```
deploy-rs uses the target's `ssh-ng` store, so the system closure is built on
the builder rather than copied from the laptop. Automatic and magic rollback
remain enabled.
## Add the host SOPS recipient
After the VM has a stable SSH host key, derive its age recipient:
```bash
ssh-keyscan -t ed25519 nix-builder 2>/dev/null | ssh-to-age
```
Add the recipient to `.sops.yaml` and add a creation rule for
`secrets/hosts/nix-builder/*.yaml`. The admin YubiKey recipient should remain in
the same key group for recovery.
## Generate the cache signing key
Run this on a trusted Nix machine, preferably with the temporary files on a
tmpfs:
```bash
nix-store --generate-binary-cache-key \
cache.app.homelabs.run-1 \
harmonia.private \
harmonia.public
```
Create `secrets/hosts/nix-builder/system.yaml` with SOPS and store the complete
contents of `harmonia.private` at `harmonia.signing-key`:
```yaml
harmonia:
signing-key: cache.app.homelabs.run-1:REDACTED
```
Copy the complete contents of `harmonia.public` to
`modules/systems/nix/homelab-cache/public-key`. The private plaintext file must
not be committed or retained.
After committing both encrypted/public files, select
`networking.homelab-cache-client` on each client host.
Redeploy the builder and verify the cache after installing the secret:
```bash
nix run .#deploy -- .#nix-builder
curl --fail http://nix-builder:5000/nix-cache-info
```
## Normal operation
Run `fleet-build` on the builder to build and root every NixOS host, or pass a
list of host names to build only those hosts. Run `fleet-deploy` with the normal
deploy-rs target syntax when additional fleet nodes have been added to
`flake/deploy.nix`:
```bash
fleet-build
fleet-build x1g13 galleria
fleet-deploy .#nix-builder
```
+25
View File
@@ -0,0 +1,25 @@
{
fileSystems."/nix/store" = {
device = "/dev/disk/by-label/nix-store";
fsType = "ext4";
options = [
"noatime"
];
neededForBoot = true;
};
fileSystems."/var/lib/nix-build" = {
device = "/dev/disk/by-label/nix-build";
fsType = "ext4";
options = [
"noatime"
];
};
nix.settings.build-dir = "/var/lib/nix-build";
services.fstrim.enable = true;
}
@@ -21,12 +21,12 @@
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = { fileSystems."/" = {
device = "/dev/disk/by-uuid/1b12ab98-2537-4207-a3f4-bb8ba7b53b00"; device = "/dev/disk/by-uuid/49fc2e1c-7909-41cc-ac78-55b4d9a01e62";
fsType = "ext4"; fsType = "ext4";
}; };
fileSystems."/boot" = { fileSystems."/boot" = {
device = "/dev/disk/by-uuid/8365-C778"; device = "/dev/disk/by-uuid/40D4-ABBE";
fsType = "vfat"; fsType = "vfat";
options = [ options = [
"fmask=0077" "fmask=0077"
+19
View File
@@ -0,0 +1,19 @@
{ lib, ... }:
let
hostSecrets = ../../secrets/hosts/nix-builder/system.yaml;
in
{
imports = [
./filesystem.nix
./hardware-configuration.nix
];
sops.secrets = lib.mkIf (builtins.pathExists hostSecrets) {
"harmonia/signing-key" = {
sopsFile = hostSecrets;
restartUnits = [ "harmonia.service" ];
};
};
networking.firewall.interfaces."tailscale0".allowedTCPPorts = [ 5000 ];
}
-6
View File
@@ -1,6 +0,0 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
];
}
+4 -11
View File
@@ -1,15 +1,8 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’ # Do not modify this file! It was generated by `nixos-generate-config` and may
# and may be overwritten by future invocations. Please make changes # be overwritten by future invocations.
# to /etc/nixos/configuration.nix instead. { lib, modulesPath, ... }:
{ {
lib, imports = [ (modulesPath + "/profiles/qemu-guest.nix") ];
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [ boot.initrd.availableKernelModules = [
"ata_piix" "ata_piix"
+3
View File
@@ -0,0 +1,3 @@
{
imports = [ ./hardware-configuration.nix ];
}
-56
View File
@@ -1,56 +0,0 @@
{ ... }:
{
imports = [
./hardware-configuration.nix
];
networking = {
useDHCP = false;
interfaces = {
ens18 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.128.20";
prefixLength = 24;
}
];
};
ens19 = {
useDHCP = false;
ipv4.addresses = [
{
address = "10.50.7.101";
prefixLength = 24;
}
];
};
ens20 = {
useDHCP = false;
ipv4.routes = [
{
address = "10.50.64.0";
prefixLength = 24;
via = "10.50.82.1";
}
];
ipv4.addresses = [
{
address = "10.50.82.10";
prefixLength = 24;
}
];
};
};
defaultGateway = {
address = "10.50.128.1";
interface = "ens18";
};
};
}
-44
View File
@@ -1,44 +0,0 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/profiles/qemu-guest.nix")
];
boot.initrd.availableKernelModules = [
"ata_piix"
"uhci_hcd"
"virtio_pci"
"virtio_scsi"
"sd_mod"
"sr_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/69fa2193-1e4f-438a-8898-5de8a3f36e5b";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/D09B-4277";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
}
+3 -13
View File
@@ -1,7 +1,6 @@
_: _:
let let
espPart = "/dev/disk/by-partuuid/a53e3b19-67de-40de-9ded-3eac3117689a"; espPart = "/dev/disk/by-partuuid/a53e3b19-67de-40de-9ded-3eac3117689a";
nixosPart = "/dev/disk/by-partuuid/311d0f9c-f35f-42e6-b6fc-a4d67dd21b2e"; nixosPart = "/dev/disk/by-partuuid/311d0f9c-f35f-42e6-b6fc-a4d67dd21b2e";
btrfsMountOptions = [ btrfsMountOptions = [
@@ -24,9 +23,7 @@ in
type = "filesystem"; type = "filesystem";
format = "vfat"; format = "vfat";
mountpoint = "/boot"; mountpoint = "/boot";
mountOptions = [ mountOptions = [ "umask=0077" ];
"umask=0077"
];
}; };
}; };
@@ -38,12 +35,8 @@ in
content = { content = {
type = "luks"; type = "luks";
name = "cryptroot"; name = "cryptroot";
askPassword = true; askPassword = true;
settings.allowDiscards = true;
settings = {
allowDiscards = true;
};
extraFormatArgs = [ extraFormatArgs = [
"--type" "--type"
@@ -85,10 +78,7 @@ in
"@swap" = { "@swap" = {
mountpoint = "/.swapvol"; mountpoint = "/.swapvol";
mountOptions = [ mountOptions = [ "noatime" ];
"noatime"
];
swap.swapfile.size = "32G"; swap.swapfile.size = "32G";
}; };
}; };
+2 -3
View File
@@ -1,6 +1,5 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’ # Do not modify this file! It was generated by `nixos-generate-config`
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Make changes in nixos.nix.
# to /etc/nixos/configuration.nix instead.
{ {
config, config,
lib, lib,
+22
View File
@@ -0,0 +1,22 @@
{
services.kanshi = {
enable = true;
settings = [
{
profile = {
name = "x1g13";
outputs = [
{
criteria = "eDP-1";
status = "enable";
position = "0,0";
scale = 1.5;
}
];
};
}
];
};
}
@@ -1,4 +1,3 @@
{ ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
+52
View File
@@ -0,0 +1,52 @@
# Do not modify this file! It was generated by ‘nixos-generate-config’
# and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead.
{
config,
lib,
modulesPath,
...
}:
{
imports = [
(modulesPath + "/installer/scan/not-detected.nix")
];
boot.initrd.availableKernelModules = [
"xhci_pci"
"thunderbolt"
"nvme"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ ];
boot.kernelModules = [ ];
boot.extraModulePackages = [ ];
fileSystems."/" = {
device = "/dev/disk/by-uuid/16b29578-6836-414b-a5e1-863bc21c5fc3";
fsType = "ext4";
};
fileSystems."/boot" = {
device = "/dev/disk/by-uuid/209A-C8C9";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
swapDevices = [ ];
# 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
# still possible to use this option, but it's recommended to use it in conjunction
# with explicit per-interface declarations with `networking.interfaces.<interface>.useDHCP`.
networking.useDHCP = lib.mkDefault true;
# networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true;
nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux";
hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware;
}
@@ -1,4 +1,3 @@
{ ... }:
{ {
imports = [ imports = [
./hardware-configuration.nix ./hardware-configuration.nix
+17
View File
@@ -0,0 +1,17 @@
{
inputs,
lib ? inputs.nixpkgs.lib,
root,
}:
let
registry = import ./registry.nix {
inherit inputs lib;
modulesRoot = root + "/modules";
};
hosts = import ./hosts.nix {
inherit inputs lib registry;
};
in
{
inherit hosts registry;
}
+191
View File
@@ -0,0 +1,191 @@
{
inputs,
lib,
registry,
}:
let
ensure =
condition: message: value:
if condition then value else throw "host registry: ${message}";
isLinux = system: lib.hasSuffix "-linux" system;
isDarwin = system: lib.hasSuffix "-darwin" system;
hostFile =
spec: name:
let
path = spec.path + "/${name}";
in
if builtins.pathExists path then path else null;
selectedUnits =
spec:
[ "users.${spec.user}" ]
++ map (name: "profiles.${name}") (spec.profiles or [ ])
++ map (name: "applications.${name}") (spec.applications or [ ])
++ (spec.units or [ ]);
validateSpec =
name: spec:
ensure (builtins.isAttrs spec) "${name}: host specification must be an attribute set" (
ensure (spec ? system && builtins.isString spec.system) "${name}: system is required" (
ensure (isLinux spec.system || isDarwin spec.system)
"${name}: unsupported system '${spec.system}'; expected a Linux NixOS or Darwin system"
(
ensure (spec ? user && builtins.isString spec.user && spec.user != "") "${name}: user is required" (
ensure (spec ? path && builtins.pathExists spec.path)
"${name}: path must name an existing host directory"
(
ensure
(
spec ? stateVersion
&& builtins.isString spec.stateVersion
&& builtins.match "[0-9][0-9]\\.[0-9][0-9]" spec.stateVersion != null
)
"${name}: stateVersion is required and must have the form YY.MM"
(
ensure
(lib.all
(field: builtins.isList (spec.${field} or [ ]) && lib.all builtins.isString (spec.${field} or [ ]))
[
"profiles"
"applications"
"units"
]
)
"${name}: profiles, applications, and units must be lists of strings"
(ensure (builtins.isBool (spec.homeManager or true)) "${name}: homeManager must be a boolean" spec)
)
)
)
)
)
);
mkSpecialArgs = name: spec: {
inherit inputs registry;
inherit (spec) system;
hostName = name;
primaryUser = spec.user;
};
mkHomeManagerModule =
name: spec: selected:
let
homePath = hostFile spec "home.nix";
homeModules = [
(registry.mkModule {
class = "home";
systemClass = "nixos";
})
(registry.mkSelectionModule selected)
{ home.stateVersion = spec.stateVersion; }
]
++ lib.optional (homePath != null) homePath;
in
{
imports = [ inputs.home-manager.nixosModules.home-manager ];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = mkSpecialArgs name spec;
users.${spec.user}.imports = homeModules;
};
};
mkDarwinHomeManagerModule =
name: spec: selected:
let
homePath = hostFile spec "home.nix";
homeModules = [
(registry.mkModule {
class = "home";
systemClass = "darwin";
})
(registry.mkSelectionModule selected)
{ home.stateVersion = spec.stateVersion; }
]
++ lib.optional (homePath != null) homePath;
in
{
imports = [ inputs.home-manager.darwinModules.home-manager ];
home-manager = {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = mkSpecialArgs name spec;
users.${spec.user}.imports = homeModules;
};
};
mkNixos =
name: rawSpec:
let
spec = validateSpec name rawSpec;
selected = registry.validateUnitIds (selectedUnits spec);
nixosPath = hostFile spec "nixos.nix";
modules = [
(registry.mkModule { class = "nixos"; })
(registry.mkSelectionModule selected)
{
networking.hostName = lib.mkDefault name;
system.stateVersion = spec.stateVersion;
}
]
++ lib.optional (spec.homeManager or true) (mkHomeManagerModule name spec selected)
++ lib.optional (nixosPath != null) nixosPath;
in
inputs.nixpkgs.lib.nixosSystem {
inherit (spec) system;
specialArgs = mkSpecialArgs name spec;
inherit modules;
};
mkDarwin =
name: rawSpec:
let
spec = validateSpec name rawSpec;
selected = registry.validateUnitIds (selectedUnits spec);
darwinPath = hostFile spec "darwin.nix";
modules = [
(registry.mkModule { class = "darwin"; })
(registry.mkSelectionModule selected)
{
networking.hostName = lib.mkDefault name;
system.primaryUser = lib.mkDefault spec.user;
}
]
++ lib.optional (spec.homeManager or true) (mkDarwinHomeManagerModule name spec selected)
++ lib.optional (darwinPath != null) darwinPath;
in
ensure (inputs ? nix-darwin) "${name}: the nix-darwin input is required" (
inputs.nix-darwin.lib.darwinSystem {
inherit (spec) system;
specialArgs = mkSpecialArgs name spec;
inherit modules;
}
);
mkConfigurations =
hostSpecs:
let
validated = lib.mapAttrs validateSpec hostSpecs;
in
{
nixosConfigurations = lib.mapAttrs mkNixos (
lib.filterAttrs (_: spec: isLinux spec.system) validated
);
darwinConfigurations = lib.mapAttrs mkDarwin (
lib.filterAttrs (_: spec: isDarwin spec.system) validated
);
};
in
{
inherit
mkConfigurations
mkDarwin
mkNixos
selectedUnits
;
}
+386
View File
@@ -0,0 +1,386 @@
{
inputs,
lib,
modulesRoot,
}:
let
rootFragmentFiles = {
common = "common.nix";
nixos = "nixos.nix";
darwin = "darwin.nix";
home = "home.nix";
meta = "meta.nix";
};
homeFragmentFiles = {
homeCommon = "common.nix";
homeNixos = "nixos.nix";
homeDarwin = "darwin.nix";
};
fragmentFileNames = rootFragmentFiles // lib.mapAttrs (_: name: "home/${name}") homeFragmentFiles;
isFile = kind: kind == "regular" || kind == "symlink";
ensure =
condition: message: value:
if condition then value else throw "unit registry: ${message}";
callWithAvailableArgs =
value: availableArgs:
if builtins.isFunction value then
value (builtins.intersectAttrs (builtins.functionArgs value) availableArgs)
else
value;
pathFor =
relativePath:
if relativePath == [ ] then
modulesRoot
else
modulesRoot + "/${lib.concatStringsSep "/" relativePath}";
entryIsFile = entries: name: builtins.hasAttr name entries && isFile entries.${name};
normalizeMeta =
unit:
let
metaPath = unit.fragments.meta;
importedValue =
if metaPath == null then
{ }
else
callWithAvailableArgs (import metaPath) {
inherit inputs lib unit;
};
imported =
ensure (builtins.isAttrs importedValue) "${unit.id}: meta.nix must return an attribute set"
importedValue;
allowedKeys = [
"description"
"includes"
"imports"
];
unknownKeys = lib.filter (name: !(builtins.elem name allowedKeys)) (builtins.attrNames imported);
description = imported.description or null;
includes = imported.includes or [ ];
imports = imported.imports or { };
allowedImportKeys = [
"nixos"
"darwin"
"home"
];
unknownImportKeys =
if builtins.isAttrs imports then
lib.filter (name: !(builtins.elem name allowedImportKeys)) (builtins.attrNames imports)
else
[ ];
normalized = {
inherit description includes;
imports = {
nixos = imports.nixos or [ ];
darwin = imports.darwin or [ ];
home = imports.home or [ ];
};
};
in
ensure (unknownKeys == [ ])
"${unit.id}: meta.nix has unsupported keys: ${lib.concatStringsSep ", " unknownKeys}"
(
ensure (description == null || builtins.isString description)
"${unit.id}: meta.description must be a string"
(
ensure (builtins.isList includes && lib.all builtins.isString includes)
"${unit.id}: meta.includes must be a list of fully qualified unit IDs"
(
ensure (lib.unique includes == includes) "${unit.id}: meta.includes contains duplicate unit IDs" (
ensure (builtins.isAttrs imports) "${unit.id}: meta.imports must be an attribute set" (
ensure (unknownImportKeys == [ ])
"${unit.id}: meta.imports has unsupported classes: ${lib.concatStringsSep ", " unknownImportKeys}"
(
ensure (lib.all builtins.isList [
normalized.imports.nixos
normalized.imports.darwin
normalized.imports.home
]) "${unit.id}: every meta.imports.<class> value must be a list" normalized
)
)
)
)
)
);
makeUnit =
relativePath: entries: homeEntries:
let
directory = pathFor relativePath;
id = lib.concatStringsSep "." relativePath;
rootFragments = lib.mapAttrs (
_class: fileName: if entryIsFile entries fileName then directory + "/${fileName}" else null
) rootFragmentFiles;
homeFragments = lib.mapAttrs (
_class: fileName: if entryIsFile homeEntries fileName then directory + "/home/${fileName}" else null
) homeFragmentFiles;
fragments = rootFragments // homeFragments;
baseUnit = {
inherit
id
directory
fragments
relativePath
;
optionPath = [ "my" ] ++ relativePath ++ [ "enable" ];
kind = builtins.head relativePath;
name = lib.last relativePath;
}
//
lib.optionalAttrs (builtins.length relativePath > 2 && builtins.head relativePath == "profiles")
{
group = builtins.elemAt relativePath 1;
};
in
ensure (relativePath != [ ]) "the modules root cannot itself be a unit" (
ensure (lib.all (component: component != "" && !(lib.hasInfix "." component)) relativePath)
"${id}: path components must be non-empty and must not contain dots"
(baseUnit // { meta = normalizeMeta baseUnit; })
);
walk =
relativePath:
let
directory = pathFor relativePath;
entries = builtins.readDir directory;
homeEntries =
if relativePath != [ ] && (entries.home or null) == "directory" then
builtins.readDir (directory + "/home")
else
{ };
hasRootFragment = lib.any (fileName: entryIsFile entries fileName) (
builtins.attrValues rootFragmentFiles
);
hasHomeFragment = lib.any (fileName: entryIsFile homeEntries fileName) (
builtins.attrValues homeFragmentFiles
);
hasFragment = hasRootFragment || hasHomeFragment;
childDirectories = lib.filter (
name: entries.${name} == "directory" && !(name == "home" && hasHomeFragment)
) (builtins.attrNames entries);
current = lib.optional hasFragment (makeUnit relativePath entries homeEntries);
children = lib.concatMap (name: walk (relativePath ++ [ name ])) childDirectories;
in
current ++ children;
discoveredUnits =
ensure (builtins.pathExists modulesRoot) "modules root does not exist: ${toString modulesRoot}"
(walk [ ]);
unitsById = builtins.listToAttrs (map (unit: lib.nameValuePair unit.id unit) discoveredUnits);
dependencyValidation = lib.foldl' (
valid: unit:
lib.foldl' (
inner: includedId:
if builtins.hasAttr includedId unitsById then
inner
else
throw "unit registry: ${unit.id} includes missing unit '${includedId}'"
) valid unit.meta.includes
) true discoveredUnits;
units = builtins.seq dependencyValidation unitsById;
unitIds = builtins.attrNames units;
getUnit =
id: if builtins.hasAttr id units then units.${id} else throw "unit registry: unknown unit '${id}'";
validateUnitIds =
ids:
ensure (
builtins.isList ids && lib.all builtins.isString ids
) "selected units must be a list of strings" (map (id: builtins.seq (getUnit id) id) ids);
optionDefinitions = lib.foldl' lib.recursiveUpdate { } (
map (
unit:
lib.setAttrByPath unit.optionPath (
lib.mkOption {
type = lib.types.bool;
default = false;
description =
if unit.meta.description == null then
"Whether to enable the ${unit.id} unit."
else
"Whether to enable ${unit.meta.description}.";
}
)
) discoveredUnits
);
enabled = config: unit: lib.getAttrFromPath unit.optionPath config;
enableUnit = id: lib.setAttrByPath (getUnit id).optionPath true;
includeConfig =
config: unit: lib.mkIf (enabled config unit) (lib.mkMerge (map enableUnit unit.meta.includes));
fragmentClasses = {
nixos = [
"common"
"nixos"
];
darwin = [
"common"
"darwin"
];
home = {
nixos = [
"home"
"homeCommon"
"homeNixos"
];
darwin = [
"home"
"homeCommon"
"homeDarwin"
];
};
};
fragmentClassesFor =
{
class,
systemClass,
}:
ensure (builtins.hasAttr class fragmentClasses) "unsupported module class '${class}'" (
if class == "home" then
ensure
(builtins.elem systemClass [
"nixos"
"darwin"
])
"the home module class requires systemClass to be 'nixos' or 'darwin'"
fragmentClasses.home.${systemClass}
else
ensure (
systemClass == null
) "systemClass is only supported for the home module class" fragmentClasses.${class}
);
applyFragment =
{
config,
fragmentName,
fragmentPath,
options,
specialArgs,
unit,
}:
let
fragment = import fragmentPath;
directArgs = specialArgs // {
inherit
config
lib
options
specialArgs
unit
;
};
fragmentArgSpec = builtins.functionArgs fragment;
fragmentArgs = builtins.listToAttrs (
lib.concatMap (
name:
if builtins.hasAttr name directArgs then
[ (lib.nameValuePair name directArgs.${name}) ]
else if fragmentArgSpec.${name} then
[ ]
else
[ (lib.nameValuePair name config._module.args.${name}) ]
) (builtins.attrNames fragmentArgSpec)
);
resultValue = if builtins.isFunction fragment then fragment fragmentArgs else fragment;
result =
ensure (builtins.isAttrs resultValue) "${unit.id}: ${fragmentName} must return an attribute set"
resultValue;
forbiddenKeys = lib.filter (name: builtins.hasAttr name result) [
"imports"
"options"
"config"
];
in
ensure (forbiddenKeys == [ ])
"${unit.id}: ${fragmentName} is a configuration fragment and cannot define top-level ${lib.concatStringsSep ", " forbiddenKeys}"
result;
externalImports = class: lib.concatMap (unit: unit.meta.imports.${class}) discoveredUnits;
mkModule =
{
class,
systemClass ? null,
}:
let
selectedFragmentClasses = fragmentClassesFor { inherit class systemClass; };
in
builtins.seq selectedFragmentClasses (
builtins.seq dependencyValidation (
{
config,
lib,
options,
specialArgs,
...
}:
let
fragmentConfigs = lib.concatMap (
unit:
lib.filter (value: value != null) (
map (
fragmentClass:
let
fragmentName = fragmentFileNames.${fragmentClass};
fragmentPath = unit.fragments.${fragmentClass};
in
if fragmentPath == null then
null
else
lib.mkIf (enabled config unit) (applyFragment {
inherit
config
fragmentName
fragmentPath
options
specialArgs
unit
;
})
) selectedFragmentClasses
)
) discoveredUnits;
in
{
imports = externalImports class;
options = optionDefinitions;
config = lib.mkMerge ((map (includeConfig config) discoveredUnits) ++ fragmentConfigs);
}
)
);
mkSelectionModule =
selectedIds:
let
checkedIds = validateUnitIds (lib.unique selectedIds);
in
{
config = lib.mkMerge (map enableUnit checkedIds);
};
in
{
inherit
getUnit
mkModule
mkSelectionModule
unitIds
units
validateUnitIds
;
}
-26
View File
@@ -1,26 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications."1password";
in
{
options.my.applications."1password" = {
enable = lib.mkEnableOption "1Password password manager";
};
config = lib.mkIf cfg.enable {
programs._1password.enable = true;
programs._1password-gui = {
enable = true;
polkitPolicyOwners = [ "moons" ];
};
programs.ssh.startAgent = lib.mkForce false;
programs.gnupg.agent.enableSSHSupport = lib.mkForce false;
services.gnome.gcr-ssh-agent.enable = lib.mkForce false;
};
}
@@ -0,0 +1,4 @@
_: {
programs._1password-gui.enable = true;
programs._1password.enable = true;
}
+9
View File
@@ -0,0 +1,9 @@
{ primaryUser, lib, ... }:
{
programs._1password-gui.polkitPolicyOwners = [ primaryUser ];
# 1Password SSH Agentと競合するagentを無効化
programs.ssh.startAgent = lib.mkForce false;
programs.gnupg.agent.enableSSHSupport = lib.mkForce false;
services.gnome.gcr-ssh-agent.enable = lib.mkForce false;
}
@@ -0,0 +1,8 @@
{
homebrew.casks = [ "activitywatch" ];
launchd.agents.activitywatch = {
command = "/usr/bin/open -gja ActivityWatch";
serviceConfig.RunAtLoad = true;
};
}
@@ -0,0 +1,11 @@
{ pkgs, ... }:
{
services.activitywatch = {
enable = true;
watchers.aw-awatcher = {
package = pkgs.awatcher;
executable = "awatcher";
};
};
}
@@ -0,0 +1,3 @@
{
description = "ActivityWatch automated time tracker";
}
-29
View File
@@ -1,29 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.arduino;
arduinoIdeX11 = pkgs.arduino-ide.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/arduino-ide \
--add-flags "--ozone-platform=x11"
'';
});
in
{
options.my.applications.arduino = {
enable = lib.mkEnableOption "Arduino development tools";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
arduino-cli # Arduino command-line interface
arduinoIdeX11 # Arduino IDE with X11 support
];
};
}
+4
View File
@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.arduino-cli ];
}
+14
View File
@@ -0,0 +1,14 @@
{ pkgs, ... }:
let
arduinoIdeX11 = pkgs.arduino-ide.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/arduino-ide \
--add-flags "--ozone-platform=x11"
'';
});
in
{
environment.systemPackages = [ arduinoIdeX11 ];
}
+9
View File
@@ -0,0 +1,9 @@
{
programs.atuin = {
enable = true;
enableZshIntegration = true;
enableBashIntegration = true;
enableFishIntegration = true;
};
}
+4
View File
@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.baobab ];
}
-23
View File
@@ -1,23 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.btop;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.btop = {
enable = lib.mkEnableOption "btop system monitor";
};
config = lib.mkIf cfg.enable {
my.applications.btop.system.enable = lib.mkDefault true;
my.applications.btop.homeManager.enable = lib.mkDefault true;
};
}
+3 -3
View File
@@ -1,5 +1,5 @@
#Bashtop theme with nord palette (https://www.nordtheme.com) # Bashtop theme with Nord palette (https://www.nordtheme.com)
#by Justin Zobel <[email protected]> # by Justin Zobel <[email protected]>
# Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255" # Colors should be in 6 or 2 character hexadecimal or single spaced rgb decimal: "#RRGGBB", "#BW" or "0-255 0-255 0-255"
# example for white: "#ffffff", "#ff" or "255 255 255". # example for white: "#ffffff", "#ff" or "255 255 255".
@@ -18,7 +18,7 @@ theme[main_fg]="#BD93F9"
# Title color for boxes # Title color for boxes
theme[title]="#f8f8f2" theme[title]="#f8f8f2"
# Higlight color for keyboard shortcuts # Highlight color for keyboard shortcuts
theme[hi_fg]="#ff79c6" theme[hi_fg]="#ff79c6"
# Background color of selected item in processes box # Background color of selected item in processes box
+5 -22
View File
@@ -1,25 +1,8 @@
{ {
lib, programs.btop = {
config, enable = true;
...
}:
let
cfg = config.my.applications.btop.homeManager;
in
{
options.my.applications.btop.homeManager = {
enable = lib.mkEnableOption "btop home-manager configuration";
};
config.home-manager.sharedModules = [ settings.color_theme = "dracula";
{ themes.dracula = builtins.readFile ./dracula.theme;
config = lib.mkIf cfg.enable { };
programs.btop = {
enable = true;
settings.color_theme = "dracula";
themes.dracula = builtins.readFile ./dracula.theme;
};
};
}
];
} }
-20
View File
@@ -1,20 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.btop.system;
in
{
options.my.applications.btop.system = {
enable = lib.mkEnableOption "btop system configuration";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = with pkgs; [
btop # Resource monitor that shows usage and stats
];
};
}
@@ -0,0 +1,31 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.celluloid ];
xdg.mimeApps = {
enable = true;
defaultApplicationPackages = [ pkgs.celluloid ];
defaultApplications = builtins.listToAttrs (
map
(mime: {
name = mime;
value = [ "io.github.celluloid_player.Celluloid.desktop" ];
})
[
"video/3gpp"
"video/3gpp2"
"video/mp2t"
"video/mp4"
"video/mpeg"
"video/ogg"
"video/quicktime"
"video/webm"
"video/x-flv"
"video/x-m4v"
"video/x-matroska"
"video/x-msvideo"
"video/x-ms-wmv"
]
);
};
}
-44
View File
@@ -1,44 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.chrome;
in
{
options.my.applications.chrome = {
enable = lib.mkEnableOption "Google Chrome browser";
};
config = lib.mkIf cfg.enable {
home-manager.sharedModules = [
{
home.packages = with pkgs; [
google-chrome # Popular web browser from Google
];
xdg.desktopEntries."google-chrome" = {
name = "Google Chrome";
genericName = "Web Browser";
exec = "${pkgs.google-chrome}/bin/google-chrome-stable --enable-features=TouchpadOverscrollHistoryNavigation %U";
terminal = false;
icon = "google-chrome";
categories = [
"Network"
"WebBrowser"
];
startupNotify = true;
type = "Application";
};
xdg.mimeApps.defaultApplications = {
"text/html" = "google-chrome.desktop";
"x-scheme-handler/http" = "google-chrome.desktop";
"x-scheme-handler/https" = "google-chrome.desktop";
};
}
];
};
}
+6
View File
@@ -0,0 +1,6 @@
{
homebrew = {
enable = true;
casks = [ "google-chrome" ];
};
}
@@ -0,0 +1,47 @@
{
config,
lib,
pkgs,
...
}:
let
chrome = pkgs.google-chrome.overrideAttrs (old: {
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [ pkgs.makeWrapper ];
postFixup = (old.postFixup or "") + ''
wrapProgram $out/bin/google-chrome-stable \
--set LIBVA_DRIVER_NAME nvidia \
--set NVD_BACKEND direct
'';
});
features = [
"MiddleClickAutoscroll"
"AcceleratedVideoDecoder"
"AcceleratedVideoDecodeLinuxGL"
"PlatformHEVCDecoderSupport"
]
++ lib.optional config.my.hardwares.nvidia.enable "VaapiOnNvidiaGPUs";
in
{
programs.google-chrome = {
enable = true;
package = if config.my.hardwares.nvidia.enable then chrome else pkgs.google-chrome;
commandLineArgs = [
"--enable-features=${lib.concatStringsSep "," features}"
"--use-gl=angle"
"--use-angle=gl"
];
};
xdg.mimeApps = {
enable = true;
defaultApplications = {
"text/html" = "google-chrome.desktop";
"x-scheme-handler/http" = "google-chrome.desktop";
"x-scheme-handler/https" = "google-chrome.desktop";
};
};
}
-23
View File
@@ -1,23 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.claude;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.claude = {
enable = lib.mkEnableOption "Claude Code AI assistant";
};
config = lib.mkIf cfg.enable {
my.applications.claude.system.enable = lib.mkDefault true;
my.applications.claude.homeManager.enable = lib.mkDefault true;
};
}
+12 -21
View File
@@ -1,27 +1,18 @@
{ {
lib, inputs,
config, pkgs,
... ...
}: }:
let
cfg = config.my.applications.claude.homeManager;
in
{ {
options.my.applications.claude.homeManager = { home.packages = [
enable = lib.mkEnableOption "Claude Code home-manager configuration"; inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.claude-code
};
config.home-manager.sharedModules = [
{
config = lib.mkIf cfg.enable {
home.file.".claude/settings.json".text = builtins.toJSON {
statusLine = {
type = "command";
command = "bun x ccusage statusline --no-offline";
padding = 0;
};
};
};
}
]; ];
home.file.".claude/settings.json".text = builtins.toJSON {
statusLine = {
type = "command";
command = "bun x ccusage statusline --no-offline";
padding = 0;
};
};
} }
-20
View File
@@ -1,20 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.claude.system;
in
{
options.my.applications.claude.system = {
enable = lib.mkEnableOption "Claude Code system configuration";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.llm-agents.claude-code # AI coding assistant
];
};
}
-65
View File
@@ -1,65 +0,0 @@
{
inputs,
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.codexDesktop;
codexCliPackage = pkgs.llm-agents.codex;
codexDesktopPackage =
inputs.codex-desktop-linux.packages.${pkgs.stdenv.hostPlatform.system}.codex-desktop-computer-use-ui;
codexDesktopLauncher = pkgs.makeDesktopItem {
name = "codex";
desktopName = "Codex";
genericName = "ChatGPT Desktop";
comment = "Run Codex Desktop on Linux";
exec = "env CODEX_CLI_PATH=${lib.getExe' codexCliPackage "codex"} BAMF_DESKTOP_FILE_HINT=codex.desktop CHROME_DESKTOP=codex.desktop ${lib.getExe' codexDesktopPackage "codex-desktop"} %u";
icon = "codex-desktop";
terminal = false;
categories = [ "Development" ];
keywords = [
"codex"
"chatgpt"
"openai"
"ai"
"assistant"
];
startupNotify = true;
startupWMClass = "codex-desktop";
actions = {
new-window = {
name = "New Window";
exec = "env CODEX_CLI_PATH=${lib.getExe' codexCliPackage "codex"} BAMF_DESKTOP_FILE_HINT=codex.desktop CHROME_DESKTOP=codex.desktop CODEX_MULTI_LAUNCH=1 ${lib.getExe' codexDesktopPackage "codex-desktop"} --new-instance";
};
};
extraConfig = {
X-GNOME-WMClass = "codex-desktop";
};
};
in
{
imports = [
inputs.codex-desktop-linux.nixosModules.default
];
options.my.applications.codexDesktop = {
enable = lib.mkEnableOption "ChatGPT Desktop for Linux";
};
config = lib.mkIf cfg.enable {
my.applications.codex.enable = true;
programs.codexDesktopLinux = {
enable = true;
package = codexDesktopPackage;
cliPackage = codexCliPackage;
computerUseUi.enable = true;
};
environment.systemPackages = [
codexDesktopLauncher # Vicinae-searchable Codex Desktop launcher alias
];
};
}
@@ -0,0 +1,8 @@
{
# The former Codex app cask is deprecated in favor of ChatGPT, whose desktop
# application includes the current Codex experience on macOS.
homebrew = {
enable = true;
casks = [ "chatgpt" ];
};
}
@@ -0,0 +1,5 @@
_: {
description = "Codex Desktop for Linux";
includes = [ "applications.codex" ];
}
@@ -0,0 +1,10 @@
{
inputs,
pkgs,
...
}:
{
environment.systemPackages = [
inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.chatgpt
];
}
@@ -0,0 +1,52 @@
{
lib,
pkgs,
inputs,
...
}:
let
codexSessionUsage = inputs.codex-session-usage.packages.${pkgs.stdenv.hostPlatform.system}.default;
in
{
home.packages = [ codexSessionUsage ];
xdg.dataFile = {
"vicinae/scripts/codex-session-usage/start" = {
executable = true;
text = ''
#!${lib.getExe pkgs.bash}
# @vicinae.schemaVersion 1
# @vicinae.title Start Codex Session Usage
# @vicinae.description Start the local Codex session usage dashboard
# @vicinae.mode compact
# @vicinae.icon 📊
# @vicinae.argument1 { "type": "text", "placeholder": "Port (optional)", "optional": true }
if [[ -z "$1" ]]; then
exec ${lib.getExe codexSessionUsage} start
fi
if [[ "$1" =~ ^[0-9]+$ ]] && (( 10#$1 >= 1 && 10#$1 <= 65535 )); then
exec ${lib.getExe codexSessionUsage} start --port "$1"
fi
printf '%s\n' 'Port must be an integer between 1 and 65535.' >&2
exit 2
'';
};
"vicinae/scripts/codex-session-usage/stop" = {
executable = true;
text = ''
#!${lib.getExe pkgs.bash}
# @vicinae.schemaVersion 1
# @vicinae.title Stop Codex Session Usage
# @vicinae.description Stop the local Codex session usage dashboard
# @vicinae.mode compact
# @vicinae.icon 📊
exec ${lib.getExe codexSessionUsage} stop
'';
};
};
}
-20
View File
@@ -1,20 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.codex;
in
{
options.my.applications.codex = {
enable = lib.mkEnableOption "Codex AI coding assistant";
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [
pkgs.llm-agents.codex # OpenAI Codex CLI
];
};
}
+13
View File
@@ -0,0 +1,13 @@
model = "gpt-5.6-sol"
model_reasoning_effort = "medium"
approval_policy = "on-request"
approvals_reviewer = "auto_review"
sandbox_mode = "workspace-write"
web_search = "cached"
[sandbox_workspace_write]
network_access = false
[projects."/home/moons/dotfiles"]
trust_level = "trusted"
+36
View File
@@ -0,0 +1,36 @@
{
config,
inputs,
lib,
pkgs,
...
}:
let
configDirectory =
if config.home.preferXdgDirectories then
"${config.xdg.configHome}/codex"
else
"${config.home.homeDirectory}/.codex";
configFile = "${configDirectory}/config.toml";
in
{
programs.codex = {
enable = true;
package = inputs.llm-agents.packages.${pkgs.stdenv.hostPlatform.system}.codex;
skills = {
grilling = inputs.skills + "/skills/productivity/grilling";
};
};
# Keep the repository copy as an initial value. Codex may mutate the live
# file between activations; each Home Manager switch resets it from here.
home.activation.resetCodexConfig = {
after = [ "writeBoundary" ];
before = [ ];
data = ''
${pkgs.coreutils}/bin/mkdir -p ${lib.escapeShellArg configDirectory}
${pkgs.coreutils}/bin/install -m 0600 ${./config.toml} ${lib.escapeShellArg configFile}
'';
};
}
-47
View File
@@ -1,47 +0,0 @@
{
imports = [
./1password.nix
./arduino.nix
./btop
./chrome.nix
./claude
./codex-desktop.nix
./codex.nix
./direnv.nix
./discord.nix
./docker.nix
./fcitx5
./ghostty
./git
./gnupg
./grok.nix
./gnome.nix
./greetd.nix
./ly
./gtk
./java
./kde.nix
./nautilus.nix
./nh.nix
./niri
./nix-index
./noctalia
./opencode.nix
./openssh.nix
./slack.nix
./ssh
./swayidle.nix
./swaylock
./tailscale.nix
./vicinae.nix
./vim
./vscode
./wayland.nix
./yazi.nix
./zed
./zellij
./zoom.nix
./zoxide.nix
./zsh
];
}
-16
View File
@@ -1,16 +0,0 @@
{ lib, config, ... }:
let
cfg = config.my.applications.direnv;
in
{
options.my.applications.direnv = {
enable = lib.mkEnableOption "direnv environment variable manager";
};
config = lib.mkIf cfg.enable {
programs.direnv = {
enable = true;
nix-direnv.enable = true;
};
};
}
+10
View File
@@ -0,0 +1,10 @@
{
programs.direnv = {
enable = true;
nix-direnv.enable = true;
config.global = {
warn_timeout = "10s";
};
};
}
-23
View File
@@ -1,23 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.discord;
in
{
options.my.applications.discord = {
enable = lib.mkEnableOption "Discord (Vesktop)";
};
config = lib.mkIf cfg.enable {
home-manager.sharedModules = [
{
programs.vesktop = {
enable = true;
};
}
];
};
}
+108
View File
@@ -0,0 +1,108 @@
{
inputs,
pkgs,
...
}:
let
unstable = inputs.nixpkgs-unstable.legacyPackages.${pkgs.stdenv.hostPlatform.system};
in
{
programs.vesktop = {
enable = true;
package = unstable.vesktop;
settings = {
discordBranch = "stable";
hardwareAcceleration = true;
hardwareVideoAcceleration = true;
tray = true;
minimizeToTray = true;
# Discord Rich Presence
arRPC = true;
openLinksWithElectron = false;
# Keep WebRTC on the public interface selected by the default route.
# Secondary private interfaces can otherwise stall voice at DTLS.
webRTCIPHandlingPolicy = "default_public_interface_only";
spellCheckLanguages = [
"ja-JP"
"en-US"
];
};
vencord = {
useSystem = false;
settings = {
autoUpdate = true;
autoUpdateNotification = false;
useQuickCss = false;
cloud.settingsSync = false;
notifications = {
position = "bottom-right";
useNative = "not-focused";
timeout = 5000;
logLimit = 50;
};
plugins = {
# プライバシー・安全性
NoTrack.enabled = true;
ClearURLs.enabled = true;
# 設定・セッション
BetterSettings.enabled = true;
BetterSessions.enabled = true;
# 画像・添付ファイル
FixImagesQuality.enabled = true;
ImageZoom.enabled = true;
ViewIcons.enabled = true;
CopyFileContents.enabled = true;
# メッセージ操作
QuickReply.enabled = true;
SendTimestamps.enabled = true;
FullSearchContext.enabled = true;
MessageLinkEmbeds.enabled = true;
Unindent.enabled = true;
ValidReply.enabled = true;
# 通知・誤操作対策
ReadAllNotificationsButton.enabled = true;
NoReplyMention.enabled = true;
NotificationVolume.enabled = true;
# UI・パフォーマンス
NoTypingAnimation.enabled = true;
FavoriteEmojiFirst.enabled = true;
KeepCurrentChannel.enabled = true;
# サーバー・権限確認
PermissionsViewer.enabled = true;
MemberCount.enabled = true;
# ボイス・アクティビティ
CallTimer.enabled = true;
GameActivityToggle.enabled = true;
# Vesktop向け
WebKeybinds.enabled = true;
WebScreenShareFixes.enabled = true;
# Message history
MessageLogger.enabled = true;
ShowHiddenChannels.enabled = true;
};
};
};
};
}
-34
View File
@@ -1,34 +0,0 @@
{
pkgs,
lib,
config,
...
}:
let
cfg = config.my.applications.docker;
in
{
options.my.applications.docker = {
enable = lib.mkEnableOption "Docker container runtime";
};
config = lib.mkIf cfg.enable {
virtualisation.docker = {
enable = true;
autoPrune = {
enable = true;
dates = "weekly";
};
daemon.settings = {
ipv6 = true;
"fixed-cidr-v6" = "fd00:30::/64";
ip6tables = true;
};
};
environment.systemPackages = with pkgs; [
docker # Container runtime
oxker # Docker TUI Tool
];
};
}
+6
View File
@@ -0,0 +1,6 @@
{
homebrew = {
enable = true;
casks = [ "orbstack" ];
};
}
@@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = [
pkgs.docker-client
];
}
@@ -0,0 +1,6 @@
{ pkgs, ... }:
{
home.packages = [
pkgs.oxker
];
}
+5
View File
@@ -0,0 +1,5 @@
{
description = "Docker command-line client and NixOS daemon";
includes = [ "services.docker" ];
}
+4
View File
@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.drawio ];
}
@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.easyeffects ];
}
-69
View File
@@ -1,69 +0,0 @@
[Hotkey]
# トリガーキーを押すたびに切り替える
EnumerateWithTriggerKeys=False
# 一時的に第1入力メソッドに切り替える
AltTriggerKeys=
# 切り替え時は第1入力メソッドをスキップする
EnumerateSkipFirst=False
# Time limit in milliseconds for triggering modifier key shortcuts
ModifierOnlyKeyTimeout=250
[Hotkey/TriggerKeys]
1=Zenkaku_Hankaku
[Hotkey/ActivateKeys]
0=Henkan
[Hotkey/DeactivateKeys]
0=Muhenkan
[Hotkey/PrevPage]
0=Up
[Hotkey/NextPage]
0=Down
[Hotkey/PrevCandidate]
0=Shift+Tab
[Hotkey/NextCandidate]
0=Tab
[Hotkey/TogglePreedit]
0=Control+Alt+P
[Behavior]
# デフォルトで有効にする
ActiveByDefault=False
# フォーカス時に状態をリセット
resetStateWhenFocusIn=No
# 入力状態を共有する
ShareInputState=No
# アプリケーションにプリエディットを表示する
PreeditEnabledByDefault=True
# 入力メソッドを切り替える際に入力メソッドの情報を表示する
ShowInputMethodInformation=True
# フォーカスを変更する際に入力メソッドの情報を表示する
showInputMethodInformationWhenFocusIn=False
# 入力メソッドの情報をコンパクトに表示する
CompactInputMethodInformation=True
# 第1入力メソッドの情報を表示する
ShowFirstInputMethodInformation=True
# デフォルトのページサイズ
DefaultPageSize=5
# XKB オプションより優先する
OverrideXkbOption=False
# カスタム XKB オプション
CustomXkbOption=
# Force Enabled Addons
EnabledAddons=
# Force Disabled Addons
DisabledAddons=
# Preload input method to be used by default
PreloadInputMethod=True
# パスワード欄に入力メソッドを許可する
AllowInputMethodForPassword=False
# パスワード入力時にプリエディットテキストを表示する
ShowPreeditForPassword=False
# ユーザーデータを保存する間隔(分)
AutoSavePeriod=30
-23
View File
@@ -1,23 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.fcitx5;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.fcitx5 = {
enable = lib.mkEnableOption "fcitx5 input method";
};
config = lib.mkIf cfg.enable {
my.applications.fcitx5.system.enable = lib.mkDefault true;
my.applications.fcitx5.homeManager.enable = lib.mkDefault true;
};
}
-24
View File
@@ -1,24 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.fcitx5.homeManager;
in
{
options.my.applications.fcitx5.homeManager = {
enable = lib.mkEnableOption "fcitx5 home-manager configuration";
};
config.home-manager.sharedModules = [
{
config = lib.mkIf cfg.enable {
home.file.".config/fcitx5/config" = {
recursive = true;
source = ./config;
};
};
}
];
}
@@ -0,0 +1,82 @@
{ inputs, pkgs, ... }:
{
services.hazkey = {
enable = true;
server.package =
inputs.nix-hazkey.packages.${pkgs.stdenv.hostPlatform.system}.hazkey-server.override
{ enableVulkan = true; };
};
i18n.inputMethod = {
enable = true;
type = "fcitx5";
fcitx5 = {
waylandFrontend = true;
addons = with pkgs; [
fcitx5-gtk
kdePackages.fcitx5-qt
qt6Packages.fcitx5-configtool
];
settings = {
inputMethod = {
GroupOrder."0" = "Default";
"Groups/0" = {
Name = "Default";
"Default Layout" = "jp";
DefaultIM = "hazkey";
};
"Groups/0/Items/0" = {
Name = "keyboard-jp";
};
"Groups/0/Items/1" = {
Name = "hazkey";
};
};
globalOptions = {
Hotkey = {
EnumerateWithTriggerKeys = false;
EnumerateSkipFirst = false;
ModifierOnlyKeyTimeout = 250;
};
"Hotkey/TriggerKeys"."1" = "Zenkaku_Hankaku";
"Hotkey/ActivateKeys"."0" = "Henkan";
"Hotkey/DeactivateKeys"."0" = "Muhenkan";
"Hotkey/PrevPage"."0" = "Up";
"Hotkey/NextPage"."0" = "Down";
"Hotkey/PrevCandidate"."0" = "Shift+Tab";
"Hotkey/NextCandidate"."0" = "Tab";
"Hotkey/TogglePreedit"."0" = "Control+Alt+P";
Behavior = {
ActiveByDefault = false;
resetStateWhenFocusIn = "No";
ShareInputState = "No";
PreeditEnabledByDefault = true;
ShowInputMethodInformation = true;
showInputMethodInformationWhenFocusIn = false;
CompactInputMethodInformation = true;
ShowFirstInputMethodInformation = true;
DefaultPageSize = 5;
OverrideXkbOption = false;
CustomXkbOption = "";
EnabledAddons = "";
DisabledAddons = "";
PreloadInputMethod = true;
AllowInputMethodForPassword = false;
ShowPreeditForPassword = false;
AutoSavePeriod = 30;
};
};
};
};
};
}
+6
View File
@@ -0,0 +1,6 @@
{ inputs, ... }:
{
description = "Fcitx 5 input method framework with Hazkey Japanese input";
imports.home = [ inputs.nix-hazkey.homeModules.hazkey ];
}
-68
View File
@@ -1,68 +0,0 @@
{
pkgs,
lib,
config,
inputs,
...
}:
let
system = pkgs.stdenv.hostPlatform.system;
cfg = config.my.applications.fcitx5.system;
in
{
options.my.applications.fcitx5.system = {
enable = lib.mkEnableOption "fcitx5 system configuration";
};
imports = [
inputs.nix-hazkey.nixosModules.hazkey
];
config = lib.mkIf cfg.enable {
services.hazkey = {
enable = true;
server.package = inputs.nix-hazkey.packages.${system}.hazkey-server.override {
enableVulkan = true;
};
installHazkeySettings = false;
installFcitx5Addon = false;
};
environment.systemPackages = [ inputs.nix-hazkey.packages.${system}.hazkey-settings ];
i18n.inputMethod = {
enable = true;
type = "fcitx5";
fcitx5 = {
waylandFrontend = true;
addons = with pkgs; [
inputs.nix-hazkey.packages.${system}.fcitx5-hazkey
fcitx5-mozc-ut
fcitx5-gtk
kdePackages.fcitx5-qt
qt6Packages.fcitx5-configtool
];
settings.inputMethod = {
GroupOrder = {
"0" = "Default";
};
"Groups/0" = {
Name = "Default";
"Default Layout" = "jp";
DefaultIM = "mozc";
};
"Groups/0/Items/0" = {
Name = "keyboard-jp";
Layout = "";
};
"Groups/0/Items/1" = {
Name = "mozc";
Layout = "";
};
};
};
};
};
}
+4
View File
@@ -0,0 +1,4 @@
{ pkgs, ... }:
{
home.packages = [ pkgs.ffmpeg ];
}
+15
View File
@@ -0,0 +1,15 @@
{
system.defaults.finder = {
AppleShowAllExtensions = true;
AppleShowAllFiles = false;
ShowPathbar = true;
ShowStatusBar = true;
_FXShowPosixPathInTitle = true;
_FXSortFoldersFirst = true;
FXDefaultSearchScope = "SCcf";
FXPreferredViewStyle = "Nlsv";
NewWindowTarget = "Home";
FXEnableExtensionChangeWarning = true;
FXRemoveOldTrashItems = true;
};
}
+17
View File
@@ -0,0 +1,17 @@
{
programs.gamemode = {
enable = true;
enableRenice = true;
settings = {
general = {
softrealtime = "auto";
renice = 10;
};
custom = {
start = "notify-send -a 'Gamemode' 'Optimizations activated'";
end = "notify-send -a 'Gamemode' 'Optimizations deactivated'";
};
};
};
}
+6
View File
@@ -0,0 +1,6 @@
{
programs.gamescope = {
enable = true;
capSysNice = true;
};
}
-40
View File
@@ -1,40 +0,0 @@
theme = dracula
background-blur-radius = 20
background-opacity = 0.9
font-family = BlexMono Nerd Font Mono
mouse-hide-while-typing = true
window-decoration = true
# keybind
# Copy/Paste
keybind = performable:ctrl+shift+c=copy_to_clipboard
keybind = ctrl+shift+v=paste_from_clipboard
# create new tab
keybind = ctrl+shift+t=new_tab
# move tabs
keybind = ctrl+alt+left_bracket=previous_tab
keybind = ctrl+alt+right_bracket=next_tab
# close tab
keybind = ctrl+alt+q=close_window
# font size
keybind = ctrl+shift+semicolon=increase_font_size:1
keybind = ctrl+shift+minus=increase_font_size:1
# quick terminal
keybind = global:super+space=toggle_quick_terminal
quick-terminal-position = top
quick-terminal-size = 100%
gtk-quick-terminal-layer = overlay
quick-terminal-keyboard-interactivity = exclusive
quick-terminal-autohide = false
quit-after-last-window-closed = false
shell-integration-features = ssh-terminfo,ssh-env
+6
View File
@@ -0,0 +1,6 @@
{
homebrew = {
enable = true;
casks = [ "ghostty" ];
};
}
-23
View File
@@ -1,23 +0,0 @@
{
lib,
config,
...
}:
let
cfg = config.my.applications.ghostty;
in
{
imports = [
./home.nix
./system.nix
];
options.my.applications.ghostty = {
enable = lib.mkEnableOption "ghostty terminal emulator";
};
config = lib.mkIf cfg.enable {
my.applications.ghostty.system.enable = lib.mkDefault true;
my.applications.ghostty.homeManager.enable = lib.mkDefault true;
};
}
-83
View File
@@ -1,83 +0,0 @@
{
pkgs,
lib,
config,
inputs,
...
}:
let
cfg = config.my.applications.ghostty.homeManager;
system = pkgs.stdenv.hostPlatform.system;
ghosttyPkg = inputs.ghostty.packages.${system}.ghostty-releasefast;
in
{
options.my.applications.ghostty.homeManager = {
enable = lib.mkEnableOption "ghostty home-manager configuration";
};
config.home-manager.sharedModules = [
(
{ lib, ... }:
{
config = lib.mkIf cfg.enable {
programs.ghostty = {
enable = true;
package = ghosttyPkg;
systemd.enable = true;
settings = {
theme = "dracula";
background-blur-radius = 20;
background-opacity = 0.9;
font-family = "BlexMono Nerd Font Mono";
mouse-hide-while-typing = true;
window-decoration = "auto";
keybind = [
# Copy/Paste
"performable:ctrl+shift+c=copy_to_clipboard"
"ctrl+shift+v=paste_from_clipboard"
# Create new tab
"ctrl+shift+t=new_tab"
# Move tabs
"ctrl+alt+left_bracket=previous_tab"
"ctrl+alt+right_bracket=next_tab"
# Close window
"ctrl+alt+q=close_window"
# Font size
"ctrl+shift+semicolon=increase_font_size:1"
"ctrl+shift+minus=decrease_font_size:1"
];
# Quick terminal
quick-terminal-position = "top";
quick-terminal-size = "98%,100%";
quick-terminal-autohide = false;
quick-terminal-keyboard-interactivity = "on-demand";
gtk-quick-terminal-layer = "top";
quit-after-last-window-closed = false;
shell-integration-features = "no-ssh-env,no-ssh-terminfo";
};
};
xdg.configFile."ghostty/themes/dracula".source = ./dracula.theme;
};
}
)
];
}
@@ -0,0 +1,39 @@
_: {
programs.ghostty = {
enable = true;
settings = {
theme = "dracula";
background-blur-radius = 20;
background-opacity = 0.9;
background-opacity-cells = true;
font-family = "BlexMono Nerd Font Mono";
mouse-hide-while-typing = true;
window-decoration = "auto";
keybind = [
"performable:ctrl+shift+c=copy_to_clipboard"
"ctrl+shift+v=paste_from_clipboard"
"ctrl+shift+t=new_tab"
"ctrl+alt+left_bracket=previous_tab"
"ctrl+alt+right_bracket=next_tab"
"alt+q=close_window"
"global:alt+space=toggle_quick_terminal"
"global:alt+t=new_window"
"ctrl+shift+semicolon=increase_font_size:1"
"ctrl+shift+minus=decrease_font_size:1"
];
quick-terminal-screen = "mouse";
quick-terminal-position = "top";
quick-terminal-size = "98%,100%";
quick-terminal-autohide = false;
quick-terminal-keyboard-interactivity = "on-demand";
gtk-quick-terminal-layer = "top";
quit-after-last-window-closed = false;
shell-integration-features = "no-ssh-env,no-ssh-terminfo";
};
};
xdg.configFile."ghostty/themes/dracula".source = ./dracula.theme;
}

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