Compare commits

...

187 Commits

Author SHA1 Message Date
lassulus
1b3f087079 WIP: zerotier refactor 2025-09-23 12:12:22 +02:00
clan-bot
59aec481b2 Merge pull request 'Update nixpkgs-dev in devFlake' (#5238) from update-devFlake-nixpkgs-dev into main 2025-09-23 10:05:00 +00:00
clan-bot
fe04eb827f Update nixpkgs-dev in devFlake 2025-09-23 10:01:27 +00:00
hsjobeki
6b059ca71d Merge pull request 'clan_lib: persist, compute static data for simpler patch validation' (#5218) from update-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5218
2025-09-22 16:39:29 +00:00
Johannes Kirschbauer
9ea5156f32 clan_lib: disable static checks temporarily 2025-09-22 18:32:58 +02:00
brianmcgee
519ff4c0f3 Merge pull request 'ui/form: use css modules for form components' (#5232) from hgl-ui-form into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5232
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-09-22 13:06:02 +00:00
Glen Huang
bc045ee972 ui/form: use css modules for form components 2025-09-22 20:59:53 +08:00
brianmcgee
5de0d37f0e Merge pull request 'ui/checkbox: use css modules' (#5228) from hgl-ui-checkbox into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5228
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-09-22 10:11:59 +00:00
Johannes Kirschbauer
3574b37a29 clan_lib: fix inventory test message assertions 2025-09-22 12:10:51 +02:00
brianmcgee
2921ae7b84 Merge pull request 'ui: use css modules for sidebar components' (#5217) from hgl into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5217
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-09-22 10:07:52 +00:00
clan-bot
8f5cae5671 Merge pull request 'Update nixpkgs-dev in devFlake' (#5230) from update-devFlake-nixpkgs-dev into main 2025-09-22 10:05:52 +00:00
clan-bot
bc241cdd5f Update nixpkgs-dev in devFlake 2025-09-22 10:01:41 +00:00
Glen Huang
d1b65d5a06 ui/checkbox: use css modules 2025-09-22 17:21:06 +08:00
clan-bot
8402463296 Merge pull request 'Update data-mesher' (#5227) from update-data-mesher into main 2025-09-22 05:06:27 +00:00
clan-bot
461e7ee968 Update data-mesher 2025-09-22 05:00:36 +00:00
Johannes Kirschbauer
b273cc9c6a clan_lib: temporarily allow missing paths again 2025-09-21 17:33:35 +02:00
Johannes Kirschbauer
51f3ffec42 clan_lib: rename writeability to write_map 2025-09-21 17:30:33 +02:00
Johannes Kirschbauer
48ddf22879 clan_lib: split utils into meaningfull files 2025-09-21 17:24:28 +02:00
clan-bot
7a9f3dfc03 Merge pull request 'Update nix-darwin' (#5224) from update-nix-darwin into main 2025-09-21 15:06:53 +00:00
clan-bot
2588813578 Merge pull request 'Update nixpkgs-dev in devFlake' (#5225) from update-devFlake-nixpkgs-dev into main 2025-09-21 15:05:09 +00:00
clan-bot
c95ab34807 Update nixpkgs-dev in devFlake 2025-09-21 15:01:29 +00:00
clan-bot
54fc2aec03 Update nix-darwin 2025-09-21 15:00:39 +00:00
Johannes Kirschbauer
9a03644a80 clan_lib: deprecate is_writeable_key 2025-09-21 16:37:50 +02:00
Johannes Kirschbauer
381c190ba2 clan_lib: inventory store use structured keys 2025-09-21 16:25:54 +02:00
Johannes Kirschbauer
bd50e1ee40 clan_lib: use structured keys for def calc_patches
This allows key that contain dot  and other potentially ambigous unicode
2025-09-21 16:02:10 +02:00
Johannes Kirschbauer
00d38180d3 clan_lib: use flatten_data_structured 2025-09-21 16:02:10 +02:00
Johannes Kirschbauer
7e1b7b056d clan_lib: use flatten_data_structured 2025-09-21 16:02:10 +02:00
Johannes Kirschbauer
4ec3043a4e clan_lib: init flatten_data_structured
Avoids ambiguity issues with keys that contain dots or other separators.
2025-09-21 16:02:10 +02:00
Johannes Kirschbauer
78634d0165 clan_lib: persist, compute static data for simpler patch validation 2025-09-21 16:02:10 +02:00
clan-bot
4d4a689519 Merge pull request 'Update sops-nix' (#5223) from update-sops-nix into main 2025-09-21 05:07:27 +00:00
clan-bot
bd4285a638 Update sops-nix 2025-09-21 05:01:24 +00:00
clan-bot
c418d688dc Merge pull request 'Update nixpkgs-dev in devFlake' (#5222) from update-devFlake-nixpkgs-dev into main 2025-09-21 00:05:33 +00:00
clan-bot
69ea1a211f Update nixpkgs-dev in devFlake 2025-09-21 00:01:33 +00:00
clan-bot
02117d8698 Merge pull request 'Update nix-darwin' (#5221) from update-nix-darwin into main 2025-09-20 20:05:15 +00:00
clan-bot
91643bafbe Update nix-darwin 2025-09-20 20:00:38 +00:00
pinpox
8223120521 Merge pull request 'Add yggdrasil clanService' (#5104) from yggdrasil-vars into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5104
2025-09-20 14:05:54 +00:00
pinpox
8e279a1e71 Add yggdrasil clanService 2025-09-20 16:03:26 +02:00
clan-bot
d6c891750d Merge pull request 'Update nixpkgs-dev in devFlake' (#5220) from update-devFlake-nixpkgs-dev into main 2025-09-20 10:04:45 +00:00
clan-bot
c73d954b55 Update nixpkgs-dev in devFlake 2025-09-20 10:01:30 +00:00
Luis Hebendanz
4ec6ec0090 Merge pull request 'clan-cli: Increase test coverage for clan flash list' (#5194) from Qubasa/clan-core:add_flash_test into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5194
2025-09-20 00:19:33 +00:00
Qubasa
ec98cdf097 clan-cli: Increase test coverage for clan flash list 2025-09-20 02:15:33 +02:00
clan-bot
4ad348d881 Merge pull request 'Update nixpkgs-dev in devFlake' (#5219) from update-devFlake-nixpkgs-dev into main 2025-09-20 00:05:55 +00:00
clan-bot
728d651ad1 Update nixpkgs-dev in devFlake 2025-09-20 00:01:33 +00:00
Luis Hebendanz
fb4c151969 Merge pull request 'clan machines generations' (#4848) from Qubasa/clan-core:add_generate_cli into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4848
2025-09-19 23:30:19 +00:00
Glen Huang
3cf979f0ed ui/divider: use css modules 2025-09-19 22:29:18 +08:00
Glen Huang
3bc31b3e3f ui: use css modules for sidebar components 2025-09-19 22:22:01 +08:00
brianmcgee
99f167a89f Merge pull request 'ui: use css modules for Typography and SidebarBody' (#5215) from hgl into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5215
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-09-19 13:48:14 +00:00
hsjobeki
ed432cc4cf Merge pull request 'UI: add update service' (#5216) from update-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5216
2025-09-19 13:44:12 +00:00
Michael Hoang
4ec5be9476 Merge pull request 'treewide: fix evaluation warnings' (#5214) from nuke-warnings into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5214
2025-09-19 13:29:41 +00:00
Michael Hoang
00a864663b flash-installer: fix evaluation warnings 2025-09-19 15:24:59 +02:00
Michael Hoang
9f1d8d22e8 demo-iso: fix evaluation warning 2025-09-19 15:23:27 +02:00
Johannes Kirschbauer
6f791ac086 UI: add update service 2025-09-19 15:01:53 +02:00
Glen Huang
133f4aee53 ui: use css modules for Typography and SidebarBody
Extra changes:
- Add missing transition to according triggers in SidebarBody
- More sensible tag for each Typography hierarchy
2025-09-19 20:52:22 +08:00
clan-bot
91985504d0 Merge pull request 'Update nuschtos in devFlake' (#5213) from update-devFlake-nuschtos into main 2025-09-19 10:09:08 +00:00
clan-bot
ba5968ce93 Merge pull request 'Update nixpkgs-dev in devFlake' (#5212) from update-devFlake-nixpkgs-dev into main 2025-09-19 10:08:02 +00:00
clan-bot
3370212cea Update nuschtos in devFlake 2025-09-19 10:01:33 +00:00
clan-bot
3043a92815 Update nixpkgs-dev in devFlake 2025-09-19 10:01:30 +00:00
brianmcgee
77921f2857 Merge pull request 'ui/onboarding: use css modules' (#5171) from hgl/clan-core:css into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5171
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-09-19 09:56:37 +00:00
Glen Huang
f22c8f166e ui: use css modules for Button, Icon and Loader
Changes:
- use mergeProps to set default values instead of using ||
- Let a parent component override a child by specifying `in`
- Button can only have at most two icons,  make it accept icon and endIcon
- Rely on class to denote Button's icon type, instead of querying the DOM structure in css
- Dynamic with undefined as the component already skips rendering, no need to explicit check the component value
- move fgClass in css.tsx to a css module
2025-09-19 17:32:29 +08:00
Qubasa
d6ae9cde3f clanServices: add deprecation warning to monitoring service settings. 2025-09-19 10:34:02 +02:00
clan-bot
51b6717202 Merge pull request 'Update nuschtos in devFlake' (#5210) from update-devFlake-nuschtos into main 2025-09-19 00:05:33 +00:00
clan-bot
d27576c130 Merge pull request 'Update nixpkgs-dev in devFlake' (#5209) from update-devFlake-nixpkgs-dev into main 2025-09-19 00:04:22 +00:00
clan-bot
0a972b387c Update nuschtos in devFlake 2025-09-19 00:01:39 +00:00
clan-bot
e8bbe91685 Update nixpkgs-dev in devFlake 2025-09-19 00:01:36 +00:00
Qubasa
455268f6ce clanServices: add ca certs for monitoring/telegraf 2025-09-19 01:29:23 +02:00
clan-bot
ce2e80bcf1 Merge pull request 'Update treefmt-nix in devFlake' (#5205) from update-devFlake-treefmt-nix into main 2025-09-18 20:04:17 +00:00
clan-bot
8e9105735c Update treefmt-nix in devFlake 2025-09-18 20:01:38 +00:00
hsjobeki
db75af2445 Merge pull request 'clanInternals: remove unused options' (#5206) from module-clan into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5206
2025-09-18 16:13:23 +00:00
clan-bot
24014564e8 Merge pull request 'Update nixpkgs-dev in devFlake' (#5204) from update-devFlake-nixpkgs-dev into main 2025-09-18 15:49:06 +00:00
clan-bot
4939723477 Update nixpkgs-dev in devFlake 2025-09-18 17:46:48 +02:00
clan-bot
8be04e790b Merge pull request 'Update treefmt-nix' (#5202) from update-treefmt-nix into main 2025-09-18 15:45:00 +00:00
clan-bot
eaf94f90fe Update treefmt-nix 2025-09-18 17:40:37 +02:00
Johannes Kirschbauer
ac07265ea4 clan/module: remove deprecated clanInternals.inventory 2025-09-18 15:35:39 +00:00
Johannes Kirschbauer
92ca540a42 clan/module: remove clanModules from clanInternals 2025-09-18 15:35:39 +00:00
Mic92
8b18418e7c Merge pull request 'fix pytest' (#5207) from fix-tests into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5207
2025-09-18 15:35:28 +00:00
Jörg Thalheim
9b1573db63 Revert "Merge pull request 'Update clan-core-for-checks in devFlake' (#5132) from update-devFlake-clan-core-for-checks into main"
This reverts commit 62eedacd33, reversing
changes made to 1a344f759a.
2025-09-18 17:31:31 +02:00
Jörg Thalheim
47be7d6865 fix pytest 2025-09-18 17:07:50 +02:00
hsjobeki
1e18d7b897 Merge pull request 'clan_lib: fix update_service:_instance api name' (#5201) from api-update-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5201
2025-09-18 14:46:00 +00:00
Michael Hoang
f099e92394 Merge pull request 'gitea: run nix with --print-build-logs to workflows' (#5200) from push-tymntmvkqxmx into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5200
2025-09-18 14:45:10 +00:00
Johannes Kirschbauer
668fc39dba clan_lib: fix update_service:_instance api name 2025-09-18 16:45:03 +02:00
Michael Hoang
589d353285 gitea: run nix with --print-build-logs to workflows 2025-09-18 16:42:15 +02:00
clan-bot
62eedacd33 Merge pull request 'Update clan-core-for-checks in devFlake' (#5132) from update-devFlake-clan-core-for-checks into main 2025-09-18 14:35:43 +00:00
Michael Hoang
4ce8f03ea6 checks: add dependency on bubblewrap 2025-09-18 16:34:15 +02:00
clan-bot
75367f4d6f Update clan-core-for-checks in devFlake 2025-09-18 16:34:15 +02:00
hsjobeki
1a344f759a Merge pull request 'clan_lib/api: init update service instance' (#5199) from api-update-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5199
2025-09-18 14:33:18 +00:00
Johannes Kirschbauer
3cc1ea6d83 clan_lib/api: init update service instance 2025-09-18 16:31:07 +02:00
Johannes Kirschbauer
09af3f38ee clan_lib: allow delete on non-existing data 2025-09-18 16:29:55 +02:00
Johannes Kirschbauer
0f71ffd3c7 clan_lib: typecast return of get_value_by_path 2025-09-18 16:29:55 +02:00
Johannes Kirschbauer
0fef161391 clan_lib: add inventory json argument 2025-09-18 16:27:05 +02:00
hsjobeki
854481fd49 Merge pull request 'Remove function syntax from extraModules' (#5152) from remove-extainv-func into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5152
Reviewed-by: hsjobeki <hsjobeki@gmail.com>
2025-09-18 14:00:28 +00:00
Qubasa
74f853bd7c clan-cli: Add a clan machines generations command
improvements

stash
2025-09-18 15:18:33 +02:00
Mic92
5613cbe7cb Merge pull request 'telegraf: move telegraf.json into runtime directory' (#5196) from telegraf into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5196
2025-09-18 12:12:45 +00:00
Jörg Thalheim
4b549365f7 telegraf: move telegraf.json into runtime directory
No need to persist this type of data. We also don't need to allocate a
persistent user for telegraf.

Also make it a directory because otherwise thre is a potential race
condition on startup.
2025-09-18 12:11:48 +02:00
clan-bot
e03fcc25e7 Merge pull request 'Update nixpkgs-dev in devFlake' (#5197) from update-devFlake-nixpkgs-dev into main 2025-09-18 10:05:24 +00:00
clan-bot
a798fcb359 Update nixpkgs-dev in devFlake 2025-09-18 10:02:43 +00:00
Glen Huang
d163f0da14 ui/onboarding: use css modules 2025-09-18 14:39:45 +08:00
clan-bot
92e2c841e3 Merge pull request 'Update disko' (#5195) from update-disko into main 2025-09-18 05:05:05 +00:00
clan-bot
01856cf4cb Update disko 2025-09-18 05:00:35 +00:00
Luis Hebendanz
0d04b24473 Merge pull request 'clanServices: init test clan_lib.metrics.version::get_nixos_systems' (#4849) from Qubasa/clan-core:build_is_installed_api into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4849
2025-09-17 23:42:25 +00:00
Qubasa
bc521a1b9b clanServices: jail telegraf-json to not write to tmp dir 2025-09-18 01:38:30 +02:00
Qubasa
eb321df10d clanServices: add indepth test for telegraf metrics 2025-09-18 01:14:10 +02:00
Qubasa
cdceb2a211 clanServices: init vars for telegraf 2025-09-17 21:18:51 +02:00
Qubasa
6546f8a952 clanServices: init test clan_lib.metrics.version::get_nixos_systems 2025-09-17 18:21:19 +02:00
clan-bot
b7798f5466 Merge pull request 'Update nix-darwin' (#5192) from update-nix-darwin into main 2025-09-17 15:06:05 +00:00
clan-bot
132728d757 Merge pull request 'Update nixpkgs-dev in devFlake' (#5193) from update-devFlake-nixpkgs-dev into main 2025-09-17 15:05:57 +00:00
clan-bot
2a52548120 Update nixpkgs-dev in devFlake 2025-09-17 15:01:36 +00:00
clan-bot
71533f118f Update nix-darwin 2025-09-17 15:00:41 +00:00
hsjobeki
c9ab0a42ac Merge pull request 'docs: bring back structured clan options' (#5191) from docs-clan-options into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5191
2025-09-17 13:20:42 +00:00
Johannes Kirschbauer
e7fe50fd6e docs: rename tab to 'search clan options' 2025-09-17 15:17:25 +02:00
Johannes Kirschbauer
757f2412a6 docs: bring back structured clan options 2025-09-17 15:15:32 +02:00
Kenji Berthold
f8d153b318 Merge pull request 'docs: Fix erroneous NixOS spelling' (#5189) from kenji/ke-fix-nixos-rebuild into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5189
2025-09-17 11:20:03 +00:00
a-kenji
782a9375bf docs: Fix erroneous NixOS spelling 2025-09-17 12:40:43 +02:00
Michael Hoang
e332ae9059 Merge pull request 'cli: don't commit the target host for privacy' (#5188) from push-yvrxxtxymrsr into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5188
2025-09-17 10:15:02 +00:00
Michael Hoang
9a9d6bf22d cli: don't commit the target host for privacy 2025-09-17 12:09:26 +02:00
Luis Hebendanz
593c2d3d5b Merge pull request 'docs: dedup vars' (#5187) from Qubasa/clan-core:dedup_docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5187
2025-09-17 09:31:53 +00:00
Qubasa
59c463f326 docs: dedup vars 2025-09-17 11:29:43 +02:00
hsjobeki
f1416bdcba Merge pull request 'lib/types: add docs for custom type' (#5186) from lib-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5186
2025-09-17 09:07:45 +00:00
Johannes Kirschbauer
7a38e976a4 lib/types: add docs for custom type 2025-09-17 11:03:08 +02:00
clan-bot
ae28196039 Merge pull request 'Update nixpkgs' (#5179) from update-nixpkgs into main 2025-09-17 05:07:50 +00:00
clan-bot
a1b7c4f8f7 Update nixpkgs 2025-09-17 05:01:06 +00:00
Luis Hebendanz
66b6290d32 Merge pull request 'feat: add zerotier to network cli' (#5178) from Qubasa/clan-core:zerotier_network into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5178
2025-09-16 19:17:48 +00:00
Qubasa
4aff2a9d40 vars: add machine name to errors 2025-09-16 21:13:54 +02:00
Qubasa
9b39ca42e0 clan_lib: implement check_zerotier_running for network overview 2025-09-16 21:13:54 +02:00
Qubasa
104058b79c zerotier: increase network prio 2025-09-16 21:13:54 +02:00
Mic92
5dd30a8edd Merge pull request 'clanServices/wifi: allow WPA3 and other key management settings' (#5159) from nim65s/clan-core:wpa3 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5159
Reviewed-by: Kenji Berthold <aks.kenji@protonmail.com>
2025-09-16 15:53:44 +00:00
clan-bot
5127a74515 Merge pull request 'Update nixpkgs' (#5174) from update-nixpkgs into main 2025-09-16 15:51:24 +00:00
clan-bot
fd1c0dfabc Update nixpkgs 2025-09-16 15:47:29 +00:00
Moritz Böhme
3d8fab062d feat: add zerotier to network cli 2025-09-16 17:24:11 +02:00
Luis Hebendanz
559c13f41b Merge pull request 'kurogeek-flakeModules-clan-nixos-test' (#5177) from Qubasa/clan-core:kurogeek-flakeModules-clan-nixos-test into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5177
2025-09-16 15:20:16 +00:00
hsjobeki
3afe48f9cf Merge pull request 'lib/jsonschema: remove unused arguments' (#5176) from lib-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5176
2025-09-16 15:15:56 +00:00
Qubasa
555c2e1bc9 clan-core: use importApply for testModule export 2025-09-16 17:14:33 +02:00
Johannes Kirschbauer
80bc3daf96 lib/jsonschema: remove unused arguments 2025-09-16 17:11:19 +02:00
clan-bot
fc1a68b99c Merge pull request 'Update nixpkgs-dev in devFlake' (#5175) from update-devFlake-nixpkgs-dev into main 2025-09-16 15:09:01 +00:00
kurogeek
cbdf8745eb nixosTests option is exposed via flakeModules.testModule 2025-09-16 17:03:31 +02:00
clan-bot
b08f9743f0 Update nixpkgs-dev in devFlake 2025-09-16 15:01:32 +00:00
Luis Hebendanz
50239028b6 Merge pull request 'docs: fix small nitpicks' (#5173) from Qubasa/clan-core:improve_vars_docs2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5173
2025-09-16 15:00:52 +00:00
Qubasa
0f0cfbc7e0 docs: fix small nitpicks 2025-09-16 16:57:40 +02:00
Luis Hebendanz
d4e601586d Merge pull request 'docs: init new structure' (#5157) from improve_vars_docs2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5157
2025-09-16 14:48:15 +00:00
Qubasa
ada80be417 docs: re-add nixos rebuild
docs: fix strict errors
2025-09-16 16:45:09 +02:00
clan-bot
e4b316c14a Merge pull request 'Update nixpkgs' (#4821) from update-nixpkgs into main 2025-09-16 14:19:39 +00:00
hsjobeki
a0fda9b819 Merge pull request 'docs: remove unused plugin' (#5172) from doc-98 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5172
2025-09-16 14:13:10 +00:00
Luis Hebendanz
125a882938 Merge pull request 'bundle nix packagemanager by default' (#5166) from nix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5166
2025-09-16 14:10:29 +00:00
Luis Hebendanz
fc223939ec Merge pull request 'simplify_http_backend' (#5167) from Qubasa/clan-core:simplify_http_backend into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5167
2025-09-16 14:09:27 +00:00
Michael Hoang
2152646df6 cli: don't hardcode system for flash list 2025-09-16 16:07:54 +02:00
Michael Hoang
1f9b44a4ad syncthing: fix vars generator not working with latest Syncthing 2025-09-16 16:07:54 +02:00
Michael Hoang
8a1f924f72 treewide: reformat 2025-09-16 16:07:54 +02:00
Michael Hoang
e43779f8d6 clanServices: remove useless importApply 2025-09-16 16:07:54 +02:00
Michael Hoang
69b0c36381 docs: use manifest.readme instead of path manipulation 2025-09-16 16:07:54 +02:00
Michael Hoang
479d7d536e cli/persist: explicitly annotate type to assist mypy 2025-09-16 16:07:54 +02:00
Michael Hoang
19a209c75a cli/templates: only catch ClanError 2025-09-16 16:07:54 +02:00
clan-bot
c249994e18 Update nixpkgs 2025-09-16 16:07:54 +02:00
hsjobeki
6910620629 Merge pull request 'docs: remove references to buildClan' (#5170) from docs-99 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5170
2025-09-16 14:07:43 +00:00
Johannes Kirschbauer
3f17a6c121 docs: remove unused plugin 2025-09-16 16:07:36 +02:00
Johannes Kirschbauer
50c8df7e40 flake: keep imports sorted 2025-09-16 16:02:10 +02:00
Johannes Kirschbauer
a80df32c59 lib: cleanup readme 2025-09-16 16:02:10 +02:00
Johannes Kirschbauer
b1e3e3616e docs: remove unused export 2025-09-16 16:02:10 +02:00
Johannes Kirschbauer
3d680bcc5f docs: remove references to buildClan 2025-09-16 16:02:05 +02:00
Qubasa
3f5bf8e171 docs: remove stale link
docs: revert nuschtos changes
2025-09-16 16:01:03 +02:00
Qubasa
31ff7b903c docs: add next step button to physical machine 2025-09-16 16:01:03 +02:00
Qubasa
62eb42ae5b docs: Add a what is clan extendable to homepage 2025-09-16 16:01:03 +02:00
Qubasa
d25818580d docs: Fixup stale references 2025-09-16 16:01:03 +02:00
Johannes Kirschbauer
13eba4d7c5 docs: changes from johannes
WIP
2025-09-16 16:01:03 +02:00
Qubasa
86c4555bc0 docs: init new structure 2025-09-16 16:00:40 +02:00
hsjobeki
39eb13eebb Merge pull request 'lib: move clan out of lib into flake' (#5169) from inv-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5169
2025-09-16 13:33:45 +00:00
Johannes Kirschbauer
daea2da358 lib: move clan out of lib into flake
This allows clanLib to stay agnostic and be more testable
2025-09-16 15:28:12 +02:00
hsjobeki
d995c0b118 Merge pull request 'inventory: remove deprecated frontmatter' (#5168) from inv-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5168
2025-09-16 13:05:46 +00:00
Johannes Kirschbauer
5e22830048 inventory: remove deprecated frontmatter 2025-09-16 14:59:39 +02:00
DavHau
15d117d06b Merge pull request 'generate_test_vars: fix + add tests' (#5163) from dave into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5163
2025-09-16 12:23:04 +00:00
DavHau
c936830bc6 generate_test_vars: add test 2025-09-16 19:16:53 +07:00
Jörg Thalheim
8e50ddc84b bundle nix packagemanager by default
detsys nix lazy-path seems to be incompatible with our caching and
deployment commands. By shipping nix, we can be sure to have binaries we
tested.
2025-09-16 13:25:06 +02:00
hsjobeki
f2134754c5 Merge pull request 'inventory: make resolve module a clanLib function' (#5165) from inv-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5165
2025-09-16 11:14:40 +00:00
Johannes Kirschbauer
f49df8d574 inventory: make resolve module a clanLib function
Unclutter inventory logic
2025-09-16 13:09:56 +02:00
Kenji Berthold
d873e667ba Merge pull request 'docs: Add information about nixos-rebuild' (#5000) from ke-docs-add-nixos-rebuild into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5000
2025-09-16 10:42:32 +00:00
hsjobeki
6c2fa3e4ed Merge pull request 'inventory: inline manifest module' (#5164) from inv-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5164
2025-09-16 10:42:17 +00:00
Johannes Kirschbauer
0bce953c2f inventory: inline manifest module
Reducing the clutter of files
Its sometimes better to have all the options in one place if reusing is not a concern
2025-09-16 12:36:58 +02:00
clan-bot
dd1f045022 Merge pull request 'Update sops-nix' (#5135) from update-sops-nix into main 2025-09-16 10:21:43 +00:00
clan-bot
f7cd8c8863 Update sops-nix 2025-09-16 10:01:09 +00:00
DavHau
ea32fdbd93 generate_test_vars: move into clan_cli
Reduces overhead by not having to manage a separate package for this small tool
2025-09-16 16:37:41 +07:00
DavHau
1f3aa0075e generate_test_vars: fix script 2025-09-16 16:37:41 +07:00
DavHau
5d38824d8e cli/debug: fix web-pdb 2025-09-16 16:37:41 +07:00
a-kenji
5ee6156b29 docs: Add information about nixos-rebuild 2025-09-16 11:29:46 +02:00
hsjobeki
a90197cfd4 Merge pull request 'inventory: unify modules' (#5154) from inventory-unify into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5154
2025-09-16 09:02:24 +00:00
hsjobeki
cd1351cd6f Merge pull request 'lib: remove usages of flip' (#5155) from remove-flip into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/5155
2025-09-16 09:01:27 +00:00
Guilhem Saurel
8c42cc377c clanServices/wifi: allow WPA3 and other key management settings 2025-09-15 19:33:19 +02:00
Johannes Kirschbauer
5750ab8d3a lib: remove usages of flip
Makes the code more consistent to read.
Usage in 9 places is rather inconsistent style.
2025-09-15 13:17:09 +02:00
Johannes Kirschbauer
d3397af442 inventory: unify modules 2025-09-15 12:18:35 +02:00
pinpox
ea3818bb50 Remove function syntax from extraModules
Related: https://git.clan.lol/clan/clan-core/issues/5151
2025-09-15 09:52:07 +02:00
263 changed files with 5419 additions and 3321 deletions

View File

@@ -8,6 +8,6 @@ jobs:
runs-on: nix
steps:
- uses: actions/checkout@v4
- run: nix run .#deploy-docs
- run: nix run --print-build-logs .#deploy-docs
env:
SSH_HOMEPAGE_KEY: ${{ secrets.SSH_HOMEPAGE_KEY }}

2
.gitignore vendored
View File

@@ -52,3 +52,5 @@ pkgs/clan-app/ui/.fonts
*.gif
*.mp4
*.mkv
.jj

View File

@@ -12,7 +12,6 @@ let
elem
filter
filterAttrs
flip
genAttrs
hasPrefix
pathExists
@@ -45,7 +44,7 @@ in
flake.check = genAttrs [ "x86_64-linux" "aarch64-darwin" ] (
system:
let
checks = flip filterAttrs self.checks.${system} (
checks = filterAttrs (
name: _check:
!(hasPrefix "nixos-test-" name)
&& !(hasPrefix "nixos-" name)
@@ -57,7 +56,7 @@ in
"clan-core-for-checks"
"clan-deps"
])
);
) self.checks.${system};
in
inputs.nixpkgs.legacyPackages.${system}.runCommand "fast-flake-checks-${system}"
{ passthru.checks = checks; }

View File

@@ -29,9 +29,20 @@
imports = [ self.nixosModules.test-install-machine-without-system ];
clan.core.vars.generators.test = lib.mkForce { };
disko.devices.disk.main.preCreateHook = lib.mkForce "";
# Every option here should match the options set through `clan flash write`
# if you get a mass rebuild on the disko derivation, this means you need to
# adjust something here. Also make sure that the injected json in clan flash write
# is up to date.
i18n.defaultLocale = "de_DE.UTF-8";
console.keyMap = "de";
services.xserver.xkb.layout = "de";
users.users.root.openssh.authorizedKeys.keys = [
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRWUusawhlIorx7VFeQJHmMkhl9X3QpnvOdhnV/bQNG root@target\n"
];
};
};
perSystem =
@@ -44,6 +55,8 @@
dependencies = [
pkgs.disko
pkgs.buildPackages.xorg.lndir
pkgs.glibcLocales
pkgs.kbd.out
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".pkgs.perlPackages.ConfigIniFiles
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".pkgs.perlPackages.FileSlurp
@@ -83,10 +96,10 @@
};
testScript = ''
start_all()
machine.succeed("echo 'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIRWUusawhlIorx7VFeQJHmMkhl9X3QpnvOdhnV/bQNG root@target' > ./test_id_ed25519.pub")
# Some distros like to automount disks with spaces
machine.succeed('mkdir -p "/mnt/with spaces" && mkfs.ext4 /dev/vdc && mount /dev/vdc "/mnt/with spaces"')
machine.succeed("clan flash write --debug --flake ${self.checks.x86_64-linux.clan-core-for-checks} --yes --disk main /dev/vdc test-flash-machine-${pkgs.hostPlatform.system}")
machine.succeed("clan flash write --ssh-pubkey ./test_id_ed25519.pub --keymap de --language de_DE.UTF-8 --debug --flake ${self.checks.x86_64-linux.clan-core-for-checks} --yes --disk main /dev/vdc test-flash-machine-${pkgs.hostPlatform.system}")
'';
} { inherit pkgs self; };
};

View File

@@ -1,4 +1,3 @@
{ ... }:
{
_class = "clan.service";
manifest.name = "clan-core/admin";

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,12 +1,8 @@
{
self,
lib,
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
module = ./default.nix;
in
{
clan.modules.certificates = module;

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
{
clan.modules = {
emergency-access = lib.modules.importApply ./default.nix { };
emergency-access = ./default.nix;
};
}

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -4,7 +4,6 @@
# The test for this module in ./tests/vm/default.nix shows an example of how
# the service is used.
{ packages }:
{ ... }:
{
_class = "clan.service";
@@ -34,20 +33,17 @@
settings,
# The name of this instance of the service
instanceName,
# The current machine
machine,
# All roles of this service, with their assigned machines
roles,
...
}:
{
# Analog to 'perSystem' of flake-parts.
# For every instance of this service we will add a nixosModule to a morning-machine
nixosModule =
{ config, ... }:
{ ... }:
{
# Interaction examples what you could do here:
# - Get some settings of this machine

View File

@@ -5,9 +5,7 @@
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
{
clan.modules = {
importer = lib.modules.importApply ./default.nix { };
importer = ./default.nix;
};
}

View File

@@ -31,7 +31,6 @@
{
roles,
lib,
settings,
...
}:
{

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.localbackup = module;

View File

@@ -144,7 +144,7 @@
};
}
// lib.mapAttrs' (
name: user:
_name: user:
lib.nameValuePair "matrix-password-${user.name}" {
files."matrix-password-${user.name}" = { };
migrateFact = "matrix-password-${user.name}";

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.matrix-synapse = module;

View File

@@ -1,4 +1,3 @@
{ packages }:
{ ... }:
{
_class = "clan.service";
@@ -11,15 +10,15 @@
{ lib, ... }:
{
options.allowAllInterfaces = lib.mkOption {
type = lib.types.bool;
default = false;
description = "If true, Telegraf will listen on all interfaces. Otherwise, it will only listen on the interfaces specified in `interfaces`";
type = lib.types.nullOr lib.types.bool;
default = null;
description = "Deprecated. Has no effect.";
};
options.interfaces = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "zt+" ];
description = "List of interfaces to expose the metrics to";
type = lib.types.nullOr (lib.types.listOf lib.types.str);
default = null;
description = "Deprecated. Has no effect.";
};
};
};

View File

@@ -1,22 +1,24 @@
{
self,
lib,
self,
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
module = ./default.nix;
in
{
clan.modules.monitoring = module;
perSystem =
{ ... }:
{ pkgs, ... }:
{
clan.nixosTests.monitoring = {
imports = [ ./tests/vm/default.nix ];
imports = [
(lib.modules.importApply ./tests/vm/default.nix {
inherit (self) packages;
inherit pkgs;
})
];
clan.modules.monitoring = module;
};
};

View File

@@ -11,34 +11,54 @@
...
}:
let
jsonpath = "/tmp/telegraf.json";
auth_user = "prometheus";
in
{
warnings =
lib.optionals (settings.allowAllInterfaces != null) [
"monitoring.settings.allowAllInterfaces is deprecated and and has no effect. Please remove it from your inventory."
"The monitoring service will now always listen on all interfaces over https."
]
++ (lib.optionals (settings.interfaces != null) [
"monitoring.settings.interfaces is deprecated and and has no effect. Please remove it from your inventory."
"The monitoring service will now always listen on all interfaces over https."
]);
networking.firewall.interfaces = lib.mkIf (settings.allowAllInterfaces == false) (
builtins.listToAttrs (
map (name: {
inherit name;
value.allowedTCPPorts = [
9273
9990
];
}) settings.interfaces
)
);
networking.firewall.allowedTCPPorts = lib.mkIf (settings.allowAllInterfaces == true) [
networking.firewall.allowedTCPPorts = [
9273
9990
];
clan.core.vars.generators."telegraf" = {
clan.core.vars.generators."telegraf-certs" = {
files.crt = {
restartUnits = [ "telegraf.service" ];
deploy = true;
secret = false;
};
files.key = {
mode = "0600";
restartUnits = [ "telegraf.service" ];
};
runtimeInputs = [
pkgs.openssl
];
script = ''
openssl req -x509 -nodes -newkey rsa:4096 \
-keyout "$out"/key \
-out "$out"/crt \
-subj "/C=US/ST=CA/L=San Francisco/O=Example Corp/OU=IT/CN=example.com"
'';
};
clan.core.vars.generators."telegraf" = {
files.password.restartUnits = [ "telegraf.service" ];
files.password-env.restartUnits = [ "telegraf.service" ];
files.miniserve-auth.restartUnits = [ "telegraf.service" ];
dependencies = [ "telegraf-certs" ];
runtimeInputs = [
pkgs.coreutils
pkgs.xkcdpass
@@ -57,11 +77,37 @@
enable = true;
wantedBy = [ "multi-user.target" ];
after = [ "telegraf.service" ];
wants = [ "telegraf.service" ];
requires = [ "telegraf.service" ];
serviceConfig = {
LoadCredential = [
"auth_file_path:${config.clan.core.vars.generators.telegraf.files.miniserve-auth.path}"
"telegraf_crt_path:${config.clan.core.vars.generators.telegraf-certs.files.crt.path}"
"telegraf_key_path:${config.clan.core.vars.generators.telegraf-certs.files.key.path}"
];
Environment = [
"AUTH_FILE_PATH=%d/auth_file_path"
"CRT_PATH=%d/telegraf_crt_path"
"KEY_PATH=%d/telegraf_key_path"
];
Restart = "on-failure";
User = "telegraf";
Group = "telegraf";
RuntimeDirectory = "telegraf-www";
};
script = "${pkgs.miniserve}/bin/miniserve -p 9990 /run/telegraf-www --auth-file \"$AUTH_FILE_PATH\" --tls-cert \"$CRT_PATH\" --tls-key \"$KEY_PATH\"";
};
systemd.services.telegraf = {
serviceConfig = {
LoadCredential = [
"telegraf_crt_path:${config.clan.core.vars.generators.telegraf-certs.files.crt.path}"
"telegraf_key_path:${config.clan.core.vars.generators.telegraf-certs.files.key.path}"
];
Environment = [
"CRT_PATH=%d/telegraf_crt_path"
"KEY_PATH=%d/telegraf_key_path"
];
};
script = "${pkgs.miniserve}/bin/miniserve -p 9990 ${jsonpath} --auth-file ${config.clan.core.vars.generators.telegraf.files.miniserve-auth.path}";
};
services.telegraf = {
@@ -69,6 +115,7 @@
environmentFiles = [
(builtins.toString config.clan.core.vars.generators.telegraf.files.password-env.path)
];
extraConfig = {
agent.interval = "60s";
inputs = {
@@ -104,10 +151,12 @@
metric_version = 2;
basic_username = "${auth_user}";
basic_password = "$${BASIC_AUTH_PWD}";
tls_cert = "$${CRT_PATH}";
tls_key = "$${KEY_PATH}";
};
outputs.file = {
files = [ jsonpath ];
files = [ "/run/telegraf-www/telegraf.json" ];
data_format = "json";
json_timestamp_units = "1s";
};

View File

@@ -1,24 +1,95 @@
{ ... }:
{
name = "monitoring";
clan = {
directory = ./.;
inventory = {
machines.peer1 = { };
machines.peer1 = {
deploy.targetHost = "[2001:db8:1::1]";
};
instances."test" = {
module.name = "monitoring";
module.input = "self";
roles.telegraf.machines.peer1 = { };
};
};
};
nodes = {
peer1 =
{ lib, ... }:
{
services.telegraf.extraConfig = {
agent.interval = lib.mkForce "1s";
outputs.prometheus_client = {
# BUG: We have to disable basic auth here because the prometheus_client
# output plugin will otherwise deadlock Telegraf on startup.
basic_password = lib.mkForce "";
basic_username = lib.mkForce "";
};
};
};
};
# !!! ANY CHANGES HERE MUST BE REFLECTED IN:
# clan_lib/metrics/telegraf.py::get_metrics
testScript =
{ ... }:
{ nodes, ... }:
''
import time
import os
import sys
import subprocess
import ssl
import json
import shlex
import urllib.request
from base64 import b64encode
start_all()
peer1.wait_for_unit("network-online.target")
peer1.wait_for_unit("telegraf.service")
peer1.wait_for_unit("telegraf-json.service")
# Fetch the basic auth password from the secret file
password = peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.telegraf.files.password.path}").strip()
credentials = f"prometheus:{password}"
print("Using credentials:", credentials)
peer1.succeed(f"curl -k -u {credentials} https://localhost:9990/telegraf.json")
peer1.succeed(f"curl -k -u {credentials} https://localhost:9273/metrics")
cert_path = "${nodes.peer1.clan.core.vars.generators.telegraf-certs.files.crt.path}"
url = "https://192.168.1.1:9990/telegraf.json" # HTTPS required
print("Waiting for /var/run/telegraf-www/telegraf.json to be bigger then 200 bytes")
peer1.wait_until_succeeds(f"test \"$(stat -c%s /var/run/telegraf-www/telegraf.json)\" -ge 200", timeout=30)
encoded_credentials = b64encode(credentials.encode("utf-8")).decode("utf-8")
headers = {"Authorization": f"Basic {encoded_credentials}"}
req = urllib.request.Request(url, headers=headers) # noqa: S310
# Trust the provided CA/server certificate
context = ssl.create_default_context(cafile=cert_path)
context.check_hostname = False
context.verify_mode = ssl.CERT_REQUIRED
found_system = False
with urllib.request.urlopen(req, context=context, timeout=5) as response:
for raw_line in response:
line_str = raw_line.decode("utf-8").strip()
if not line_str:
continue
obj = json.loads(line_str)
if obj.get("name") == "nixos_systems":
found_system = True
print("Found nixos_systems metric in json output")
break
assert found_system, "nixos_systems metric not found in json output"
'';
}

View File

@@ -0,0 +1,6 @@
[
{
"publickey": "age1ntpf7lqqw4zrk8swjvwtyfak7f2wg04uf7ggu6vk2yyt9qt74qkswn25ck",
"type": "age"
}
]

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:ACFpRJRDIgVPurZwHYW0J1MnvyuiRGnXMeQj1nb9rDAIqHbZzZk8+E0Nu1+EdXwk78ziP6tHR1GQP2ILTtpLME4lXXRVjouW5Eo=,iv:ctR1HENO3XGIq1/gzYi47nateYzsSK317EKn92ptqDI=,tag:q1yuk/ZMx3nuORkiT/XXqg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvMUtabnp3V0dzNFFYRzk0\nd0ZJbUtDMXRPRGxpRjhYR1MyQzdJYWdJTUFrCjBNV0pPTTlIOHBBbzlEQkFzVy92\ndENxcDdIZlNDSm1oZTNveUtIeVc3MXcKLS0tIGtocENjMFNYT0s1LzhYNy92QU5G\nREVEdjErb0xPSE1yb0g5bGlackh6bEUKwxBoDteD7+JfnlFF71CHx4oEdV/TFYcF\n3JPYUbTWAIyMtUu/CLbX+Pn9Mv+McrEIqhwT7TWL/YbELKVadX/k5Q==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-18T14:33:37Z",
"mac": "ENC[AES256_GCM,data:4631iJmioJ2vZ2PTFbdEJu7UqtyQbp43XBlgEbFAviGZdugb3weVI24rJ8m1Rdnxq8uciEeiX6YHBhURdWQY4JNm2wTGnjz7e2PwQ8FCwOmxCcIQPpdKKsziq/M4HArgD66eUxIWfTt1yJfHgBcUuuANbrbH8MirllT+hJTBhqE=,iv:rM8a/MpKbK7DlqjuR4BG77XDHLK11Q+E2rzZLDJalhk=,tag:bbGMn4anXrLHg4eLA0/CXA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../users/admin

View File

@@ -0,0 +1,4 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}

View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFuTCCA6GgAwIBAgIUMXnA00bMrYvYSq0PjU5/HhXTpmcwDQYJKoZIhvcNAQEL
BQAwbDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1TYW4gRnJh
bmNpc2NvMRUwEwYDVQQKDAxFeGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRQwEgYD
VQQDDAtleGFtcGxlLmNvbTAeFw0yNTA5MTgxNDMzMzZaFw0yNTEwMTgxNDMzMzZa
MGwxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5j
aXNjbzEVMBMGA1UECgwMRXhhbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEUMBIGA1UE
AwwLZXhhbXBsZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC7
sdy27E/XMAyKrgeFcXY70R/vX0gx6EcZlWGp2vZSUVAfW1ni/Vq/LVC02sxGEGwv
10+42yP2yghi89doKo8oCoLsbVu+Pi+TmRsgAijy4jN8pHqbn9/Vk8M8utLa1u4z
VonSIx9pzCYd2+IIdwVuWoyPAAnK/JIKS3n0A8KWkZ/1lq6YDl2whj8iY4YF2Ekg
M0SWhquLZiaApAs7STTYvcP7iLfL4U6cH65dRAbwWMpMErPuLf/CedkXiSUp8Zqx
YIXXE5lf7wqt7tM6k6BHic9FEzAo1HnBWBXV5eB5fs1lX9M1VPmx43XINCfzKwxE
xODtIBrmvj+qOp6/ihBsu3LlOoOikxmL+T9Wgvf7fOuFC4BgmX85mGUV+EMZCDoJ
44jlwFF8wgrfG/ZawkP+opNsQLsdOm9DbAdWpx5+JYdgWBahjxuH4z2eIiBmMKgj
puqDgXdZzcERiYtOEEn0p0tvIkVLO3Tm2GjtHbmg1yF2nwsZjupGfcOGTVX4Zi5x
ZCs7vYgBtZy96kNAuyZcFl8eBUr/oVg//i3Zc9Vnw/UJryB7I6dvj228hlrSz0Ve
pGoeZXbcCzRv8NX2V0V1VTtrblSA3w5WRxVzK7UAVetPZ4dlJX+eyx3x2wiC3TiW
ZYH8haFubQqr1h9oXFHgDE5xYZKr51T3SRGfpn6KvQIDAQABo1MwUTAdBgNVHQ4E
FgQUJHOErJYWaGdla1XhxWha4XBKFYgwHwYDVR0jBBgwFoAUJHOErJYWaGdla1Xh
xWha4XBKFYgwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAgEAXqcg
DW6qzFccR+JTqNR5HBOneB07LxaUqfBTAzU5GTRljY3mVpnTa6vVvXlStChqdmwU
JJdRhWzTpzE4K92l4UKiYKy486PT1ff34aPLPX5BB9OzL4dgvC3gO0MYDJ84AFZl
6BN/MRTinioG+s14SsxmgcUTl+HXsxt75r3WKjXvqECqhONLPXEXDJ6TVmfb2yd5
X9cE6HLS2IXqfvs0EdXmQhSQVS7AlUQWZPDeoBTDUA1tT6ZKCcG0BuHEFnHxg4Yg
W9xp/wMJCEly+9eNJYZYzyK1AHRGnTMRCSifTJEybwI4A35v68FyRLfAC0lM2qVL
yQIGjj55+r4yGCK7bySSKjs59LLLxi6Px3S61OxAYq9KMT65nBLK9JAPFyTnikw9
q/xW208lL+kcRtG+ARo5ycx5QUjWdsHn7TCnqxnDhHznwSV4KGbJFaGQZTtgfcz0
g5a1GwxqHjEZ9IWiN38f2l4kpLLybKhwVQMYeG000s7rDa5hgjbh13qtQN6vUvI6
VozzZPnFcR1Rsa8RR9njDugxbVwlJQfGkoMiMZwNGgXnZRC2XaI6SCyPwqTPBuVP
ZR1eWv4qwsIGKJzJYcdChb5dimlTuVSfZmONpnrOP/4mhQLyaWr3XLqxxP3mIXsz
k1PNWTkgLsXO8DNkCudxcvPElXfmaw6zwaLrZys=
-----END CERTIFICATE-----

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data: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,iv:q3j8EAokyyxiszf+wyRqxEr2igaD1bX7YnFx/NbsGg8=,tag:HKKYWRJEUwW2/TxL+5dSng==,type:str]",
"sops": {
"age": [
{
"recipient": "age1ntpf7lqqw4zrk8swjvwtyfak7f2wg04uf7ggu6vk2yyt9qt74qkswn25ck",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBaeXRjU214aWk5ajl1aW9E\naGJlb1ViaVRmMTBHdkFDQUNDZS94WFZiNUNvCllmWTJBck9hR3U3V09VWDZwQ2xI\nd3ZEQnBIUG5ZSTVIdS8rQ2FMYVhyNk0KLS0tIEE1UG8rSzFyU01sVXhGVHpoaE9i\nSis4Qi9tMGFqbTNMTDZUVk1ZdXkrM28Km4VkfaOsZ69ckjvrg+os43H/O1IoWHzC\nt4LqZRz1Tk7/d1aLWavSPPjVYrCOMZeNBqGbQpGfjjuXrafClRNQdQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3R1RHTGViTnRLVVkyM3J0\nbm96cGVPTlo4NXBNL0g1eEVSNG9DUkgwVFRBCmRKVTlMRmV3Tmg2RTZIclBlWlcr\ndzI5MUxhcllzbE1IMDNxa08zVkpITmsKLS0tIG01Y2dyQkY3UmRudFk2d0p6bThn\nemlaWnZoS3p4VHhMTFFwTm9VN0ttYzQKVbLFgtK6NIRIiryWHeeOPD45iwUds4QD\n7b8xYYoxlo+DETggxK6Vz3IdT/BSK5bFtgAxl864b5gW+Aw4c6AO5w==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-18T14:33:37Z",
"mac": "ENC[AES256_GCM,data:XKCnd0QrAlOCECSeSvbLYHMLbmUh4fMRnLaTb5ARoP4Zc9joWGsCaRZxokc2/sG4BXA/6pkbQXHyIOudKbcBpVjjvs9E+6Mnzt53nfRoH/iOkYPbN2EO49okVZJXW0M1rlBxrxvGuiDlz2p2p6L7neKLy4EB482pYea5+dUr2Yw=,iv:oj/MkZCfkvCmAb79uzEvKwEAm1bKtWhS4rPRAWSgRgw=,tag:h5TPPILXkhJplnDT2Gqtfw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:Q0Vn7J0nERccBYT8HZxHF0Zi5qxmMu40n0H1c+L2SCRF6vRLdURxXKDwvh8xtTU=,iv:ucExjoYDFYy19GsBbNNldJRPBSpT+L+x4PrwTG+m2K8=,tag:/Quupyy/nnUNZsDudEMmNA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1ntpf7lqqw4zrk8swjvwtyfak7f2wg04uf7ggu6vk2yyt9qt74qkswn25ck",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQWWo5OEJ5N1RTR0xMaDhL\nQnlUV2RrRXIzM01OemhQWjVkd3FNZjRhR2dzCi9IeE56b3VZTkNkdW9DMzVia3Zx\nbklxWmFpenRjdEIrc0ZDTGdmSTAxRTQKLS0tIHZJdjdYUzhhY0YzQjRqS0psZmpI\nVHJpUjNZNHRpc2ZWSml1TVNNejhiT28K8TTP/J+XspXZ7TVYj9YaBhEodPIXjojB\nRLqAIgJXRaK4NCLukC6l0IMii6w5J/512RnO2ZBTGhKfbdLfyLOFqg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBrZVc5b0FhbzNXcG1zUDlD\neEVWcWpSRkRCMkxBTHdBM3dCbjVpR3FBa0VjCitlTmx4eUJOMHlaU0dFZEhpK3ZD\nZzlMQXVuZWpnaUNmQW9kOGtOaGVDMU0KLS0tIFNlUi9LSzF0UEJCSVBiRlRSNFQz\nNHhMbmNlRXd4ZEJQWVcvTWdCRWEzMUkKls7RbmNOdPDx8z15F+7qay9qIWx6jNsN\nTahT+GgbG29t1aGQCb0yEzKuUyAp39maxxSWToPsfCgJSYJ8RYiUng==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-18T14:33:39Z",
"mac": "ENC[AES256_GCM,data:g+9/fRiqom2+W28ZpiF+oBj9V6ieq5Xz3sRz3GyzvHoLr6yw51JvpG2QuYNYANW0WCiUjFDkU0qPj/9gLHcuX52nc+gNaTzznb1QGPg7WCGSQI7xaMzyYsPxHpg/BOdj5CL8GyLiOWstD1ch0kc3bJmyu68sJUs04uGtHAADzsE=,iv:oASrYaZarEPDu0R3hd/jMazLgwG5r//hIdMyU/tN15o=,tag:o1fgf5oy+rlWXg88FN5Nfw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:4NIUEK05kEQAKjR8F9mU3M/XvtZXw+X6CejVI0usMcb4WzagNz7XTVDhLWXZ9St5Ev0Y,iv:bD2+rDLMoWSqUAIZRJof0wRrJVya1xwZUTIJBdCs98I=,tag:g2s4byFHTzwU3ikcBGMElA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1ntpf7lqqw4zrk8swjvwtyfak7f2wg04uf7ggu6vk2yyt9qt74qkswn25ck",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBQeVh2M2tqSGlOVkpzNlhU\nd0pMd1R0c0tQWnZzdXViWmtxcjl1Wk1Ka0FNCnBUUWJVbjlyR1hSNGpXNWlPRHJB\nNnMzN3BMQ2NDamFBMlhHbVdJUEZ6cjQKLS0tIEJjWmI0ZDl1NXgrSW9uc0R0LzAr\neEwwOC9DdDg2RTJHQ0M3QTFlcVBaSE0K2Du4NguefdEyY1gS6OuVdO3gHga4omcR\n8B+K1wUfIQbArxZLawPxrj7WNDoW5d4mF9fA3MeV1DFyc4KwtYZmUw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvWkdBakVrMVR4RU8xdDlF\nRDkvL0Mrb3ltazhIMjRLZDVlSTVlaFY2ODBBCnlQM2s0SGEvZjFDN3dGWDhIN0dK\nenhQbjZ1ZS9QZzg5SE5XazZXS3dFSkkKLS0tIHJhKzhadGpjTXd4L3hOQkhpR0Fy\nYzhTN2dxVSt3OE5uZFpuWmVlYW4vd1kKwHOxP0C5mLcm4oIT/sGQtUsdsmu3LSN0\nSola5+N+IrAZ+HKnuZlDLZ5JmJSc5j/YhGNn7KR1xhkhfGSS1e3UZw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-18T14:33:39Z",
"mac": "ENC[AES256_GCM,data:ehbrYqTJcsBKGHUB25JHFnKXrJ6z3LkcElZ89xVr4XxLet+odbhsjIoP2FCcxex7PlXcegMduhHBpXwNGUbX+IUNAXTxlWA9CLDmYhWuS2WLiEVXrS11NE03/zUyHdVx/C38dbIPrWD9iaYSrAiuOyfqDTh9k/Bn7vehLTtadoE=,iv:Nk2WVuJydi5tfsb1Mib4A6NocBCDp9QoIbSadq3bIDI=,tag:IaoyfCv3SkmtemXMR9XnkA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:0BmP+NwG/NGe6R5yU55/MdPEQ8E5u+VXWtvstHc4GpDtmBY=,iv:vo8XBcN7KcYjiyKvvp+XDOdP9yR9B7wJi0XlaiCdVbk=,tag:brK9ntAPSuOvw/C+oDo51g==,type:str]",
"sops": {
"age": [
{
"recipient": "age1ntpf7lqqw4zrk8swjvwtyfak7f2wg04uf7ggu6vk2yyt9qt74qkswn25ck",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA4Tk1INGtybUVlejlNNlZE\nVms3TkdRVVF1T0E4TmV3NmxvYWVEL2U3WVhNCjJIaHhBcWVlMEYxRjg5bzJpTWdJ\neUhaRTNRTmtlTW0zUXQxTVZEMkQ2MFEKLS0tIFNGWDI4b2FXTE8xQ2xqb0cyK3FI\ncktHWnE5c1ZSVFpmQU1HZmU2VVB1QmcK/s1fVmwpMMg4BYkkAJzSY7hVQWae1F7g\nmfH8EGlr74mifWUNEbd49/K13nl8atQx6bcau83JIEQR+yyihuY4Jw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBsL2FXVytUUVZnVU90bG5L\nYURiYjgwN3RuTldWMGl4clpUWmxkeUsrVzM0CkhKZFgwWHl4dWhNSWRQRXVPNDR6\na3hHNmp2RG9YNDhNM2MyV2FuOGY2UlUKLS0tIFpNU2tNOHdhRDRTdHhYWVh2NGZa\nU3J3S0hpclZzWGIwTlFyczdNZkZSZTAKXCZrLaIOVq90ejoKMaRiK0xNw8WOPcnm\nz2uxProEYvQhY8k29mhCFX5HCN0tGn1XTtHeDL7uHuKuFsnSG/fgYQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-18T14:33:39Z",
"mac": "ENC[AES256_GCM,data:QkGJKj/H+MI9Mr9Up5NDUToSddY5eTz47egc2+IatfxR8RebKJ2/mYaeLV26vPdmY60bIac4N/nZkoa6IVBhkHHMvsEHsx3nD6Lro9Wf/pWP8Zddzr90LF5p2+wusq25JutKQiPKOb2gmrcagmSsH/7V/UqI/my3PMeKmw6irhw=,iv:hOtHF/cDFdNfvqCKRhJsOwAHEiQmCPjENzsg23sKG+Q=,tag:K7qG9b4fQD0VbAV8OYp3vw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -5,9 +5,7 @@
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -11,7 +11,9 @@
pkgs.syncthing
];
script = ''
syncthing generate --config "$out"
export TMPDIR=/tmp
TEMPORARY=$(mktemp -d)
syncthing generate --config "$out" --data "$TEMPORARY"
mv "$out"/key.pem "$out"/key
mv "$out"/cert.pem "$out"/cert
cat "$out"/config.xml | grep -oP '(?<=<device id=")[^"]+' | uniq > "$out"/id

View File

@@ -58,7 +58,7 @@
priority = lib.mkDefault 10;
# TODO add user space network support to clan-cli
module = "clan_lib.network.tor";
peers = lib.mapAttrs (name: machine: {
peers = lib.mapAttrs (name: _machine: {
host.var = {
machine = name;
generator = "tor_${instanceName}";

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules = {

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.trusted-nix-caches = module;

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.users = module;

View File

@@ -1,4 +1,3 @@
{ packages }:
{ lib, ... }:
let
inherit (lib)
@@ -29,6 +28,15 @@ in
default = true;
description = "Automatically try to join this wifi network";
};
keyMgmt = lib.mkOption {
type = lib.types.str;
default = "wpa-psk";
description = ''
Key management used for the connection.
One of "none" (WEP or no password protection), "ieee8021x" (Dynamic WEP), "owe" (Opportunistic Wireless Encryption), "wpa-psk" (WPA2 + WPA3 personal),
"sae" (WPA3 personal only), "wpa-eap" (WPA2 + WPA3 enterprise) or "wpa-eap-suite-b-192" (WPA3 enterprise only).
'';
};
};
}
)
@@ -50,7 +58,7 @@ in
ssid_path =
network_name: config.clan.core.vars.generators."wifi.${network_name}".files.network-name.path;
secret_generator = name: value: {
secret_generator = name: _value: {
name = "wifi.${name}";
value = {
prompts.network-name.type = "line";
@@ -80,7 +88,7 @@ in
wifi.mode = "infrastructure";
wifi.ssid = "$ssid_${name}";
wifi-security.psk = "$pw_${name}";
wifi-security.key-mgmt = "wpa-psk";
wifi-security.key-mgmt = networkCfg.keyMgmt;
}
);

View File

@@ -1,12 +1,8 @@
{
self,
lib,
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
module = ./default.nix;
in
{
clan.modules.wifi = module;

View File

@@ -1,6 +1,6 @@
{ lib, ... }:
{ ... }:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.wireguard = module;

View File

@@ -0,0 +1,33 @@
This module sets up [yggdrasil](https://yggdrasil-network.github.io/) across
your clan.
Yggdrasil is designed to be a future-proof and decentralised alternative to
the structured routing protocols commonly used today on the internet. Inside
your clan, it will allow you to reach all of your machines.
## Example Usage
While you can specify statically configured peers for each host, yggdrasil does
auto-discovery of local peers.
```nix
inventory = {
machines = {
peer1 = { };
peer2 = { };
};
instances = {
yggdrasil = {
# Deploy on all machines
roles.default.tags.all = { };
# Or individual hosts
roles.default.machines.peer1 = { };
roles.default.machines.peer2 = { };
};
};
};
```

View File

@@ -0,0 +1,125 @@
{ ... }:
{
_class = "clan.service";
manifest.name = "clan-core/yggdrasil";
manifest.description = "Yggdrasil encrypted IPv6 routing overlay network";
roles.default = {
interface =
{ lib, ... }:
{
options.extraMulticastInterfaces = lib.mkOption {
type = lib.types.listOf lib.types.attrs;
default = [ ];
description = ''
Additional interfaces to use for Multicast. See
https://yggdrasil-network.github.io/configurationref.html#multicastinterfaces
for reference.
'';
example = [
{
Regex = "(wg).*";
Beacon = true;
Listen = true;
Port = 5400;
Priority = 1020;
}
];
};
options.peers = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Static peers to configure for this host.
If not set, local peers will be auto-discovered
'';
example = [
"tcp://192.168.1.1:6443"
"quic://192.168.1.1:6443"
"tls://192.168.1.1:6443"
"ws://192.168.1.1:6443"
];
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{
config,
pkgs,
...
}:
{
clan.core.vars.generators.yggdrasil = {
files.privateKey = { };
files.publicKey.secret = false;
files.address.secret = false;
runtimeInputs = with pkgs; [
yggdrasil
jq
openssl
];
script = ''
# Generate private key
openssl genpkey -algorithm Ed25519 -out $out/privateKey
# Generate corresponding public key
openssl pkey -in $out/privateKey -pubout -out $out/publicKey
# Derive IPv6 address from key
echo "{\"PrivateKeyPath\": \"$out/privateKey\"}" | yggdrasil -useconf -address | tr -d '\n' > $out/address
'';
};
systemd.services.yggdrasil.serviceConfig.BindReadOnlyPaths = [
"%d/key:/key"
];
systemd.services.yggdrasil.serviceConfig.LoadCredential =
"key:${config.clan.core.vars.generators.yggdrasil.files.privateKey.path}";
services.yggdrasil = {
enable = true;
openMulticastPort = true;
# We don't need this option, because we persist our keys with
# vars by ourselfs. This option creates an unnessesary additional
# systemd service to save/load the keys and should be removed
# from the NixOS module entirely, as it can be replaced by the
# (at the time of writing undocumented) PrivateKeyPath= setting.
# See https://github.com/NixOS/nixpkgs/pull/440910#issuecomment-3301835895 for details.
persistentKeys = false;
settings = {
PrivateKeyPath = "/key";
IfName = "ygg";
Peers = settings.peers;
MulticastInterfaces = [
# Ethernet is preferred over WIFI
{
Regex = "(eth|en).*";
Beacon = true;
Listen = true;
Port = 5400;
Priority = 1024;
}
{
Regex = "(wl).*";
Beacon = true;
Listen = true;
Port = 5400;
Priority = 1025;
}
]
++ settings.extraMulticastInterfaces;
};
};
networking.firewall.allowedTCPPorts = [ 5400 ];
};
};
};
}

View File

@@ -0,0 +1,24 @@
{
self,
lib,
...
}:
let
module = lib.modules.importApply ./default.nix {
inherit (self) packages;
};
in
{
clan.modules = {
yggdrasil = module;
};
perSystem =
{ ... }:
{
clan.nixosTests.yggdrasil = {
imports = [ ./tests/vm/default.nix ];
clan.modules.yggdrasil = module;
};
};
}

View File

@@ -0,0 +1,67 @@
{
name = "yggdrasil";
clan = {
test.useContainers = false;
directory = ./.;
inventory = {
machines.peer1 = { };
machines.peer2 = { };
instances."yggdrasil" = {
module.name = "yggdrasil";
module.input = "self";
# Assign the roles to the two machines
roles.default.machines.peer1 = { };
roles.default.machines.peer2 = { };
};
};
};
testScript = ''
start_all()
# Wait for both machines to be ready
peer1.wait_for_unit("multi-user.target")
peer2.wait_for_unit("multi-user.target")
# Check that yggdrasil service is running on both machines
peer1.wait_for_unit("yggdrasil")
peer2.wait_for_unit("yggdrasil")
peer1.succeed("systemctl is-active yggdrasil")
peer2.succeed("systemctl is-active yggdrasil")
# Check that both machines have yggdrasil network interfaces
peer1.wait_until_succeeds("ip link show | grep -E 'ygg'", 30)
peer2.wait_until_succeeds("ip link show | grep -E 'ygg'", 30)
# Get yggdrasil IPv6 addresses from both machines
peer1_ygg_ip = peer1.succeed("yggdrasilctl -json getself | jq -r '.address'").strip()
peer2_ygg_ip = peer2.succeed("yggdrasilctl -json getself | jq -r '.address'").strip()
# Compare runtime addresses with saved addresses from vars
expected_peer1_ip = "${builtins.readFile ./vars/per-machine/peer1/yggdrasil/address/value}"
expected_peer2_ip = "${builtins.readFile ./vars/per-machine/peer2/yggdrasil/address/value}"
print(f"peer1 yggdrasil IP: {peer1_ygg_ip}")
print(f"peer2 yggdrasil IP: {peer2_ygg_ip}")
print(f"peer1 expected IP: {expected_peer1_ip}")
print(f"peer2 expected IP: {expected_peer2_ip}")
# Verify that runtime addresses match expected addresses
assert peer1_ygg_ip == expected_peer1_ip, f"peer1 runtime IP {peer1_ygg_ip} != expected IP {expected_peer1_ip}"
assert peer2_ygg_ip == expected_peer2_ip, f"peer2 runtime IP {peer2_ygg_ip} != expected IP {expected_peer2_ip}"
# Wait a bit for the yggdrasil network to establish connectivity
import time
time.sleep(10)
# Test connectivity: peer1 should be able to ping peer2 via yggdrasil
peer1.succeed(f"ping -6 -c 3 {peer2_ygg_ip}")
# Test connectivity: peer2 should be able to ping peer1 via yggdrasil
peer2.succeed(f"ping -6 -c 3 {peer1_ygg_ip}")
'';
}

View File

@@ -0,0 +1,6 @@
[
{
"publickey": "age1p8trv2dmpanl3gnzj294c4t5uysu7d6rfjncp5lmn6redyda8fns6p7kca",
"type": "age"
}
]

View File

@@ -0,0 +1,6 @@
[
{
"publickey": "age107mprppm3r9u7f26e6t5mhtdny0h5ugfmfjy8kac2tw9nrh9a3ksex0xca",
"type": "age"
}
]

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:jDEog7FFXl28Le3rh5VTiY0DFmLhIy2ZccFjuYWx+OQrKNEqTLI1fzaeMWIcgu6ln6wfGUk640d3IhmrF45MVZiJGkpkOU8UFx0=,iv:4oGaoxhFQwr9OQfdLL7y1N/gJo/uGkTPG/xicVprIAQ=,tag:Smu0/P2bQB66w+0J2Bjlxw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpQ2hib2Mrb0plWUVwNWU5\nWmpxNlduaUVJckhuQlhQbUJpanloWGFLelJ3CjJJMlBGbGRTWEhGUHh2VVkzUzNa\nL3FGVkF3R3JJT051UTg4UlkwOHRNanMKLS0tIDVWcHU4NmFMUWp3STFTYmg5YmNp\nVzd1Uzg2Wkp5QnJ3V1Qyb2lwSXdBRDgK/V5lgw2TePhUC9ngW53ZapIMkcwPvJus\ns0jUYkStHXjsvEiN7BG8cG7/vRbLD8CnKXnmieM20mT6o7GHGfhHMg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-17T07:12:51Z",
"mac": "ENC[AES256_GCM,data:gy/1NFmpFz/tdhgU/Vr+xg46DUjy9ZbrAtCBnIxclwZLJ/fneBpblv8TFgdysY4Ay6jp1S/TOc8eyr+KLHMqcBlje09wd1ac/Y3ee6GccXitB+/c5ayuXX/ShVCdicsr/9COw7vfndAQPU8XIz6tdy0dbL7jgVTyViZW/P5CXEU=,iv:BQ/INwTTCshl5BVnJbVzHW8rwafERS6bKh2JAJsMv9s=,tag:QhsbjeEBivbl8fQLHjiKtQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../users/admin

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:1rVgSwg2qPHuXUOQCgOunaNYiBbsh99dZ2y0BV4TxzACwdb3lb6/XnLeDenLELOpKruZQoNJax/NziRr+VHzmh/TlQhNgTkS71A=,iv:Wi5/cFOETb1rhAYeyzkpppzSSm+S+8cCQYc7zkp74FY=,tag:JQHFZJwYMQH4jUqSw6Ld8Q==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGV3ZLZmNrejlvTFF6NDZW\nYmljS0VXQUtCR3IzMG9tMksvSllVVkIxVTEwCi9Fd1dBbmFlYmF2cE1raVJoS3RR\nWmxQY3RwanRZUE5aN1Q2SzhJOFU1elEKLS0tIG9RMElDMEo3TFJjU0RvU3FMQk12\nT1pNc1VjeUliejk3YmJ6d29zUU15aDQKuZ62Q/ywLrpyu1jB34OCPKQEDd150qH6\nHzyw+MasUlzKNs0ZrALwfhnCKiNb/Pq0Lu660Dx5/sFxI/TAqC7NGg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-17T07:13:24Z",
"mac": "ENC[AES256_GCM,data:N7mmiEZxinOgWdd7QcZBAumnWaApjlQVww4EzAQ1/JH5i8r8CIfPh/7lGMQntlJj5ob+UgrS96nl6XKdvs3Bt7z34zPq7KV3c0mSmclEctRfcZiG4F+rZ0QIMIRJjq7xJL/M9WupSn8Lgms7qHJMdJyHdDkw47bmXz3MIw9c9zo=,iv:ZYPoo5jTIGnZ1HcAWlr26gloVhSjfhwbO/xH5YCbgF0=,tag:UKMVMGEfqyfo04cIkuKD0A==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../users/admin

View File

@@ -0,0 +1,4 @@
{
"publickey": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"type": "age"
}

View File

@@ -0,0 +1 @@
200:fa3b:ad0e:6821:9a51:3ad5:62a4:9ab1

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:oLWxmCqCLyKCdN90eScYC4eMsY5mcpXexk03P+KfQX9hCUg7iOSv+BTujvAFuJA0z2Pgg7B/L0noYSImE3208gDC2exdZme+szpNwxD6oh1bBx5XuYGc/TDzEl7IdPrf1piuqCkWgD6wNb9aFVA9NB/CrNaszY8=,iv:pU8OGFwtqkxy0+iyhWaOnWdSVvaxYBUgnQwv89CTfKc=,tag:V/GVEvjEpeaf3Tl3XCVL7w==,type:str]",
"sops": {
"age": [
{
"recipient": "age1p8trv2dmpanl3gnzj294c4t5uysu7d6rfjncp5lmn6redyda8fns6p7kca",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBidXZxMVg2bkFCekFza3FV\naGVJTjRSSnQrVkgyTVU4Vk9YZFR2Nk1Xcnl3ClNTZnJsR2xZc3hGRFA0NGp2L2Uy\nU2w0N1ZON0xQRXRKL0NId1J3dWNSeXcKLS0tIFlKNk5walJrM2FGM0ozYTBUNVN1\nNHd0N3g2VWFjTUZtbHExdmsvSjJQUGMKDHgRMyTf4CuoIRdsfl6TmPLgcjxHdR4N\nzNmnSmT6QXJr4gBQ7e/3zpMdq4sKzyAOjJPkQra8nJ/KvhpFwXkdtg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB1L3hBYnNTdEhTK1M0TEUx\nM1BFb3IwWDZPc2tkN0JUNXRPWkhEWHpXaFFNCkFlZ3Ixb1hhVWMvUmpKdCtjbW5h\nTVpLSkdxUXI4SVE3MW5LZkFVSmM3dDgKLS0tICtKWGYzbFQ1VGQydktHSDVadVQy\nM3JTSGc0NWVHWGl4akV2VUNNVjVvT00KKmbkGJ2KclTBb7NI0MamWZnlWMaXscws\nYO261RHc/j4s3KdbWATklh2KTicKpgta0mh294Y+hKYLGgBpnXjtOw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-17T07:12:51Z",
"mac": "ENC[AES256_GCM,data:YG4k+PvsF0NVfjqKY/MBhCOwn9Kcn5orq8aD41X3NEPBT+wU5RlN0XqXhH2nkZ52ZHdCN84Ulbd4guwBcJcUtGvxqOpfE4SJ9RFE+SjYw+2+S9wlArQx5R5Zd+Sr+Rgtaip3moENbxETxHZazbEK3u5o0aXKrZvoXH2xgPRYUOg=,iv:lDnNELLpqykrsmoORMW7p6gF43C2QvPwf0PZep2pEo8=,tag:CZNOBx3Aeoq5WeDbANqFVw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAguIpeMvvMtdilU6tsqdBClci2YUgBKEUPQ5ID55zOVY=
-----END PUBLIC KEY-----

View File

@@ -0,0 +1 @@
200:3975:b69f:fd15:f39a:bf24:f644:432b

View File

@@ -0,0 +1 @@
../../../../../../sops/machines/peer2

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:Ik+mzD41SwfGZrqGi5oy0u8ZS8qCKgV34aohIt7J/11S3ayhKKN8451cYPltGg+2i/+2DWRSkqYZsctgIahvthnvb30r91XHRUCtE3oT8iPOKwEuW2xnZBL2dK0qHrKFGn8B/o3Bl/+4cWuR5Jt9QHlN4oF3o50=,iv:a9mSIr7TT9im19P5XKiDGL71hMLfQE8IB6NV8WABZ+s=,tag:dVQ0HZdpbkcmFA37Il+VIw==,type:str]",
"sops": {
"age": [
{
"recipient": "age107mprppm3r9u7f26e6t5mhtdny0h5ugfmfjy8kac2tw9nrh9a3ksex0xca",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3WEtncHIrd2YrbHduUm4y\nYkh1U0NERDR0MzRNQXZ0elNMZzl0ZmJPMlVVCnJ1UC9uNnk0dC9JVzdReUxLZmdR\nMGIwSjBKUW8yQmQ1R3dqU29ZM2czMEUKLS0tIFpMM3l6YnVFRUtLOFRvSTBXRXU0\nQUJWNk5obzBINS90dWwybXlXdEZFZjgKrZtViJwgPpKT+Bhx6ymEhf6QmnMmZ6Jf\n3kIxzDWxGbxrDTrrdXm33gYs9bRvtXsTACRT3TRAKIwSjIV/ycCUBA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArY1A4blFZNjdTU3lGUFA3\nb1hscVhLVmtuQnJMS3VHZVVEOXBDRktXNVhjCkdLZEFFZXhubFJrZTU3RjRDN1lh\nVzgyd3E3a0NGTGh1N2lPQWZBVG9BaW8KLS0tIFN1eEhpMk5mUkNaL29MS2NlWDdP\nVXFtb3c0Y25MT3NLK0N2RStkY1R0MGsKLv8yOSl2iQx39JRJA/e0dOtIz7ZND0+o\nzmqxapD6pxbj8RGswj0szLrxaveWT6Vkmmy/a4fz35uw3xuF7uiJJA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-09-17T07:13:24Z",
"mac": "ENC[AES256_GCM,data:KCBHfavyg1U/Z1e3rr0jdHivUa5/rl42N/K6c0BR47srdYqcpAS+SWW6tH7kPI3EO+P7TgXVoGlmcXaKgrlRpe37eNzdAT6PJYm7rhe6rm2UgZ1yw/NFqA11p/i3dDbTzYHaHMNGGGg9t/BdT1tD0zCICfptGQnSSBx/BEmT3ak=,iv:GOk8/z1mLIVKxFX4ayt9HvA90gv0Af1KqcDbdJRUYu4=,tag:hJpOBFRESQXmE7iMqDqO6g==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1 @@
../../../../../../sops/users/admin

View File

@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA40UksAF1BjKgbYTd3motmeXa/belhNOoRfaaPQTXy8E=
-----END PUBLIC KEY-----

View File

@@ -6,77 +6,74 @@
manifest.categories = [ "Utility" ];
manifest.readme = builtins.readFile ./README.md;
roles.peer = {
perInstance =
{ instanceName, roles, ... }:
{
nixosModule =
{
config,
lib,
pkgs,
...
}:
{
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
})
];
};
};
};
roles.moon = {
roles.default = {
interface =
{ lib, ... }:
{
options.stableEndpoints = lib.mkOption {
type = lib.types.listOf lib.types.str;
options.networkId = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
Make this machine a moon.
Other machines can join this moon by adding this moon in their config.
It will be reachable under the given stable endpoints.
'';
example = ''
[ "1.2.3.4" "10.0.0.3/9993" "2001:abcd:abcd::3/9993" ]
The zerotier network id to use. If not set, a network will be generated for you.
If you administrate your zerotier network via my.zerotier.com, you should set this.
'';
example = "8056c2e21c000001";
};
};
perInstance =
{
instanceName,
settings,
roles,
...
}:
{ instanceName, settings, ... }:
{
nixosModule =
{
config,
lib,
pkgs,
lib,
...
}:
{
config.clan.core.networking.zerotier.moon.stableEndpoints = settings.stableEndpoints;
config = lib.mkMerge [
# code to start/configure zerotier
({ config, ... }: {
services.zerotierone = {
enable = true;
joinNetworks = [ config.clan."zerotier_${instanceName}".networkId ];
};
systemd.network.networks."09-zerotier" = {
matchConfig.Name = "zt*";
networkConfig = {
LLDP = true;
MulticastDNS = true;
KeepConfiguration = "static";
};
};
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
systemd.services.zerotierone.serviceConfig.ExecStartPre = [
"+${pkgs.writeShellScript "init-zerotier" ''
# compare hashes of the current identity secret and the one in the config
hash1=$(sha256sum /var/lib/zerotier-one/identity.secret | cut -d ' ' -f 1)
hash2=$(sha256sum ${config.clan.core.vars.generators.zerotier.files.zerotier-identity-secret.path} | cut -d ' ' -f 1)
if [[ "$hash1" != "$hash2" ]]; then
echo "Identity secret has changed, backing up old identity to /var/lib/zerotier-one/identity.secret.bac"
cp /var/lib/zerotier-one/identity.secret /var/lib/zerotier-one/identity.secret.bac
cp /var/lib/zerotier-one/identity.public /var/lib/zerotier-one/identity.public.bac
cp ${config.clan.core.vars.generators.zerotier.files.zerotier-identity-secret.path} /var/lib/zerotier-one/identity.secret
zerotier-idtool getpublic /var/lib/zerotier-one/identity.secret > /var/lib/zerotier-one/identity.public
fi
# cleanup old networks
if [[ -d /var/lib/zerotier-one/networks.d ]]; then
find /var/lib/zerotier-one/networks.d \
-type f \
-name "*.conf" \
-not \( ${
lib.concatMapStringsSep " -o " (
netId: ''-name "${netId}.conf"''
) config.services.zerotierone.joinNetworks
} \) \
-delete
fi
''}"
];
})
];
};
@@ -87,16 +84,22 @@
interface =
{ lib, ... }:
{
options.allowedIps = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Extra machines by their zerotier ip that the zerotier controller
should accept. These could be external machines.
'';
example = ''
[ "fd5d:bbe3:cbc5:fe6b:f699:935d:bbe3:cbc5" ]
'';
options = {
allowedIps = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Extra machines by their zerotier ip that the zerotier controller
should accept. These could be external machines.
'';
example = ''
[ "fd5d:bbe3:cbc5:fe6b:f699:935d:bbe3:cbc5" ]
'';
};
settings = lib.mkOption {
description = "override the network config in /var/lib/zerotier/bla/$network.json";
type = lib.types.json;
};
};
};
@@ -119,54 +122,135 @@
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
in
{
imports = [
(import ./shared.nix {
inherit
instanceName
roles
config
lib
pkgs
;
})
];
config = {
systemd.services.zerotier-inventory-autoaccept =
let
machines = uniqueStrings (
(lib.optionals (roles ? moon) (lib.attrNames roles.moon.machines))
++ (lib.optionals (roles ? controller) (lib.attrNames roles.controller.machines))
++ (lib.optionals (roles ? peer) (lib.attrNames roles.peer.machines))
);
networkIps = builtins.foldl' (
ips: name:
if
builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then
ips
++ [
(builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value")
]
else
ips
) [ ] machines;
allHostIPs = settings.allowedIps ++ networkIps;
in
{
wantedBy = [ "multi-user.target" ];
after = [ "zerotierone.service" ];
path = [ config.clan.core.clanPkgs.zerotierone ];
serviceConfig.ExecStart = pkgs.writeShellScript "zerotier-inventory-autoaccept" ''
${lib.concatMapStringsSep "\n" (host: ''
${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow --member-ip ${host}
'') allHostIPs}
'';
};
systemd.services.zerotierone.serviceConfig.ExecStartPre = [
"+${pkgs.writeShellScript "init-zerotier-${instanceName}" ''
mkdir -p /var/lib/zerotier-one/controller.d/${instanceName}
ln -sfT ${pkgs.writeText "net.json" (builtins.toJSON settings.settings)} /var/lib/zerotier-one/controller.d/network/${config.clan."zerotier_${instanceName}".networkId}.json
clan.core.networking.zerotier.controller.enable = lib.mkDefault true;
};
''}"
];
systemd.services.zerotierone.serviceConfig.ExecStartPost = [
"+${pkgs.writeShellScript "whitelist-controller" ''
${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow ${
builtins.substring 0 10 config.clan."zerotier_${instanceName}".networkId
}
''}"
];
systemd.services.zerotier-inventory-autoaccept =
let
machines = uniqueStrings (
(lib.optionals (roles ? moon) (lib.attrNames roles.moon.machines))
++ (lib.optionals (roles ? controller) (lib.attrNames roles.controller.machines))
++ (lib.optionals (roles ? peer) (lib.attrNames roles.peer.machines))
);
networkIps = builtins.foldl' (
ips: name:
if
builtins.pathExists "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value"
then
ips
++ [
(builtins.readFile "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value")
]
else
ips
) [ ] machines;
allHostIPs = settings.allowedIps ++ networkIps;
in
{
wantedBy = [ "multi-user.target" ];
after = [ "zerotierone.service" ];
path = [ config.clan.core.clanPkgs.zerotierone ];
serviceConfig.ExecStart = pkgs.writeShellScript "zerotier-inventory-autoaccept" ''
${lib.concatMapStringsSep "\n" (host: ''
${config.clan.core.clanPkgs.zerotier-members}/bin/zerotier-members allow --member-ip ${host}
'') allHostIPs}
'';
};
};
};
};
# there a bunch of different scenarios that can happen which we need to take care of
## controller is not a peer (the controller doesn't have an ipv4 and is not part of the network)
## controller has multiple networks (currently the code only creates a single network per controller, so we need to figure out the API call to get another network created)
## controller has multiple networks but is peer in only some
## I guess we need to make an attrset of controllers to networks and then create the networks with the controller key
# every controller key will be shared, so all network specific ids can be shared
perMachine = { instances, machine, lib, ... }: let
# an attrset of { controller1 = { instance1 = {}; instance2 = {}; }; controller2 = { instance3 = {}; }; }
controllerNetworks = lib.foldlAttrs (acc: instanceName: instance: lib.recursiveUpdate acc { ${lib.head (lib.attrNames instance.roles.controller.machines)} = { ${instanceName} = {}; }; }) {} instances;
getInstanceController = instance: lib.head (lib.attrNames instance.roles.controller.machines);
in {
nixosModule = { pkgs, config, ... }: {
config = lib.mkMerge [
{ # every controller gets a shared network key, from which we can derive multiple network ids
# we have this var shared, so we can create it when evaluating any machine
clan.core.vars.generators = lib.mapAttrs' (controllerName: _: lib.nameValuePair "zerotier_controller_${controllerName}" {
shared = true;
files.zerotier-identity-secret.deploy = false;
runtimeInputs = [
config.services.zerotierone.package
pkgs.python3
];
script = ''
python3 ${./generate.py} --mode network \
--ip "$out/zerotier-ip" \
--identity-secret "$out/zerotier-identity-secret"
'';
}) controllerNetworks;
}
{ # every instance in a controller gets a network id, which is derived from the controller's shared network key
clan.core.vars.generators = lib.mapAttrs' (instanceName: instance: lib.nameValuePair "zerotier_network_${instanceName}" {
shared = true;
files.zerotier-network-id.secret = false;
dependencies = [
config.clan.core.vars.generators."zerotier_controller_${getInstanceController instance}"
];
runtimeInputs = [
config.services.zerotierone.package
pkgs.python3
];
script = ''
python3 ${./generate.py} --mode network-id \
--network-id "$out/zerotier-network-id"
# TODO we need to pass in the controller key
'';
}) instances;
}
{ # define nixos options, which we need to propagate certain information to other roles (like controller)
options.clan = lib.mapAttrs' (instanceName: _: lib.nameValuePair "zerotier_${instanceName}" {
networkId = lib.mkOption {
type = lib.types.str;
description = "The zerotier network id assigned to this machine";
default = if instances.${instanceName}.settings.networkId != null then instances.${instanceName}.settings.networkId else "generated-per-machine";
};
});
}
# if we have set null as networkId, we assume that we have a controller and generate a shared key for it
# (lib.mkIf (settings.networkId == null) {
# clan.core.vars.generators."zerotier_${instanceName}" = {
# files.zerotier-network-id.secret = false;
# files.zerotier-identity-secret.deploy = false;
# shared = true;
# runtimeInputs = [
# config.services.zerotierone.package
# pkgs.python3
# ];
# script = ''
# source ${(pkgs.callPackage ../../../pkgs/minifakeroot { })}/share/minifakeroot/rc
# python3 ${./generate.py} --mode network \
# --ip "$out/zerotier-ip" \
# --identity-secret "$out/zerotier-identity-secret" \
# --network-id "$out/zerotier-network-id"
# '';
# };
# clan."zerotier_${instanceName}".networkId =
# config.clan.core.vars.generators."zerotier_${instanceName}".files.zerotier-network-id.value;
# })
];
};
};
};
}

View File

@@ -5,7 +5,7 @@
...
}:
let
module = lib.modules.importApply ./default.nix { };
module = ./default.nix;
in
{
clan.modules.zerotier = module;

View File

@@ -28,38 +28,5 @@ in
config = {
clan.core.networking.zerotier.networkId = networkId;
clan.core.networking.zerotier.name = instanceName;
systemd.services.zerotierone.serviceConfig.ExecStartPost = lib.mkIf (moonIps != [ ]) (
lib.mkAfter [
"+${pkgs.writeScript "orbit-moons-by-ip" ''
#!${pkgs.python3.interpreter}
import json
import ipaddress
import subprocess
def compute_member_id(ipv6_addr: str) -> str:
addr = ipaddress.IPv6Address(ipv6_addr)
addr_bytes = bytearray(addr.packed)
# Extract the bytes corresponding to the member_id (node_id)
node_id_bytes = addr_bytes[10:16]
node_id = int.from_bytes(node_id_bytes, byteorder="big")
member_id = format(node_id, "x").zfill(10)[-10:]
return member_id
def main() -> None:
ips = json.loads(${builtins.toJSON (builtins.toJSON moonIps)})
for ip in ips:
member_id = compute_member_id(ip)
res = subprocess.run(["zerotier-cli", "orbit", member_id, member_id])
if res.returncode != 0:
print(f"Failed to add {member_id} to orbit")
if __name__ == "__main__":
main()
''}"
]
);
};
}

18
devFlake/flake.lock generated
View File

@@ -84,11 +84,11 @@
},
"nixpkgs-dev": {
"locked": {
"lastModified": 1757924820,
"narHash": "sha256-to/hwbY9/jsRaejPa5oJmPUFZsJfFCB3WReKhD0+/+E=",
"lastModified": 1758573205,
"narHash": "sha256-0ybDco+HjG5h46wx7ww4JIyg3y/mBDgkMCVX/Ua0e/Q=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "aa54acd34af0e86f49d55ea52823031e2da399df",
"rev": "803b1683f562edc00665874bf98c1aad0b111482",
"type": "github"
},
"original": {
@@ -107,11 +107,11 @@
]
},
"locked": {
"lastModified": 1757885130,
"narHash": "sha256-56CMb5W/pgjKLh0bx2ekhn5rde/YmgR63HAqrY9/BCw=",
"lastModified": 1758272005,
"narHash": "sha256-1u3xTH+3kaHhztPmWtLAD8LF5pTYLR2CpsPFWTFnVtQ=",
"owner": "NuschtOS",
"repo": "search",
"rev": "fae3c59a646e00c4b1d359c50b27458a0713d2fd",
"rev": "aa975a3757f28ce862812466c5848787b868e116",
"type": "github"
},
"original": {
@@ -165,11 +165,11 @@
"nixpkgs": []
},
"locked": {
"lastModified": 1756662192,
"narHash": "sha256-F1oFfV51AE259I85av+MAia221XwMHCOtZCMcZLK2Jk=",
"lastModified": 1758206697,
"narHash": "sha256-/DbPkh6PZOgfueCbs3uzlk4ASU2nPPsiVWhpMCNkAd0=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "1aabc6c05ccbcbf4a635fb7a90400e44282f61c4",
"rev": "128222dc911b8e2e18939537bed1762b7f3a04aa",
"type": "github"
},
"original": {

View File

@@ -1,4 +1,4 @@
site_name: Clan Documentation
site_name: Documentation
site_url: https://docs.clan.lol
repo_url: https://git.clan.lol/clan/clan-core/
repo_name: "_>"
@@ -45,82 +45,80 @@ exclude_docs: |
/drafts/
nav:
- Home: index.md
- Getting Started:
- Overview: index.md
- Creating Your First Clan: guides/getting-started/index.md
- Add Machines: guides/getting-started/add-machines.md
- Add User: guides/getting-started/add-user.md
- Add Services: guides/getting-started/add-services.md
- Deploy to Physical Machine:
- Create USB Installer: guides/getting-started/create-installer.md
- Deploy Physical Machine: guides/getting-started/hardware-report-physical.md
- Deploy to Virtual Machine: guides/getting-started/hardware-report-virtual.md
- Configure Disk Config: guides/getting-started/choose-disk.md
- Update Machine: guides/getting-started/update.md
- Continuous Integration: guides/getting-started/flake-check.md
- Convert Existing NixOS Config: guides/getting-started/convert-flake.md
- Guides:
- Getting Started:
- Creating Your First Clan: guides/getting-started/index.md
- Add Machines: guides/getting-started/add-machines.md
- Add User: guides/getting-started/add-user.md
- Add Services: guides/getting-started/add-services.md
- Deploy to Physical Machine:
- Create USB Installer: guides/getting-started/create-installer.md
- Deploy Physical Machine: guides/getting-started/hardware-report-physical.md
- Deploy to Virtual Machine: guides/getting-started/hardware-report-virtual.md
- Configure Disk Config: guides/getting-started/choose-disk.md
- Update Machine: guides/getting-started/update.md
- Continuous Integration: guides/getting-started/flake-check.md
- Convert Existing NixOS Config: guides/getting-started/convert-flake.md
- ClanServices: guides/clanServices.md
- Inventory:
- Introduction to Inventory: guides/inventory/inventory.md
- File Autoincludes: guides/inventory/autoincludes.md
- Clan Services:
- Inventory Guide: guides/inventory/clanServices.md
- Author Your Own Service: guides/services/community.md
- Vars:
- Overview: guides/vars/vars-overview.md
- Getting Started: guides/vars/vars-backend.md
- Concepts: guides/vars/vars-concepts.md
- Sops Backend:
- Yubikeys & Age Plugins: guides/vars/sops/age-plugins.md
- Introduction to Vars: guides/vars/vars-overview.md
- Minimal Example: guides/vars/vars-backend.md
- Diving deeper: guides/vars/vars-concepts.md
- Advanced Examples: guides/vars/vars-advanced-examples.md
- Troubleshooting: guides/vars/vars-troubleshooting.md
- Backup & Restore: guides/backups.md
- Disk Encryption: guides/disk-encryption.md
- Secrets management: guides/secrets.md
- Networking: guides/networking.md
- Zerotier VPN: guides/mesh-vpn.md
- How to disable Secure Boot: guides/secure-boot.md
- Sops Backend:
- Yubikeys & Age Plugins: guides/vars/sops/age-plugins.md
- Managing Users (OLD): guides/secrets.md
- Networking:
- Introduction to Networking: guides/networking/networking.md
- Zerotier VPN: guides/networking/mesh-vpn.md
- Disko Templates:
- Community Disko Templates: guides/disko-templates/community.md
- Backups:
- Introduction to Backups: guides/backups.md
- Flake-parts: guides/flake-parts.md
- macOS: guides/macos.md
- NixOS Rebuild: guides/nixos-rebuild.md
- macOS:
- Managing macOS Machines: guides/macos.md
# Should be part of the respective sections above
# machines, disko, clan
- Templates: concepts/templates.md
- Migrations:
- clan modules --> clan services: guides/migrations/migrate-inventory-services.md
- Facts --> Vars: guides/migrations/migration-facts-vars.md
- Disk id: guides/migrations/disk-id.md
- Disk Encryption: guides/disk-encryption.md
- Disable Secure Boot: guides/secure-boot.md
- Contributing:
- Contributing: guides/contributing/CONTRIBUTING.md
- Debugging: guides/contributing/debugging.md
- Hacking: guides/contributing/CONTRIBUTING.md
- Advanced Debugging: guides/contributing/debugging.md
- Testing: guides/contributing/testing.md
- Writing a Service Module: guides/services/community.md
- Writing a Disko Template: guides/disko-templates/community.md
- Migrations:
- Migrate from clan modules to services: guides/migrations/migrate-inventory-services.md
- Facts Vars Migration: guides/migrations/migration-facts-vars.md
- Disk id: guides/migrations/disk-id.md
- Concepts:
- Inventory: concepts/inventory.md
- Autoincludes: concepts/autoincludes.md
- Templates: concepts/templates.md
- Reference:
- Overview: reference/index.md
- Browse Options: "/options"
- Services:
- Overview:
- reference/clanServices/index.md
- reference/clanServices/admin.md
- reference/clanServices/borgbackup.md
- reference/clanServices/certificates.md
- reference/clanServices/coredns.md
- reference/clanServices/data-mesher.md
- reference/clanServices/dyndns.md
- reference/clanServices/emergency-access.md
- reference/clanServices/garage.md
- reference/clanServices/hello-world.md
- reference/clanServices/importer.md
- reference/clanServices/localbackup.md
- reference/clanServices/matrix-synapse.md
- reference/clanServices/mycelium.md
- reference/clanServices/monitoring.md
- reference/clanServices/packages.md
- reference/clanServices/sshd.md
- reference/clanServices/syncthing.md
- reference/clanServices/trusted-nix-caches.md
- reference/clanServices/users.md
- reference/clanServices/wifi.md
- reference/clanServices/wireguard.md
- reference/clanServices/zerotier.md
- API: reference/clanServices/clan-service-author-interface.md
- Clan Options: reference/options/clan.md
- Clan Inventory Options: reference/options/clan_inventory.md
- Clan Service API: reference/clanServices/clan-service-author-interface.md
- clan.core (Machine Options):
- Overview: reference/clan.core/index.md
- reference/clan.core/backups.md
- reference/clan.core/deployment.md
- reference/clan.core/facts.md
- reference/clan.core/networking.md
- reference/clan.core/postgresql.md
- reference/clan.core/settings.md
- reference/clan.core/sops.md
- reference/clan.core/state.md
- reference/clan.core/vars.md
- CLI:
- Overview: reference/cli/index.md
@@ -139,19 +137,7 @@ nav:
- reference/cli/vars.md
- reference/cli/vms.md
- clan.core (NixOS Options):
- Overview: reference/clan.core/index.md
- reference/clan.core/backups.md
- reference/clan.core/deployment.md
- reference/clan.core/facts.md
- reference/clan.core/networking.md
- reference/clan.core/postgresql.md
- reference/clan.core/settings.md
- reference/clan.core/sops.md
- reference/clan.core/state.md
- reference/clan.core/vars.md
- Developer-api: api.md
- HTTP API: api.md
- Decisions:
- Architecture Decisions: decisions/README.md
@@ -162,7 +148,35 @@ nav:
- 05-deployment-parameters: decisions/05-deployment-parameters.md
- Template: decisions/_template.md
- Glossary: reference/glossary.md
- Browse Options: "/options"
- Services:
- Introduction to ClanServices: reference/clanServices/index.md
- Official:
- reference/clanServices/admin.md
- reference/clanServices/borgbackup.md
- reference/clanServices/certificates.md
- reference/clanServices/coredns.md
- reference/clanServices/data-mesher.md
- reference/clanServices/dyndns.md
- reference/clanServices/emergency-access.md
- reference/clanServices/garage.md
- reference/clanServices/hello-world.md
- reference/clanServices/importer.md
- reference/clanServices/localbackup.md
- reference/clanServices/matrix-synapse.md
- reference/clanServices/mycelium.md
- reference/clanServices/monitoring.md
- reference/clanServices/packages.md
- reference/clanServices/sshd.md
- reference/clanServices/syncthing.md
- reference/clanServices/trusted-nix-caches.md
- reference/clanServices/users.md
- reference/clanServices/wifi.md
- reference/clanServices/wireguard.md
- reference/clanServices/yggdrasil.md
- reference/clanServices/zerotier.md
- Community: community/services/index.md
- Search Clan Options: "/options"
docs_dir: site
site_dir: out
@@ -220,7 +234,6 @@ extra:
plugins:
- search
- macros
- redoc-tag
- redirects:
redirect_maps:

View File

@@ -37,7 +37,6 @@ pkgs.stdenv.mkDerivation {
++ (with pkgs.python3Packages; [
mkdocs
mkdocs-material
mkdocs-macros
mkdocs-redoc-tag
mkdocs-redirects
]);

View File

@@ -11,7 +11,6 @@
...
}:
let
buildClanOptions = self'.legacyPackages.clan-internals-docs;
# Simply evaluated options (JSON)
# { clanCore = «derivation JSON»; clanModules = { ${name} = «derivation JSON» }; }
jsonDocs = pkgs.callPackage ./get-module-docs.nix {
@@ -73,8 +72,7 @@
# A file that contains the links to all clanModule docs
export CLAN_MODULES_VIA_SERVICE=${clanModulesViaService}
export CLAN_SERVICE_INTERFACE=${self'.legacyPackages.clan-service-module-interface}/share/doc/nixos/options.json
export BUILD_CLAN_PATH=${buildClanOptions}/share/doc/nixos/options.json
export CLAN_OPTIONS_PATH=${self'.legacyPackages.clan-options}/share/doc/nixos/options.json
mkdir $out

View File

@@ -13,7 +13,6 @@
let
inherit (lib)
mapAttrsToList
flip
mapAttrs
mkOption
types
@@ -41,10 +40,7 @@
prefix = [ ];
}).config.manifest;
loadFile = file: if builtins.pathExists file then builtins.readFile file else "";
settingsModules =
module: flip mapAttrs (getRoles module) (_roleName: roleConfig: roleConfig.interface);
settingsModules = module: mapAttrs (_roleName: roleConfig: roleConfig.interface) (getRoles module);
# Map each letter to its capitalized version
capitalizeChar =
@@ -99,7 +95,7 @@
**${manifest.description}**
${loadFile (module._file + "/../README.md")}
${lib.optionalString (manifest ? readme) manifest.readme}
${
if manifest.categories != [ ] then
@@ -115,7 +111,7 @@
instances.${name} = lib.mkOption {
inherit description;
type = types.submodule {
options.roles = flip mapAttrs (settingsModules module) (
options.roles = mapAttrs (
roleName: roleSettingsModule:
mkOption {
type = types.submodule {
@@ -138,7 +134,7 @@
];
};
}
);
) (settingsModules module);
};
};
};

View File

@@ -27,6 +27,7 @@
import json
import os
import sys
from dataclasses import dataclass, field
from pathlib import Path
from typing import Any
@@ -40,7 +41,7 @@ from clan_lib.services.modules import (
# Get environment variables
CLAN_CORE_PATH = Path(os.environ["CLAN_CORE_PATH"])
CLAN_CORE_DOCS = Path(os.environ["CLAN_CORE_DOCS"])
BUILD_CLAN_PATH = os.environ.get("BUILD_CLAN_PATH")
CLAN_OPTIONS_PATH = Path(os.environ["CLAN_OPTIONS_PATH"])
# Options how to author clan.modules
# perInstance, perMachine, ...
@@ -326,7 +327,7 @@ Each `clanService`:
See [Migration Guide](../../guides/migrations/migrate-inventory-services.md) for help on migrating.
Learn how to use `clanServices` in practice in the [Using clanServices guide](../../guides/clanServices.md).
Learn how to use `clanServices` in practice in the [Using clanServices guide](../../guides/inventory/clanServices.md).
"""
with indexfile.open("w") as of:
@@ -442,6 +443,84 @@ Typically needed by module authors to define roles, behavior and metadata for di
of.write(output)
def produce_inventory_docs() -> None:
if not CLAN_OPTIONS_PATH:
msg = f"Environment variables are not set correctly: CLAN_OPTIONS_PATH={CLAN_OPTIONS_PATH}. Expected a path to the optionsJSON"
raise ClanError(msg)
if not OUT:
msg = f"Environment variables are not set correctly: $out={OUT}"
raise ClanError(msg)
output = """# Inventory
This provides an overview of the available options of the `inventory` model.
It can be set via the `inventory` attribute of the [`clan`](./clan.md#inventory) function, or via the [`clan.inventory`](./clan.md#inventory) attribute of flake-parts.
"""
# Inventory options are already included under the clan attribute
# We just omitted them in the clan docs, because we want a separate output for the inventory model
with Path(CLAN_OPTIONS_PATH).open() as f:
options: dict[str, dict[str, Any]] = json.load(f)
clan_root_option = options_to_tree(options)
# Find the inventory options
inventory_opt: None | Option = None
for opt in clan_root_option.suboptions:
if opt.name == "inventory":
inventory_opt = opt
break
if not inventory_opt:
print("No inventory options found.")
sys.exit(1)
# Render the inventory options
# This for loop excludes the root node
for option in inventory_opt.suboptions:
output += options_docs_from_tree(option, init_level=2)
outfile = Path(OUT) / "options/clan_inventory.md"
outfile.parent.mkdir(parents=True, exist_ok=True)
with Path.open(outfile, "w") as of:
of.write(output)
def produce_clan_options_docs() -> None:
if not CLAN_OPTIONS_PATH:
msg = f"Environment variables are not set correctly: CLAN_OPTIONS_PATH={CLAN_OPTIONS_PATH}. Expected a path to the optionsJSON"
raise ClanError(msg)
if not OUT:
msg = f"Environment variables are not set correctly: $out={OUT}"
raise ClanError(msg)
output = """# Clan Options
This provides an overview of the available options
Those can be set via [`clan-core.lib.clan`](./clan.md#inventory) function,
or via the [`clan`](./clan.md) attribute of flake-parts.
"""
# Inventory options are already included under the clan attribute
# We just omitted them in the clan docs, because we want a separate output for the inventory model
with Path(CLAN_OPTIONS_PATH).open() as f:
options: dict[str, dict[str, Any]] = json.load(f)
clan_root_option = options_to_tree(options)
# Render the inventory options
# This for loop excludes the root node
# Exclude inventory options
for option in clan_root_option.suboptions:
if "inventory" in option.name:
continue
output += options_docs_from_tree(option, init_level=2)
outfile = Path(OUT) / "options/clan.md"
outfile.parent.mkdir(parents=True, exist_ok=True)
with Path.open(outfile, "w") as of:
of.write(output)
@dataclass
class Option:
name: str
@@ -556,6 +635,7 @@ def options_docs_from_tree(
if __name__ == "__main__":
produce_clan_core_docs()
produce_inventory_docs()
produce_clan_options_docs()
produce_clan_service_author_docs()
produce_clan_service_docs()

View File

@@ -0,0 +1,27 @@
Services provided by the community
!!! tip "Add your own!"
Have you built a service or a tool for? Open a PR adding a link to this page!
<div class="grid cards" markdown>
- [Your Service Foo](https://example.com) :octicons-link-external-16:
---
Does this and that
- [Your Service Foo](https://example.com) :octicons-link-external-16:
---
Does this and that
- [Your Service Foo](https://example.com) :octicons-link-external-16:
---
Does this and that
</div>

View File

@@ -5,7 +5,7 @@ This guide provides an example setup for a single-disk ZFS system with native en
This configuration only applies to `systemd-boot` enabled systems and **requires** UEFI booting.
!!! Info "Secure Boot"
This guide is compatible with systems that have [secure boot disabled](../guides/secure-boot.md). If you encounter boot issues, check if secure boot needs to be disabled in your UEFI settings.
This guide is compatible with systems that have [secure boot disabled](./secure-boot.md). If you encounter boot issues, check if secure boot needs to be disabled in your UEFI settings.
Replace the highlighted lines with your own disk-id.
You can find our your disk-id by executing:

View File

@@ -2,11 +2,11 @@
Machines can be added using the following methods
- Create a file `machines/{machine_name}/configuration.nix` (See: [File Autoincludes](../../concepts/autoincludes.md))
- Create a file `machines/{machine_name}/configuration.nix` (See: [File Autoincludes](../inventory/autoincludes.md))
- Imperative via cli command: `clan machines create`
- Editing nix expressions in flake.nix See [`clan-core.lib.clan`](/options/?scope=Flake Options (clan.nix file))
See the complete [list](../../concepts/autoincludes.md) of auto-loaded files.
See the complete [list](../inventory/autoincludes.md) of auto-loaded files.
## Create a machine

View File

@@ -10,7 +10,7 @@ In Clan Services are multi-Host & role-based:
- You can use tags instead of explicit machine names.
To learn more: [Guide about clanService](../clanServices.md)
To learn more: [Guide about clanService](../inventory/clanServices.md)
!!! Important
It is recommended to add at least one networking service such as `zerotier` that allows to reach all your clan machines from your setup computer across the globe.
@@ -41,7 +41,7 @@ To learn more: [Guide about clanService](../clanServices.md)
```
1. See [reference/clanServices](../../reference/clanServices/index.md) for all available services and how to configure them.
Or read [authoring/clanServices](../../guides/services/community.md) if you want to bring your own
Or read [authoring/clanServices](../services/community.md) if you want to bring your own
2. Replace `__YOUR_CONTROLLER_` with the *name* of your machine.

View File

@@ -171,7 +171,7 @@ Clan needs to know where it can reach your hosts. For testing purpose set
}
```
See our guide on for properly [configuring machines networking](../networking.md)
See our guide on for properly [configuring machines networking](../networking/networking.md)
## Next Steps

View File

@@ -152,7 +152,7 @@ sudo umount /dev/sdb1
## Boot From USB Stick
- To use, boot from the Clan USB drive with **secure boot turned off**. For step by step instructions go to [Disabling Secure Boot](../../guides/secure-boot.md)
- To use, boot from the Clan USB drive with **secure boot turned off**. For step by step instructions go to [Disabling Secure Boot](../secure-boot.md)
## (Optional) Connect to Wifi Manually

View File

@@ -3,7 +3,7 @@
Now that you have created a machine, added some services, and set up secrets, this guide will walk you through how to deploy it.
### Step 0. Prerequisites
### Prerequisites
- [x] RAM > 2GB
- [x] **Two Computers**: You need one computer that you're getting ready (we'll call this the Target Computer) and another one to set it up from (we'll call this the Setup Computer). Make sure both can talk to each other over the network using SSH.
- [x] **Machine configuration**: See our basic [adding and configuring machine guide](./add-machines.md)
@@ -45,7 +45,7 @@ This is an example of the booted installer.
│ │Onion address: 6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion │ │
│ │Multicast DNS: nixos-installer.local │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ Press 'Ctrl-C' for console access │
│ Press 'Ctrl-C' for console access │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
```
@@ -75,12 +75,12 @@ This is an example of the booted installer.
There are two ways to deploy your machine:
### Generating a Hardware Report
The following command will generate a hardware report with [nixos-facter](https://github.com/nix-community/nixos-facter) and writes it back into your machine folder. The `--phases kexec` flag makes sure we are not yet formatting anything, instead if the target system is not a NixOS machine it will use [kexec](https://wiki.archlinux.org/title/Kexec) to switch to a NixOS kernel.
=== "Password"
### Generating a Hardware Report
The following command will generate a hardware report with [nixos-facter](https://github.com/nix-community/nixos-facter) and writes it back into your machine folder. The `--phases kexec` flag makes sure we are not yet formatting anything, instead if the target system is not a NixOS machine it will use [kexec](https://wiki.archlinux.org/title/Kexec) to switch to a NixOS kernel.
**Password**
```terminal
clan machines install [MACHINE] \
@@ -90,11 +90,10 @@ There are two ways to deploy your machine:
```
=== "QR Code"
### Generating a Hardware Report
**QR Code**
The following command will generate a hardware report with [nixos-facter](https://github.com/nix-community/nixos-facter) and writes it back into your machine folder. The `--phases kexec` flag makes sure we are not yet formatting anything, instead if the target system is not a NixOS machine it will use [kexec](https://wiki.archlinux.org/title/Kexec) to switch to a NixOS kernel.
**Using a JSON String or File Path**:
#### Using a JSON String or File Path
Copy the JSON string contained in the QR Code and provide its path or paste it directly:
```terminal
clan machines install [MACHINE] --json [JSON] \
@@ -102,7 +101,8 @@ There are two ways to deploy your machine:
--phases kexec
```
#### Using an Image Containing the QR Code
**Using an Image Containing the QR Code**:
Provide the path to an image file containing the QR code displayed by the installer:
```terminal
clan machines install [MACHINE] --png [PATH] \
@@ -112,3 +112,5 @@ There are two ways to deploy your machine:
If you are using our template `[MACHINE]` would be `jon`
[Next Step (Choose Disk Format)](./choose-disk.md){ .md-button .md-button--primary }

View File

@@ -2,7 +2,7 @@
# Update Machines
The Clan command line interface enables you to update machines remotely over SSH.
In this guide we will teach you how to set a `targetHost` in Nix,
In this guide we will teach you how to set a `targetHost` in Nix,
and how to define a remote builder for your machine closures.
@@ -32,7 +32,7 @@ Ensure that the root login is secured and only used when necessary.
## Multiple Target Hosts
You can now experiment with a new interface that allows you to define multiple `targetHost` addresses for different VPNs. Learn more and try it out in our [networking guide](../networking.md).
You can now experiment with a new interface that allows you to define multiple `targetHost` addresses for different VPNs. Learn more and try it out in our [networking guide](../networking/networking.md).
## Updating Machine Configurations
@@ -65,7 +65,7 @@ During an update, clan will ssh into the `buildHost` and run `nixos-rebuild` fro
```{.nix hl_lines="5" .no-copy}
buildClan {
clan {
# ...
machines = {
"jon" = {
@@ -101,7 +101,7 @@ To exclude machines from being updated when running `clan machines update` witho
one can set the `clan.deployment.requireExplicitUpdate` option to true:
```{.nix hl_lines="5" .no-copy}
buildClan {
clan {
# ...
machines = {
"jon" = {

View File

@@ -1,5 +1,3 @@
# Using the Inventory
Clan's inventory system is a composable way to define and deploy services across
machines.
@@ -70,7 +68,7 @@ inventory.instances = {
## Module Settings
Each role might expose configurable options. See clan's [clanServices
reference](../reference/clanServices/index.md) for all available options.
reference](../../reference/clanServices/index.md) for all available options.
Settings can be set in per-machine or per-role. The latter is applied to all
machines that are assigned to that role.
@@ -157,13 +155,13 @@ inventory.instances = {
You can use services exposed by Clan's core module library, `clan-core`.
🔗 See: [List of Available Services in clan-core](../reference/clanServices/index.md)
🔗 See: [List of Available Services in clan-core](../../reference/clanServices/index.md)
## Defining Your Own Service
You can also author your own `clanService` modules.
🔗 Learn how to write your own service: [Authoring a service](../guides/services/community.md)
🔗 Learn how to write your own service: [Authoring a service](../services/community.md)
You might expose your service module from your flake — this makes it easy for other people to also use your module in their clan.
@@ -179,7 +177,7 @@ ______________________________________________________________________
## What's Next?
- [Author your own clanService →](../guides/services/community.md)
- [Migrate from clanModules →](../guides/migrations/migrate-inventory-services.md)
- [Author your own clanService →](../services/community.md)
- [Migrate from clanModules →](../migrations/migrate-inventory-services.md)
<!-- TODO: * [Understand the architecture →](../explanation/clan-architecture.md) -->

View File

@@ -17,13 +17,13 @@ The following tutorial will walk through setting up a Backup service where the t
## Prerequisites
- [x] [Add some machines](../guides/getting-started/add-machines.md) to your Clan.
- [x] [Add some machines](../getting-started/add-machines.md) to your Clan.
## Services
The inventory defines `instances` of clan services. Membership of `machines` is defined via `roles` exclusively.
See each [modules documentation](../reference/clanServices/index.md) for its available roles.
See each [modules documentation](../../reference/clanServices/index.md) for its available roles.
### Adding services to machines

View File

@@ -7,7 +7,7 @@ This guide explains how to manage macOS machines using Clan.
Currently, Clan supports the following features for macOS:
- `clan machines update` for existing [nix-darwin](https://github.com/nix-darwin/nix-darwin) installations
- Support for [vars](../guides/vars/vars-overview.md)
- Support for [vars](./vars/vars-overview.md)
## Add Your Machine to Your Clan Flake

View File

@@ -1,7 +1,7 @@
# Migrating from using `clanModules` to `clanServices`
**Audience**: This is a guide for **people using `clanModules`**.
If you are a **module author** and need to migrate your modules please consult our **new** [clanServices authoring guide](../../guides/services/community.md)
If you are a **module author** and need to migrate your modules please consult our **new** [clanServices authoring guide](../services/community.md)
## What's Changing?
@@ -353,7 +353,7 @@ roles.client.extraModules = [ self.nixosModules.borgbackup ];
# Or inline module definition
roles.client.extraModules = [
{ config, ... }: {
{
# Your module configuration here
}
];
@@ -378,6 +378,6 @@ instances = {
## Further reference
* [Inventory Concept](../../concepts/inventory.md)
* [Authoring a 'clan.service' module](../../guides/services/community.md)
* [ClanServices](../clanServices.md)
* [Inventory Concept](../inventory/inventory.md)
* [Authoring a 'clan.service' module](../services/community.md)
* [ClanServices](../inventory/clanServices.md)

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