Compare commits

...

589 Commits

Author SHA1 Message Date
a-kenji
f6cec3521a clan-cli: add --json and --png flags to machine install
Allow using `clan machines [machine] install` in conjunction with the
`--json` and `--png` flags.

Fixes #1180
2024-05-07 14:38:42 +02:00
clan-bot
b702ca686e Merge pull request 'add: cd command' (#1265) from a-kenji-docs-patch-1 into main 2024-04-23 18:57:09 +00:00
a-kenji
acdb0a9b27 add: cd command 2024-04-23 20:52:41 +02:00
clan-bot
70ed0757a3 Merge pull request 'vm-manager: add empty list screen' (#1264) from hsjobeki-vm-manager/empty-splash into main 2024-04-23 14:22:47 +00:00
Johannes Kirschbauer
9778c432c2 vm-manager: add empty list screen 2024-04-23 16:18:10 +02:00
Johannes Kirschbauer
1da6a0c5a2 vm-manager: add empty list screen 2024-04-23 16:17:09 +02:00
Johannes Kirschbauer
5f5155023c vm-manager: add empty list screen 2024-04-23 16:16:48 +02:00
Johannes Kirschbauer
1366d0bcf6 WIP 2024-04-23 11:16:33 +02:00
clan-bot
351571a655 Merge pull request 'installer: fix qr code again' (#1260) from lassulus-HEAD into main 2024-04-22 19:10:59 +00:00
lassulus
3c02453705 installer: fix qr code again 2024-04-22 21:04:41 +02:00
clan-bot
7a74c86c70 Merge pull request 'clan-cli ssh: --json can be file or str' (#1259) from lassulus-HEAD into main 2024-04-22 18:56:19 +00:00
lassulus
4ae5b24d24 installer: make qrcode compatible with nixos-images 2024-04-22 20:49:35 +02:00
clan-bot
05b510230f Merge pull request 'clan-cli ssh: --json can be file or str' (#1258) from lassulus-HEAD into main 2024-04-22 18:27:35 +00:00
lassulus
9cb23b807c clan-cli ssh: fix qr code format 2024-04-22 20:21:44 +02:00
lassulus
0a1cc29abf clan-cli ssh: --json can be file or str 2024-04-22 20:13:17 +02:00
clan-bot
1a87df646d Merge pull request 'facts password-store: take path from variable' (#1256) from lassulus-HEAD into main 2024-04-21 17:16:32 +00:00
lassulus
4964415d34 facts password-store: take path from variable 2024-04-21 19:09:46 +02:00
clan-bot
9ac0839bd5 Merge pull request 'clan: clan machines install use verbose flag' (#1252) from a-kenji-clan/install into main 2024-04-19 14:45:29 +00:00
a-kenji
6becce81cb clan: clan machines install use verbose flag 2024-04-19 16:38:39 +02:00
clan-bot
8b1eae8c27 Merge pull request 'fix actual installer' (#1251) from image into main 2024-04-19 12:18:06 +00:00
Jörg Thalheim
5cfc9f7db4 fix actual installer 2024-04-19 14:13:02 +02:00
Jörg Thalheim
2c96e467fa deploy-docs: fix undefined variable 2024-04-19 13:59:39 +02:00
Mic92
3db2ecece6 Merge pull request 'deploy-docs: fix undefined variable' (#1250) from image into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1250
2024-04-19 11:59:35 +00:00
Jörg Thalheim
8d74983103 deploy-docs: fix undefined variable 2024-04-19 11:59:35 +00:00
clan-bot
81f7237a41 Merge pull request 'Change iso to nixos-images version' (#1249) from image into main 2024-04-19 11:49:51 +00:00
Jörg Thalheim
3ebc2e8be9 Change iso to nixos-images version 2024-04-19 13:43:40 +02:00
clan-bot
a810e96a20 Merge pull request 'docs: clan core ref' (#1246) from hsjobeki-main into main 2024-04-18 11:12:28 +00:00
Johannes Kirschbauer
1a99e033eb docs: clan core ref 2024-04-18 13:05:58 +02:00
clan-bot
6d2ec12cca Merge pull request 'clan: clan ssh fix password login' (#1245) from a-kenji-clan-cli/fix-ssh-passowrd into main 2024-04-17 19:52:00 +00:00
a-kenji
e81a7415d8 clan: clan ssh fix password login 2024-04-17 21:45:14 +02:00
clan-bot
d2dffe30a3 Merge pull request 'docs: add clan modules readme support' (#1244) from hsjobeki-main into main 2024-04-17 16:31:17 +00:00
Johannes Kirschbauer
a2074bb82b docs: init synthing & deltachat 2024-04-17 18:26:37 +02:00
clan-bot
f964304224 Merge pull request 'clan: clan ssh fix for new installer image' (#1243) from a-kenji-clan/fix-ssh into main 2024-04-17 16:25:38 +00:00
a-kenji
72811d0828 clan: clan ssh fix for new installer image 2024-04-17 18:20:40 +02:00
clan-bot
22b767466c Merge pull request 'pkgs: add metadata' (#1238) from a-kenji-pkgs/add-metadata into main 2024-04-17 11:35:19 +00:00
a-kenji
9f808b1bdb pkgs: add metadata
Closes #1151
2024-04-17 13:32:50 +02:00
clan-bot
ed9d65a91c Merge pull request 'docs: add clan modules readme support' (#1237) from hsjobeki-main into main 2024-04-17 10:58:17 +00:00
Johannes Kirschbauer
87559613ed docs: add clan modules readme support 2024-04-17 12:52:04 +02:00
kenji
0bae84b1ae Merge pull request 'clan-cli: fix clan ssh --json and --png' (#1234) from clan/ssh into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1234
2024-04-17 10:12:37 +00:00
a-kenji
498d29cca1 clan-cli: fix clan ssh --json and --png
This fixes `clan ssh` with the `--json` and `--png` flags.

It will now correctly use the actual fields that are present in the
generated json.

- probes if the ports are accessible
- if accessible will attempt a single ssh connection with the provided
password, in order to not spam ssh attempts

Fixes #1177
2024-04-17 10:12:37 +00:00
clan-bot
a33a76ecd2 Merge pull request 'rework multicast support' (#1236) from parallelism into main 2024-04-17 09:05:05 +00:00
Jörg Thalheim
8658e1694a rework multicast support 2024-04-17 10:57:17 +02:00
clan-bot
0dde758296 Merge pull request 'docs: split clan-core options into sub-pages' (#1235) from hsjobeki-main into main 2024-04-17 07:45:54 +00:00
Johannes Kirschbauer
5e33a0b3b8 docs: split clan-core options into sub-pages 2024-04-17 09:39:40 +02:00
clan-bot
c57cc5204c Merge pull request 'docs: generate api docs' (#1233) from hsjobeki-tutorials into main 2024-04-16 17:13:38 +00:00
Johannes Kirschbauer
9a3f27ea08 docs: generate api docs 2024-04-16 19:07:28 +02:00
clan-bot
b7f5e98db0 Merge pull request 'documentation: convert note to admonition' (#1227) from a-kenji-docs/set-target-host into main 2024-04-16 10:34:38 +00:00
a-kenji
1db0ace17b documentation: convert note to admonition 2024-04-16 12:28:32 +02:00
clan-bot
059e4efcdc Merge pull request 'docs: improve flake-parts configuration' (#1226) from hsjobeki-tutorials into main 2024-04-16 10:08:54 +00:00
Johannes Kirschbauer
581b48b518 docs: improve flake-parts configuration 2024-04-16 12:02:44 +02:00
clan-bot
f8b881c41e Merge pull request 'refactor facts command to regenerate facts for all machines' (#1223) from parallelism into main 2024-04-15 20:35:22 +00:00
Jörg Thalheim
dcad0d0d79 include machine name when generating secrets 2024-04-15 22:17:53 +02:00
Jörg Thalheim
a4b15d2ca2 flake-parts: fix merging of all-machines-json 2024-04-15 22:14:54 +02:00
Jörg Thalheim
f385e0e037 refactor facts command to regenerate facts for all machines 2024-04-15 22:14:54 +02:00
clan-bot
060e3baa08 Merge pull request 'documentation: improve presentation' (#1222) from a-kenji-docs/improve into main 2024-04-15 10:03:34 +00:00
a-kenji
2d42af3675 documentation: improve presentation 2024-04-15 11:57:23 +02:00
kenji
ca0c109b76 Merge pull request 'broken links replaced (and linking to doc pages (mkdocs rendered pages))' (#1220) from vater/clan-core:main into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1220
2024-04-15 09:49:14 +00:00
vater
8ffe5a562f broken links removed (and linking to doc pages (mkdocs rendered pages)) 2024-04-14 22:38:05 +00:00
clan-bot
997b9d5426 Merge pull request 'documentation: add contribution standards' (#1219) from a-kenji-documentation/standards into main 2024-04-14 15:00:44 +00:00
a-kenji
8322d5dc27 documentation: add contribution standards 2024-04-14 16:54:23 +02:00
clan-bot
419936d1b4 Merge pull request 'documentation: small admonition nit' (#1216) from a-kenji-documentation/nits into main 2024-04-14 13:24:29 +00:00
a-kenji
a81da72ec4 documentation: small admonition nit 2024-04-14 15:18:16 +02:00
clan-bot
4ae5840078 Merge pull request 'documentation: improve configuration' (#1215) from a-kenji-docs/configuration into main 2024-04-14 13:05:18 +00:00
a-kenji
5b846c7c6f documentation: improve configuration 2024-04-14 15:00:41 +02:00
clan-bot
03c109c7f5 Merge pull request 'documenation: improve flake-parts' (#1214) from a-kenji-documentation/improve/flake-parts into main 2024-04-14 12:27:34 +00:00
a-kenji
a1f5024fde documenation: improve flake-parts 2024-04-14 14:23:11 +02:00
clan-bot
09a5fd31a6 Merge pull request 'docs: fix contributing casing' (#1213) from a-kenji-docs/fix-contrib into main 2024-04-14 11:29:15 +00:00
a-kenji
933401eb62 docs: fix contributing casing 2024-04-14 13:22:51 +02:00
clan-bot
b1c0b90fb0 Merge pull request 'documentation: improve secrets page' (#1212) from a-kenji-docs/secrets into main 2024-04-14 11:19:49 +00:00
a-kenji
4442ba777a documentation: improve secrets page 2024-04-14 13:15:26 +02:00
clan-bot
bc7c3ad782 Merge pull request 'documentation: improve networking section' (#1211) from a-kenji-docs/improve-networking into main 2024-04-14 10:49:36 +00:00
a-kenji
062de6866e documentation: improve networking section 2024-04-14 12:43:09 +02:00
clan-bot
1140a847ad Merge pull request 'documenation: improve styling' (#1210) from a-kenji-docs/installer-style into main 2024-04-14 10:35:15 +00:00
a-kenji
711d5d4319 documenation: improve styling 2024-04-14 12:30:56 +02:00
clan-bot
f8675949b9 Merge pull request 'documentation: improve installer wording' (#1209) from a-kenji-docs/installer-wording into main 2024-04-14 10:26:43 +00:00
a-kenji
18a961332e documentation: improve installer wording 2024-04-14 12:20:30 +02:00
clan-bot
d1457c424a Merge pull request 'documentation: improve templates section' (#1208) from a-kenji-docs/update-template into main 2024-04-14 09:58:50 +00:00
clan-bot
d717d9e90d Merge pull request 'documentation: fix typo' (#1207) from a-kenji-fix/typ into main 2024-04-14 09:56:20 +00:00
clan-bot
1bec39cfc6 Merge pull request 'documentation: disable copy for outputs' (#1206) from a-kenji-docs/outputs into main 2024-04-14 09:52:01 +00:00
a-kenji
3d0d124b8a documentation: improve templates section 2024-04-14 11:51:43 +02:00
a-kenji
6cfe735c69 documentation: fix typo 2024-04-14 11:46:53 +02:00
a-kenji
b28d7e45d3 documentation: disable copy for outputs 2024-04-14 11:45:20 +02:00
clan-bot
d7feff104e Merge pull request 'docs: fix migrated build directory' (#1205) from hsjobeki-tutorials into main 2024-04-13 17:45:24 +00:00
Johannes Kirschbauer
10ad6da359 docs: fix migrated build directory 2024-04-13 19:40:28 +02:00
clan-bot
57791ef52a Merge pull request 'docs: decompose configuration guide' (#1204) from hsjobeki-tutorials into main 2024-04-13 15:52:29 +00:00
Johannes Kirschbauer
3a9c84cb45 docs: decompose configuration guide 2024-04-13 15:46:38 +00:00
clan-bot
d2b7bd593b Merge pull request 'documentation: standardize on bash doccomments' (#1203) from a-kenji-docs/standardize-bash into main 2024-04-13 14:41:20 +00:00
a-kenji
7f89740d1b documentation: standardize on bash doccomments 2024-04-13 16:35:16 +02:00
clan-bot
b8d863240c Merge pull request 'docs: improve template' (#1201) from hsjobeki-tutorials into main 2024-04-13 14:33:28 +00:00
Johannes Kirschbauer
b2a1f8571c format 2024-04-13 16:29:24 +02:00
Johannes Kirschbauer
d021b2fb34 template: remove system 2024-04-13 16:00:01 +02:00
Johannes Kirschbauer
fa5058bce4 docs: reword 2024-04-13 15:55:15 +02:00
Johannes Kirschbauer
1978aae39f docs: improve template 2024-04-13 15:53:45 +02:00
clan-bot
6212492c89 Merge pull request 'documentation: make lsblk command copyable' (#1200) from a-kenji-docs/impr into main 2024-04-13 13:21:59 +00:00
a-kenji
4874500b8f documentation: make lsblk command copyable 2024-04-13 15:16:05 +02:00
clan-bot
579994aea6 Merge pull request 'hsjobeki-tutorials' (#1199) from hsjobeki-tutorials into main 2024-04-13 12:57:33 +00:00
Johannes Kirschbauer
2207fd8961 docs: add success block 2024-04-13 14:53:18 +02:00
Johannes Kirschbauer
ff99b10616 docs: rephrase tabs 2024-04-13 14:48:26 +02:00
Johannes Kirschbauer
babf7e3d12 docs: clean up directory structure 2024-04-13 14:48:26 +02:00
clan-bot
7d543da8c2 Merge pull request 'documentation: fix wording' (#1198) from a-kenji-docs/wording into main 2024-04-13 12:19:10 +00:00
a-kenji
f464eafe6c documentation: fix wording 2024-04-13 14:12:47 +02:00
clan-bot
a9347f4ed9 Merge pull request 'docs: move hardware / cloud computers behind tab selection' (#1197) from hsjobeki-tutorials into main 2024-04-13 12:03:57 +00:00
Johannes Kirschbauer
8de732239d docs: move hardware / cloud computers behind tab selection 2024-04-13 13:59:48 +02:00
clan-bot
e52a9f3a16 Merge pull request 'documentation: allow code content to be copied' (#1196) from a-kenji-documentation/impl/copy into main 2024-04-13 11:55:52 +00:00
clan-bot
579b800755 Merge pull request 'docs: remove custom css' (#1195) from hsjobeki-tutorials into main 2024-04-13 11:50:12 +00:00
a-kenji
92de72427e documentation: allow code content to be copied
Allow code content to be copied.

Fixes #1179
2024-04-13 13:48:25 +02:00
Johannes Kirschbauer
e74d0aa3d2 docs: remove custom css 2024-04-13 11:44:32 +00:00
clan-bot
1f11c67e23 Merge pull request 'documentation: improve wifi' (#1194) from a-kenji-docs/improve into main 2024-04-13 11:36:58 +00:00
a-kenji
077598b3ac documentation: improve wifi 2024-04-13 13:32:54 +02:00
clan-bot
35a5131b24 Merge pull request 'vm-manager: fix typos in error message' (#1193) from a-kenji-vm-manager/fix into main 2024-04-13 10:28:54 +00:00
clan-bot
1b77f746bc Merge pull request 'documentation: fix wording' (#1192) from a-kenji-docs/fix into main 2024-04-13 10:25:30 +00:00
clan-bot
275b61925a Merge pull request 'documentation: fix wording' (#1191) from a-kenji-docs/wording into main 2024-04-13 10:22:59 +00:00
clan-bot
e8e37bfb6c Merge pull request 'documentation: add missing character' (#1190) from a-kenji-docs/missing into main 2024-04-13 10:19:05 +00:00
a-kenji
b474de8137 vm-manager: fix typos in error message 2024-04-13 12:18:58 +02:00
clan-bot
57096ae0f4 Merge pull request 'documentation: add correct nix-shell invocation' (#1189) from a-kenji-docs/add-clan-cli into main 2024-04-13 10:14:45 +00:00
a-kenji
b5746906fb documentation: fix wording 2024-04-13 12:14:20 +02:00
a-kenji
ff035d34ed documentation: fix wording 2024-04-13 12:11:13 +02:00
clan-bot
9747d77461 Merge pull request 'docs: fix wording' (#1188) from a-kenji-docs/install into main 2024-04-13 10:10:51 +00:00
a-kenji
e58204a5a7 documentation: add missing character 2024-04-13 12:09:40 +02:00
a-kenji
985deb27a9 documentation: add correct nix-shell invocation 2024-04-13 12:08:35 +02:00
a-kenji
1c690c2a66 docs: fix wording 2024-04-13 12:06:29 +02:00
clan-bot
136b317def Merge pull request 'clan-vm-manager: fix wording in toast' (#1187) from a-kenji-clan-vm-manager/fix/toast into main 2024-04-13 10:02:03 +00:00
a-kenji
9f3fcaf68e clan-vm-manager: fix wording in toast 2024-04-13 11:55:58 +02:00
clan-bot
c4ef4b1950 Merge pull request 'docs: fix wording and typo' (#1185) from a-kenji-doc/fix/wording into main 2024-04-13 09:53:15 +00:00
a-kenji
42e653a647 docs: fix wording and typo 2024-04-13 11:41:00 +02:00
clan-bot
8d6659e60b Merge pull request 'clan-cli: fix typos' (#1183) from a-kenji-clan-cli/fix/typos into main 2024-04-12 15:47:32 +00:00
a-kenji
fff810ed43 clan-cli: fix typos 2024-04-12 17:40:54 +02:00
hsjobeki
2df2787989 Merge pull request 'docs: self host documentation with mkDocs' (#1176) from hsjobeki-tutorials into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1176
2024-04-12 15:14:43 +00:00
Johannes Kirschbauer
70cdf23875 docs: add theming 2024-04-12 17:13:11 +02:00
Jörg Thalheim
4d75feea65 deploy-docs: fail on error 2024-04-12 17:13:11 +02:00
Jörg Thalheim
c3f2c548a6 add deploy script for homepage 2024-04-12 17:13:11 +02:00
Jörg Thalheim
30663d563d fix build on macos 2024-04-12 17:13:11 +02:00
Johannes Kirschbauer
43102906aa disable module docs until migrated 2024-04-12 17:13:11 +02:00
Johannes Kirschbauer
445d547814 remove checks 2024-04-12 17:13:11 +02:00
Johannes Kirschbauer
28773725ec docs: fix links 2024-04-12 17:13:11 +02:00
Johannes Kirschbauer
ecd48df496 worklow: disable link checking, this is done by mkDocs 2024-04-12 17:13:11 +02:00
Valentin Gagarin
d4f10c34c4 fix up title 2024-04-12 17:13:11 +02:00
Valentin Gagarin
e04e4e4fdb make "Getting Started" the start page 2024-04-12 17:13:11 +02:00
Valentin Gagarin
60f2bf54c3 add instructions to live reload docs 2024-04-12 17:13:11 +02:00
Johannes Kirschbauer
1e08a454fb docs: self host documentation with mkDocs 2024-04-12 17:13:11 +02:00
clan-bot
f61a78a1cf Merge pull request 'docs: fix diskLayouts' (#1182) from a-kenji-documentation/fix/docs into main 2024-04-12 14:54:54 +00:00
a-kenji
f76e6cfd1e docs: fix diskLayouts 2024-04-12 16:44:00 +02:00
kenji
ae8e15dc5e Merge pull request 'fix installer' (#1175) from docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1175
2024-04-12 14:00:25 +00:00
a-kenji
26c71d9720 installer: add zstd compression 2024-04-12 14:00:25 +00:00
Jörg Thalheim
088e0d3eee fix installer 2024-04-12 14:00:25 +00:00
clan-bot
cb20f62486 Merge pull request 'docs: fix iso location' (#1174) from a-kenji-fix/docss into main 2024-04-12 13:15:29 +00:00
clan-bot
828d61fef5 Merge pull request 'docs: remove superfluous heading' (#1173) from a-kenji-fix/docs into main 2024-04-12 13:11:25 +00:00
a-kenji
75fc8fd35a docs: fix iso location 2024-04-12 15:06:01 +02:00
a-kenji
684cadebc3 docs: remove superfluous heading 2024-04-12 14:55:59 +02:00
Mic92
6ddd70e2be Merge pull request 'fix case when secrets are regenerated during update/install' (#1172) from docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1172
2024-04-12 12:51:27 +00:00
Jörg Thalheim
b3522b73aa fix case when secrets are regenerated during update/install 2024-04-12 14:46:51 +02:00
Mic92
573a462aee Merge pull request 'Rework and fix root-password module' (#1171) from docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1171
2024-04-12 12:00:43 +00:00
Jörg Thalheim
3f8ab35a19 rework root-password module 2024-04-12 12:00:43 +00:00
clan-bot
895f6fbc8a Merge pull request 'sops/compat: fix name reference' (#1170) from docs into main 2024-04-12 11:29:32 +00:00
Jörg Thalheim
6958da2d57 sops/compat: fix name reference 2024-04-12 13:23:52 +02:00
clan-bot
2e6e9b175e Merge pull request 'sops: fix secret path generation' (#1168) from docs into main 2024-04-12 11:19:56 +00:00
Jörg Thalheim
58446db110 sops: fix secret path generation 2024-04-12 13:12:31 +02:00
Mic92
396071a925 Merge pull request 'quickstart: fix link' (#1162) from docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1162
2024-04-12 10:09:28 +00:00
Jörg Thalheim
439714a242 quickstart: fix link 2024-04-12 10:09:28 +00:00
clan-bot
13e1aefb65 Merge pull request 'clan-vm-manager: Add install-desktop.sh' (#1161) from Qubasa-main into main 2024-04-12 09:54:09 +00:00
Qubasa
057d0defee clan-vm-manager: Add install-desktop.sh. Fix incorrect doku link 2024-04-12 11:47:18 +02:00
hsjobeki
7dcadd3025 Merge pull request 'docs: fix unsupported languages' (#1157) from hsjobeki-tutorials into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1157
2024-04-10 16:50:07 +00:00
Johannes Kirschbauer
d292f2de98 docs: fix unsupported languages 2024-04-10 18:40:51 +02:00
hsjobeki
6aec3ac73d Merge pull request 'docs: improve tutorials' (#1156) from hsjobeki-tutorials into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1156
2024-04-10 16:25:18 +00:00
Johannes Kirschbauer
e6acbadae6 docs: improve template & secrets 2024-04-10 16:25:18 +00:00
Mic92
00558923a5 Merge pull request 'factstore: secret backends now can return the path to a secret dynamically' (#1143) from networkd into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1143
2024-04-10 15:14:30 +00:00
Jörg Thalheim
82aafc287e also enable LLMNR 2024-04-10 15:14:30 +00:00
Jörg Thalheim
0d4e1f870b factstore: secret backends now can return the path to a secret dynamically
try to move path function out
2024-04-10 15:14:30 +00:00
Jörg Thalheim
faaf6649c5 fix multicast dns for ethernet 2024-04-10 15:14:30 +00:00
clan-bot
f33c3ece3d Merge pull request 'don't hard-code page weight' (#1118) from fricklerhandwerk/clan-core:doc-contributing into main 2024-04-10 13:35:50 +00:00
clan-bot
a5586d27f0 Merge pull request 'build iso with nixos-generators' (#1155) from lassulus-generators-iso into main 2024-04-10 13:20:00 +00:00
lassulus
70282b8d77 build iso with nixos-generators 2024-04-10 15:03:55 +02:00
clan-bot
6d050c0c10 Merge pull request 'docs: improve tutorials' (#1154) from hsjobeki-tutorials into main 2024-04-10 13:01:21 +00:00
Johannes Kirschbauer
87eb38a2c9 docs: move install stick into sperate docs 2024-04-10 14:54:41 +02:00
clan-bot
388c9c94e4 Merge pull request 'tutorials' (#1149) from tutorials into main 2024-04-10 11:43:07 +00:00
Johannes Kirschbauer
960e560d84 docs: fix links 2024-04-10 13:37:54 +02:00
Johannes Kirschbauer
d951c570f0 docs: improve getting started 2024-04-10 13:33:47 +02:00
Johannes Kirschbauer
adfdc96b64 docs: improve tutorials 2024-04-10 13:33:47 +02:00
clan-bot
f7a29ebaf8 Merge pull request 'templates: makes template working' (#1148) from hsjobeki-main into main 2024-04-10 10:38:56 +00:00
Johannes Kirschbauer
996fdd6c9c templates: makes template working 2024-04-10 12:28:41 +02:00
clan-bot
d3e42a3ad2 Merge pull request 'add root-password module' (#1147) from hsjobeki-main into main 2024-04-10 09:36:16 +00:00
Johannes Kirschbauer
292ac97067 add root-password module 2024-04-10 11:23:39 +02:00
Mic92
84f527fc39 Merge pull request 'docs: improve tutorials' (#1126) from tutorials into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1126
2024-04-10 09:14:03 +00:00
Johannes Kirschbauer
c4c843ba18 docs: improve tutorials 2024-04-10 09:14:03 +00:00
Mic92
915864f637 Merge pull request 'fix quickstart instructions' (#1146) from alejandrosame/clan-core:fix/quickstart into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1146
2024-04-10 09:13:13 +00:00
Alejandro Sanchez Medina
8ab9021c3d fix quickstart instructions
The guide instructs the reader to look for the PTUUID (partition ID) to fill
disk ID in the disklayout. This leads to an error as the partition gets deleted
and the UUID is no longer valid. The ID-LINK field is a unique ID provided by
the hardware manufacturer.
2024-04-09 20:57:36 +02:00
Mic92
36ce43bfcf Merge pull request 'enable multicast fore default dhcp network' (#1141) from networkd into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1141
2024-04-09 13:35:51 +00:00
Jörg Thalheim
a8718b92d4 enable multicast fore default dhcp network 2024-04-09 13:35:51 +00:00
clan-bot
5dac575be8 Merge pull request 'Set networking.hostName to clanCore.machineName' (#1140) from networkd into main 2024-04-09 13:14:44 +00:00
Jörg Thalheim
19a62817f2 sops: strip out clanCore.machineName instead of networking.hostName 2024-04-09 15:10:27 +02:00
Jörg Thalheim
1ac982fbdb set networking.hostName to clanCore.machineName 2024-04-09 15:10:08 +02:00
clan-bot
26146edbc5 Merge pull request 'drop custom systemd-networkd unit' (#1132) from networkd into main 2024-04-09 10:37:51 +00:00
Jörg Thalheim
e8ebfb2e2a drop custom systemd-networkd unit
We no longer use multicast dns. This one doesn't
conflict with nixos-generate-config.
2024-04-09 12:31:57 +02:00
clan-bot
3480b7d089 Merge pull request 'vms/run.py: refactor use kwargs instead of dataclass for function args' (#1125) from DavHau-dave into main 2024-04-09 07:36:02 +00:00
DavHau
fc73301ed9 vms/run.py: refactor use kwargs instead of dataclass for function args 2024-04-09 14:30:46 +07:00
clan-bot
30db1039d1 Merge pull request 'Automatic flake update - 2024-04-08T00:00+00:00' (#1124) from flake-update-2024-04-08 into main 2024-04-08 00:13:31 +00:00
Clan Merge Bot
8429ccccb3 update flake lock - 2024-04-08T00:00+00:00
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/502241afa3de2a24865ddcbe4c122f4546e32092' (2024-03-28)
  → 'github:nix-community/disko/0a17298c0d96190ef3be729d594ba202b9c53beb' (2024-04-05)
• Updated input 'flake-parts':
    'github:hercules-ci/flake-parts/f7b3c975cf067e56e7cda6cb098ebe3fb4d74ca2' (2024-03-01)
  → 'github:hercules-ci/flake-parts/9126214d0a59633752a136528f5f3b9aa8565b7d' (2024-04-01)
• Updated input 'nixos-generators':
    'github:nix-community/nixos-generators/63194fceafbfe583a9eb7d16ab499adc0a6c0bc2' (2024-03-28)
  → 'github:nix-community/nixos-generators/0c15e76bed5432d7775a22e8d22059511f59d23a' (2024-04-04)
• Updated input 'nixos-generators/nixlib':
    'github:nix-community/nixpkgs.lib/b2a1eeef8c185f6bd27432b053ff09d773244cbc' (2024-03-24)
  → 'github:nix-community/nixpkgs.lib/90b1a963ff84dc532db92f678296ff2499a60a87' (2024-03-31)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/cd1c70d941d69d8d6425984ff8aefca9b28e861a' (2024-03-31)
  → 'github:NixOS/nixpkgs/298edc8f1e0dfffce67f50375c9f5952e04a6d02' (2024-04-07)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/99b1e37f9fc0960d064a7862eb7adfb92e64fa10' (2024-03-31)
  → 'github:Mic92/sops-nix/39191e8e6265b106c9a2ba0cfd3a4dafe98a31c6' (2024-04-07)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/1810d51a015c1730f2fe05a255258649799df416' (2024-03-30)
  → 'github:numtide/treefmt-nix/49dc4a92b02b8e68798abd99184f228243b6e3ac' (2024-04-01)
2024-04-08 00:00:15 +00:00
clan-bot
d89edef9a1 Merge pull request 'improve starter template' (#1123) from Qubasa-better-template into main 2024-04-07 19:12:02 +00:00
Qubasa
1e0d73e8a9 Improve documentation 2024-04-07 21:07:02 +02:00
Qubasa
4faba7c8e1 template: Reverted systemd-boot in installer. EF02 partition on wrong second place 2024-04-07 17:09:44 +02:00
Qubasa
83346eeff5 template: Fixed incorrect nix code 2024-04-07 15:59:33 +02:00
Johannes Kirschbauer
55f3878e67 machine.md: clean up guide 2024-04-07 14:32:23 +02:00
Johannes Kirschbauer
49d83fd659 migrate.md: make docs more approachable 2024-04-07 12:53:15 +02:00
Qubasa
6a610c7a0b Improve documentation 2024-04-06 13:35:17 +02:00
Qubasa
033f7c67f4 Improve documentation 2024-04-06 13:34:40 +02:00
Qubasa
6d8d211968 Improve documentation 2024-04-06 12:34:49 +02:00
Qubasa
91dddc2281 Fix merge issue 2024-04-06 11:56:06 +02:00
Qubasa
a520116584 Improve documentation 2024-04-06 11:54:34 +02:00
Valentin Gagarin
0681f6bf7c docs: don't set page weight
since currently the web site simply dumps these pages, this makes it
impossible to control the item order
2024-04-05 21:52:56 +02:00
Jörg Thalheim
e68eba914e improve starter template 2024-04-05 18:55:14 +02:00
Mic92
fa74d1c0b3 Merge pull request 'flash-fixes' (#1116) from flash-fixes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1116
2024-04-05 16:54:31 +00:00
Jörg Thalheim
1fd28f2f4c flake-parts: fixup type for specialArgs 2024-04-05 18:48:37 +02:00
Jörg Thalheim
818cc4d135 flash: expose mode option 2024-04-05 18:48:37 +02:00
Jörg Thalheim
c5e5a7edc7 grub: enable efi support by default 2024-04-05 18:47:11 +02:00
Qubasa
2e29c031ef Improved docs 2024-04-05 18:03:14 +02:00
Qubasa
f2ff815aa7 Add machines/my-machine/settings.json 2024-04-05 16:25:05 +02:00
Jörg Thalheim
1fc4739ee3 improve starter template 2024-04-05 13:08:32 +02:00
clan-bot
cb103c7772 Merge pull request 'add flake parts tutorial' (#1106) from flake-parts into main 2024-04-04 13:09:52 +00:00
Jörg Thalheim
7b230e2308 add flake parts tutorial 2024-04-04 15:05:08 +02:00
clan-bot
e78d0da30f Merge pull request 'flake-parts: fix clan-core reference' (#1105) from flake-parts into main 2024-04-04 11:42:32 +00:00
Jörg Thalheim
28e8af60cf flake-parts: fix clan-core reference 2024-04-04 13:38:15 +02:00
Mic92
2bc027cece Merge pull request 'Add flake-parts module' (#1104) from flake-parts into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1104
2024-04-04 11:08:08 +00:00
Jörg Thalheim
5ffae2070d drop unused test_backup_client machine 2024-04-04 11:24:30 +02:00
Jörg Thalheim
3212410704 add flake-parts module for clan 2024-04-03 16:45:06 +02:00
Jörg Thalheim
f7077e3540 flash: improve prompt if no disk is specified 2024-04-03 12:00:02 +02:00
Jörg Thalheim
1c1c143b8d docs: replace hashedPassword with initialHashedPassword 2024-04-03 12:00:02 +02:00
clan-bot
6e4786d08e Merge pull request 'Clan Manager: connect events with feedback system' (#1103) from hsjobeki-main into main 2024-04-03 09:41:03 +00:00
Johannes Kirschbauer
de91938760 Clan VM Manager: connect feedback with events 2024-04-03 11:36:33 +02:00
clan-bot
a6ba73c4a0 Merge pull request 'fix: readme typo' (#1102) from hsjobeki-main into main 2024-04-03 07:51:04 +00:00
Johannes Kirschbauer
a6f8f3fb58 fix: readme typo 2024-04-03 09:43:24 +02:00
clan-bot
69aa46a1d5 Merge pull request 'sops: fix decrypte path on machine' (#1091) from fact_refactor2 into main 2024-04-02 11:55:53 +00:00
Jörg Thalheim
8b4dbc60b5 clan/install: drop -t flag from nixos-anywhere 2024-04-02 13:50:24 +02:00
Jörg Thalheim
5b838c0d9c sops: fix decrypte path on machine 2024-04-02 13:50:24 +02:00
clan-bot
b342e3f991 Merge pull request 'syncthing: fix conflicting definition of fs.inotify.max_user_watches' (#1090) from DavHau-dave into main 2024-04-02 11:00:26 +00:00
DavHau
dd0dbbd29f syncthing: fix conflicting definition of fs.inotify.max_user_watches 2024-04-02 17:56:07 +07:00
clan-bot
7de7e25e78 Merge pull request 'flatpak: add gitignore' (#1089) from a-kenji-gi/flatpak into main 2024-04-02 10:54:34 +00:00
a-kenji
97be9f1c4d flatpak: add gitignore 2024-04-02 12:48:19 +02:00
clan-bot
439293a079 Merge pull request 'clan-cli: add a check for the flatpak sandbox' (#1088) from a-kenji-clan-cli/check/flatpak-sandbox into main 2024-04-02 10:24:49 +00:00
a-kenji
9bb4c8d094 clan-cli: add a check for the flatpak sandbox
Allows for differentiation between sandbox and non sandbox usage.
2024-04-02 12:19:48 +02:00
clan-bot
44d897e89f Merge pull request 'modules: add ergochat' (#1078) from a-kenji-add/ergo into main 2024-04-02 09:36:55 +00:00
a-kenji
1a40ce0a8f modules: add ergochat 2024-04-02 11:30:22 +02:00
clan-bot
ff0e66512f Merge pull request 'buildClan: add clan-core to specialArgs' (#1076) from DavHau-dave into main 2024-04-02 09:15:37 +00:00
clan-bot
78259ad61e Merge pull request 'modules: add thelounge' (#1075) from a-kenji-init/ergochat into main 2024-04-02 09:07:18 +00:00
DavHau
6f9216d3b6 buildClan: add clan-core to specialArgs 2024-04-02 16:03:45 +07:00
a-kenji
3bdface3db modules: add thelounge 2024-04-02 11:01:00 +02:00
clan-bot
388eff3baa Merge pull request 'cli/secrets: show hint in --help on how to retrieve a key' (#1074) from DavHau-dave into main 2024-04-02 07:40:54 +00:00
DavHau
16ae51105e cli/secrets: show hint in --help on how to retrieve a key 2024-04-02 14:36:01 +07:00
clan-bot
3428b76dcb Merge pull request 'moonlight: fix facts declaration' (#1072) from DavHau-dave into main 2024-04-01 10:48:25 +00:00
DavHau
1a3d5e1ad6 moonlight: fix facts declaration 2024-04-01 17:44:22 +07:00
clan-bot
d075b18653 Merge pull request 'Automatic flake update - 2024-04-01T00:00+00:00' (#1070) from flake-update-2024-04-01 into main 2024-04-01 00:11:28 +00:00
Clan Merge Bot
c9108d5460 update flake lock - 2024-04-01T00:00+00:00
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/5d2d3e421ade554b19b4dbb0d11a04023378a330' (2024-03-24)
  → 'github:nix-community/disko/502241afa3de2a24865ddcbe4c122f4546e32092' (2024-03-28)
• Updated input 'nixos-generators':
    'github:nix-community/nixos-generators/2b3720c7af2271be8cee713cd2f69c5127b0a8e4' (2024-03-25)
  → 'github:nix-community/nixos-generators/63194fceafbfe583a9eb7d16ab499adc0a6c0bc2' (2024-03-28)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/57e6b3a9e4ebec5aa121188301f04a6b8c354c9b' (2024-03-25)
  → 'github:NixOS/nixpkgs/cd1c70d941d69d8d6425984ff8aefca9b28e861a' (2024-03-31)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/405987a66cce9a4a82f321f11b205982a7127c88' (2024-03-24)
  → 'github:Mic92/sops-nix/99b1e37f9fc0960d064a7862eb7adfb92e64fa10' (2024-03-31)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/7ee5aaac63c30d3c97a8c56efe89f3b2aa9ae564' (2024-03-18)
  → 'github:numtide/treefmt-nix/1810d51a015c1730f2fe05a255258649799df416' (2024-03-30)
2024-04-01 00:00:15 +00:00
clan-bot
eeb703985e Merge pull request 'docs: render zola pages in clan-core flake' (#1069) from DavHau-dave into main 2024-03-31 05:37:36 +00:00
DavHau
492256ec54 docs: render zola pages in clan-core flake
This integrates the generated options docs part of our website into the clan-core project. This is better than having it in a separate repos because we want to lear about breakages as early as possible.

Changes which break the documentation should be blocked by this early on
2024-03-31 12:33:31 +07:00
clan-bot
62f201696d Merge pull request 'docs: render module options docs' (#1068) from DavHau-dave into main 2024-03-30 17:31:34 +00:00
DavHau
e0bdf1ce39 docs: render module options docs
fix errors while rendering some modules
2024-03-31 00:26:08 +07:00
clan-bot
ec105d8ef8 Merge pull request 'secrets: improve description of generator script' (#1067) from DavHau-dave into main 2024-03-30 10:22:40 +00:00
DavHau
72cc85cd2f secrets: improve description of generator script 2024-03-30 17:16:26 +07:00
clan-bot
0f73a6e1cf Merge pull request 'migrate secrets to new api' (#1064) from fact_refactor2 into main 2024-03-28 10:17:24 +00:00
Jörg Thalheim
65d116ec28 migrate secrets to new api 2024-03-28 11:02:14 +01:00
clan-bot
b10c4f5846 Merge pull request 'refactor clanCore.secrets -> clanCore.facts' (#1040) from facts_refactor2 into main 2024-03-27 15:20:21 +00:00
lassulus
a8d35d37e7 refactor clanCore.secrets -> clanCore.facts 2024-03-27 16:03:16 +01:00
clan-bot
8950c8d3bd Merge pull request 'clan-cli: Fix tmpdir leak and fix tests/temporary_dir inconsistencies' (#1063) from Qubasa-fix_tmpdir_leak2 into main 2024-03-27 14:58:20 +00:00
Qubasa
e6ad0cfbc1 clan-cli: Fix tmpdir leak and fix tests/temporary_dir inconsistencies 2024-03-27 15:51:52 +01:00
clan-bot
0676bf7283 Merge pull request 'checks: add check for rendering docs' (#1058) from DavHau-dave into main 2024-03-27 10:03:38 +00:00
DavHau
3771be2110 checks: add check for rendering docs 2024-03-27 16:59:42 +07:00
clan-bot
d59673e89a Merge pull request 'Improved README' (#1057) from Qubasa-improv_readme3 into main 2024-03-26 18:29:50 +00:00
Qubasa
946f026c23 Improved README 2024-03-26 19:20:00 +01:00
clan-bot
8715c3ef88 Merge pull request 'rewrite backups documentation' (#1055) from Mic92-main into main 2024-03-26 16:29:32 +00:00
Jörg Thalheim
0c21fcf2eb rewrite backups documentation 2024-03-26 17:21:06 +01:00
clan-bot
9a82f8cc8b Merge pull request 'localbackup: also create mountpoints' (#1053) from Mic92-main into main 2024-03-26 14:59:11 +00:00
Jörg Thalheim
e27e6e6102 localbackup: also create mountpoints 2024-03-26 15:53:13 +01:00
clan-bot
4ff262fd60 Merge pull request 'localbackup: rename mountHook/umountHook to preMountHook/postUnmountHook' (#1050) from Mic92-main into main 2024-03-26 14:02:40 +00:00
Jörg Thalheim
74b5f6c61a localbackup: rename mountHook/umountHook to preMountHook/postUnmountHook 2024-03-26 14:58:37 +01:00
clan-bot
553b8b8476 Merge pull request 'cli/ssh: allocate tty by default' (#1043) from Mic92-main into main 2024-03-26 12:18:27 +00:00
Jörg Thalheim
80abeef994 Revert "ssh: add interactive flag"
This reverts commit c5db14dea8.
2024-03-26 13:13:35 +01:00
Jörg Thalheim
7b8a49bf6c ssh: default tty to False
nix behaves weird when the terminal is interactive because
we are also do line buffering.
2024-03-26 13:05:11 +01:00
Jörg Thalheim
54f0526c5b update nixos-generators 2024-03-26 12:52:00 +01:00
Jörg Thalheim
10a12eb85c ruff: switch to check subcommand 2024-03-26 12:52:00 +01:00
Jörg Thalheim
c5db14dea8 ssh: add interactive flag 2024-03-26 12:51:46 +01:00
Jörg Thalheim
0e2cb172e6 cli/ssh: allocate tty by default
-t is only enabled when the local ssh command is also connected to a tty,
so it seems to be enabled by default.
2024-03-26 12:07:15 +01:00
clan-bot
a21f731536 Merge pull request 'localbackup: add missing config arg to submodule' (#1042) from Mic92-main into main 2024-03-26 10:47:35 +00:00
Jörg Thalheim
bd989085ac localbackup: add missing config arg to submodule 2024-03-26 11:41:03 +01:00
clan-bot
dca1eee3a3 Merge pull request 'documentation: fix grammer' (#1041) from a-kenji-fix/grammar into main 2024-03-25 15:10:10 +00:00
a-kenji
92b1f86b7e documentation: fix grammer 2024-03-25 16:03:18 +01:00
clan-bot
6055dbe123 Merge pull request 'documentation fixes for facts generate command' (#1038) from facts-generate into main 2024-03-25 14:38:30 +00:00
Jörg Thalheim
68ac6321ee docs/backup: update command needed to regenerate backups 2024-03-25 15:33:57 +01:00
Jörg Thalheim
270f906412 fix casing in facts generate logs 2024-03-25 15:33:57 +01:00
clan-bot
ffa1d9ca6c Merge pull request 'waypipe: fix the waypipe module' (#1037) from a-kenji-modules/waypipe/fix into main 2024-03-25 14:27:14 +00:00
a-kenji
187bebae47 waypipe: fix the waypipe module 2024-03-25 15:21:16 +01:00
clan-bot
a6f1fede97 Merge pull request 'localbackup: add regression test' (#1035) from localbackup into main 2024-03-25 13:00:14 +00:00
Mic92
e3c608c16d Merge pull request 'switch back to upstream waypipe' (#1025) from waypipe into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1025
2024-03-25 12:54:16 +00:00
Jörg Thalheim
fee37dc1db bump nixpkgs 2024-03-25 13:36:30 +01:00
Jörg Thalheim
a886fd9b2d switch back to upstream waypipe 2024-03-25 13:34:02 +01:00
Jörg Thalheim
d291b1db63 localbackup: integrate into regression test 2024-03-25 13:26:42 +01:00
Jörg Thalheim
45212e2ba5 localbackup: add mounthooks 2024-03-25 13:26:42 +01:00
Jörg Thalheim
916e37eb26 localbackup: add pre/post exec hooks 2024-03-25 12:42:59 +01:00
Jörg Thalheim
58ae9d9cd0 localbackup: default to empty target list 2024-03-25 12:42:59 +01:00
clan-bot
62bef16092 Merge pull request 'Re-encrypt secrets after rotating users/machines keys' (#1034) from yubikey-support into main 2024-03-25 11:40:32 +00:00
Jörg Thalheim
0fa36252c2 re-encrypt secrets after rotating users/machines keys 2024-03-25 12:34:29 +01:00
Jörg Thalheim
b6d5f8a6ce docs/backup: extend documentation 2024-03-25 11:07:09 +01:00
Jörg Thalheim
cd9db02db0 add hint to use --force when a key already exists 2024-03-25 11:06:20 +01:00
clan-bot
bc75c637ef Merge pull request 'clanCore/packages.nix: add gitMinimal' (#1031) from DavHau-dave into main 2024-03-25 04:54:00 +00:00
DavHau
4b8b1107ba clanCore/packages.nix: add gitMinimal
WIthout this, deployment via `clan machines update` will fail on the remote machine if the flake.nix has a git input
2024-03-25 11:47:32 +07:00
clan-bot
644c85866e Merge pull request 'Automatic flake update - 2024-03-25T00:00+00:00' (#1030) from flake-update-2024-03-25 into main 2024-03-25 00:22:15 +00:00
Clan Merge Bot
7cdb18331d update flake lock - 2024-03-25T00:00+00:00
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/21d89b333ca300bef82c928c856d48b94a9f997c' (2024-03-14)
  → 'github:nix-community/disko/5d2d3e421ade554b19b4dbb0d11a04023378a330' (2024-03-24)
• Updated input 'nixos-generators':
    'github:nix-community/nixos-generators/efd4e38532b5abfaa5c9fc95c5a913157dc20ccb' (2024-03-14)
  → 'github:nix-community/nixos-generators/417a857dfb824e60930881a254dd67d6796f5884' (2024-03-22)
• Updated input 'nixos-generators/nixlib':
    'github:nix-community/nixpkgs.lib/630ebdc047ca96d8126e16bb664c7730dc52f6e6' (2024-03-10)
  → 'github:nix-community/nixpkgs.lib/fa827dda806c5aa98f454da4c567991ab8ce422c' (2024-03-17)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/f471be9644f3ab2f3cb868de1787ab70a537b0e7' (2024-03-17)
  → 'github:NixOS/nixpkgs/3d41d1087707826b3a90685ab69147f8dc8145d5' (2024-03-24)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/83b68a0e8c94b72cdd0a6e547a14ca7eb1c03616' (2024-03-17)
  → 'github:Mic92/sops-nix/405987a66cce9a4a82f321f11b205982a7127c88' (2024-03-24)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/35791f76524086ab4b785a33e4abbedfda64bd22' (2024-03-12)
  → 'github:numtide/treefmt-nix/7ee5aaac63c30d3c97a8c56efe89f3b2aa9ae564' (2024-03-18)
2024-03-25 00:00:15 +00:00
clan-bot
b07490ca60 Merge pull request 'select-shell: Fix breakage with previous shell.nix change' (#1029) from Qubasa-main into main 2024-03-24 23:37:57 +00:00
Qubasa
e26d1052b6 select-shell: Fix breakage with previous shell.nix change 2024-03-25 00:32:03 +01:00
clan-bot
f7866d264d Merge pull request 'clan-vm-manager: devshell doesn't require clan-cli derivation' (#1028) from Qubasa-main into main 2024-03-24 22:57:52 +00:00
Qubasa
9dbc71e446 clan-vm-manager: devshell doesn't require clan-cli derivation 2024-03-24 23:52:30 +01:00
clan-bot
5fd4a63e17 Merge pull request 'clan-vm-manager: Basic pytest framework established' (#1026) from Qubasa-main into main 2024-03-24 22:41:07 +00:00
Qubasa
8ab9d20342 clan-vm-manager: Working pytest skeleton. clan-cli: Fixing devshell depending on itself 2024-03-24 23:36:00 +01:00
clan-bot
a185ad0c59 Merge pull request 'refactor secrets & facts into secret_facts & public_facts' (#1027) from facts_refactor into main 2024-03-24 10:10:45 +00:00
lassulus
f16667e25a refactor secrets & facts -> secret_facts & public_facts 2024-03-23 05:46:54 +01:00
Qubasa
0ee8dceee2 clan-vm-manager: Basic pytest framework established 2024-03-22 19:08:35 +01:00
Mic92
ddc28f53df Merge pull request 'backup docs' (#949) from docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/949
2024-03-22 14:56:22 +00:00
Jörg Thalheim
0b6e03b3d5 backup docs 2024-03-22 14:56:22 +00:00
clan-bot
1d6cc49da5 Merge pull request 'clanModules: init matrix-synapse' (#1017) from matrix-synapse into main 2024-03-22 11:39:50 +00:00
lassulus
786a4586a6 checks/matrix-synapse: init 2024-03-22 12:26:37 +01:00
lassulus
ba772c201d clanModules: init matrix-synapse 2024-03-22 12:26:37 +01:00
clan-bot
ae50796e1d Merge pull request 'sunshine: improve launching of pairing' (#1021) from a-kenji-sunshine/improve-accept into main 2024-03-20 09:00:58 +00:00
a-kenji
f0b00b7360 sunshine: improve launching of pairing 2024-03-20 09:55:25 +01:00
clan-bot
1b8ae090b8 Merge pull request 'localbackup' (#1020) from localbackup into main 2024-03-20 08:49:07 +00:00
Jörg Thalheim
350593ccde backups: add test for pre and post restore command 2024-03-20 09:32:01 +01:00
Jörg Thalheim
82507a975a backups: fix name extraction for borgbackup restore 2024-03-20 09:32:01 +01:00
Jörg Thalheim
539df08706 backups: skip preRestore and postRestore if not specified by a service 2024-03-20 09:32:01 +01:00
Jörg Thalheim
aa659bcc17 backups: no longer interpret backup interface as bash commands 2024-03-20 09:32:01 +01:00
Jörg Thalheim
92ac151292 rework backup interface to no longer need to list backups to restore them 2024-03-20 09:32:01 +01:00
Jörg Thalheim
f5d32d0b22 add localbackup provider 2024-03-20 09:32:01 +01:00
Mic92
691d2ca3e9 Merge pull request 'make backup provider more generic' (#1019) from backup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/1019
2024-03-20 08:29:05 +00:00
Jörg Thalheim
2560eef424 backups: don't export all local environment over ssh 2024-03-20 08:29:05 +00:00
Jörg Thalheim
5f9d3b514b fix case when we have multiple backup destinations 2024-03-20 08:29:05 +00:00
Jörg Thalheim
9383e41d68 make backup provider more generic 2024-03-20 08:29:05 +00:00
clan-bot
7c4c6c07af Merge pull request 'refactor backup test to be just a single machine' (#1016) from Mic92-openssh into main 2024-03-19 13:38:10 +00:00
Jörg Thalheim
65b6ae8bb7 refactor backup test to be just a single machine 2024-03-19 14:32:11 +01:00
clan-bot
f8a8a92e39 Merge pull request 'moonlight: drop libnotify' (#1012) from a-kenji-moonlight/libnotify into main 2024-03-19 12:21:29 +00:00
a-kenji
f98d39cdeb moonlight: drop libnotify 2024-03-19 13:14:04 +01:00
clan-bot
7c378fced6 Merge pull request 'sunshine: drop unused files' (#1003) from a-kenji-drop/sunshine into main 2024-03-19 11:59:41 +00:00
a-kenji
626a9af638 sunshine: drop unused files 2024-03-19 12:53:28 +01:00
clan-bot
ceb1c95817 Merge pull request 'init: sunshine-moonlight-accept module' (#1002) from a-kenji-init/sunshine-accept into main 2024-03-19 11:50:15 +00:00
a-kenji
83efb33eb7 fmt 2024-03-19 12:40:58 +01:00
a-kenji
0695e2c0fc Merge branch 'main' into init/sunshine-accept 2024-03-19 12:33:45 +01:00
a-kenji
91ed6549a7 fmt: module 2024-03-19 12:30:40 +01:00
a-kenji
32d0f1ccd4 init: sunshine-moonlight-accept module 2024-03-19 12:11:09 +01:00
clan-bot
9f81f75f8c Merge pull request 'devshell: remove dependency on clan-cli derivation' (#1000) from DavHau-dave into main 2024-03-19 06:05:15 +00:00
DavHau
580010581c devshell: remove dependency on clan-cli derivation
The devShell depended on clan-cli due to it being included as a dependency in the treefmt config. This is not optimal because this makes the devshell rebuild unnecessary often and also lead to build failures of the dev-shell if the clan-cli code is in a broken state (git rebasing, or during development etc.)
2024-03-19 13:00:59 +07:00
clan-bot
b2b94b269a Merge pull request 'Automatic flake update - 2024-03-18T00:00+00:00' (#998) from flake-update-2024-03-18 into main 2024-03-18 00:11:00 +00:00
Clan Merge Bot
9300ecbfe2 update flake lock - 2024-03-18T00:00+00:00
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/fe064a639319ed61cdf12b8f6eded9523abcc498' (2024-03-11)
  → 'github:nix-community/disko/21d89b333ca300bef82c928c856d48b94a9f997c' (2024-03-14)
• Updated input 'nixos-generators':
    'github:nix-community/nixos-generators/1d9c8cd24eba7942955f92fdcefba5a6a7543bc6' (2024-03-11)
  → 'github:nix-community/nixos-generators/efd4e38532b5abfaa5c9fc95c5a913157dc20ccb' (2024-03-14)
• Updated input 'nixos-generators/nixlib':
    'github:nix-community/nixpkgs.lib/7873d84a89ae6e4841528ff7f5697ddcb5bdfe6c' (2024-03-03)
  → 'github:nix-community/nixpkgs.lib/630ebdc047ca96d8126e16bb664c7730dc52f6e6' (2024-03-10)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/e4e2121b151e492fd15d4bdb034e793738fdc120' (2024-03-12)
  → 'github:NixOS/nixpkgs/f471be9644f3ab2f3cb868de1787ab70a537b0e7' (2024-03-17)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/e52d8117b330f690382f1d16d81ae43daeb4b880' (2024-03-11)
  → 'github:Mic92/sops-nix/83b68a0e8c94b72cdd0a6e547a14ca7eb1c03616' (2024-03-17)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/720322c5352d7b7bd2cb3601a9176b0e91d1de7d' (2024-03-10)
  → 'github:numtide/treefmt-nix/35791f76524086ab4b785a33e4abbedfda64bd22' (2024-03-12)
2024-03-18 00:00:14 +00:00
clan-bot
4a5b9cf0f4 Merge pull request 'nixos-install: also respect port' (#997) from Mic92-openssh into main 2024-03-17 21:23:24 +00:00
Jörg Thalheim
5ff36a2cd8 nixos-install: also respect port 2024-03-17 22:18:22 +01:00
clan-bot
d50eeb8f89 Merge pull request 'drop secret store logging from install command' (#996) from Mic92-openssh into main 2024-03-17 20:41:39 +00:00
Jörg Thalheim
9f25f47298 allow to debug nixos-anywhere 2024-03-17 21:36:22 +01:00
Jörg Thalheim
dd0ad2683b drop secret store logging from install command 2024-03-17 21:32:23 +01:00
Mic92
3555001c0d Merge pull request 'change from nixpkgs-fmt to rfc style formatter' (#995) from openssh into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/995
2024-03-17 18:53:59 +00:00
Jörg Thalheim
e296a3019d re-format with nixfmt 2024-03-17 19:48:49 +01:00
Jörg Thalheim
916e4dff84 change from nixpkgs-fmt to rfc style formatter 2024-03-17 19:44:57 +01:00
clan-bot
50aa98c53a Merge pull request 'make installer nixos module stand-alone' (#994) from openssh into main 2024-03-17 18:42:55 +00:00
Jörg Thalheim
77c0e6b31a make installer nixos module stand-alone 2024-03-17 19:38:50 +01:00
clan-bot
915ce52355 Merge pull request 'installer: also match qemu and serial consoles for prompting qrcode' (#993) from openssh into main 2024-03-17 18:23:07 +00:00
Jörg Thalheim
2dcdcd98e9 installer: also match qemu and serial consoles for prompting qrcode 2024-03-17 19:14:24 +01:00
clan-bot
ee9be35dcb Merge pull request 'add nix to devShell' (#992) from openssh into main 2024-03-17 17:36:00 +00:00
Jörg Thalheim
d7939e3cba add nix to devShell
It's important for some tests that package manager used inside NixOS vms is the same as outside
2024-03-17 18:31:16 +01:00
clan-bot
c727d87213 Merge pull request 'sshd: module fix impurity' (#987) from openssh into main 2024-03-17 17:20:10 +00:00
Jörg Thalheim
c15043c4f1 fix evaluation of backup module 2024-03-17 18:16:08 +01:00
Jörg Thalheim
a6c3e15aca don't use impure builtins.storePath 2024-03-17 18:10:23 +01:00
Jörg Thalheim
377302ff6c change facts path to be reachable as a store path 2024-03-17 18:10:23 +01:00
clan-bot
91a51e837e Merge pull request 'clan-vm-manager: init log view with current state of log' (#990) from hsjobeki-main into main 2024-03-17 14:03:49 +00:00
Johannes Kirschbauer
e4f4680206 clan-vm-manager: init log view with current state of log 2024-03-17 14:57:32 +01:00
clan-bot
9a2549ddb8 Merge pull request 'clan-vm-manager: connect log view to build state of machines' (#989) from hsjobeki-main into main 2024-03-17 13:14:49 +00:00
Johannes Kirschbauer
b44cbf5c76 clan-vm-manager: connect log view to build state of machines 2024-03-17 14:08:39 +01:00
clan-bot
b322b3071b Merge pull request 'dev-shell: make python shell load fast' (#985) from DavHau-dave into main 2024-03-14 10:23:53 +00:00
DavHau
f4b8133037 dev-shell: make python shell load fast
- Add caching for editable installs
- Remove sleep statement in GUI code
2024-03-14 17:19:08 +07:00
DavHau
7537af3943 merge-after-ci: fix bug 2024-03-14 12:46:17 +07:00
clan-bot
3476945fff Merge pull request 'openssh fixes' (#983) from openssh into main 2024-03-13 14:04:25 +00:00
Jörg Thalheim
a6d52a669d fix openssh secrets
change facts path to be the full path

sshd: fixup store path
2024-03-13 14:59:46 +01:00
Mic92
08e8027347 Merge pull request 'fix openssh secrets' (#982) from openssh into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/982
2024-03-13 13:27:10 +00:00
Jörg Thalheim
59cb2b2a29 fix openssh secrets 2024-03-13 13:27:10 +00:00
clan-bot
e67ac52a33 Merge pull request 'merge-after-ci: set labels correctly' (#981) from DavHau-dave into main 2024-03-13 12:20:20 +00:00
DavHau
a9dbd92ff3 merge-after-ci: set labels correctly 2024-03-13 19:11:12 +07:00
clan-bot
be1bd8f252 Merge pull request 'secrets-improvements' (#948) from secrets-improvements into main 2024-03-13 10:23:27 +00:00
Jörg Thalheim
a9fc8de2d0 allow multi-line interactive secrets 2024-03-13 11:18:56 +01:00
Jörg Thalheim
c2e43a4e65 allow fact-only secrets 2024-03-13 11:08:36 +01:00
Jörg Thalheim
8ab6fcd4c0 add sshd module 2024-03-13 11:08:36 +01:00
clan-bot
5b02dda003 Merge pull request 'sunshine: add path' (#947) from a-kenji-sunshine/add-path into main 2024-03-12 22:06:37 +00:00
a-kenji
bcf26682c3 sunshine: add path 2024-03-12 23:01:02 +01:00
clan-bot
2dd7304b57 Merge pull request 'sunshine: add apps, improve uaccess rules' (#946) from a-kenji-imp/sunshine into main 2024-03-12 21:23:06 +00:00
a-kenji
71cd46b0e9 sunshine: add apps, improve uaccess rules 2024-03-12 22:17:08 +01:00
clan-bot
a23a64d0f9 Merge pull request 'sunshine: improve module' (#945) from a-kenji-imp/sunshine into main 2024-03-12 19:59:09 +00:00
a-kenji
8a3250b1c9 sunshine: improve module 2024-03-12 20:53:04 +01:00
clan-bot
d01ea573f9 Merge pull request 'vm: improve xfce and vm-user module' (#944) from a-kenji-fix/vm into main 2024-03-12 18:59:19 +00:00
a-kenji
df1729a841 vm: improve xfce and vm-user module 2024-03-12 19:53:11 +01:00
clan-bot
64ec958014 Merge pull request 'clan-modules: add xfce-vm module' (#943) from a-kenji-init/vm-module into main 2024-03-12 18:42:19 +00:00
clan-bot
9b51dc7b4d Merge pull request 'fix: typo' (#942) from a-kenji-fix/devshell into main 2024-03-12 18:37:21 +00:00
a-kenji
c15d762dc7 clan-modules: add xfce-vm module
A specific module for vm's that don't (yet) support the waypipe module.
2024-03-12 19:36:11 +01:00
a-kenji
4044e42e58 fix: typo 2024-03-12 17:37:19 +01:00
clan-bot
29012304c0 Merge pull request 'clan-modules: add vm-user module' (#932) from a-kenji-add/vm-user into main 2024-03-12 16:36:24 +00:00
Mic92
c8ba2e9721 Merge pull request 'reduce eval worker' (#941) from ci into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/941
2024-03-12 16:34:24 +00:00
Jörg Thalheim
c4642ad041 reduce eval worker 2024-03-12 17:34:07 +01:00
Mic92
e654b7fe95 Merge branch 'main' into a-kenji-add/vm-user 2024-03-12 16:32:03 +00:00
clan-bot
7bcbe67f4d Merge pull request 'clan_vm_manager: Fix mypy errors for clan_cli types' (#938) from Qubasa-main into main 2024-03-12 16:31:48 +00:00
Qubasa
4e5d051847 clan_vm_manager: Fix mypy errors for clan_cli types 2024-03-12 23:27:20 +07:00
Mic92
7c2e22de72 Merge pull request 'Revert "workaround gitea bug"' (#940) from ci into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/940
2024-03-12 16:26:50 +00:00
Jörg Thalheim
0c688a0919 Revert "workaround gitea bug"
This reverts commit 38190adfb1.
2024-03-12 17:23:12 +01:00
a-kenji
b5433beef9 clan-modules: add vm-user module 2024-03-12 17:20:02 +01:00
Mic92
422b3f096e Merge pull request 'ci' (#935) from ci into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/935
2024-03-12 16:10:54 +00:00
Jörg Thalheim
38190adfb1 workaround gitea bug 2024-03-12 16:10:54 +00:00
Jörg Thalheim
934cf6e57a mypy: fix clan-cli import in vm-manager 2024-03-12 16:10:54 +00:00
kenji
4ef513de58 Merge pull request 'enable: spice-vdagent if xserver is enable' (#931) from a-kenji-add/spice-vm-profile into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/931
2024-03-12 16:00:54 +00:00
a-kenji
5d5f504013 enable: spice-vdagent if xserver is enable 2024-03-12 16:00:54 +00:00
Mic92
acf1dace5c Merge pull request 'clan.borgbackup: drop enable option' (#918) from Mic92-main into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/918
2024-03-12 15:50:33 +00:00
Jörg Thalheim
823b5e67ed fix backup not beeing activated 2024-03-12 13:17:04 +01:00
Jörg Thalheim
349d3b379c update flake 2024-03-12 13:06:12 +01:00
Jörg Thalheim
b1897530c8 clan.borgbackup: drop enable option 2024-03-12 11:21:10 +01:00
clan-bot
6d76a724c0 Merge pull request 'clan-vm-manager: add log view' (#927) from hsjobeki-main into main 2024-03-10 13:14:54 +00:00
Johannes Kirschbauer
4687c816ab clan-vm-manager: add log view 2024-03-10 14:10:59 +01:00
Johannes Kirschbauer
ee8fa1da0a vm-manager: add toast overlay to main window 2024-03-10 10:40:00 +01:00
clan-bot
bfa6ff6085 Merge pull request 'clan-cli: Add py.typed to make mypy work when used as library in clan-vm-manager' (#923) from Qubasa-main into main 2024-03-10 09:10:21 +00:00
Qubasa
129a1516f6 clan-cli: Readd mypy ignore clan_cli because of treefmt complaining 2024-03-10 16:06:03 +07:00
Qubasa
167f7f4eb3 clan-cli: Add py.typed to make mypy work when used as library in clan-vm-manager 2024-03-10 15:18:18 +07:00
clan-bot
d9f5e050d8 Merge pull request 'clan-vm-manager: Add library for mypy pygobject types' (#921) from Qubasa-main into main 2024-03-09 16:55:54 +00:00
Qubasa
14900a702b clan-vm-manager: Readd ignore for clan_cli because nix fmt fails in CI. But why \? 2024-03-09 23:51:59 +07:00
Qubasa
5c8343d943 clan-vm-manager: Remove mypy ignore clan_cli types 2024-03-09 23:17:00 +07:00
Qubasa
01351ff5a1 clan-vm-manager: Add library for mypy pygobject types 2024-03-09 23:15:32 +07:00
clan-bot
b985215cd6 Merge pull request 'docs: improve readme for better onboarding' (#920) from hsjobeki-main into main 2024-03-09 10:28:52 +00:00
Johannes Kirschbauer
59de33b68a docs: improve start command 2024-03-09 11:25:11 +01:00
Johannes Kirschbauer
11cfc49d27 docs: improve readme for better onboarding 2024-03-09 10:58:12 +01:00
clan-bot
79e4cb344f Merge pull request 'clan-vm-manager: Fix ClanUrl not pickable' (#919) from Qubasa-main into main 2024-03-08 16:51:45 +00:00
Qubasa
372e212c0c clan_cli: Renamed ClanUrl to FlakeId 2024-03-08 23:47:27 +07:00
Qubasa
f4f3176374 clan-vm-manager: Fix ClanUrl not pickable 2024-03-08 23:23:18 +07:00
clan-bot
1e7f63fb05 Merge pull request 'clan_vm_manager: Starting rewrite of Machine class' (#917) from Qubasa-main into main 2024-03-08 15:06:19 +00:00
Qubasa
e4896814f2 clan_cli: Add TimeTable class to cmd.py. Fix bugs in Machine rewrite 2024-03-08 22:01:54 +07:00
Qubasa
068f89e453 clan_vm_manager: Rewrite of Machine Class Part 1 2024-03-08 15:32:12 +07:00
clan-bot
2532c780ab Merge pull request 'add flash command and tests' (#916) from Mic92-main into main 2024-03-07 16:29:11 +00:00
Jörg Thalheim
4dfe4ecfa6 fix building installer iso 2024-03-07 17:24:57 +01:00
Jörg Thalheim
3cc97ebc56 fix container tests 2024-03-07 14:13:11 +01:00
Jörg Thalheim
26dd962799 treefmt 2024-03-07 14:13:11 +01:00
Jörg Thalheim
93afd06bcb fix install test 2024-03-07 14:13:11 +01:00
Jörg Thalheim
f599243cbd add flash command 2024-03-07 14:13:11 +01:00
Jörg Thalheim
dd73406a92 installer: switch to systemd-boot
grub is not able to boot from the disks that we flash for weird reasons.
Since BIOS-boot is on life-support, we may as well just use systemd-boot.
2024-03-07 14:13:11 +01:00
Jörg Thalheim
ab2defa9e4 add confirmation prompt when installing 2024-03-07 14:13:11 +01:00
clan-bot
1cc5dc98d3 Merge pull request 'clan_cli: Rewrite ClanURI' (#915) from Qubasa-main into main 2024-03-07 12:12:28 +00:00
Qubasa
a17eb3e8a3 clan_vm_manager: Fix broken vm start 2024-03-07 19:09:01 +07:00
clan-bot
718c0a06e2 Merge pull request 'clan_cli: Rewrite ClanURI' (#914) from Qubasa-main into main 2024-03-07 12:08:16 +00:00
Qubasa
442e5b45ba clan_cli: Simplify ClanURI 2024-03-07 19:04:48 +07:00
Qubasa
93c868a3b7 clan_cli: Rewrite ClanURI 2024-03-07 16:41:37 +07:00
clan-bot
9f632e90c5 Merge pull request 'fix: typos' (#913) from a-kenji-fix/typos into main 2024-03-06 12:15:23 +00:00
a-kenji
94caea382f fix: typos 2024-03-06 13:11:49 +01:00
clan-bot
8d72a36298 Merge pull request 'clan_cli,clan_vm_manager: Moved profiler to clan_cli. Add cmd timer to see how long run commands take' (#912) from Qubasa-main into main 2024-03-06 10:15:37 +00:00
Qubasa
a6f652bdfc clan_cli,clan_vm_manager: Moved profiler to clan_cli. Add cmd timer to see how long run commands take 2024-03-06 17:12:20 +07:00
clan-bot
dcf7f2f733 Merge pull request 'clan_vm_manager: Fix switch desync when pressed too fast. Secrets folder shared between build and run. clan_cli: run_vm now can have custom tmpdir location' (#910) from Qubasa-main into main 2024-03-06 09:35:38 +00:00
Qubasa
0e8622c491 clan_vm_manager: Fix switch desync when pressed too fast. Secrets folder shared between build and run. clan_cli: run_vm now can have custom tmpdir location 2024-03-06 16:32:19 +07:00
clan-bot
ff8d08e4e4 Merge pull request 'drop meshnamed from repository' (#909) from Mic92-main into main 2024-03-06 09:05:41 +00:00
Jörg Thalheim
0481746198 drop meshnamed from repository
It's not super useful and we can always add it back later if we need it.
2024-03-06 10:02:21 +01:00
Jörg Thalheim
cb564059e2 bump disko 2024-03-06 09:51:02 +01:00
clan-bot
cee9beb8a9 Merge pull request 'clan-cli sops: accept bytes' (#891) from sops_bytes into main 2024-03-06 08:45:44 +00:00
clan-bot
c4c4cd3ba8 Merge pull request 'clan-vm-manager: Add register_on_change to GKVStore. Improve overall signal typing.' (#908) from Qubasa-main into main 2024-03-06 08:07:53 +00:00
Qubasa
fb21a7378d clan-vm-manager: Add register_on_change to GKVStore. Improve overall signal typing. 2024-03-06 15:05:10 +07:00
clan-bot
b9ae911246 Merge pull request 'clan_vm_manager: Fix incorrect detection of vm already in list' (#907) from Qubasa-main into main 2024-03-05 17:35:09 +00:00
Qubasa
6f590ce389 clan_vm_manager: Fix switch <-> vm status desync 2024-03-06 00:32:22 +07:00
Qubasa
cd5afa1329 clan_vm_manager: Fix join list not rerendering correctly when updating clan_store 2024-03-06 00:18:42 +07:00
Qubasa
0840fffe26 clan_vm_manager: Fix incorrect detection of vm already in list 2024-03-06 00:18:42 +07:00
clan-bot
1986ecc564 Merge pull request 'clan_vm_manager: Fix vms not shutting down after closing GTK app. Sync JoinList with ClanStore' (#906) from Qubasa-main into main 2024-03-05 16:13:26 +00:00
Qubasa
580c63e760 clan_vm_manager: Fix vms not shutting down after closing GTK app. Sync JoinList with ClanStore 2024-03-05 23:10:30 +07:00
clan-bot
06bc425797 Merge pull request 'secrets: fix typo' (#905) from a-kenji-fix-typo into main 2024-03-05 11:02:59 +00:00
a-kenji
603893872e secrets: fix typo 2024-03-05 11:59:55 +01:00
clan-bot
e6b494a849 Merge pull request 'clan_vm_manager: Add CUMTIME to profiler output' (#904) from Qubasa-main into main 2024-03-04 09:02:49 +00:00
Qubasa
cde72f3710 clan_vm_manager: Add CUMTIME to profiler output 2024-03-04 16:00:04 +07:00
clan-bot
5047b6686d Merge pull request 'clan_vm_manager: Cache profiler obj for multi call functions' (#903) from Qubasa-main into main 2024-03-04 08:55:47 +00:00
Qubasa
b77ffac4d4 clan_vm_manager: Cache profiler obj for multi call functions 2024-03-04 15:52:57 +07:00
clan-bot
b2d3ff4431 Merge pull request 'clan_vm_manager: Extracted VMObject to own component' (#901) from Qubasa-main into main 2024-03-04 07:14:16 +00:00
Qubasa
f70879aa63 clan_vm_manager: Add profiler component 2024-03-04 14:01:30 +07:00
Qubasa
31190ed8e5 clan_vm_manager: Extracted VMObject to own component 2024-03-04 12:38:20 +07:00
clan-bot
36dbb8fafd Merge pull request 'clan_vm_manager: Renamed Views to ViewStack' (#899) from Qubasa-main into main 2024-03-03 09:54:26 +00:00
Qubasa
47ae5981f6 clan_vm_manager: Renamed Views to ViewStack 2024-03-03 16:51:34 +07:00
clan-bot
11c3b6f353 Merge pull request 'clan_vm_manager: Renamed VMs singleton to ClanStore. And VM to VMObject' (#898) from Qubasa-main into main 2024-03-03 09:50:32 +00:00
Qubasa
191562a84e clan_vm_manager: Renamed VMs singleton to ClanStore. And VM to VMObject 2024-03-03 16:47:38 +07:00
clan-bot
06a54c21c3 Merge pull request 'clan_vm_manager: New directory structure' (#897) from Qubasa-main into main 2024-03-03 09:41:16 +00:00
Qubasa
359ad22c90 clan_vm_manager: New directory structure 2024-03-03 16:38:25 +07:00
clan-bot
754e0ca9e8 Merge pull request 'clan_vm_manager: Added suffix task to glib task functions' (#894) from Qubasa-main into main 2024-03-03 09:18:42 +00:00
Qubasa
8290660f20 clan_vm_manager: Improved readability of GKVStore 2024-03-03 16:15:50 +07:00
Qubasa
78a50c5d74 clan_vm_manager: Added suffix task to glib task functions 2024-03-03 16:01:08 +07:00
clan-bot
496555b405 Merge pull request 'clan-vm-manager: Fix incorrect use of all Glib.idle_add uses' (#893) from Qubasa-main into main 2024-03-03 08:55:43 +00:00
Qubasa
216e5a53d4 clan_vm_manager: Remove superfluous argument to build_vm 2024-03-03 15:52:56 +07:00
clan-bot
a1af14db57 Merge pull request 'clan-vm-manager: Fix incorrect use of all Glib.idle_add uses' (#892) from Qubasa-main into main 2024-03-03 08:49:07 +00:00
Qubasa
976b4a2c3a clan_vm_manager: Fix incorrect signal behaviour in GKVStore setitem 2024-03-03 15:47:00 +07:00
Qubasa
c6a2db15a7 clan_vm_manager: Fix dynamic join 2024-03-03 15:47:00 +07:00
Qubasa
6f80cee971 clan_cli: history_add now returns newly added HistoryEntry. clan-vm-manager: Join now uses signals instead of callbacks. 2024-03-03 15:47:00 +07:00
Qubasa
f17cf41093 clan-vm-manager: Fix incorrect use of all Glib.idle_add uses 2024-03-03 15:47:00 +07:00
Qubasa
483e2c05ea clan_vm_manager: Fix incorrect signal behaviour in GKVStore setitem 2024-03-03 15:44:16 +07:00
lassulus
11bf0b8b9e clan-cli sops: accept bytes 2024-03-03 09:25:40 +01:00
clan-bot
da34bd7199 Merge pull request 'clan_cli secrets generate: fix type in error msg' (#890) from interactive_secrets into main 2024-03-03 07:43:48 +00:00
lassulus
3478dea8b2 clan_cli secrets generate: fix type in error msg 2024-03-03 08:40:22 +01:00
Qubasa
ce3fc6973b clan_vm_manager: Fix dynamic join 2024-03-03 13:50:49 +07:00
clan-bot
c228d72da2 Merge pull request 'interactive_secrets' (#885) from interactive_secrets into main 2024-03-03 06:15:44 +00:00
Qubasa
127009b303 clan_cli: history_add now returns newly added HistoryEntry. clan-vm-manager: Join now uses signals instead of callbacks. 2024-03-03 12:47:18 +07:00
lassulus
ed653fa8b9 fix pyproject syntax, ignore E731 2024-03-03 06:20:08 +01:00
lassulus
b8da149453 clan-cli sops: fix super class interface compliance 2024-03-03 06:20:08 +01:00
lassulus
a23c251b09 clan-cli secrets: actually check if only service needs regeneration 2024-03-03 06:20:08 +01:00
Qubasa
bf214011cf clan-vm-manager: Fix incorrect use of all Glib.idle_add uses 2024-03-03 11:21:12 +07:00
lassulus
a1dcddf9b4 clan-cli: add interactive secrets/fact generation 2024-03-03 04:06:18 +01:00
lassulus
f500aee786 clanCore secrets: rename toplevel secret to service 2024-03-02 11:43:20 +01:00
lassulus
4cfd580447 outputs: pass secretsData directly 2024-03-02 11:43:20 +01:00
lassulus
b1a4b4de96 clan-cli vms run: remove unused vm arg 2024-03-02 11:20:05 +01:00
lassulus
108a37b0a3 clan-cli machines: cache machines_func via store 2024-03-02 11:20:05 +01:00
clan-bot
8c7db195ab Merge pull request 'devshells: cleanup' (#888) from DavHau-dave into main 2024-03-02 04:58:32 +00:00
DavHau
f7bb5d7aaf devshells: cleanup 2024-03-02 11:55:15 +07:00
clan-bot
8e9053cf80 Merge pull request 'rename lol.clan to org.clan' (#887) from Mic92-main into main 2024-03-01 11:55:24 +00:00
Jörg Thalheim
9ec66195eb rename lol.clan to org.clan 2024-03-01 12:52:05 +01:00
clan-bot
93475ab4b3 Merge pull request 'devShells: one global python devshell + activation via command' (#886) from DavHau-dave into main 2024-03-01 11:22:09 +00:00
DavHau
d1e8b1ed96 devShells: one global python devshell + activation via command
- this adds devShells.{system}.python
- a 'select-shell' command to switch between devshells
2024-03-01 18:16:38 +07:00
clan-bot
3acc4b4d25 Merge pull request 'clan_vm_manager: Add GKVStore to combat O(n2) runtimes. Add pygdb to devshell' (#884) from Qubasa-main into main 2024-03-01 03:49:53 +00:00
Qubasa
7932517b4a clan_vm_manager: Fix gdb package incompatible with aarch darwin 2024-03-01 10:46:35 +07:00
Qubasa
5f1191148e clan_vm_manager: Fix GLib.idle_add rexecuting the VM push multiple times because of missing GLib.SOURCE_REMOVE 2024-03-01 01:58:03 +07:00
Qubasa
d079bc85a8 clan_vm_manager: Working GKVStore that emulates the ListStore Object 2024-03-01 01:26:45 +07:00
Qubasa
df6683a0bd clan_vm_manager: Add GKVStore to combat O(n2) runtimes. Add pygdb to devshell 2024-02-29 22:46:09 +07:00
clan-bot
4b3b573e8c Merge pull request 'writers: fix bug by typo' (#883) from DavHau-dave into main 2024-02-27 15:25:28 +00:00
DavHau
e930e14238 writers: fix bug by typo 2024-02-27 22:21:42 +07:00
clan-bot
2ccf32c36b Merge pull request 'merge-after-ci: rewrite according to #814' (#882) from DavHau-dave into main 2024-02-27 11:35:26 +00:00
DavHau
398a61acbc merge-after-ci: rewrite according to #814 2024-02-27 18:32:11 +07:00
DavHau
fdedf40e27 formatting: exclude script-writers.nix
Was copied from nixpkgs -> Keeping the diff low in order to upstream easier
2024-02-27 18:20:33 +07:00
DavHau
45fd64a930 script-writers: add wrapping support (makeWrapperArgs) 2024-02-27 18:20:33 +07:00
DavHau
31722d9dc0 script-writers: init (copied from nixpkgs) 2024-02-27 18:20:33 +07:00
clan-bot
d804c6059d Merge pull request 'clan-vm-manager: Moved switch from list view to VM object.' (#881) from Qubasa-main into main 2024-02-26 20:56:55 +00:00
Qubasa
4d1437b5cc clan-vm-manager: Moved switch from list view to VM object. 2024-02-27 03:53:19 +07:00
clan-bot
58bc8d162d Merge pull request 'Automatic flake update - 2024-02-26T00:00+00:00' (#880) from flake-update-2024-02-26 into main 2024-02-26 09:22:27 +00:00
DavHau
d12019d290 fix formatting 2024-02-26 16:19:30 +07:00
Clan Merge Bot
1918cfd707 update flake lock - 2024-02-26T00:00+00:00
Flake lock file updates:

• Updated input 'disko':
    'github:nix-community/disko/d07de570ba05cec2807d058daaa044f6955720c7' (2024-02-10)
  → 'github:nix-community/disko/23d308f0059955e3719efc81a34d1fc0369fbb74' (2024-02-22)
• Updated input 'nixos-generators':
    'github:nix-community/nixos-generators/843e2f04c716092797ffa4ce14c446adce2f09ef' (2024-02-08)
  → 'github:nix-community/nixos-generators/f4631dee1a0fd56c0db89860e83e3588a28c7631' (2024-02-22)
• Updated input 'nixos-generators/nixlib':
    'github:nix-community/nixpkgs.lib/f5af57d3ef9947a70ac86e42695231ac1ad00c25' (2023-09-03)
  → 'github:nix-community/nixpkgs.lib/e623008d8a46517470e6365505f1a3ce171fa46a' (2024-02-18)
• Updated input 'nixpkgs':
    'github:NixOS/nixpkgs/bdc57436da855500d44e9c1ce7450c0772e1cfa1' (2024-02-11)
  → 'github:NixOS/nixpkgs/2a34566b67bef34c551f204063faeecc444ae9da' (2024-02-25)
• Updated input 'sops-nix':
    'github:Mic92/sops-nix/2eb7c4ba3aa75e2660fd217eb1ab64d5b793608e' (2024-02-11)
  → 'github:Mic92/sops-nix/2874fbbe4a65bd2484b0ad757d27a16107f6bc17' (2024-02-25)
• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/ac599dab59a66304eb511af07b3883114f061b9d' (2024-02-07)
  → 'github:numtide/treefmt-nix/e497a9ddecff769c2a7cbab51e1ed7a8501e7a3a' (2024-02-25)
2024-02-26 00:00:15 +00:00
clan-bot
067da45082 Merge pull request 'clan-vm-manager: Fix ui state desync on build error. Add build progress bar' (#879) from Qubasa-main into main 2024-02-25 19:03:44 +00:00
Qubasa
0a8b8713d9 clan-vm-manager: Fix ui state desync on build error. Add build progress bar 2024-02-26 01:59:45 +07:00
clan-bot
4993b98258 Merge pull request 'clan_vm_manager: Fix qmp shutdown command, bad socket error on retried shutdown' (#878) from Qubasa-main into main 2024-02-25 18:21:43 +00:00
Qubasa
183c1f4235 clan_vm_manager: Fix qmp shutdown command, bad socket error on retried shutdown 2024-02-26 01:18:13 +07:00
clan-bot
ea7b0c8b90 Merge pull request 'clan_vm_manager: Improve VM start and stop switch. Switch will be disabled while stopping vm' (#877) from Qubasa-main into main 2024-02-25 18:11:38 +00:00
Qubasa
27b9c8915b clan_vm_manager: Improve VM start and stop switch. Switch will be disabled while stopping vm 2024-02-26 01:04:09 +07:00
clan-bot
36771f3ecd Merge pull request 'Also commit files when adding machines/users or removing secrets' (#876) from Mic92-main into main 2024-02-22 15:15:21 +00:00
Jörg Thalheim
52fcc91479 Also commit files when adding machines/users or removing secrets 2024-02-22 16:12:11 +01:00
Jörg Thalheim
65d2a4e081 secrets: commit when renaming secrets 2024-02-22 15:59:12 +01:00
Mic92
9dc362437c Merge pull request 'borgbackup: drop comment from string' (#875) from Mic92-main into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/875
2024-02-22 14:45:07 +00:00
Jörg Thalheim
6eb8fe47c4 borgbackup: drop comment from string
Looks weird in the logs.
2024-02-22 14:45:07 +00:00
Jörg Thalheim
7208d63e78 borgbackup: drop comment from string
Looks weird in the logs.
2024-02-22 15:42:19 +01:00
clan-bot
01f1a6900a Merge pull request 'print backup archive ids instead of bare objects' (#874) from Mic92-main into main 2024-02-22 14:29:47 +00:00
Jörg Thalheim
12ce8238f1 print backup archive ids instead of bare objects 2024-02-22 15:26:20 +01:00
clan-bot
c5071bc212 Merge pull request 'encrypt backups by default' (#873) from Mic92-main into main 2024-02-22 14:06:07 +00:00
Jörg Thalheim
81fc60eef8 encrypt backups by default 2024-02-22 15:03:22 +01:00
clan-bot
bb25e136c3 Merge pull request 'secret cli: accept a pattern in secrets list' (#872) from Mic92-main into main 2024-02-22 13:25:07 +00:00
Jörg Thalheim
a1e2a4f64a secret cli: accept a pattern in secrets list 2024-02-22 14:21:53 +01:00
clan-bot
943c19939a Merge pull request 'borgbackup: use persistent timers' (#871) from Mic92-main into main 2024-02-22 12:50:25 +00:00
Jörg Thalheim
17d7eec0ae borgbackup: use persistent timers 2024-02-22 13:47:09 +01:00
clan-bot
7b4e76df29 Merge pull request 'add lychee link checker' (#870) from Mic92-main into main 2024-02-21 16:21:48 +00:00
Jörg Thalheim
1cb33a5c6c add lychee link checker 2024-02-21 17:18:28 +01:00
clan-bot
cd11f6ad10 Merge pull request 'Updating contribution documentation' (#869) from Mic92-main into main 2024-02-21 16:05:50 +00:00
Jörg Thalheim
67ceba6637 Updating contribution documentation 2024-02-21 17:02:13 +01:00
Jörg Thalheim
1330c60190 drop obsolete documentation 2024-02-21 17:02:13 +01:00
clan-bot
e8d4cd9936 Merge pull request 'drop obsolete documentation' (#868) from Mic92-main into main 2024-02-21 15:54:47 +00:00
Jörg Thalheim
537a1ae87f drop obsolete documentation 2024-02-21 16:51:27 +01:00
clan-bot
0aa876a06c Merge pull request 'clan-cli: remove unused flag' (#867) from Mic92-fix-cross-system into main 2024-02-21 10:19:26 +00:00
Jörg Thalheim
457e45d989 clan-cli: remove unused flag 2024-02-21 10:55:53 +01:00
Jörg Thalheim
1356ca9b8c fix cross-system deploy
This allows to be nixpkgs.pkgs and deploy systems of a different arch.
2024-02-21 10:55:53 +01:00
clan-bot
df8074100d Merge pull request 'README: fix links harder' (#866) from fix_links into main 2024-02-21 09:25:12 +00:00
clan-bot
d441f1d60c Merge pull request 'clan-vm-manager: Fix double instantiation of Singleton. clan_cli: Shorten filepath of logging messages' (#865) from Qubasa-main into main 2024-02-21 09:23:21 +00:00
lassulus
a0097dab66 README: fix links harder 2024-02-21 10:22:09 +01:00
Qubasa
6c17fa648f clan_cli: Add exception handling in logger 2024-02-21 16:20:01 +07:00
Qubasa
51b087f7ae clan-vm-manager: Fix double instantiation of Singleton. clan_cli: Shorten filepath of logging messages 2024-02-21 16:16:58 +07:00
clan-bot
c340831edd Merge pull request 'README: fix links' (#864) from fix_links into main 2024-02-21 09:15:49 +00:00
lassulus
c3dc315576 README: fix links 2024-02-21 10:12:41 +01:00
clan-bot
ff3a1dc928 Merge pull request 'secret_store: drop update_check and generate_hash as abstract methods' (#863) from Mic92-target_host into main 2024-02-20 18:01:51 +00:00
Jörg Thalheim
3695a5adf2 disable vgpu on non-nixos systems 2024-02-20 18:58:38 +01:00
Jörg Thalheim
4d404cfc50 secret_store: drop update_check and generate_hash as abstract methods
Only password implements those just now
2024-02-20 18:58:38 +01:00
clan-bot
7091b09fa7 Merge pull request 'secrets: add git support when updating secrets' (#862) from Mic92-target_host into main 2024-02-20 11:45:13 +00:00
Jörg Thalheim
77c84e7471 secrets: add git support when updating secrets 2024-02-20 12:41:52 +01:00
clan-bot
413e172cbd Merge pull request 'abstract_fixes' (#861) from abstract_fixes into main 2024-02-20 10:51:42 +00:00
lassulus
3b975ed993 clan-cli SecretStore: remove generate_hash from base class 2024-02-20 11:48:13 +01:00
lassulus
36baec8d48 clan-cli SecretStore: implement update_check in base class 2024-02-20 11:47:53 +01:00
clan-bot
eb8d5167e7 Merge pull request 'sops: unbreak edit flags' (#860) from Mic92-target_host into main 2024-02-20 10:18:17 +00:00
Jörg Thalheim
b358089488 sops: unbreak edit flags 2024-02-20 11:07:00 +01:00
clan-bot
36b20f18d4 Merge pull request 'add option to set defaultGroups for secrets' (#858) from Mic92-target_host into main 2024-02-16 16:29:28 +00:00
Jörg Thalheim
52c6ad548d improve error message if group does not exists 2024-02-16 17:26:20 +01:00
Jörg Thalheim
57e9b27ff8 add option to set defaultGroups for secrets 2024-02-16 17:26:20 +01:00
clan-bot
661004972b Merge pull request 'make secrets stores inherit from an interface' (#857) from Mic92-target_host into main 2024-02-16 14:00:20 +00:00
Jörg Thalheim
714f3b0378 upload_secrets: call update_check directly without introspection 2024-02-16 14:57:01 +01:00
Jörg Thalheim
87f301122e split of generate_secrets method into smaller functions 2024-02-16 14:48:46 +01:00
Jörg Thalheim
53d658a3c0 make facts stores inherit from an interface 2024-02-16 14:47:39 +01:00
Jörg Thalheim
9257f140ba make secrets stores inherit from an interface 2024-02-16 14:47:28 +01:00
clan-bot
b68e39e8fa Merge pull request 'demo script' (#856) from Qubasa-HEAD into main 2024-02-16 10:55:02 +00:00
Qubasa
c566872f05 Working demo script 2024-02-16 17:51:55 +07:00
Qubasa
446039b02b Working demo script 2024-02-16 17:47:34 +07:00
Qubasa
5a69bbe93e demo script 2024-02-16 17:47:05 +07:00
clan-bot
a715364338 Merge pull request 'clan-vm-manager: Added clan icon to trayicon' (#855) from Qubasa-main into main 2024-02-16 09:14:08 +00:00
clan-bot
7bf1c0e42a Merge pull request 'waypipe: disable gpu for now' (#854) from Mic92-target_host into main 2024-02-16 08:55:35 +00:00
Jörg Thalheim
81545766a0 update comments about virtio-gpu 2024-02-16 09:52:13 +01:00
Jörg Thalheim
4e0ae54471 waypipe: disable gpu for now 2024-02-16 09:50:53 +01:00
287 changed files with 11095 additions and 4816 deletions

6
.envrc
View File

@@ -2,4 +2,10 @@ if ! has nix_direnv_version || ! nix_direnv_version 3.0.4; then
source_url "https://raw.githubusercontent.com/nix-community/nix-direnv/3.0.4/direnvrc" "sha256-DzlYZ33mWF/Gs8DDeyjr8mnVmQGx7ASYqA5WlxwvBG4="
fi
watch_file .direnv/selected-shell
if [ -e .direnv/selected-shell ]; then
use flake .#$(cat .direnv/selected-shell)
else
use flake
fi

View File

@@ -1,12 +0,0 @@
name: checks-impure
on:
pull_request:
push:
branches: main
jobs:
test:
if: ${{ github.actor != 'ui-asset-bot' }}
runs-on: nix
steps:
- uses: actions/checkout@v3
- run: nix run .#impure-checks

View File

@@ -2,11 +2,16 @@ name: checks
on:
pull_request:
push:
branches: main
branches:
- main
jobs:
test:
if: ${{ github.actor != 'ui-asset-bot' }}
checks:
runs-on: nix
steps:
- uses: actions/checkout@v3
- run: nix run --refresh github:Mic92/nix-fast-build -- --no-nom --eval-workers 20
- run: nix run --refresh github:Mic92/nix-fast-build -- --no-nom --eval-workers 10
checks-impure:
runs-on: nix
steps:
- uses: actions/checkout@v3
- run: nix run .#impure-checks

9
.gitignore vendored
View File

@@ -9,9 +9,9 @@ example_clan
result*
/pkgs/clan-cli/clan_cli/nixpkgs
/pkgs/clan-cli/clan_cli/webui/assets
/machines
nixos.qcow2
**/*.glade~
/docs/out
# python
__pycache__
@@ -21,3 +21,10 @@ __pycache__
.reports
.ruff_cache
htmlcov
# flatpak
.flatpak-builder
build
build-dir
repo
.env

21
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,21 @@
# Contributing to cLAN
## Live-reloading documentation
Enter the `docs` directory:
```shell-session
cd docs
```
Enter the development shell or enable `direnv`:
```shell-session
direnv allow
```
Run a local server:
```shell-session
mkdocs serve
```

View File

@@ -1,23 +1,45 @@
# cLAN Core Repository
Welcome to the cLAN Core Repository, the heart of the [clan.lol](https://clan.lol/) project! This monorepo houses all the essential packages, NixOS modules, CLI tools, and tests you need to contribute and work with the cLAN project.
Welcome to the cLAN Core Repository, the heart of the [clan.lol](https://clan.lol/) project! This monorepo is the foundation of Clan, a revolutionary open-source project aimed at restoring fun, freedom, and functionality to computing. Here, you'll find all the essential packages, NixOS modules, CLI tools, and tests needed to contribute to and work with the cLAN project. Clan leverages the Nix system to ensure reliability, security, and seamless management of digital environments, putting the power back into the hands of users.
## Getting Started
## Why Clan?
If you're new to cLAN and eager to dive in, start with our quickstart guide:
Our mission is simple: to democratize computing by providing tools that empower users, foster innovation, and challenge outdated paradigms. Clan represents our contribution to a future where technology serves humanity, not the other way around. By participating in Clan, you're joining a movement dedicated to creating a secure, user-empowered digital future.
- **Quickstart Guide**: Check out [quickstart.md](docs/quickstart.md) to get up and running with cLAN in no time.
## Features of Clan
## Managing Secrets
- **Full-Stack System Deployment:** Utilize Clans toolkit alongside Nix's reliability to build and manage systems effortlessly.
- **Overlay Networks:** Secure, private communication channels between devices.
- **Virtual Machine Integration:** Seamless operation of VM applications within the main operating system.
- **Robust Backup Management:** Long-term, self-hosted data preservation.
- **Intuitive Secret Management:** Simplified encryption and password management processes.
Security is paramount, and cLAN provides guidelines for handling secrets effectively:
## Getting Started with cLAN
- **Secrets Management**: Learn how to manage secrets securely by reading [secrets-management.md](docs/secrets-management.md).
If you're new to cLAN and eager to dive in, start with our quickstart guide and explore the core functionalities that Clan offers:
## Contributing to cLAN
- **Quickstart Guide**: Check out [getting started](https://docs.clan.lol/#starting-with-a-new-clan-project)<!-- [docs/site/index.md](docs/site/index.md) --> to get up and running with cLAN in no time.
We welcome contributions from the community, and we've prepared a comprehensive guide to help you get started:
### Managing Secrets
- **Contribution Guidelines**: Find out how to contribute and make a meaningful impact on the cLAN project by reading [contributing.md](docs/contributing.md).
In the Clan ecosystem, security is paramount. Learn how to handle secrets effectively:
- **Secrets Management**: Securely manage secrets by consulting [secrets](https://docs.clan.lol/getting-started/secrets/)<!-- [secrets.md](docs/site/getting-started/secrets.md) -->.
### Contributing to cLAN
The Clan project thrives on community contributions. We welcome everyone to contribute and collaborate:
- **Contribution Guidelines**: Make a meaningful impact by following the steps in [contributing](https://docs.clan.lol/contributing/contributing/)<!-- [contributing.md](docs/CONTRIBUTING.md) -->.
## Join the Revolution
Clan is more than a tool; it's a movement towards a better digital future. By contributing to the cLAN project, you're part of changing technology for the better, together.
### Community and Support
Connect with us and the Clan community for support and discussion:
- [Matrix channel](https://matrix.to/#/!djzOHBBBHnwQkgNgdV:matrix.org?via=blog.clan.lol) for live discussions.
- IRC bridges (coming soon) for real-time chat support.
Whether you're a newcomer or a seasoned developer, we look forward to your contributions and collaboration on the cLAN project. Let's build amazing things together!

View File

@@ -1,53 +1,85 @@
{ self, ... }:
let
clan = self.lib.buildClan {
clanName = "testclan";
directory = ../..;
machines = {
test_backup_client = {
clan.networking.targetHost = "client";
imports = [ self.nixosModules.test_backup_client ];
{
clan.machines.test-backup = {
imports = [ self.nixosModules.test-backup ];
fileSystems."/".device = "/dev/null";
boot.loader.grub.device = "/dev/null";
};
};
};
in
{
flake.nixosConfigurations = { inherit (clan.nixosConfigurations) test_backup_client; };
flake.clanInternals = clan.clanInternals;
flake.nixosModules = {
test_backup_server = { ... }: {
imports = [
self.clanModules.borgbackup
];
services.sshd.enable = true;
services.borgbackup.repos.testrepo = {
authorizedKeys = [
(builtins.readFile ../lib/ssh/pubkey)
];
};
};
test_backup_client = { pkgs, lib, config, ... }:
test-backup =
{
pkgs,
lib,
config,
...
}:
let
dependencies = [
self
pkgs.stdenv.drvPath
clan.clanInternals.machines.x86_64-linux.test_backup_client.config.system.clan.deployment.file
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-backup.config.system.clan.deployment.file
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
imports = [
self.clanModules.borgbackup
self.clanModules.localbackup
self.clanModules.sshd
];
networking.hostName = "client";
services.sshd.enable = true;
users.users.root.openssh.authorizedKeys.keyFiles = [
../lib/ssh/pubkey
clan.networking.targetHost = "machine";
networking.hostName = "machine";
services.openssh.settings.UseDns = false;
programs.ssh.knownHosts = {
machine.hostNames = [ "machine" ];
machine.publicKey = builtins.readFile ../lib/ssh/pubkey;
};
users.users.root.openssh.authorizedKeys.keyFiles = [ ../lib/ssh/pubkey ];
systemd.tmpfiles.settings."vmsecrets" = {
"/root/.ssh/id_ed25519" = {
C.argument = "${../lib/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/ssh.id_ed25519" = {
C.argument = "${../lib/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/borgbackup.ssh" = {
C.argument = "${../lib/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = {
mode = "0400";
user = "root";
};
};
};
clanCore.facts.secretStore = "vm";
environment.systemPackages = [
self.packages.${pkgs.system}.clan-cli
(pkgs.writeShellScriptBin "pre-restore-command" ''
touch /var/test-service/pre-restore-command
'')
(pkgs.writeShellScriptBin "post-restore-command" ''
touch /var/test-service/post-restore-command
'')
];
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ];
environment.etc."install-closure".source = "${closureInfo}/store-paths";
environment.etc.install-closure.source = "${closureInfo}/store-paths";
nix.settings = {
substituters = lib.mkForce [ ];
hashed-mirrors = null;
@@ -56,74 +88,91 @@ in
};
system.extraDependencies = dependencies;
clanCore.state.test-backups.folders = [ "/var/test-backups" ];
clan.borgbackup = {
enable = true;
destinations.test_backup_server = {
repo = "borg@server:.";
rsh = "ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=no";
clanCore.state.test-service = {
preRestoreCommand = "pre-restore-command";
postRestoreCommand = "post-restore-command";
folders = [ "/var/test-service" ];
};
clan.borgbackup.destinations.test-backup.repo = "borg@machine:.";
fileSystems."/mnt/external-disk" = {
device = "/dev/vdb"; # created in tests with virtualisation.emptyDisks
autoFormat = true;
fsType = "ext4";
options = [
"defaults"
"noauto"
];
};
clan.localbackup.targets.hdd = {
directory = "/mnt/external-disk";
preMountHook = ''
touch /run/mount-external-disk
'';
postUnmountHook = ''
touch /run/unmount-external-disk
'';
};
services.borgbackup.repos.test-backups = {
path = "/var/lib/borgbackup/test-backups";
authorizedKeys = [ (builtins.readFile ../lib/ssh/pubkey) ];
};
};
};
};
perSystem = { nodes, pkgs, ... }: {
perSystem =
{ nodes, pkgs, ... }:
{
checks = pkgs.lib.mkIf (pkgs.stdenv.isLinux) {
test-backups =
(import ../lib/test-base.nix)
{
test-backups = (import ../lib/test-base.nix) {
name = "test-backups";
nodes.server = {
nodes.machine = {
imports = [
self.nixosModules.test_backup_server
self.nixosModules.clanCore
{
clanCore.machineName = "server";
clanCore.clanDir = ../..;
}
];
};
nodes.client = {
imports = [
self.nixosModules.test_backup_client
self.nixosModules.clanCore
{
clanCore.machineName = "client";
clanCore.clanDir = ../..;
}
self.nixosModules.test-backup
];
virtualisation.emptyDiskImages = [ 256 ];
};
testScript = ''
import json
start_all()
# setup
client.succeed("mkdir -m 700 /root/.ssh")
client.succeed(
"cat ${../lib/ssh/privkey} > /root/.ssh/id_ed25519"
)
client.succeed("chmod 600 /root/.ssh/id_ed25519")
client.wait_for_unit("sshd", timeout=30)
client.succeed("ssh -o StrictHostKeyChecking=accept-new root@client hostname")
# dummy data
client.succeed("mkdir /var/test-backups")
client.succeed("echo testing > /var/test-backups/somefile")
machine.succeed("mkdir -p /var/test-backups /var/test-service")
machine.succeed("echo testing > /var/test-backups/somefile")
# create
client.succeed("clan --debug --flake ${../..} backups create test_backup_client")
client.wait_until_succeeds("! systemctl is-active borgbackup-job-test_backup_server")
machine.succeed("clan --debug --flake ${self} backups create test-backup")
machine.wait_until_succeeds("! systemctl is-active borgbackup-job-test-backup >&2")
machine.succeed("test -f /run/mount-external-disk")
machine.succeed("test -f /run/unmount-external-disk")
# list
backup_id = json.loads(client.succeed("borg-job-test_backup_server list --json"))["archives"][0]["archive"]
assert(backup_id in client.succeed("clan --debug --flake ${../..} backups list test_backup_client"))
backup_id = json.loads(machine.succeed("borg-job-test-backup list --json"))["archives"][0]["archive"]
out = machine.succeed("clan --debug --flake ${self} backups list test-backup").strip()
print(out)
assert backup_id in out, f"backup {backup_id} not found in {out}"
localbackup_id = "hdd::/mnt/external-disk/snapshot.0"
assert localbackup_id in out, "localbackup not found in {out}"
# restore
client.succeed("rm -f /var/test-backups/somefile")
client.succeed(f"clan --debug --flake ${../..} backups restore test_backup_client borgbackup {backup_id}")
assert(client.succeed("cat /var/test-backups/somefile").strip() == "testing")
## borgbackup restore
machine.succeed("rm -f /var/test-backups/somefile")
machine.succeed(f"clan --debug --flake ${self} backups restore test-backup borgbackup 'test-backup::borg@machine:.::{backup_id}' >&2")
assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
machine.succeed("test -f /var/test-service/pre-restore-command")
machine.succeed("test -f /var/test-service/post-restore-command")
## localbackup restore
machine.succeed("rm -f /var/test-backups/somefile /var/test-service/{pre,post}-restore-command")
machine.succeed(f"clan --debug --flake ${self} backups restore test-backup localbackup '{localbackup_id}' >&2")
assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
machine.succeed("test -f /var/test-service/pre-restore-command")
machine.succeed("test -f /var/test-service/post-restore-command")
'';
}
{ inherit pkgs self; };
} { inherit pkgs self; };
};
};
}

View File

@@ -1,16 +1,18 @@
(import ../lib/test-base.nix) ({ ... }: {
(import ../lib/test-base.nix) (
{ ... }:
{
name = "borgbackup";
nodes.machine = { self, ... }: {
nodes.machine =
{ self, pkgs, ... }:
{
imports = [
self.clanModules.borgbackup
self.nixosModules.clanCore
{
services.openssh.enable = true;
services.borgbackup.repos.testrepo = {
authorizedKeys = [
(builtins.readFile ../lib/ssh/pubkey)
];
authorizedKeys = [ (builtins.readFile ../lib/ssh/pubkey) ];
};
}
{
@@ -18,22 +20,25 @@
clanCore.clanDir = ./.;
clanCore.state.testState.folders = [ "/etc/state" ];
environment.etc.state.text = "hello world";
systemd.tmpfiles.settings = {
"ssh-key"."/root/.ssh/id_ed25519" = {
systemd.tmpfiles.settings."vmsecrets" = {
"/etc/secrets/borgbackup.ssh" = {
C.argument = "${../lib/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
};
clan.borgbackup = {
enable = true;
destinations.test = {
repo = "borg@localhost:.";
rsh = "ssh -i /root/.ssh/id_ed25519 -o StrictHostKeyChecking=no";
"/etc/secrets/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = {
mode = "0400";
user = "root";
};
};
};
clanCore.facts.secretStore = "vm";
clan.borgbackup.destinations.test.repo = "borg@localhost:.";
}
];
};
@@ -42,4 +47,5 @@
machine.systemctl("start --wait borgbackup-job-test.service")
assert "machine-test" in machine.succeed("BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes /run/current-system/sw/bin/borg-job-test list")
'';
})
}
)

View File

@@ -1,7 +1,11 @@
(import ../lib/container-test.nix) ({ ... }: {
(import ../lib/container-test.nix) (
{ ... }:
{
name = "secrets";
nodes.machine = { ... }: {
nodes.machine =
{ ... }:
{
networking.hostName = "machine";
services.openssh.enable = true;
services.openssh.startWhenNeeded = false;
@@ -11,4 +15,5 @@
machine.succeed("systemctl status sshd")
machine.wait_for_unit("sshd")
'';
})
}
)

View File

@@ -1,7 +1,11 @@
(import ../lib/container-test.nix) ({ pkgs, ... }: {
(import ../lib/container-test.nix) (
{ pkgs, ... }:
{
name = "secrets";
nodes.machine = { self, ... }: {
nodes.machine =
{ self, ... }:
{
imports = [
self.clanModules.deltachat
self.nixosModules.clanCore
@@ -21,4 +25,5 @@
# smtp
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 25")
'';
})
}
)

View File

@@ -1,12 +1,34 @@
{ self, ... }: {
{ self, ... }:
{
imports = [
./impure/flake-module.nix
./backups/flake-module.nix
./installation/flake-module.nix
./flash/flake-module.nix
];
perSystem = { pkgs, lib, self', ... }: {
perSystem =
{
pkgs,
lib,
self',
...
}:
{
checks =
let
# ensure all options can be rendered after importing clan into nixos
renderClanOptions =
let
docs = pkgs.nixosOptionsDoc {
options =
(pkgs.nixos {
imports = [ self.nixosModules.clanCore ];
clanCore.clanDir = ./.;
}).options;
warningsAreErrors = false;
};
in
docs.optionsJSON;
nixosTestArgs = {
# reference to nixpkgs for the current system
inherit pkgs;
@@ -18,22 +40,25 @@
secrets = import ./secrets nixosTestArgs;
container = import ./container nixosTestArgs;
deltachat = import ./deltachat nixosTestArgs;
meshnamed = import ./meshnamed nixosTestArgs;
matrix-synapse = import ./matrix-synapse nixosTestArgs;
zt-tcp-relay = import ./zt-tcp-relay nixosTestArgs;
borgbackup = import ./borgbackup nixosTestArgs;
syncthing = import ./syncthing nixosTestArgs;
wayland-proxy-virtwl = import ./wayland-proxy-virtwl nixosTestArgs;
};
schemaTests = pkgs.callPackages ./schemas.nix {
inherit self;
};
schemaTests = pkgs.callPackages ./schemas.nix { inherit self; };
flakeOutputs = lib.mapAttrs' (name: config: lib.nameValuePair "nixos-${name}" config.config.system.build.toplevel) self.nixosConfigurations
flakeOutputs =
lib.mapAttrs' (
name: config: lib.nameValuePair "nixos-${name}" config.config.system.build.toplevel
) self.nixosConfigurations
// lib.mapAttrs' (n: lib.nameValuePair "package-${n}") self'.packages
// lib.mapAttrs' (n: lib.nameValuePair "devShell-${n}") self'.devShells
// lib.mapAttrs' (name: config: lib.nameValuePair "home-manager-${name}" config.activation-script) (self'.legacyPackages.homeConfigurations or { });
// lib.mapAttrs' (name: config: lib.nameValuePair "home-manager-${name}" config.activation-script) (
self'.legacyPackages.homeConfigurations or { }
);
in
nixosTests // schemaTests // flakeOutputs;
{ inherit renderClanOptions; } // nixosTests // schemaTests // flakeOutputs;
legacyPackages = {
nixosTests =
let

View File

@@ -0,0 +1,49 @@
{ self, ... }:
{
perSystem =
{
nodes,
pkgs,
lib,
...
}:
let
dependencies = [
self
pkgs.stdenv.drvPath
self.clanInternals.machines.${pkgs.hostPlatform.system}.test_install_machine.config.system.build.toplevel
self.clanInternals.machines.${pkgs.hostPlatform.system}.test_install_machine.config.system.build.diskoScript
self.clanInternals.machines.${pkgs.hostPlatform.system}.test_install_machine.config.system.clan.deployment.file
self.inputs.nixpkgs.legacyPackages.${pkgs.hostPlatform.system}.disko
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
checks = pkgs.lib.mkIf (pkgs.stdenv.isLinux) {
flash = (import ../lib/test-base.nix) {
name = "flash";
nodes.target = {
virtualisation.emptyDiskImages = [ 4096 ];
virtualisation.memorySize = 3000;
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ];
environment.etc."install-closure".source = "${closureInfo}/store-paths";
nix.settings = {
substituters = lib.mkForce [ ];
hashed-mirrors = null;
connect-timeout = lib.mkForce 3;
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
experimental-features = [
"nix-command"
"flakes"
];
};
};
testScript = ''
start_all()
machine.succeed("clan --flake ${../..} flash --debug --yes --disk main /dev/vdb test_install_machine")
'';
} { inherit pkgs self; };
};
};
}

View File

@@ -1,15 +1,19 @@
{
perSystem = { pkgs, lib, ... }: {
perSystem =
{ pkgs, lib, ... }:
{
# a script that executes all other checks
packages.impure-checks = pkgs.writeShellScriptBin "impure-checks" ''
#!${pkgs.bash}/bin/bash
set -euo pipefail
export PATH="${lib.makeBinPath [
export PATH="${
lib.makeBinPath [
pkgs.gitMinimal
pkgs.nix
pkgs.rsync # needed to have rsync installed on the dummy ssh server
]}"
]
}"
ROOT=$(git rev-parse --show-toplevel)
cd "$ROOT/pkgs/clan-cli"
nix develop "$ROOT#clan-cli" -c bash -c "TMPDIR=/tmp python -m pytest -s -m impure ./tests $@"

View File

@@ -1,65 +1,54 @@
{ self, ... }:
let
clan = self.lib.buildClan {
clanName = "testclan";
directory = ../..;
machines = {
test_install_machine = {
{ self, lib, ... }:
{
clan.machines.test_install_machine = {
clan.networking.targetHost = "test_install_machine";
fileSystems."/".device = lib.mkDefault "/dev/null";
boot.loader.grub.device = lib.mkDefault "/dev/null";
imports = [ self.nixosModules.test_install_machine ];
};
};
};
in
{
flake.nixosConfigurations = { inherit (clan.nixosConfigurations) test_install_machine; };
flake.clanInternals = clan.clanInternals;
flake.nixosModules = {
test_install_machine = { lib, modulesPath, ... }: {
test_install_machine =
{ lib, modulesPath, ... }:
{
imports = [
self.clanModules.diskLayouts
(modulesPath + "/testing/test-instrumentation.nix") # we need these 2 modules always to be able to run the tests
(modulesPath + "/profiles/qemu-guest.nix")
];
fileSystems."/nix/store" = lib.mkForce {
device = "nix-store";
fsType = "9p";
neededForBoot = true;
options = [ "trans=virtio" "version=9p2000.L" "cache=loose" ];
};
clan.diskLayouts.singleDiskExt4.device = "/dev/vdb";
environment.etc."install-successful".text = "ok";
boot.consoleLogLevel = lib.mkForce 100;
boot.kernelParams = [
"boot.shell_on_fail"
];
boot.kernelParams = [ "boot.shell_on_fail" ];
};
};
perSystem = { nodes, pkgs, lib, ... }:
perSystem =
{
nodes,
pkgs,
lib,
...
}:
let
dependencies = [
self
self.nixosConfigurations.test_install_machine.config.system.build.toplevel
self.nixosConfigurations.test_install_machine.config.system.build.diskoScript
self.nixosConfigurations.test_install_machine.config.system.clan.deployment.file
pkgs.stdenv.drvPath
clan.clanInternals.machines.x86_64-linux.test_install_machine.config.system.build.toplevel
clan.clanInternals.machines.x86_64-linux.test_install_machine.config.system.build.diskoScript
clan.clanInternals.machines.x86_64-linux.test_install_machine.config.system.clan.deployment.file
pkgs.nixos-anywhere
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
checks = pkgs.lib.mkIf (pkgs.stdenv.isLinux) {
test-installation =
(import ../lib/test-base.nix)
{
test-installation = (import ../lib/test-base.nix) {
name = "test-installation";
nodes.target = {
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keyFiles = [
../lib/ssh/pubkey
];
users.users.root.openssh.authorizedKeys.keyFiles = [ ../lib/ssh/pubkey ];
system.nixos.variant_id = "installer";
virtualisation.emptyDiskImages = [ 4096 ];
nix.settings = {
@@ -92,22 +81,22 @@ in
testScript = ''
def create_test_machine(oldmachine=None, args={}): # taken from <nixpkgs/nixos/tests/installer.nix>
startCommand = "${pkgs.qemu_test}/bin/qemu-kvm"
startCommand += " -cpu max -m 1024 -virtfs local,path=/nix/store,security_model=none,mount_tag=nix-store"
startCommand += f' -drive file={oldmachine.state_dir}/empty0.qcow2,id=drive1,if=none,index=1,werror=report'
startCommand += ' -device virtio-blk-pci,drive=drive1'
machine = create_machine({
"qemuFlags":
'-cpu max -m 1024 -virtfs local,path=/nix/store,security_model=none,mount_tag=nix-store,'
f' -drive file={oldmachine.state_dir}/empty0.qcow2,id=drive1,if=none,index=1,werror=report'
f' -device virtio-blk-pci,drive=drive1',
"startCommand": startCommand,
} | args)
driver.machines.append(machine)
return machine
start_all()
client.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../lib/ssh/privkey} /root/.ssh/id_ed25519")
client.wait_until_succeeds("ssh -o StrictHostKeyChecking=accept-new -v root@target hostname")
client.succeed("clan --debug --flake ${../..} machines install test_install_machine root@target >&2")
client.succeed("clan --debug --flake ${../..} machines install --yes test_install_machine root@target >&2")
try:
target.shutdown()
except BrokenPipeError:
@@ -117,8 +106,7 @@ in
new_machine = create_test_machine(oldmachine=target, args={ "name": "new_machine" })
assert(new_machine.succeed("cat /etc/install-successful").strip() == "ok")
'';
}
{ inherit pkgs self; };
} { inherit pkgs self; };
};
};
}

View File

@@ -1,17 +1,23 @@
{ hostPkgs, lib, config, ... }:
{
hostPkgs,
lib,
config,
...
}:
let
testDriver = hostPkgs.python3.pkgs.callPackage ./package.nix {
inherit (config) extraPythonPackages;
inherit (hostPkgs.pkgs) util-linux systemd;
};
containers = map (m: m.system.build.toplevel) (lib.attrValues config.nodes);
pythonizeName = name:
pythonizeName =
name:
let
head = lib.substring 0 1 name;
tail = lib.substring 1 (-1) name;
in
(if builtins.match "[A-z_]" head == null then "_" else head) +
lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
(if builtins.match "[A-z_]" head == null then "_" else head)
+ lib.stringAsChars (c: if builtins.match "[A-z0-9_]" c == null then "_" else c) tail;
nodeHostNames =
let
nodesList = map (c: c.system.name) (lib.attrValues config.nodes);
@@ -21,7 +27,8 @@ let
pythonizedNames = map pythonizeName nodeHostNames;
in
{
driver = lib.mkForce (hostPkgs.runCommand "nixos-test-driver-${config.name}"
driver = lib.mkForce (
hostPkgs.runCommand "nixos-test-driver-${config.name}"
{
nativeBuildInputs = [
hostPkgs.makeWrapper
@@ -61,9 +68,11 @@ in
wrapProgram $out/bin/nixos-test-driver \
${lib.concatStringsSep " " (map (name: "--add-flags '--container ${name}'") containers)} \
--add-flags "--test-script '$out/test-script'"
'');
''
);
test = lib.mkForce (lib.lazyDerivation {
test = lib.mkForce (
lib.lazyDerivation {
# lazyDerivation improves performance when only passthru items and/or meta are used.
derivation = hostPkgs.stdenv.mkDerivation {
name = "vm-test-run-${config.name}";
@@ -84,5 +93,6 @@ in
meta = config.meta;
};
inherit (config) passthru meta;
});
}
);
}

View File

@@ -1,8 +1,18 @@
{ extraPythonPackages, python3Packages, buildPythonApplication, setuptools, util-linux, systemd }:
{
extraPythonPackages,
python3Packages,
buildPythonApplication,
setuptools,
util-linux,
systemd,
}:
buildPythonApplication {
pname = "test-driver";
version = "0.0.1";
propagatedBuildInputs = [ util-linux systemd ] ++ extraPythonPackages python3Packages;
propagatedBuildInputs = [
util-linux
systemd
] ++ extraPythonPackages python3Packages;
nativeBuildInputs = [ setuptools ];
format = "pyproject";
src = ./.;

View File

@@ -19,8 +19,8 @@ test_driver = ["py.typed"]
target-version = "py311"
line-length = 88
select = [ "E", "F", "I", "U", "N", "RUF", "ANN", "A" ]
ignore = ["E501", "ANN101", "ANN401", "A003"]
lint.select = [ "E", "F", "I", "U", "N", "RUF", "ANN", "A" ]
lint.ignore = ["E501", "ANN101", "ANN401", "A003"]
[tool.mypy]
python_version = "3.11"

View File

@@ -258,7 +258,7 @@ class Driver:
self.machines = []
for container in containers:
name_match = re.match(r".*-nixos-system-(.+)-\d.+", container.name)
name_match = re.match(r".*-nixos-system-(.+)-(.+)", container.name)
if not name_match:
raise ValueError(f"Unable to extract hostname from {container.name}")
name = name_match.group(1)

View File

@@ -1,13 +1,12 @@
test:
{ pkgs
, self
, ...
}:
{ pkgs, self, ... }:
let
inherit (pkgs) lib;
nixos-lib = import (pkgs.path + "/nixos/lib") { };
in
(nixos-lib.runTest ({ hostPkgs, ... }: {
(nixos-lib.runTest (
{ hostPkgs, ... }:
{
hostPkgs = pkgs;
# speed-up evaluation
defaults = {
@@ -30,4 +29,5 @@ in
test
./container-driver/module.nix
];
})).config.result
}
)).config.result

View File

@@ -1,8 +1,5 @@
test:
{ pkgs
, self
, ...
}:
{ pkgs, self, ... }:
let
inherit (pkgs) lib;
nixos-lib = import (pkgs.path + "/nixos/lib") { };

View File

@@ -0,0 +1,37 @@
(import ../lib/container-test.nix) (
{ pkgs, ... }:
{
name = "matrix-synapse";
nodes.machine =
{ self, lib, ... }:
{
imports = [
self.clanModules.matrix-synapse
self.nixosModules.clanCore
{
clanCore.machineName = "machine";
clanCore.clanDir = ./.;
clan.matrix-synapse = {
enable = true;
domain = "clan.test";
};
}
{
# secret override
clanCore.facts.services.matrix-synapse.secret.synapse-registration_shared_secret.path = "${./synapse-registration_shared_secret}";
services.nginx.virtualHosts."matrix.clan.test" = {
enableACME = lib.mkForce false;
forceSSL = lib.mkForce false;
};
}
];
};
testScript = ''
start_all()
machine.wait_for_unit("matrix-synapse")
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 8008")
machine.succeed("${pkgs.curl}/bin/curl -Ssf -L http://localhost/_matrix/static/ -H 'Host: matrix.clan.test'")
'';
}
)

View File

@@ -0,0 +1 @@
registration_shared_secret: supersecret

View File

@@ -1,21 +0,0 @@
(import ../lib/container-test.nix) ({ pkgs, ... }: {
name = "meshnamed";
nodes.machine = { self, ... }: {
imports = [
self.nixosModules.clanCore
{
clanCore.machineName = "machine";
clan.networking.meshnamed.networks.vpn.subnet = "fd43:7def:4b50:28d0:4e99:9347:3035:17ef/88";
clanCore.clanDir = ./.;
}
];
};
testScript = ''
start_all()
machine.wait_for_unit("meshnamed")
out = machine.succeed("${pkgs.dnsutils}/bin/dig AAAA foo.7vbx332lkaunatuzsndtanix54.vpn @meshnamed +short")
print(out)
assert out.strip() == "fd43:7def:4b50:28d0:4e99:9347:3035:17ef"
'';
})

View File

@@ -1,35 +1,48 @@
{ self, runCommand, check-jsonschema, pkgs, lib, ... }:
{
self,
runCommand,
check-jsonschema,
pkgs,
lib,
...
}:
let
clanModules.clanCore = self.nixosModules.clanCore;
baseModule = {
imports =
(import (pkgs.path + "/nixos/modules/module-list.nix"))
++ [{
imports = (import (pkgs.path + "/nixos/modules/module-list.nix")) ++ [
{
nixpkgs.hostPlatform = "x86_64-linux";
clanCore.clanName = "dummy";
}];
}
];
};
optionsFromModule = module:
optionsFromModule =
module:
let
evaled = lib.evalModules {
modules = [ module baseModule ];
modules = [
module
baseModule
];
};
in
evaled.options.clan;
clanModuleSchemas = lib.mapAttrs (_: module: self.lib.jsonschema.parseOptions (optionsFromModule module)) clanModules;
clanModuleSchemas = lib.mapAttrs (
_: module: self.lib.jsonschema.parseOptions (optionsFromModule module)
) clanModules;
mkTest = name: schema: runCommand "schema-${name}" { } ''
mkTest =
name: schema:
runCommand "schema-${name}" { } ''
${check-jsonschema}/bin/check-jsonschema \
--check-metaschema ${builtins.toFile "schema-${name}" (builtins.toJSON schema)}
touch $out
'';
in
lib.mapAttrs'
(name: schema: {
lib.mapAttrs' (name: schema: {
name = "schema-${name}";
value = mkTest name schema;
})
clanModuleSchemas
}) clanModuleSchemas

View File

@@ -1,10 +1,10 @@
(import ../lib/test-base.nix) {
name = "secrets";
nodes.machine = { self, config, ... }: {
imports = [
(self.nixosModules.clanCore)
];
nodes.machine =
{ self, config, ... }:
{
imports = [ (self.nixosModules.clanCore) ];
environment.etc."secret".source = config.sops.secrets.secret.path;
environment.etc."group-secret".source = config.sops.secrets.group-secret.path;
sops.age.keyFile = ./key.age;

View File

@@ -19,7 +19,7 @@
"syncthing.key".source = ./introducer/introducer_test_key;
"syncthing.api".source = ./introducer/introducer_test_api;
};
clanCore.secrets.syncthing.secrets."syncthing.api".path = "/etc/syncthing.api";
clanCore.facts.services.syncthing.secret."syncthing.api".path = "/etc/syncthing.api";
services.syncthing.cert = "/etc/syncthing.pam";
services.syncthing.key = "/etc/syncthing.key";
# Doesn't test zerotier!

View File

@@ -1,7 +1,16 @@
import ../lib/test-base.nix ({ config, pkgs, lib, ... }: {
import ../lib/test-base.nix (
{
config,
pkgs,
lib,
...
}:
{
name = "wayland-proxy-virtwl";
nodes.machine = { self, ... }: {
nodes.machine =
{ self, ... }:
{
imports = [
self.nixosModules.clanCore
{
@@ -22,4 +31,5 @@ import ../lib/test-base.nix ({ config, pkgs, lib, ... }: {
# use machinectl
machine.succeed("machinectl shell .host ${config.nodes.machine.systemd.package}/bin/systemctl --user start wayland-proxy-virtwl >&2")
'';
})
}
)

View File

@@ -1,7 +1,11 @@
(import ../lib/container-test.nix) ({ pkgs, ... }: {
(import ../lib/container-test.nix) (
{ pkgs, ... }:
{
name = "zt-tcp-relay";
nodes.machine = { self, ... }: {
nodes.machine =
{ self, ... }:
{
imports = [
self.nixosModules.clanCore
self.clanModules.zt-tcp-relay
@@ -17,4 +21,5 @@
out = machine.succeed("${pkgs.netcat}/bin/nc -z -v localhost 4443")
print(out)
'';
})
}
)

View File

@@ -1,15 +1,21 @@
{ config, lib, pkgs, ... }:
{
config,
lib,
pkgs,
...
}:
let
cfg = config.clan.borgbackup;
in
{
options.clan.borgbackup = {
enable = lib.mkEnableOption "backups with borgbackup";
destinations = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
options.clan.borgbackup.destinations = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
type = lib.types.strMatching "^[a-zA-Z0-9._-]+$";
default = name;
description = "the name of the backup job";
};
@@ -19,72 +25,107 @@ in
};
rsh = lib.mkOption {
type = lib.types.str;
default = "ssh -i ${config.clanCore.secrets.borgbackup.secrets."borgbackup.ssh".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
default = "ssh -i ${
config.clanCore.facts.services.borgbackup.secret."borgbackup.ssh".path
} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
defaultText = "ssh -i \${config.clanCore.facts.services.borgbackup.secret.\"borgbackup.ssh\".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
description = "the rsh to use for the backup";
};
};
}));
}
)
);
default = { };
description = ''
destinations where the machine should be backuped to
'';
};
};
config = lib.mkIf cfg.enable {
services.borgbackup.jobs = lib.mapAttrs
(_: dest: {
paths = lib.flatten (map (state: state.folders) (lib.attrValues config.clanCore.state));
exclude = [
"*.pyc"
imports = [
(lib.mkRemovedOptionModule [
"clan"
"borgbackup"
"enable"
] "Just define clan.borgbackup.destinations to enable it")
];
config = lib.mkIf (cfg.destinations != { }) {
services.borgbackup.jobs = lib.mapAttrs (_: dest: {
paths = lib.flatten (map (state: state.folders) (lib.attrValues config.clanCore.state));
exclude = [ "*.pyc" ];
repo = dest.repo;
environment.BORG_RSH = dest.rsh;
encryption.mode = "none";
compression = "auto,zstd";
startAt = "*-*-* 01:00:00";
persistentTimer = true;
preHook = ''
set -x
'';
encryption = {
mode = "repokey";
passCommand = "cat ${config.clanCore.facts.services.borgbackup.secret."borgbackup.repokey".path}";
};
prune.keep = {
within = "1d"; # Keep all archives from the last day
daily = 7;
weekly = 4;
monthly = 0;
};
})
cfg.destinations;
}) cfg.destinations;
clanCore.secrets.borgbackup = {
facts."borgbackup.ssh.pub" = { };
secrets."borgbackup.ssh" = { };
generator.path = [ pkgs.openssh pkgs.coreutils ];
clanCore.facts.services.borgbackup = {
public."borgbackup.ssh.pub" = { };
secret."borgbackup.ssh" = { };
secret."borgbackup.repokey" = { };
generator.path = [
pkgs.openssh
pkgs.coreutils
pkgs.xkcdpass
];
generator.script = ''
ssh-keygen -t ed25519 -N "" -f "$secrets"/borgbackup.ssh
mv "$secrets"/borgbackup.ssh.pub "$facts"/borgbackup.ssh.pub
xkcdpass -n 4 -d - > "$secrets"/borgbackup.repokey
'';
};
clanCore.backups.providers.borgbackup = {
# TODO list needs to run locally or on the remote machine
list = ''
${lib.concatMapStringsSep "\n" (dest: ''
# we need yes here to skip the changed url verification
yes y | borg-job-${dest.name} list --json | jq -r '. + {"job-name": "${dest.name}"}'
'') (lib.attrValues cfg.destinations)}
'';
create = ''
environment.systemPackages = [
(pkgs.writeShellScriptBin "borgbackup-create" ''
set -efu -o pipefail
${lib.concatMapStringsSep "\n" (dest: ''
systemctl start borgbackup-job-${dest.name}
'') (lib.attrValues cfg.destinations)}
'';
restore = ''
'')
(pkgs.writeShellScriptBin "borgbackup-list" ''
set -efu
(${
lib.concatMapStringsSep "\n" (
dest:
# we need yes here to skip the changed url verification
''yes y | borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.name}::${dest.repo}::" + .name)}]' ''
) (lib.attrValues cfg.destinations)
}) | ${pkgs.jq}/bin/jq -s 'add'
'')
(pkgs.writeShellScriptBin "borgbackup-restore" ''
set -efux
cd /
IFS=';' read -ra FOLDER <<< "$FOLDERS"
yes y | borg-job-"$JOB" extract --list "$LOCATION"::"$ARCHIVE_ID" "''${FOLDER[@]}"
'';
job_name=$(echo "$NAME" | ${pkgs.gawk}/bin/awk -F'::' '{print $1}')
backup_name=''${NAME#"$job_name"::}
if ! command -v borg-job-"$job_name" &> /dev/null; then
echo "borg-job-$job_name not found: Backup name is invalid" >&2
exit 1
fi
yes y | borg-job-"$job_name" extract --list "$backup_name" "''${FOLDER[@]}"
'')
];
clanCore.backups.providers.borgbackup = {
list = "borgbackup-list";
create = "borgbackup-create";
restore = "borgbackup-restore";
};
};
}

View File

@@ -0,0 +1,15 @@
Email-based instant messaging for Desktop.
!!! warning "Under construction"
!!! info
This module will automatically configure an email server on the machine for handling the e-mail messaging seamlessly.
## Features
- [x] **Email-based**: Uses any email account as its backend.
- [x] **End-to-End Encryption**: Supports Autocrypt to automatically encrypt messages.
- [x] **No Phone Number Required**: Uses your email address instead of a phone number.
- [x] **Cross-Platform**: Available on desktop and mobile platforms.
- [x] **Automatic Server Setup**: Includes your own DeltaChat server for enhanced control and privacy.
- [ ] **Bake a cake**: This module cannot cake a bake.

View File

@@ -1,12 +1,11 @@
{ config, pkgs, ... }: {
{ config, pkgs, ... }:
{
networking.firewall.interfaces."zt+".allowedTCPPorts = [ 25 ]; # smtp with other hosts
environment.systemPackages = [ pkgs.deltachat-desktop ];
services.maddy =
let
# FIXME move this to public setting
meshname = config.clanCore.secrets.zerotier.facts.zerotier-meshname.value or null;
domain = if meshname == null then "${config.clanCore.machineName}.local" else "${meshname}.vpn";
domain = "${config.clanCore.machineName}.local";
in
{
enable = true;
@@ -136,9 +135,7 @@
storage &local_mailboxes
}
'';
ensureAccounts = [
"user@${domain}"
];
ensureAccounts = [ "user@${domain}" ];
ensureCredentials = {
"user@${domain}".passwordFile = pkgs.writeText "dummy" "foobar";
};

View File

@@ -6,7 +6,10 @@
example = "/dev/disk/by-id/ata-Samsung_SSD_850_EVO_250GB_S21PNXAGB12345";
};
};
config.disko.devices = {
config = {
boot.loader.grub.efiSupport = lib.mkDefault true;
boot.loader.grub.efiInstallAsRemovable = lib.mkDefault true;
disko.devices = {
disk = {
main = {
type = "disk";
@@ -40,5 +43,5 @@
};
};
};
};
}

14
clanModules/ergochat.nix Normal file
View File

@@ -0,0 +1,14 @@
_: {
services.ergochat = {
enable = true;
settings = {
datastore = {
autoupgrade = true;
path = "/var/lib/ergo/ircd.db";
};
};
};
clanCore.state.ergochat.folders = [ "/var/lib/ergo" ];
}

View File

@@ -1,4 +1,5 @@
{ inputs, ... }: {
{ inputs, ... }:
{
flake.clanModules = {
diskLayouts = {
imports = [
@@ -7,13 +8,22 @@
];
};
borgbackup = ./borgbackup.nix;
deltachat = ./deltachat.nix;
moonlight = ./moonlight.nix;
sunshine = ./sunshine.nix;
syncthing = ./syncthing.nix;
xfce = ./xfce.nix;
zt-tcp-relay = ./zt-tcp-relay.nix;
ergochat = ./ergochat.nix;
deltachat = ./deltachat;
graphical = ./graphical.nix;
localbackup = ./localbackup.nix;
localsend = ./localsend.nix;
matrix-synapse = ./matrix-synapse.nix;
moonlight = ./moonlight.nix;
sshd = ./sshd.nix;
sunshine = ./sunshine.nix;
syncthing = ./syncthing;
root-password = ./root-password;
thelounge = ./thelounge.nix;
vm-user = ./vm-user.nix;
waypipe = ./waypipe.nix;
xfce = ./xfce.nix;
xfce-vm = ./xfce-vm.nix;
zt-tcp-relay = ./zt-tcp-relay.nix;
};
}

View File

@@ -0,0 +1 @@
_: { fonts.enableDefaultPackages = true; }

223
clanModules/localbackup.nix Normal file
View File

@@ -0,0 +1,223 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.clan.localbackup;
rsnapshotConfig = target: states: ''
config_version 1.2
snapshot_root ${target.directory}
sync_first 1
cmd_cp ${pkgs.coreutils}/bin/cp
cmd_rm ${pkgs.coreutils}/bin/rm
cmd_rsync ${pkgs.rsync}/bin/rsync
cmd_ssh ${pkgs.openssh}/bin/ssh
cmd_logger ${pkgs.inetutils}/bin/logger
cmd_du ${pkgs.coreutils}/bin/du
cmd_rsnapshot_diff ${pkgs.rsnapshot}/bin/rsnapshot-diff
${lib.optionalString (target.preBackupHook != null) ''
cmd_preexec ${pkgs.writeShellScript "preexec.sh" ''
set -efu -o pipefail
${target.preBackupHook}
''}
''}
${lib.optionalString (target.postBackupHook != null) ''
cmd_postexec ${pkgs.writeShellScript "postexec.sh" ''
set -efu -o pipefail
${target.postBackupHook}
''}
''}
retain snapshot ${builtins.toString config.clan.localbackup.snapshots}
${lib.concatMapStringsSep "\n" (state: ''
${lib.concatMapStringsSep "\n" (folder: ''
backup ${folder} ${config.networking.hostName}/
'') state.folders}
'') states}
'';
in
{
options.clan.localbackup = {
targets = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.strMatching "^[a-zA-Z0-9._-]+$";
default = name;
description = "the name of the backup job";
};
directory = lib.mkOption {
type = lib.types.str;
description = "the directory to backup";
};
mountpoint = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = "mountpoint of the directory to backup. If set, the directory will be mounted before the backup and unmounted afterwards";
};
preMountHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run before the directory is mounted";
};
postMountHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run after the directory is mounted";
};
preUnmountHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run before the directory is unmounted";
};
postUnmountHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run after the directory is unmounted";
};
preBackupHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run before the backup";
};
postBackupHook = lib.mkOption {
type = lib.types.nullOr lib.types.lines;
default = null;
description = "Shell commands to run after the backup";
};
};
}
)
);
default = { };
description = "List of directories where backups are stored";
};
snapshots = lib.mkOption {
type = lib.types.int;
default = 20;
description = "Number of snapshots to keep";
};
};
config =
let
mountHook = target: ''
if [[ -x /run/current-system/sw/bin/localbackup-mount-${target.name} ]]; then
/run/current-system/sw/bin/localbackup-mount-${target.name}
fi
if [[ -x /run/current-system/sw/bin/localbackup-unmount-${target.name} ]]; then
trap "/run/current-system/sw/bin/localbackup-unmount-${target.name}" EXIT
fi
'';
in
lib.mkIf (cfg.targets != { }) {
environment.systemPackages =
[
(pkgs.writeShellScriptBin "localbackup-create" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsnapshot
pkgs.coreutils
pkgs.util-linux
]
}
${lib.concatMapStringsSep "\n" (target: ''
(
${mountHook target}
echo "Creating backup '${target.name}'"
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target (lib.attrValues config.clanCore.state))}" sync
rsnapshot -c "${pkgs.writeText "rsnapshot.conf" (rsnapshotConfig target (lib.attrValues config.clanCore.state))}" snapshot
)
'') (builtins.attrValues cfg.targets)}
'')
(pkgs.writeShellScriptBin "localbackup-list" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.jq
pkgs.findutils
pkgs.coreutils
pkgs.util-linux
]
}
(${
lib.concatMapStringsSep "\n" (target: ''
(
${mountHook target}
find ${lib.escapeShellArg target.directory} -mindepth 1 -maxdepth 1 -name "snapshot.*" -print0 -type d \
| jq -Rs 'split("\u0000") | .[] | select(. != "") | { "name": ("${target.name}::" + .)}'
)
'') (builtins.attrValues cfg.targets)
}) | jq -s .
'')
(pkgs.writeShellScriptBin "localbackup-restore" ''
set -efu -o pipefail
export PATH=${
lib.makeBinPath [
pkgs.rsync
pkgs.coreutils
pkgs.util-linux
pkgs.gawk
]
}
name=$(awk -F'::' '{print $1}' <<< $NAME)
backupname=''${NAME#$name::}
if command -v localbackup-mount-$name; then
localbackup-mount-$name
fi
if command -v localbackup-unmount-$name; then
trap "localbackup-unmount-$name" EXIT
fi
if [[ ! -d $backupname ]]; then
echo "No backup found $backupname"
exit 1
fi
IFS=';' read -ra FOLDER <<< "$FOLDERS"
for folder in "''${FOLDER[@]}"; do
rsync -a "$backupname/${config.networking.hostName}$folder/" "$folder"
done
'')
]
++ (lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-mount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preMountHook != null) target.preMountHook}
${lib.optionalString (target.mountpoint != null) ''
if ! ${pkgs.util-linux}/bin/mountpoint -q ${lib.escapeShellArg target.mountpoint}; then
${pkgs.util-linux}/bin/mount -o X-mount.mkdir ${lib.escapeShellArg target.mountpoint}
fi
''}
${lib.optionalString (target.postMountHook != null) target.postMountHook}
''
) cfg.targets)
++ lib.mapAttrsToList (
name: target:
pkgs.writeShellScriptBin ("localbackup-unmount-" + name) ''
set -efu -o pipefail
${lib.optionalString (target.preUnmountHook != null) target.preUnmountHook}
${lib.optionalString (
target.mountpoint != null
) "${pkgs.util-linux}/bin/umount ${lib.escapeShellArg target.mountpoint}"}
${lib.optionalString (target.postUnmountHook != null) target.postUnmountHook}
''
) cfg.targets;
clanCore.backups.providers.localbackup = {
# TODO list needs to run locally or on the remote machine
list = "localbackup-list";
create = "localbackup-create";
restore = "localbackup-restore";
};
};
}

View File

@@ -1,7 +1,8 @@
{ config
, pkgs
, lib
, ...
{
config,
pkgs,
lib,
...
}:
{
# Integration can be improved, if the following issues get implemented:
@@ -16,10 +17,7 @@
package = lib.mkPackageOption pkgs "localsend" { };
};
imports =
if config.clan.localsend.enable then
[
{
config = lib.mkIf config.clan.localsend.enable {
clanCore.state.localsend.folders = [
"/var/localsend"
config.clan.localsend.defaultLocation
@@ -36,8 +34,5 @@
Address = "192.168.56.2/24";
};
};
}
]
else
[ ];
};
}

View File

@@ -0,0 +1,127 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.clan.matrix-synapse;
in
{
options.clan.matrix-synapse = {
enable = lib.mkEnableOption "Enable matrix-synapse";
domain = lib.mkOption {
type = lib.types.str;
description = "The domain name of the matrix server";
};
};
config = lib.mkIf cfg.enable {
services.matrix-synapse = {
enable = true;
settings = {
server_name = cfg.domain;
database = {
args.user = "matrix-synapse";
args.database = "matrix-synapse";
name = "psycopg2";
};
turn_uris = [
"turn:turn.matrix.org?transport=udp"
"turn:turn.matrix.org?transport=tcp"
];
listeners = [
{
port = 8008;
bind_addresses = [ "::1" ];
type = "http";
tls = false;
x_forwarded = true;
resources = [
{
names = [ "client" ];
compress = true;
}
{
names = [ "federation" ];
compress = false;
}
];
}
];
};
extraConfigFiles = [ "/var/lib/matrix-synapse/registration_shared_secret.yaml" ];
};
systemd.services.matrix-synapse.serviceConfig.ExecStartPre = [
"+${pkgs.writeScript "copy_registration_shared_secret" ''
#!/bin/sh
cp ${config.clanCore.facts.services.matrix-synapse.secret.synapse-registration_shared_secret.path} /var/lib/matrix-synapse/registration_shared_secret.yaml
chown matrix-synapse:matrix-synapse /var/lib/matrix-synapse/registration_shared_secret.yaml
chmod 600 /var/lib/matrix-synapse/registration_shared_secret.yaml
''}"
];
clanCore.facts.services."matrix-synapse" = {
secret."synapse-registration_shared_secret" = { };
generator.path = with pkgs; [
coreutils
pwgen
];
generator.script = ''
echo "registration_shared_secret: $(pwgen -s 32 1)" > "$secrets"/synapse-registration_shared_secret
'';
};
services.postgresql.enable = true;
# we need to use both ensusureDatabases and initialScript, because the former runs everytime but with the wrong collation
services.postgresql = {
ensureDatabases = [ "matrix-synapse" ];
ensureUsers = [
{
name = "matrix-synapse";
ensureDBOwnership = true;
}
];
initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE DATABASE "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
};
services.nginx = {
enable = true;
virtualHosts = {
${cfg.domain} = {
locations."= /.well-known/matrix/server".extraConfig = ''
add_header Content-Type application/json;
return 200 '${builtins.toJSON { "m.server" = "matrix.${cfg.domain}:443"; }}';
'';
locations."= /.well-known/matrix/client".extraConfig = ''
add_header Content-Type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${
builtins.toJSON {
"m.homeserver" = {
"base_url" = "https://matrix.${cfg.domain}";
};
"m.identity_server" = {
"base_url" = "https://vector.im";
};
}
}';
'';
};
"matrix.${cfg.domain}" = {
forceSSL = true;
enableACME = true;
locations."/_matrix" = {
proxyPass = "http://localhost:8008";
};
locations."/test".extraConfig = ''
return 200 "Hello, world!";
'';
};
};
};
};
}

View File

@@ -1,4 +1,86 @@
{ pkgs, ... }: {
{ pkgs, config, ... }:
let
ms-accept = pkgs.callPackage ../pkgs/moonlight-sunshine-accept { };
defaultPort = 48011;
in
{
hardware.opengl.enable = true;
environment.systemPackages = [ pkgs.moonlight-qt ];
environment.systemPackages = [
pkgs.moonlight-qt
ms-accept
];
systemd.tmpfiles.rules = [
"d '/var/lib/moonlight' 0770 'user' 'users' - -"
"C '/var/lib/moonlight/moonlight.cert' 0644 'user' 'users' - ${
config.clanCore.facts.services.moonlight.secret."moonlight.cert".path or ""
}"
"C '/var/lib/moonlight/moonlight.key' 0644 'user' 'users' - ${
config.clanCore.facts.services.moonlight.secret."moonlight.key".path or ""
}"
];
systemd.user.services.init-moonlight = {
enable = false;
description = "Initializes moonlight";
wantedBy = [ "graphical-session.target" ];
script = ''
${ms-accept}/bin/moonlight-sunshine-accept moonlight init-config --key /var/lib/moonlight/moonlight.key --cert /var/lib/moonlight/moonlight.cert
'';
serviceConfig = {
user = "user";
Type = "oneshot";
WorkingDirectory = "/home/user/";
RunTimeDirectory = "moonlight";
TimeoutSec = "infinity";
Restart = "on-failure";
RemainAfterExit = true;
ReadOnlyPaths = [
"/var/lib/moonlight/moonlight.key"
"/var/lib/moonlight/moonlight.cert"
];
};
};
systemd.user.services.moonlight-join = {
description = "Join sunshine hosts";
script = ''${ms-accept}/bin/moonlight-sunshine-accept moonlight join --port ${builtins.toString defaultPort} --cert '${
config.clanCore.facts.services.moonlight.public."moonlight.cert".value or ""
}' --host fd2e:25da:6035:c98f:cd99:93e0:b9b8:9ca1'';
serviceConfig = {
Type = "oneshot";
TimeoutSec = "infinity";
Restart = "on-failure";
ReadOnlyPaths = [
"/var/lib/moonlight/moonlight.key"
"/var/lib/moonlight/moonlight.cert"
];
};
};
systemd.user.timers.moonlight-join = {
description = "Join sunshine hosts";
wantedBy = [ "timers.target" ];
timerConfig = {
OnUnitActiveSec = "5min";
OnBootSec = "0min";
Persistent = true;
Unit = "moonlight-join.service";
};
};
clanCore.facts.services.moonlight = {
secret."moonlight.key" = { };
secret."moonlight.cert" = { };
public."moonlight.cert" = { };
generator.path = [
pkgs.coreutils
ms-accept
];
generator.script = ''
moonlight-sunshine-accept moonlight init
mv credentials/cakey.pem "$secrets"/moonlight.key
cp credentials/cacert.pem "$secrets"/moonlight.cert
mv credentials/cacert.pem "$facts"/moonlight.cert
'';
};
}

View File

@@ -0,0 +1,13 @@
Creates a root-password
!!! tip "This module sets the password for the root user (automatically)."
After the system was installed/deployed the following command can be used to display the root-password:
```bash
clan secrets get {machine_name}-password
```
---
See also: [Facts / Secrets](../../getting-started/secrets.md)

View File

@@ -0,0 +1,20 @@
{ pkgs, config, ... }:
{
users.mutableUsers = false;
users.users.root.hashedPasswordFile =
config.clanCore.facts.services.root-password.secret.password-hash.path;
sops.secrets."${config.clanCore.machineName}-password-hash".neededForUsers = true;
clanCore.facts.services.root-password = {
secret.password = { };
secret.password-hash = { };
generator.path = with pkgs; [
coreutils
xkcdpass
mkpasswd
];
generator.script = ''
xkcdpass --numwords 3 --delimiter - --count 1 > $secrets/password
cat $secrets/password | mkpasswd -s -m sha-512 > $secrets/password-hash
'';
};
}

24
clanModules/sshd.nix Normal file
View File

@@ -0,0 +1,24 @@
{ config, pkgs, ... }:
{
services.openssh.enable = true;
services.openssh.hostKeys = [
{
path = config.clanCore.facts.services.openssh.secret."ssh.id_ed25519".path;
type = "ed25519";
}
];
clanCore.facts.services.openssh = {
secret."ssh.id_ed25519" = { };
public."ssh.id_ed25519.pub" = { };
generator.path = [
pkgs.coreutils
pkgs.openssh
];
generator.script = ''
ssh-keygen -t ed25519 -N "" -f $secrets/ssh.id_ed25519
mv $secrets/ssh.id_ed25519.pub $facts/ssh.id_ed25519.pub
'';
};
}

View File

@@ -1,4 +1,21 @@
{ pkgs, config, ... }:
{
pkgs,
config,
lib,
...
}:
let
ms-accept = pkgs.callPackage ../pkgs/moonlight-sunshine-accept { };
sunshineConfiguration = pkgs.writeText "sunshine.conf" ''
address_family = both
channels = 5
pkey = /var/lib/sunshine/sunshine.key
cert = /var/lib/sunshine/sunshine.cert
file_state = /var/lib/sunshine/state.json
credentials_file = /var/lib/sunshine/credentials.json
'';
listenPort = 48011;
in
{
networking.firewall = {
allowedTCPPorts = [
@@ -6,6 +23,7 @@
47989
47990
48010
48011
];
allowedUDPPorts = [
@@ -29,81 +47,161 @@
to = 48010;
}
];
networking.firewall.interfaces."zt+".allowedTCPPorts = [
47984
47989
47990
48010
listenPort
];
networking.firewall.interfaces."zt+".allowedUDPPortRanges = [
{
from = 47998;
to = 48010;
}
];
environment.systemPackages = [
ms-accept
pkgs.sunshine
pkgs.avahi
# Convenience script, until we find a better UX
(pkgs.writers.writeDashBin "sun" ''
${pkgs.sunshine}/bin/sunshine -1 ${
pkgs.writeText "sunshine.conf" ''
address_family = both
''
} "$@"
${pkgs.sunshine}/bin/sunshine -0 ${sunshineConfiguration} "$@"
'')
# Create a dummy account, for easier setup,
# don't use this account in actual production yet.
(pkgs.writers.writeDashBin "init-sun" ''
${pkgs.sunshine}/bin/sunshine \
--creds "sun" "sun"
--creds "sunshine" "sunshine"
'')
];
# Required to simulate input
boot.kernelModules = [ "uinput" ];
security.rtkit.enable = true;
# services.udev.extraRules = ''
# KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"
# '';
services.udev.extraRules = ''
KERNEL=="uinput", GROUP="input", MODE="0660" OPTIONS+="static_node=uinput"
KERNEL=="uinput", SUBSYSTEM=="misc", OPTIONS+="static_node=uinput", TAG+="uaccess"
'';
security.wrappers.sunshine = {
security = {
rtkit.enable = true;
wrappers.sunshine = {
owner = "root";
group = "root";
capabilities = "cap_sys_admin+p";
source = "${pkgs.sunshine}/bin/sunshine";
};
};
systemd.tmpfiles.rules = [
"d '/var/lib/sunshine' 0770 'user' 'users' - -"
"C '/var/lib/sunshine/sunshine.cert' 0644 'user' 'users' - ${
config.clanCore.facts.services.sunshine.secret."sunshine.cert".path or ""
}"
"C '/var/lib/sunshine/sunshine.key' 0644 'user' 'users' - ${
config.clanCore.facts.services.sunshine.secret."sunshine.key".path or ""
}"
];
hardware.opengl.enable = true;
systemd.user.services.sunshine = {
description = "sunshine";
wantedBy = [ "graphical-session.target" ];
environment = {
DISPLAY = ":0";
};
enable = true;
description = "Sunshine self-hosted game stream host for Moonlight";
startLimitBurst = 5;
startLimitIntervalSec = 500;
script = "/run/current-system/sw/bin/env /run/wrappers/bin/sunshine ${sunshineConfiguration}";
serviceConfig = {
ExecStart = "${config.security.wrapperDir}/sunshine";
Restart = "on-failure";
RestartSec = "5s";
ReadWritePaths = [ "/var/lib/sunshine" ];
ReadOnlyPaths = [
(config.clanCore.facts.services.sunshine.secret."sunshine.key".path or "")
(config.clanCore.facts.services.sunshine.secret."sunshine.cert".path or "")
];
};
wantedBy = [ "graphical-session.target" ];
partOf = [ "graphical-session.target" ];
wants = [ "graphical-session.target" ];
after = [
"sunshine-init-state.service"
"sunshine-init-credentials.service"
];
};
# xdg.configFile."sunshine/apps.json".text = builtins.toJSON {
# env = "/run/current-system/sw/bin";
# apps = [
# {
# name = "Steam";
# output = "steam.txt";
# detached = [
# "${pkgs.util-linux}/bin/setsid ${pkgs.steam}/bin/steam steam://open/bigpicture"
# ];
# image-path = "steam.png";
# }
# ];
# };
systemd.user.services.sunshine-init-state = {
enable = true;
description = "Sunshine self-hosted game stream host for Moonlight";
startLimitBurst = 5;
startLimitIntervalSec = 500;
script = ''
${ms-accept}/bin/moonlight-sunshine-accept sunshine init-state --uuid ${
config.clanCore.facts.services.sunshine.public.sunshine-uuid.value or null
} --state-file /var/lib/sunshine/state.json
'';
serviceConfig = {
Restart = "on-failure";
RestartSec = "5s";
Type = "oneshot";
ReadWritePaths = [ "/var/lib/sunshine" ];
};
wantedBy = [ "graphical-session.target" ];
};
services = {
avahi = {
systemd.user.services.sunshine-init-credentials = {
enable = true;
reflector = true;
nssmdns = true;
publish = {
description = "Sunshine self-hosted game stream host for Moonlight";
startLimitBurst = 5;
startLimitIntervalSec = 500;
script = ''
${lib.getExe pkgs.sunshine} ${sunshineConfiguration} --creds sunshine sunshine
'';
serviceConfig = {
Restart = "on-failure";
RestartSec = "5s";
Type = "oneshot";
ReadWritePaths = [ "/var/lib/sunshine" ];
};
wantedBy = [ "graphical-session.target" ];
};
systemd.user.services.sunshine-listener = {
enable = true;
addresses = true;
userServices = true;
workstation = true;
description = "Sunshine self-hosted game stream host for Moonlight";
startLimitBurst = 5;
startLimitIntervalSec = 500;
script = ''
${ms-accept}/bin/moonlight-sunshine-accept sunshine listen --port ${builtins.toString listenPort} --uuid ${
config.clanCore.facts.services.sunshine.public.sunshine-uuid.value or null
} --state /var/lib/sunshine/state.json --cert '${
config.clanCore.facts.services.sunshine.public."sunshine.cert".value or null
}'
'';
serviceConfig = {
# );
Restart = "on-failure";
RestartSec = 5;
ReadWritePaths = [ "/var/lib/sunshine" ];
};
wantedBy = [ "graphical-session.target" ];
};
clanCore.facts.services.ergochat = {
secret."sunshine.key" = { };
secret."sunshine.cert" = { };
public."sunshine-uuid" = { };
public."sunshine.cert" = { };
generator.path = [
pkgs.coreutils
ms-accept
];
generator.script = ''
moonlight-sunshine-accept sunshine init
mv credentials/cakey.pem "$secrets"/sunshine.key
cp credentials/cacert.pem "$secrets"/sunshine.cert
mv credentials/cacert.pem "$facts"/sunshine.cert
mv uuid "$facts"/sunshine-uuid
'';
};
}

View File

@@ -0,0 +1,34 @@
Syncthing is a free, open-source file synchronization application designed to allow users to synchronize files between multiple devices over the internet or local networks securely and privately.
It is an alternative to cloud-based file sharing services.
## Usage
We recommend configuring this module as an sync-service through the provided options. Although it provides a Web GUI through which more usage scenarios are supported.
## Features
- **Private and Secure**: Syncthing uses TLS encryption to secure data transfer between devices, ensuring that only the intended devices can read your data.
- **Decentralized**: No central server is involved in the data transfer. Each device communicates directly with others.
- **Open Source**: The source code is openly available for audit and contribution, fostering trust and continuous improvement.
- **Cross-Platform**: Syncthing supports multiple platforms including Windows, macOS, Linux, BSD, and Android.
- **Real-time Synchronization**: Changes made to files are synchronized in real-time across all connected devices.
- **Web GUI**: It includes a user-friendly web interface for managing devices and configurations. (`127.0.0.1:8384`)
## Configuration
- **Share Folders**: Select folders to share with connected devices and configure permissions and synchronization parameters.
!!! info
Clan automatically discovers other devices. Automatic discovery requires one machine to be an [introducer](#clan.syncthing.introducer)
If that is not the case you can add the other device by its Device ID manually.
You can find and share Device IDs under the "Add Device" button in the Web GUI. (`127.0.0.1:8384`)
## Troubleshooting
- **Sync Conflicts**: Resolve synchronization conflicts manually by reviewing file versions and modification times in the Web GUI (`127.0.0.1:8384`).
## Support
- **Documentation**: Extensive documentation is available on the [Syncthing website](https://docs.syncthing.net/).

View File

@@ -1,14 +1,16 @@
{ config
, pkgs
, lib
, ...
{
config,
pkgs,
lib,
...
}:
{
options.clan.syncthing = {
id = lib.mkOption {
type = lib.types.nullOr lib.types.str;
example = "BABNJY4-G2ICDLF-QQEG7DD-N3OBNGF-BCCOFK6-MV3K7QJ-2WUZHXS-7DTW4AS";
default = config.clanCore.secrets.syncthing.facts."syncthing.pub".value or null;
default = config.clanCore.facts.services.syncthing.public."syncthing.pub".value or null;
defaultText = "config.clanCore.facts.services.syncthing.public.\"syncthing.pub\".value";
};
introducer = lib.mkOption {
description = ''
@@ -53,17 +55,19 @@
assertions = [
{
assertion =
lib.all (attr: builtins.hasAttr attr config.services.syncthing.settings.folders)
config.clan.syncthing.autoShares;
assertion = lib.all (
attr: builtins.hasAttr attr config.services.syncthing.settings.folders
) config.clan.syncthing.autoShares;
message = ''
Syncthing: If you want to AutoShare a folder, you need to have it configured on the sharing device.
'';
}
];
# Activates inofify compatibilty on syncthing
boot.kernel.sysctl."fs.inotify.max_user_watches" = lib.mkDefault 524288;
# Activates inotify compatibility on syncthing
# use mkOverride 900 here as it otherwise would collide with the default of the
# upstream nixos xserver.nix
boot.kernel.sysctl."fs.inotify.max_user_watches" = lib.mkOverride 900 524288;
services.syncthing = {
enable = true;
@@ -80,12 +84,8 @@
group = "syncthing";
key =
lib.mkDefault
config.clan.secrets.syncthing.secrets."syncthing.key".path or null;
cert =
lib.mkDefault
config.clan.secrets.syncthing.secrets."syncthing.cert".path or null;
key = lib.mkDefault config.clan.secrets.syncthing.secrets."syncthing.key".path or null;
cert = lib.mkDefault config.clan.secrets.syncthing.secrets."syncthing.cert".path or null;
settings = {
options = {
@@ -115,7 +115,7 @@
getPendingDevices = "/rest/cluster/pending/devices";
postNewDevice = "/rest/config/devices";
SharedFolderById = "/rest/config/folders/";
apiKey = config.clanCore.secrets.syncthing.secrets."syncthing.api".path or null;
apiKey = config.clanCore.facts.services.syncthing.secret."syncthing.api".path or null;
in
lib.mkIf config.clan.syncthing.autoAcceptDevices {
description = "Syncthing auto accept devices";
@@ -127,38 +127,24 @@
set -x
# query pending deviceID's
APIKEY=$(cat ${apiKey})
PENDING=$(${
lib.getExe pkgs.curl
} -X GET -H "X-API-Key: $APIKEY" ${baseAddress}${getPendingDevices})
PENDING=$(${lib.getExe pkgs.curl} -X GET -H "X-API-Key: $APIKEY" ${baseAddress}${getPendingDevices})
PENDING=$(echo $PENDING | ${lib.getExe pkgs.jq} keys[])
# accept pending deviceID's
for ID in $PENDING;do
${
lib.getExe pkgs.curl
} -X POST -d "{\"deviceId\": $ID}" -H "Content-Type: application/json" -H "X-API-Key: $APIKEY" ${baseAddress}${postNewDevice}
${lib.getExe pkgs.curl} -X POST -d "{\"deviceId\": $ID}" -H "Content-Type: application/json" -H "X-API-Key: $APIKEY" ${baseAddress}${postNewDevice}
# get all shared folders by their ID
for folder in ${builtins.toString config.clan.syncthing.autoShares}; do
SHARED_IDS=$(${
lib.getExe pkgs.curl
} -X GET -H "X-API-Key: $APIKEY" ${baseAddress}${SharedFolderById}"$folder" | ${
lib.getExe pkgs.jq
} ."devices")
PATCHED_IDS=$(echo $SHARED_IDS | ${
lib.getExe pkgs.jq
} ".+= [{\"deviceID\": $ID, \"introducedBy\": \"\", \"encryptionPassword\": \"\"}]")
${
lib.getExe pkgs.curl
} -X PATCH -d "{\"devices\": $PATCHED_IDS}" -H "X-API-Key: $APIKEY" ${baseAddress}${SharedFolderById}"$folder"
SHARED_IDS=$(${lib.getExe pkgs.curl} -X GET -H "X-API-Key: $APIKEY" ${baseAddress}${SharedFolderById}"$folder" | ${lib.getExe pkgs.jq} ."devices")
PATCHED_IDS=$(echo $SHARED_IDS | ${lib.getExe pkgs.jq} ".+= [{\"deviceID\": $ID, \"introducedBy\": \"\", \"encryptionPassword\": \"\"}]")
${lib.getExe pkgs.curl} -X PATCH -d "{\"devices\": $PATCHED_IDS}" -H "X-API-Key: $APIKEY" ${baseAddress}${SharedFolderById}"$folder"
done
done
'';
};
systemd.timers.syncthing-auto-accept =
lib.mkIf config.clan.syncthing.autoAcceptDevices
{
systemd.timers.syncthing-auto-accept = lib.mkIf config.clan.syncthing.autoAcceptDevices {
description = "Syncthing Auto Accept";
wantedBy = [ "syncthing-auto-accept.service" ];
@@ -171,7 +157,7 @@
systemd.services.syncthing-init-api-key =
let
apiKey = config.clanCore.secrets.syncthing.secrets."syncthing.api".path or null;
apiKey = config.clanCore.facts.services.syncthing.secret."syncthing.api".path or null;
in
lib.mkIf config.clan.syncthing.autoAcceptDevices {
description = "Set the api key";
@@ -182,9 +168,7 @@
set -efu pipefail
APIKEY=$(cat ${apiKey})
${
lib.getExe pkgs.gnused
} -i "s/<apikey>.*<\/apikey>/<apikey>$APIKEY<\/apikey>/" /var/lib/syncthing/config.xml
${lib.getExe pkgs.gnused} -i "s/<apikey>.*<\/apikey>/<apikey>$APIKEY<\/apikey>/" /var/lib/syncthing/config.xml
# sudo systemctl restart syncthing.service
systemctl restart syncthing.service
'';
@@ -195,11 +179,11 @@
};
};
clanCore.secrets.syncthing = {
secrets."syncthing.key" = { };
secrets."syncthing.cert" = { };
secrets."syncthing.api" = { };
facts."syncthing.pub" = { };
clanCore.facts.services.syncthing = {
secret."syncthing.key" = { };
secret."syncthing.cert" = { };
secret."syncthing.api" = { };
public."syncthing.pub" = { };
generator.path = [
pkgs.coreutils
pkgs.gnugrep

15
clanModules/thelounge.nix Normal file
View File

@@ -0,0 +1,15 @@
_: {
services.thelounge = {
enable = true;
public = true;
extraConfig = {
prefetch = true;
defaults = {
port = 6667;
tls = false;
};
};
};
clanCore.state.thelounde.folders = [ "/var/lib/thelounge" ];
}

20
clanModules/vm-user.nix Normal file
View File

@@ -0,0 +1,20 @@
{
security = {
sudo.wheelNeedsPassword = false;
polkit.enable = true;
rtkit.enable = true;
};
users.users.user = {
isNormalUser = true;
createHome = true;
uid = 1000;
initialHashedPassword = "";
extraGroups = [
"wheel"
"video"
"render"
];
shell = "/run/current-system/sw/bin/bash";
};
}

View File

@@ -1,7 +1,8 @@
{ pkgs
, lib
, config
, ...
{
pkgs,
lib,
config,
...
}:
{
options.clan.services.waypipe = {
@@ -49,7 +50,10 @@
isNormalUser = true;
uid = 1000;
password = "";
extraGroups = [ "wheel" "video" ];
extraGroups = [
"wheel"
"video"
];
shell = "/run/current-system/sw/bin/bash";
};
@@ -64,7 +68,7 @@
SDL_VIDEODRIVER=wayland
'';
script = ''
${lib.getExe config.clanCore.clanPkgs.waypipe} \
${lib.getExe pkgs.waypipe} \
${lib.escapeShellArgs config.clan.services.waypipe.flags} \
${lib.escapeShellArgs config.clan.services.waypipe.command}
'';

15
clanModules/xfce-vm.nix Normal file
View File

@@ -0,0 +1,15 @@
{
imports = [
./vm-user.nix
./graphical.nix
];
services.xserver = {
enable = true;
displayManager.autoLogin.enable = true;
displayManager.autoLogin.user = "user";
desktopManager.xfce.enable = true;
desktopManager.xfce.enableScreensaver = false;
xkb.layout = "us";
};
}

View File

@@ -1,4 +1,10 @@
{ pkgs, lib, config, ... }: {
{
pkgs,
lib,
config,
...
}:
{
options.clan.zt-tcp-relay = {
port = lib.mkOption {
type = lib.types.port;
@@ -13,7 +19,9 @@
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
serviceConfig = {
ExecStart = "${pkgs.callPackage ../pkgs/zt-tcp-relay {}}/bin/zt-tcp-relay --listen [::]:${builtins.toString config.clan.zt-tcp-relay.port}";
ExecStart = "${
pkgs.callPackage ../pkgs/zt-tcp-relay { }
}/bin/zt-tcp-relay --listen [::]:${builtins.toString config.clan.zt-tcp-relay.port}";
Restart = "always";
RestartSec = "5";
dynamicUsers = true;

View File

@@ -1,13 +1,32 @@
{
perSystem =
{ pkgs
, self'
, config
, ...
}: {
{
pkgs,
self',
config,
...
}:
let
writers = pkgs.callPackage ./pkgs/builders/script-writers.nix { };
ansiEscapes = {
reset = ''\033[0m'';
green = ''\033[32m'';
};
# A python program to switch between dev-shells
# usage: select-shell shell-name
# the currently enabled dev-shell gets stored in ./.direnv/selected-shell
select-shell = writers.writePython3Bin "select-shell" {
flakeIgnore = [ "E501" ];
} ./pkgs/scripts/select-shell.py;
in
{
devShells.default = pkgs.mkShell {
packages = [
select-shell
pkgs.tea
pkgs.nix
self'.packages.tea-create-pr
self'.packages.merge-after-ci
self'.packages.pending-reviews
@@ -17,6 +36,8 @@
shellHook = ''
# no longer used
rm -f "$(git rev-parse --show-toplevel)/.git/hooks/pre-commit"
echo -e "${ansiEscapes.green}switch to another dev-shell using: select-shell${ansiEscapes.reset}"
'';
};
};

6
docs/.envrc Normal file
View File

@@ -0,0 +1,6 @@
source_up
watch_file $(find ./nix -name "*.nix" -printf '"%p" ')
# Because we depend on nixpkgs sources, uploading to builders takes a long time
use flake .#docs --builders ''

1
docs/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/site/reference

View File

@@ -1,10 +1,6 @@
# Contributing
**Frontend**: Our frontend is powered by [React NextJS](https://nextjs.org/), a popular and versatile framework for building web applications.
**Backend**: For the backend, we use Python along with the [FastAPI framework](https://fastapi.tiangolo.com/). To ensure seamless communication between the frontend and backend, we generate an `openapi.json` file from the Python code, which defines the REST API. This file is then used with [Orval](https://orval.dev/) to generate TypeScript bindings for the REST API. We're committed to code correctness, so we use [mypy](https://mypy-lang.org/) to ensure that our Python code is statically typed correctly. For backend testing, we rely on [pytest](https://docs.pytest.org/en/7.4.x/).
**Continuous Integration (CI)**: We've set up a CI bot that rigorously checks your code using the quality assurance (QA) tools mentioned above. If any errors are detected, it will block pull requests until they're resolved.
**Continuous Integration (CI)**: Each pull request gets automatically tested by gitea. If any errors are detected, it will block pull requests until they're resolved.
**Dependency Management**: We use the [Nix package manager](https://nixos.org/) to manage dependencies and ensure reproducibility, making your development process more robust.
@@ -34,7 +30,7 @@ Let's get your development environment up and running:
3. **Add direnv to your shell**:
- Direnv needs to [hook into your shell](https://direnv.net/docs/hook.html) to work.
You can do this by executing following command:
You can do this by executing following command. The example below will setup direnv for `zsh` and `bash`
```bash
echo 'eval "$(direnv hook zsh)"' >> ~/.zshrc && echo 'eval "$(direnv hook bash)"' >> ~/.bashrc && eval "$SHELL"
@@ -52,39 +48,6 @@ Let's get your development environment up and running:
```
- Execute `direnv allow` to automatically execute the shell script `.envrc` when entering the directory.
6. **Build the Backend**:
- Go to the `pkgs/clan-cli` directory and execute:
```bash
direnv allow
```
- Wait for the backend to build.
7. **Start the Backend Server**:
- To start the backend server, execute:
```bash
clan webui --reload --no-open --log-level debug
```
- The server will automatically restart if any Python files change.
8. **Build the Frontend**:
- In a different shell, navigate to the `pkgs/ui` directory and execute:
```bash
direnv allow
```
- Wait for the frontend to build.
NOTE: If you have the error "@clan/colors.json" you executed `npm install`, please do not do that. `direnv reload` will handle dependency management. Please delete node_modules with `rm -rf node_modules`.
9. **Start the Frontend**:
- To start the frontend, execute:
```bash
npm run dev
```
- Access the website by going to [http://localhost:3000](http://localhost:3000).
# Setting Up Your Git Workflow
Let's set up your Git workflow to collaborate effectively:
@@ -96,7 +59,7 @@ Let's set up your Git workflow to collaborate effectively:
tea login add
```
- Fill out the prompt as follows:
- URL of Gitea instance: `https://gitea.gchq.icu`
- URL of Gitea instance: `https://git.clan.lol`
- Name of new Login [gitea.gchq.icu]: `gitea.gchq.icu:7171`
- Do you have an access token? No
- Username: YourUsername
@@ -125,7 +88,7 @@ Let's set up your Git workflow to collaborate effectively:
4. **Review Your Pull Request**:
- Visit https://gitea.gchq.icu and go to the project page. Check under "Pull Requests" for any issues with your pull request.
- Visit https://git.clan.lol and go to the project page. Check under "Pull Requests" for any issues with your pull request.
5. **Push Your Changes**:
- If there are issues, fix them and redo step 2. Afterward, execute:
@@ -136,21 +99,22 @@ Let's set up your Git workflow to collaborate effectively:
# Debugging
When working on the backend of your project, debugging is an essential part of the development process. Here are some methods for debugging and testing the backend of your application:
Here are some methods for debugging and testing the clan-cli:
## Test Backend Locally in Devshell with Breakpoints
## Test Locally in Devshell with Breakpoints
To test the backend locally in a development environment and set breakpoints for debugging, follow these steps:
To test the cli locally in a development environment and set breakpoints for debugging, follow these steps:
1. Run the following command to execute your tests and allow for debugging with breakpoints:
```bash
pytest -n0 -s --maxfail=1
cd ./pkgs/clan-cli
pytest -n0 -s --maxfail=1 ./tests/test_nameofthetest.py
```
You can place `breakpoint()` in your Python code where you want to trigger a breakpoint for debugging.
## Test Backend Locally in a Nix Sandbox
## Test Locally in a Nix Sandbox
To run your backend tests in a Nix sandbox, you have two options depending on whether your test functions have been marked as impure or not:
To run tests in a Nix sandbox, you have two options depending on whether your test functions have been marked as impure or not:
### Running Tests Marked as Impure
@@ -190,28 +154,8 @@ If you need to inspect the Nix sandbox while running tests, follow these steps:
psgrep -a -x your_python_process_name
```
These debugging and testing methods will help you identify and fix issues in your backend code efficiently, ensuring the reliability and robustness of your application.
For more information on testing read [property and contract based testing](testing.md)
# Standards
# Using this Template
To make the most of this template:
1. Set up a new Gitea account named `ui-asset-bot`. Generate an access token with all access permissions and set it under `settings/actions/secrets` as a secret called `BOT_ACCESS_TOKEN`.
- Also, edit the file `.gitea/workflows/ui_assets.yaml` and change the `BOT_EMAIL` variable to match the email you set for that account. Gitea matches commits to accounts by their email address, so this step is essential.
2. Create a second Gitea account named `merge-bot`. Edit the file `pkgs/merge-after-ci/default.nix` if the name should be different. Under "Branches," set the main branch to be protected and add `merge-bot` to the whitelisted users for pushing. Set the unprotected file pattern to `**/ui-assets.nix`.
- Enable the status check for "build / test (pull_request)."
3. Add both `merge-bot` and `ui-asset-bot` as collaborators.
- Set the option to "Delete pull request branch after merge by default."
- Also, set the default merge style to "Rebase then create merge commit."
With this template, you're well-equipped to build and collaborate on high-quality websites efficiently. Happy coding!.
# API guidelines
see [./api-guidelines](./api-guidelines)
Every new module name should be in kebab-case.
Every fact definition, where possible should be in kebab-case.

View File

@@ -1,10 +0,0 @@
+++
title = "Admin Documentation"
description = "Documentation administrators creating or managing cLANs"
date = 2025-05-01T19:00:00+00:00
updated = 2021-05-01T19:00:00+00:00
template = "docs/section.html"
weight = 15
sort_by = "title"
draft = false
+++

View File

@@ -1,69 +0,0 @@
# cLAN config
`clan config` allows you to manage your nixos configuration via the terminal.
Similar as how `git config` reads and sets git options, `clan config` does the same with your nixos options
It also supports auto completion making it easy to find the right options.
## Set up clan-config
Add the clan tool to your flake inputs:
```
clan.url = "git+https://git.clan.lol/clan/clan-core";
```
and inside the mkFlake:
```
imports = [
inputs.clan.flakeModules.clan-config
];
```
Add an empty config file and add it to git
```command
echo "{}" > ./clan-settings.json
git add ./clan-settings.json
```
Import the clan-config module into your nixos configuration:
```nix
{
imports = [
# clan-settings.json is located in the same directory as your flake.
# Adapt the path if necessary.
(builtins.fromJSON (builtins.readFile ./clan-settings.json))
];
}
```
Make sure your nixos configuration is set a default
```nix
{self, ...}: {
flake.nixosConfigurations.default = self.nixosConfigurations.my-machine;
}
```
Use all inputs provided by the clan-config devShell in your own devShell:
```nix
{ ... }: {
perSystem = { pkgs, self', ... }: {
devShells.default = pkgs.mkShell {
inputsFrom = [ self'.devShells.clan-config ];
# ...
};
};
}
```
re-load your dev-shell to make the clan tool available.
```command
clan config --help
```

View File

@@ -1,138 +0,0 @@
# Managing NixOS Machines
## Add Your First Machine
To start managing a new machine, use the following commands to create and then list your machines:
```shellSession
$ clan machines create my-machine
$ clan machines list
my-machine
```
## Configure Your Machine
In the example below, we demonstrate how to add a new user named `my-user` and set a password. This user will be configured to log in to the machine `my-machine`.
### Creating a New User
```shellSession
# Add a new user
$ clan config --machine my-machine users.users.my-user.isNormalUser true
# Set a password for the user
$ clan config --machine my-machine users.users.my-user.hashedPassword $(mkpasswd)
```
_Note: The `$(mkpasswd)` command generates a hashed password. Ensure you have the `mkpasswd` utility installed or use an alternative method to generate a secure hashed password._
## Test Your Machine Configuration Inside a VM
Before deploying your configuration to a live environment, you can run a virtual machine (VM) to test the settings:
```shellSession
$ clan vms run my-machine
```
This command run a VM based on the configuration of `my-machine`, allowing you to verify changes in a controlled environment.
## Installing a New Machine
Clan CLI, in conjunction with [nixos-anywhere](https://github.com/nix-community/nixos-anywhere), provides a seamless method for installing NixOS on various machines.
This process involves preparing a suitable hardware and disk partitioning configuration and ensuring the target machine is accessible via SSH.
### Prerequisites
- A running Linux system with SSH on the target machine is required. This is typically pre-configured for many server providers.
- For installations on physical hardware, create a NixOS installer image and transfer it to a bootable USB drive as described below.
## Creating a Bootable USB Drive on Linux
To create a bootable USB flash drive with the NixOS installer:
1. **Build the Installer Image**:
```shellSession
$ nix build git+https://git.clan.lol/clan/clan-core.git#install-iso
```
2. **Prepare the USB Flash Drive**:
- Insert your USB flash drive into your computer.
- Identify your flash drive with `lsblk`. Look for the device with a matching size.
- Ensure all partitions on the drive are unmounted. Replace `sdX` in the command below with your device identifier (like `sdb`, etc.):
```shellSession
sudo umount /dev/sdX*
```
3. **Write the Image to the USB Drive**:
- Use the `dd` utility to write the NixOS installer image to your USB drive:
```shellSession
sudo dd bs=4M conv=fsync oflag=direct status=progress if=./result/stick.raw of=/dev/sdX
```
4. **Boot and Connect**:
- After writing the installer to the USB drive, use it to boot the target machine.
- The installer will display an IP address and a root password, which you can use to connect via SSH.
### Finishing the installation
With the target machine running Linux and accessible via SSH, execute the following command to install NixOS on the target machine, replacing `<target_host>` with the machine's hostname or IP address:
```shellSession
$ clan machines install my-machine <target_host>
```
## Update Your Machines
Clan CLI enables you to remotely update your machines over SSH. This requires setting up a target address for each target machine.
### Setting the Target Host
Replace `host_or_ip` with the actual hostname or IP address of your target machine:
```shellSession
$ clan config --machine my-machine clan.networking.targetHost root@host_or_ip
```
_Note: The use of `root@` in the target address implies SSH access as the root user.
Ensure that the root login is secured and only used when necessary._
### Updating Machine Configurations
Execute the following command to update the specified machine:
```shellSession
$ clan machines update my-machine
```
You can also update all configured machines simultaneously by omitting the machine name:
```shellSession
$ clan machines update
```
### Setting a Build Host
If the machine does not have enough resources to run the NixOS evaluation or build itself,
it is also possible to specify a build host instead.
During an update, the cli will ssh into the build host and run `nixos-rebuild` from there.
```shellSession
$ clan config --machine my-machine clan.networking.buildHost root@host_or_ip
```
### Excluding a machine from `clan machine update`
To exclude machines from beeing updated when running `clan machines update` without any machines specified,
one can set the `clan.deployment.requireExplicitUpdate` option to true:
```shellSession
$ clan config --machine my-machine clan.deployment.requireExplicitUpdate true
```
This is useful for machines that are not always online or are not part of the regular update cycle.

View File

@@ -1,135 +0,0 @@
# Initializing a New Clan Project
## Create a new flake
1. To start a new project, execute the following command to add the clan cli to your shell:
```shellSession
$ nix shell git+https://git.clan.lol/clan/clan-core
```
2. Then use the following commands to initialize a new clan-flake:
```shellSession
$ clan flake create my-clan
```
This action will generate two primary files: `flake.nix` and `.clan-flake`.
```shellSession
$ ls -la
drwx------ joerg users 5 B a minute ago ./
drwxrwxrwt root root 139 B 12 seconds ago ../
.rw-r--r-- joerg users 77 B a minute ago .clan-flake
.rw-r--r-- joerg users 4.8 KB a minute ago flake.lock
.rw-r--r-- joerg users 242 B a minute ago flake.nix
```
### Understanding the .clan-flake Marker File
The `.clan-flake` marker file serves an optional purpose: it helps the `clan-cli` utility locate the project's root directory.
If `.clan-flake` is missing, `clan-cli` will instead search for other indicators like `.git`, `.hg`, `.svn`, or `flake.nix` to identify the project root.
## What's next
After creating your flake, you can check out how to add [new machines](./machines.md)
---
# Migrating Existing NixOS Configuration Flake
Absolutely, let's break down the migration step by step, explaining each action in detail:
#### Before You Begin
1. **Backup Your Current Configuration**: Always start by making a backup of your current NixOS configuration to ensure you can revert if needed.
```shellSession
$ cp -r /etc/nixos ~/nixos-backup
```
2. **Update Flake Inputs**: Add a new input for the `clan-core` dependency:
```nix
inputs.clan-core = {
url = "git+https://git.clan.lol/clan/clan-core";
# Don't do this if your machines are on nixpkgs stable.
inputs.nixpkgs.follows = "nixpkgs";
};
```
- `url`: Specifies the Git repository URL for Clan Core.
- `inputs.nixpkgs.follows`: Tells Nix to use the same `nixpkgs` input as your main input (in this case, it follows `nixpkgs`).
3. **Update Outputs**: Then modify the `outputs` section of your `flake.nix` to adapt to Clan Core's new provisioning method. The key changes are as follows:
Add `clan-core` to the output
```diff
- outputs = { self, nixpkgs, }:
+ outputs = { self, nixpkgs, clan-core }:
```
Previous configuration:
```nix
{
nixosConfigurations.example-desktop = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
./configuration.nix
];
[...]
};
}
```
After change:
```nix
let clan = clan-core.lib.buildClan {
# this needs to point at the repository root
directory = self;
specialArgs = {};
clanName = "NEEDS_TO_BE_UNIQUE"; # TODO: Changeme
machines = {
example-desktop = {
nixpkgs.hostPlatform = "x86_64-linux";
imports = [
./configuration.nix
];
};
};
};
in { inherit (clan) nixosConfigurations clanInternals; }
```
- `nixosConfigurations`: Defines NixOS configurations, using Clan Cores `buildClan` function to manage the machines.
- Inside `machines`, a new machine configuration is defined (in this case, `example-desktop`).
- Inside `example-desktop` which is the target machine hostname, `nixpkgs.hostPlatform` specifies the host platform as `x86_64-linux`.
- `clanInternals`: Is required to enable evaluation of the secret generation/upload script on every architecture
- `clanName`: Is required and needs to be globally unique, as else we have a cLAN name clash
4. **Rebuild and Switch**: Rebuild your NixOS configuration using the updated flake:
```shellSession
$ sudo nixos-rebuild switch --flake .
```
- This command rebuilds and switches to the new configuration. Make sure to include the `--flake .` argument to use the current directory as the flake source.
5. **Test Configuration**: Before rebooting, verify that your new configuration builds without errors or warnings.
6. **Reboot**: If everything is fine, you can reboot your system to apply the changes:
```shellSession
$ sudo reboot
```
7. **Verify**: After the reboot, confirm that your system is running with the new configuration, and all services and applications are functioning as expected.
By following these steps, you've successfully migrated your NixOS Flake configuration to include the `clan-core` input and adapted the `outputs` section to work with Clan Core's new machine provisioning method.
## What's next
After creating your flake, you can check out how to add [new machines](./machines.md)

View File

@@ -1,69 +0,0 @@
# ZeroTier Configuration with NixOS in Clan
This guide provides detailed instructions for configuring
[ZeroTier VPN](https://zerotier.com) within Clan. Follow the
outlined steps to set up a machine as a VPN controller (`<CONTROLLER>`) and to
include a new machine into the VPN.
## 1. Setting Up the VPN Controller
The VPN controller is initially essential for providing configuration to new
peers. Post the address allocation, the controller's continuous operation is not
crucial.
### Instructions:
1. **Designate a Machine**: Label a machine as the VPN controller in the clan,
referred to as `<CONTROLLER>` henceforth in this guide.
2. **Add Configuration**: Input the below configuration to the NixOS
configuration of the controller machine:
```nix
clan.networking.zerotier.controller = {
enable = true;
public = true;
};
```
3. **Update the Controller Machine**: Execute the following:
```console
$ clan machines update <CONTROLLER>
```
Your machine is now operational as the VPN controller.
## 2. Integrating a New Machine to the VPN
To introduce a new machine to the VPN, adhere to the following steps:
### Instructions:
1. **Update Configuration**: On the new machine, incorporate the below to its
configuration, substituting `<CONTROLLER>` with the controller machine name:
```nix
{ config, ... }: {
clan.networking.zerotier.networkId = builtins.readFile (config.clanCore.clanDir + "/machines/<CONTROLLER>/facts/zerotier-network-id");
}
```
2. **Update the New Machine**: Execute:
```console
$ clan machines update <NEW_MACHINE>
```
Replace `<NEW_MACHINE>` with the designated new machine name.
3. **Retrieve the ZeroTier ID**: On the `new_machine`, execute:
```console
$ sudo zerotier-cli info
```
Example Output: `200 info d2c71971db 1.12.1 OFFLINE`, where `d2c71971db` is
the ZeroTier ID.
4. **Authorize the New Machine on Controller**: On the controller machine,
execute:
```console
$ sudo zerotier-members allow <ID>
```
Substitute `<ID>` with the ZeroTier ID obtained previously.
5. **Verify Connection**: On the `new_machine`, re-execute:
```console
$ sudo zerotier-cli info
```
The status should now be "ONLINE" e.g., `200 info 47303517ef 1.12.1 ONLINE`.
Congratulations! The new machine is now part of the VPN, and the ZeroTier
configuration on NixOS within the Clan project is complete.

View File

@@ -1,138 +0,0 @@
# API Guidelines
This issue serves to collect our common understanding how to design our API so that it is extensible and usable and understandable.
## Resource oriented
A resource-oriented API is generally modeled as a resource hierarchy, where each node is either a simple resource or a collection resource. For convenience, they are often called a resource and a collection, respectively.
Examples of Resource Nouns:
`machine`
`user`
`flake`
Often resources have sub-resources. Even if it is not foreseen, it is recommended to use plural (trailing `s`) on resources to allow them to be collections of sub-resources.
e.g,
`users`
->
`users/*/profile`
## Verbs
Verbs should not be part of the URL
Bad:
`/api/create-products`
Good:
`/api/products`
Only resources are part of the URL, verbs are described via the HTTP Method.
Exception:
If a different HTTP Method must be used for technical reasons it is okay to terminate the path with a (short) verb / action.
Okay ish:
`/api/products/create`
## Usually the following HTTP Methods exist to interact with a resource
- POST (create an order for a resource)
- GET (retrieve the information)
- PUT (update and replace information)
- PATCH (update and modify information) **(Not used yet)**
- DELETE (delete the item)
## Every resource should be CRUD compatible
All API resources MUST be designed in a way that allows the typical CRUD operations.
Where crud stands for:
C - Create
R - Read
U - Update
D - Delete
Resources should implement at least a "Read" operation.
## Body
Use JSON as an exchange format.
All responses MUST be JSON parseable.
Bad:
`bare string`
Better:
`"quoted string"`
Best: (Enveloped see next section)
`{ name: "quoted string"}`
Errors should have a consistent JSON format, such that it is clear in which field to look at for displaying error messages.
## Envelop all Data collections
Response data should be wrapped into an JSON Object `{}`
Lists `[]` should also contain Objects `{}`.
This allows everything, to be extensible, without breaking backwards compatibility. (Adding fields is trivial, since the schema doesn't change)
Example:
```
{
"users": [{
first_name: "John",
last_name: "Doe",
}, {
first_name: "Jane",
last_name: "Doe",
}
....
],
"skip": 0,
"limit": 20,
....
}
```
Bad Example of a breaking change:
`GET /api/flakes`
`old`
```
[
"dream2nix"
"disko"
]
```
`new`
```
[
{
name: "dream2nix",
url: "github/...."
},
{
name: "disko",
url: "github/...."
}
]
```
Those kind of breaking changes can be avoided by using an object from the beginning.
Even if the object only contains one key, it is extensible, without breaking.
## More will follow.
...maybe

View File

@@ -1,111 +0,0 @@
# Property vs Contract based testing
In this section, we'll explore the importance of testing the backend of your FastAPI application, specifically focusing on the advantages of using contract-based testing with property-based testing frameworks.
## Why Use Property-Based Testing?
Property-based testing is a powerful approach to test your APIs, offering several key benefits:
### 1. Scope
Instead of having to write numerous test cases for various input arguments, property-based testing enables you to test a range of arguments for each parameter using a single test. This approach significantly enhances the robustness of your test suite while reducing redundancy in your testing code. In short, your test code becomes cleaner, more DRY (Don't Repeat Yourself), and more efficient. It also becomes more effective as you can easily test numerous edge cases.
### 2. Reproducibility
Property-based testing tools retain test cases and their results, allowing you to reproduce and replay tests in case of failure. This feature is invaluable for debugging and ensuring the stability of your application over time.
## Frameworks for Property-Based Testing
To implement property-based testing in FastAPI, you can use the following framework:
- [Hypothesis: Property-Based Testing](https://hypothesis.readthedocs.io/en/latest/quickstart.html)
- [Schemathesis](https://schemathesis.readthedocs.io/en/stable/#id2)
## Example
Running schemathesis fuzzer on GET requests
```bash
nix run .#runSchemaTests
```
If you want to test more request types edit the file [flake-module.nix](../checks/impure/flake-module.nix)
After a run it will upload the results to `schemathesis.io` and give you a link to the report.
The credentials to the account are `Username: schemathesis@qube.email` and `Password:6tv4eP96WXsarF`
## Why Schemas Are Not Contracts
A schema is a description of the data structure of your API, whereas a contract defines not only the structure but also the expected behavior and constraints. The following resource explains why schemas are not contracts in more detail:
- [Why Schemas Are Not Contracts](https://pactflow.io/blog/schemas-are-not-contracts/)
In a nutshell, schemas may define the data structure but often fail to capture complex constraints and the expected interactions between different API endpoints. Contracts fill this gap by specifying both the structure and behavior of your API.
## Why Use Contract-Driven Testing?
Contract-driven testing combines the benefits of type annotations and property-based testing, providing a robust approach to ensuring the correctness of your APIs.
- Contracts become an integral part of the function signature and can be checked statically, ensuring that the API adheres to the defined contract.
- Contracts, like property-based tests, allow you to specify conditions and constraints, with the testing framework automatically generating test cases and verifying call results.
### Frameworks for Contract-Driven Testing
To implement contract-driven testing in FastAPI, consider the following framework and extension:
- [Deal: Contract Driven Development](https://deal.readthedocs.io/)
By adopting contract-driven testing, you can ensure that your FastAPI application not only has a well-defined structure but also behaves correctly, making it more robust and reliable.
- [Whitepaper: Python by contract](https://users.ece.utexas.edu/~gligoric/papers/ZhangETAL22PythonByContractDataset.pdf) This paper goes more into detail how it works
## Examples
You can annotate functions with `@deal.raises(ClanError)` to say that they can _only_ raise a ClanError Exception.
```python
import deal
@deal.raises(ClanError)
def get_task(uuid: UUID) -> BaseTask:
global POOL
return POOL[uuid]
```
To say that it can raise multiple exceptions just add after one another separated with a `,`
```python
import deal
@deal.raises(ClanError, IndexError, ZeroDivisionError)
def get_task(uuid: UUID) -> BaseTask:
global POOL
return POOL[uuid]
```
### Adding deal annotated functions to pytest
```python
from clan_cli.task_manager import get_task
import deal
@deal.cases(get_task) # <--- Add function get_task to testing corpus
def test_get_task(case: deal.TestCase) -> None:
case() # <--- Call testing framework with function
```
### Adding example input for deeper testing
You can combine hypothesis annotations with deal annotations to add example inputs to the function so that the verifier can reach deeper parts of the function.
```python
import deal
@deal.example(lambda: get_task(UUID("5c2061e0-4512-4b30-aa8e-7be4a75b8b45"))) # type: ignore
@deal.example(lambda: get_task(UUID("7c2061e6-4512-4b30-aa8e-7be4a75b8b45"))) # type: ignore
@deal.raises(ClanError)
def get_task(uuid: UUID) -> BaseTask:
global POOL
return POOL[uuid]
```
You can also add `pre` and `post` conditions. A `pre` condition must be true before the function is executed. A `post` condition must be true after the function was executed. For more information read the [Writing Contracts Section](https://deal.readthedocs.io/basic/values.html).
Or read the [API doc of Deal](https://deal.readthedocs.io/details/api.html)

112
docs/mkdocs.yml Normal file
View File

@@ -0,0 +1,112 @@
site_name: cLAN documentation
site_url: https://docs.clan.lol
repo_url: https://git.clan.lol/clan/clan-core/
repo_name: clan-core
edit_uri: _edit/main/docs/docs/
validation:
omitted_files: warn
absolute_links: warn
unrecognized_links: warn
markdown_extensions:
- attr_list
- pymdownx.emoji:
emoji_index: !!python/name:material.extensions.emoji.twemoji
emoji_generator: !!python/name:material.extensions.emoji.to_svg
- pymdownx.tasklist:
custom_checkbox: true
- pymdownx.superfences
- pymdownx.tabbed:
alternate_style: true
- footnotes
- meta
- admonition
- pymdownx.details
- pymdownx.highlight:
use_pygments: true
- toc:
title: On this page
exclude_docs: |
.*
!templates/
/drafts/
nav:
- Getting started:
- index.md
- Configure: getting-started/configure.md
- Deploy Machine: getting-started/machines.md
- Installer: getting-started/installer.md
- Setup Networking: getting-started/networking.md
- Provision Secrets & Passwords: getting-started/secrets.md
- Backup & Restore: getting-started/backups.md
- Flake-parts: getting-started/flake-parts.md
- Templates: templates/index.md
- Reference:
- clan-core:
- reference/clan-core/index.md
- reference/clan-core/backups.md
- reference/clan-core/facts.md
- reference/clan-core/sops.md
- reference/clan-core/state.md
- clanModules:
- reference/clanModules/borgbackup.md
- reference/clanModules/deltachat.md
- reference/clanModules/diskLayouts.md
- reference/clanModules/ergochat.md
- reference/clanModules/graphical.md
- reference/clanModules/localbackup.md
- reference/clanModules/localsend.md
- reference/clanModules/matrix-synapse.md
- reference/clanModules/moonlight.md
- reference/clanModules/root-password.md
- reference/clanModules/sshd.md
- reference/clanModules/sunshine.md
- reference/clanModules/syncthing.md
- reference/clanModules/thelounge.md
- reference/clanModules/vm-user.md
- reference/clanModules/waypipe.md
- reference/clanModules/xfce-vm.md
- reference/clanModules/xfce.md
- reference/clanModules/zt-tcp-relay.md
- Contributing: contributing/contributing.md
docs_dir: site
site_dir: out
theme:
logo: static/logo.png
name: material
features:
- navigation.instant
- navigation.tabs
- content.code.annotate
- content.code.copy
- content.tabs.link
icon:
repo: fontawesome/brands/git
palette:
# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
primary: teal
accent: deep purple
toggle:
icon: material/weather-night
name: Switch to dark mode
# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
primary: teal
accent: deep purple
scheme: slate
toggle:
icon: material/weather-sunny
name: Switch to light mode
plugins:
- search

27
docs/nix/default.nix Normal file
View File

@@ -0,0 +1,27 @@
{ pkgs, module-docs, ... }:
pkgs.stdenv.mkDerivation {
name = "clan-documentation";
src = ../.;
nativeBuildInputs =
[ pkgs.python3 ]
++ (with pkgs.python3Packages; [
mkdocs
mkdocs-material
]);
configurePhase = ''
mkdir -p ./site/reference
cp -af ${module-docs}/* ./site/reference/
'';
buildPhase = ''
mkdocs build --strict
ls -la .
'';
installPhase = ''
cp -a out/ $out/
'';
}

36
docs/nix/deploy-docs.nix Normal file
View File

@@ -0,0 +1,36 @@
{
writeShellScriptBin,
coreutils,
openssh,
rsync,
lib,
docs,
}:
writeShellScriptBin "deploy-docs" ''
set -eux -o pipefail
export PATH="${
lib.makeBinPath [
coreutils
openssh
rsync
]
}"
if [ -n "''${SSH_HOMEPAGE_KEY:-}" ]; then
echo "$SSH_HOMEPAGE_KEY" > ./ssh_key
chmod 600 ./ssh_key
sshExtraArgs="-i ./ssh_key"
else
sshExtraArgs=
fi
rsync \
-e "ssh -o StrictHostKeyChecking=no $sshExtraArgs" \
-a ${docs}/ \
www@clan.lol:/var/www/docs.clan.lol
if [ -e ./ssh_key ]; then
rm ./ssh_key
fi
''

72
docs/nix/flake-module.nix Normal file
View File

@@ -0,0 +1,72 @@
{ inputs, self, ... }:
{
perSystem =
{
config,
self',
pkgs,
...
}:
let
# Simply evaluated options (JSON)
# { clanCore = «derivation JSON»; clanModules = { ${name} = «derivation JSON» }; }
jsonDocs = import ./get-module-docs.nix {
inherit (inputs) nixpkgs;
inherit pkgs self;
inherit (self.nixosModules) clanCore;
inherit (self) clanModules;
};
clanModulesFileInfo = pkgs.writeText "info.json" (builtins.toJSON jsonDocs.clanModules);
clanModulesReadmes = pkgs.writeText "info.json" (builtins.toJSON jsonDocs.clanModulesReadmes);
# Simply evaluated options (JSON)
renderOptions =
pkgs.runCommand "renderOptions.py"
{
# TODO: ruff does not splice properly in nativeBuildInputs
depsBuildBuild = [ pkgs.ruff ];
nativeBuildInputs = [
pkgs.python3
pkgs.mypy
];
}
''
install ${./scripts/renderOptions.py} $out
patchShebangs --build $out
ruff format --check --diff $out
ruff --line-length 88 $out
mypy --strict $out
'';
module-docs = pkgs.runCommand "rendered" { nativeBuildInputs = [ pkgs.python3 ]; } ''
export CLAN_CORE=${jsonDocs.clanCore}/share/doc/nixos/options.json
# A file that contains the links to all clanModule docs
export CLAN_MODULES=${clanModulesFileInfo}
export CLAN_MODULES_READMES=${clanModulesReadmes}
mkdir $out
# The python script will place mkDocs files in the output directory
python3 ${renderOptions}
'';
in
{
devShells.docs = pkgs.callPackage ./shell.nix {
inherit (self'.packages) docs;
inherit module-docs;
};
packages = {
docs = pkgs.python3.pkgs.callPackage ./default.nix {
inherit (inputs) nixpkgs;
inherit module-docs;
};
deploy-docs = pkgs.callPackage ./deploy-docs.nix { inherit (config.packages) docs; };
inherit module-docs;
};
legacyPackages = {
foo = jsonDocs;
};
};
}

View File

@@ -0,0 +1,64 @@
{
nixpkgs,
pkgs,
clanCore,
clanModules,
self,
}:
let
allNixosModules = (import "${nixpkgs}/nixos/modules/module-list.nix") ++ [
"${nixpkgs}/nixos/modules/misc/assertions.nix"
{ nixpkgs.hostPlatform = "x86_64-linux"; }
];
clanCoreNixosModules = [
clanCore
{ clanCore.clanDir = ./.; }
] ++ allNixosModules;
# TODO: optimally we would not have to evaluate all nixos modules for every page
# but some of our module options secretly depend on nixos modules.
# We would have to get rid of these implicit dependencies and make them explicit
clanCoreNixos = pkgs.nixos { imports = clanCoreNixosModules; };
# using extendModules here instead of re-evaluating nixos every time
# improves eval performance slightly (10%)
getOptions = modules: (clanCoreNixos.extendModules { inherit modules; }).options;
evalDocs =
options:
pkgs.nixosOptionsDoc {
options = options;
warningsAreErrors = false;
};
# clanModules docs
clanModulesDocs = builtins.mapAttrs (
name: module: (evalDocs ((getOptions [ module ]).clan.${name} or { })).optionsJSON
) clanModules;
clanModulesReadmes = builtins.mapAttrs (
module_name: _module:
let
readme = "${self}/clanModules/${module_name}/README.md";
readmeContents =
if
builtins.trace "Trying to get Module README.md for ${module_name} from ${readme}"
# TODO: Edge cases
(builtins.pathExists readme)
then
(builtins.readFile readme)
else
null;
in
readmeContents
) clanModules;
# clanCore docs
clanCoreDocs = (evalDocs (getOptions [ ]).clanCore).optionsJSON;
in
{
inherit clanModulesReadmes;
clanCore = clanCoreDocs;
clanModules = clanModulesDocs;
}

View File

@@ -0,0 +1,235 @@
# Options are available in the following format:
# https://github.com/nixos/nixpkgs/blob/master/nixos/lib/make-options-doc/default.nix
#
# ```json
# {
# ...
# "fileSystems.<name>.options": {
# "declarations": ["nixos/modules/tasks/filesystems.nix"],
# "default": {
# "_type": "literalExpression",
# "text": "[\n \"defaults\"\n]"
# },
# "description": "Options used to mount the file system.",
# "example": {
# "_type": "literalExpression",
# "text": "[\n \"data=journal\"\n]"
# },
# "loc": ["fileSystems", "<name>", "options"],
# "readOnly": false,
# "type": "non-empty (list of string (with check: non-empty))"
# "relatedPackages": "- [`pkgs.tmux`](\n https://search.nixos.org/packages?show=tmux&sort=relevance&query=tmux\n )\n",
# }
# }
# ```
import json
import os
from pathlib import Path
from typing import Any
# Get environment variables
CLAN_CORE = os.getenv("CLAN_CORE")
CLAN_MODULES = os.environ.get("CLAN_MODULES")
CLAN_MODULES_READMES = os.environ.get("CLAN_MODULES_READMES")
OUT = os.environ.get("out")
def sanitize(text: str) -> str:
return text.replace(">", "\\>")
def replace_store_path(text: str) -> Path:
res = text
if text.startswith("/nix/store/"):
res = "https://git.clan.lol/clan/clan-core/src/branch/main/" + str(
Path(*Path(text).parts[4:])
)
return Path(res)
def render_option_header(name: str) -> str:
return f"# {name}\n"
def join_lines_with_indentation(lines: list[str], indent: int = 4) -> str:
"""
Joins multiple lines with a specified number of whitespace characters as indentation.
Args:
lines (list of str): The lines of text to join.
indent (int): The number of whitespace characters to use as indentation for each line.
Returns:
str: The indented and concatenated string.
"""
# Create the indentation string (e.g., four spaces)
indent_str = " " * indent
# Join each line with the indentation added at the beginning
return "\n".join(indent_str + line for line in lines)
def render_option(name: str, option: dict[str, Any], level: int = 3) -> str:
read_only = option.get("readOnly")
res = f"""
{"#" * level} {sanitize(name)} {{#{sanitize(name)}}}
{"Readonly" if read_only else ""}
{option.get("description", "No description available.")}
**Type**: `{option["type"]}`
"""
if option.get("default"):
res += f"""
**Default**:
```nix
{option["default"]["text"] if option.get("default") else "No default set."}
```
"""
example = option.get("example", {}).get("text")
if example:
example_indented = join_lines_with_indentation(example.split("\n"))
res += f"""
???+ example
```nix
{example_indented}
```
"""
if option.get("relatedPackages"):
res += f"""
### Related Packages
{option["relatedPackages"]}
"""
decls = option.get("declarations", [])
source_path = replace_store_path(decls[0])
res += f"""
:simple-git: [{source_path.name}]({source_path})
"""
res += "\n"
return res
def module_header(module_name: str) -> str:
return f"# {module_name}\n"
def module_usage(module_name: str) -> str:
return f"""## Usage
To use this module, import it like this:
```nix
{{config, lib, inputs, ...}}: {{
imports = [ inputs.clan-core.clanModules.{module_name} ];
# ...
}}
```
"""
clan_core_descr = """ClanCore delivers all the essential features for every clan.
It's always included in your setup, and you can customize your clan's behavior with the configuration [options](#module-options) provided below.
"""
options_head = "\n## Module Options\n"
def produce_clan_core_docs() -> None:
if not CLAN_CORE:
raise ValueError(
f"Environment variables are not set correctly: $CLAN_CORE={CLAN_CORE}"
)
if not OUT:
raise ValueError(f"Environment variables are not set correctly: $out={OUT}")
# A mapping of output file to content
core_outputs: dict[str, str] = {}
with open(CLAN_CORE) as f:
options: dict[str, dict[str, Any]] = json.load(f)
module_name = "clan-core"
for option_name, info in options.items():
outfile = f"{module_name}/index.md"
# Create seperate files for nested options
if len(option_name.split(".")) <= 2:
# i.e. clan-core.clanDir
output = core_outputs.get(
outfile,
module_header(module_name) + clan_core_descr + options_head,
)
output += render_option(option_name, info)
# Update the content
core_outputs[outfile] = output
else:
# Clan sub-options
[_, sub] = option_name.split(".")[0:2]
outfile = f"{module_name}/{sub}.md"
# Get the content or write the header
output = core_outputs.get(outfile, render_option_header(sub))
output += render_option(option_name, info)
# Update the content
core_outputs[outfile] = output
for outfile, output in core_outputs.items():
(Path(OUT) / outfile).parent.mkdir(parents=True, exist_ok=True)
with open(Path(OUT) / outfile, "w") as of:
of.write(output)
def produce_clan_modules_docs() -> None:
if not CLAN_MODULES:
raise ValueError(
f"Environment variables are not set correctly: $CLAN_MODULES={CLAN_MODULES}"
)
if not CLAN_MODULES_READMES:
raise ValueError(
f"Environment variables are not set correctly: $CLAN_MODULES_READMES={CLAN_MODULES_READMES}"
)
if not OUT:
raise ValueError(f"Environment variables are not set correctly: $out={OUT}")
with open(CLAN_MODULES) as f:
links: dict[str, str] = json.load(f)
with open(CLAN_MODULES_READMES) as readme:
readme_map: dict[str, str] = json.load(readme)
# {'borgbackup': '/nix/store/hi17dwgy7963ddd4ijh81fv0c9sbh8sw-options.json', ... }
for module_name, options_file in links.items():
with open(Path(options_file) / "share/doc/nixos/options.json") as f:
options: dict[str, dict[str, Any]] = json.load(f)
print(f"Rendering options for {module_name}...")
output = module_header(module_name)
if readme_map.get(module_name, None):
output += f"{readme_map[module_name]}\n"
output += module_usage(module_name)
output += options_head if len(options.items()) else ""
for option_name, info in options.items():
output += render_option(option_name, info)
outfile = Path(OUT) / f"clanModules/{module_name}.md"
outfile.parent.mkdir(
parents=True,
exist_ok=True,
)
with open(outfile, "w") as of:
of.write(output)
if __name__ == "__main__":
produce_clan_core_docs()
produce_clan_modules_docs()

16
docs/nix/shell.nix Normal file
View File

@@ -0,0 +1,16 @@
{
docs,
pkgs,
module-docs,
...
}:
pkgs.mkShell {
inputsFrom = [ docs ];
shellHook = ''
mkdir -p ./site/reference
cp -af ${module-docs}/* ./site/reference/
chmod +w ./site/reference/*
echo "Generated API documentation in './site/reference/' "
'';
}

View File

@@ -0,0 +1 @@
../../CONTRIBUTING.md

View File

@@ -0,0 +1,146 @@
# Hardware Installation
For installations on physical hardware, create a NixOS installer image and transfer it to a bootable USB drive as described below.
## Creating a Bootable USB Drive on Linux
To create a bootable USB flash drive with the NixOS installer:
### Download the install iso
Either with wget:
```shellSession
wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-x86_64-linux.iso
```
or with curl:
```shellSession
curl -L https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-x86_64-linux.iso -o nixos-installer-x86_64-linux.iso
```
### Prepare the USB Flash Drive
1. Insert your USB flash drive into your computer.
2. Identify your flash drive with `lsblk`.
```shellSession
lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb 8:0 1 117,2G 0 disk
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
nvme0n1 259:0 0 1,8T 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot
└─nvme0n1p2 259:2 0 1,8T 0 part
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
```
In this case it's `sdb`
3. Ensure all partitions on the drive are unmounted. Replace `sdX` in the command below with your device identifier (like `sdb`, etc.):
```shellSession
sudo umount /dev/sdb1
```
### Write the Image to the USB Drive
Use the `dd` utility to write the NixOS installer image to your USB drive:
```shellSession
sudo dd bs=4M conv=fsync oflag=direct status=progress if=./nixos-installer-x86_64-linux.iso of=/dev/sd<X>
```
In this case, the USB device is `sdb` use `of=/dev/sdb`
### Boot and Connect
After writing the installer to the USB drive, use it to boot the target machine.
1. For this secure boot needs to be disabled. Go into your UEFI / Bios settings by pressing one of the keys outlined below while booting:
- **Dell**: F2/Del (BIOS Setup)
- **HP**: Esc (Startup Menu)
- **Lenovo**: F2/Fn+F2/Novo Button (IdeaPad Boot Menu/BIOS Setup)
- **Acer**: F2/Del (BIOS Setup)
- **Asus**: F2/Del (BIOS Setup)
- **Toshiba**: Esc then F12 (Alternate Method)
- **Sony**: F11
- **Samsung**: F2 (BIOS Setup)
- **MSI**: Del (BIOS Setup)
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
2. Inside the UEFI/Bios Menu go to `Security->Secure Boot` and disable secure boot
3. Save your settings. Put in the USB stick and reboot.
4. Press one of keys outlined below to go into the Boot Menu
- **Dell**: F12 (Boot Menu)
- **HP**: F9 (Boot Menu)
- **Lenovo**: F12 (ThinkPad Boot Menu)
- **Acer**: F12 (Boot Menu)
- **Asus**: F8/Esc (Boot Menu)
- **Toshiba**: F12/F2 (Boot Menu)
- **Sony**: F11
- **Samsung**: F2/F12/Esc (Boot Menu)
- **MSI**: F11
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
5. Select `NixOS` to boot into the clan installer
6. The installer will display an IP address and a root password, which you can use to connect via SSH.
Alternatively you can also use the displayed QR code.
7. Set your keyboard language (i.e. `de` for German keyboards, default is English). Important for writing passwords correctly.
```shellSession
loadkeys de
```
8. If you only have Wifi available, execute:
1. Bring up the `iwd` shell
```shellSession
iwctl
```
2. List available networks. Double press tab after station for autocompleting your wlan device. In this case `wlan0`
```shellSession
[iwd] station wlan0 get-networks
```
3. Connect to a Wifi network. Replace `SSID` with the wlan network name.
```shellSession
[iwd] station wlan0 connect SSID
```
9. Now that you have internet re-execute the init script by pressing `Ctrl+D` or by executing:
```shellSession
bash
```
10. Connect to the machine over ssh
```shellSession
ssh-copy-id -o PreferredAuthentications=password root@<ip>
```
Use the root password displayed on your screen as login.
---
# Whats next?
- Deploy a clan machine-configuration on your prepared machine
---

View File

@@ -0,0 +1,149 @@
# Backups
## Introduction to Backups
When you're managing your own services, creating regular backups is crucial to ensure your data's safety.
This guide introduces you to Clan's built-in backup functionalities.
Clan supports backing up your data to both local storage devices (like USB drives) and remote servers, using well-known tools like borgbackup and rsnapshot.
We might add more options in the future, but for now, let's dive into how you can secure your data.
## Backing Up Locally with Localbackup
### What is Localbackup?
Localbackup lets you backup your data onto physical storage devices connected to your computer,
such as USB hard drives or network-attached storage. It uses a tool called rsnapshot for this purpose.
### Setting Up Localbackup
1. **Identify Your Backup Device:**
First, figure out which device you'll use for backups. You can see all connected devices by running this command in your terminal:
```bash
lsblk --output NAME,PTUUID,FSTYPE,SIZE,MOUNTPOINT
```
Look for the device you intend to use for backups and note its details.
2. **Configure Your Backup Device:**
Once you've identified your device, you'll need to add it to your configuration.
Here's an example NixOS configuration for a device located at `/dev/sda2` with an `ext4` filesystem:
```nix
{
fileSystems."/mnt/hdd" = {
device = "/dev/sda2";
fsType = "ext4";
options = [ "defaults" "noauto" ];
};
}
```
Replace `/dev/sda2` with your device and `/mnt/hdd` with your preferred mount point.
3. **Set Backup Targets:** Next, define where on your device you'd like the backups to be stored:
```nix
{
clan.localbackup.targets.hdd = {
directory = "/mnt/hdd/backup";
mountpoint = "/mnt/hdd";
};
}
```
Change `/mnt/hdd` to the actual mount point you're using.
4. **Create Backups:** To create a backup, run:
```bash
clan backups create mymachine
```
This command saves snapshots of your data onto the backup device.
5. **Listing Backups:** To see available backups, run:
```bash
clan backups list mymachine
```
## Remote Backups with Borgbackup
### Overview of Borgbackup
Borgbackup splits the backup process into two parts: a backup client that sends data to a backup server.
The server stores the backups.
### Setting Up the Borgbackup Client
1. **Specify Backup Server:**
Start by indicating where your backup data should be sent. Replace `hostname` with your server's address:
```nix
{
clan.borgbackup.destinations = {
myhostname = {
repo = "borg@backuphost:/var/lib/borgbackup/myhostname";
};
};
}
```
2. **Select Folders to Backup:**
Decide which folders you want to back up. For example, to backup your home and root directories:
```nix
{ clanCore.state.userdata.folders = [ "/home" "/root" ]; }
```
3. **Generate Backup Credentials:**
Run `clan facts generate <yourmachine>` to prepare your machine for backup, creating necessary SSH keys and credentials.
### Setting Up the Borgbackup Server
1. **Configure Backup Repository:**
On the server where backups will be stored, enable the SSH daemon and set up a repository for each client:
```nix
{
services.borgbackup.repos.myhostname = {
path = "/var/lib/borgbackup/myhostname";
authorizedKeys = [
(builtins.readFile ./machines/myhostname/facts/borgbackup.ssh.pub)
];
};
}
```
Ensure the path to the public key is correct.
2. **Update Your Systems:** Apply your changes by running `clan machines update` to both the server and your client
### Managing Backups
- **Scheduled Backups:**
Backups are automatically performed nightly. To check the next scheduled backup, use:
```bash
systemctl list-timers | grep -E 'NEXT|borg'
```
- **Listing Backups:** To see available backups, run:
```bash
clan backups list mymachine
```
- **Manual Backups:** You can also initiate a backup manually:
```bash
clan backups create mymachine
```

View File

@@ -0,0 +1,150 @@
# Configuration - How to configure clan with your own machines
## Global configuration
In the `flake.nix` file:
- [x] set a unique `clanName`.
- [ ] set `clanIcon` (optional)
- [ ] Set `machineIcon` per machine (optional)
These icons will be used by our future GUI.
=== "**buildClan**"
```nix title="clan-core.lib.buildClan"
buildClan {
# Set a unique name
clanName = "Lobsters";
# Optional, a path to an image file
clanIcon = ./path/to/file;
# Should usually point to the directory of flake.nix
directory = ./.;
machines = {
jon = {
# ...
# Optional, a path to an image file
clanCore.machineIcon = ./path/to/file;
};
# ...
}
}
```
=== "**flakeParts**"
!!! info "See [Clan with flake-parts](./flake-parts.md) for help migrating to flake-parts."
```nix title="clan-core.flakeModules.default"
clan = {
# Set a unique name
clanName = "Lobsters";
# Optional, a path to an image file
clanIcon = ./path/to/file;
machines = {
jon = {
# ...
# Optional, a path to an image file
clanCore.machineIcon = ./path/to/file;
};
# ...
}
};
```
## Machine configuration
Adding or configuring a new machine requires two simple steps:
### Step 1. Identify Target Disk-ID
1. Find the remote disk id by executing:
```bash title="setup computer"
ssh root@<target-computer> lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT
```
Which should show something like:
```bash
NAME ID-LINK FSTYPE SIZE MOUNTPOINT
sda usb-ST_16GB_AA6271026J1000000509-0:0 14.9G
├─sda1 usb-ST_16GB_AA6271026J1000000509-0:0-part1 1M
├─sda2 usb-ST_16GB_AA6271026J1000000509-0:0-part2 vfat 100M /boot
└─sda3 usb-ST_16GB_AA6271026J1000000509-0:0-part3 ext4 2.9G /
nvme0n1 nvme-eui.e8238fa6bf530001001b448b4aec2929 476.9G
├─nvme0n1p1 nvme-eui.e8238fa6bf530001001b448b4aec2929-part1 vfat 512M
├─nvme0n1p2 nvme-eui.e8238fa6bf530001001b448b4aec2929-part2 ext4 459.6G
└─nvme0n1p3 nvme-eui.e8238fa6bf530001001b448b4aec2929-part3 swap 16.8G
```
1. Edit the following fields inside the `flake.nix`
=== "**buildClan**"
```nix title="clan-core.lib.buildClan"
buildClan {
# ...
machines = {
"jon" = {
# ...
# Change this to the correct ip-address or hostname
# The hostname is the machine name by default
clan.networking.targetHost = pkgs.lib.mkDefault "root@<hostname>"
# Change this to the ID-LINK of the desired disk shown by 'lsblk'
clan.diskLayouts.singleDiskExt4 = {
device = "/dev/disk/by-id/__CHANGE_ME__";
}
# ...
};
};
}
```
=== "**flakeParts**"
```nix title="clan-core.flakeModules.default"
clan = {
# ...
machines = {
"jon" = {
# ...
# Change this to the correct ip-address or hostname
# The hostname is the machine name by default
clan.networking.targetHost = pkgs.lib.mkDefault "root@<hostname>"
# Change this to the ID-LINK of the desired disk shown by 'lsblk'
clan.diskLayouts.singleDiskExt4 = {
device = "/dev/disk/by-id/__CHANGE_ME__";
}
# ...
};
};
};
```
### Step 2. Detect hardware specific drivers
1. Generate a `hardware-configuration.nix` for your target computer
```bash
ssh root@<target-computer> nixos-generate-config --no-filesystems --show-hardware-config > hardware-configuration.nix
```
2. Move the generated file to `machines/jon/hardware-configuration.nix`.
### Initialize the facts
!!! Info
**All facts are automatically initialized.**
If you need additional help see our [facts chapter](./secrets.md)

View File

@@ -0,0 +1,102 @@
# Clan with `flake-parts`
Clan supports integration with [flake.parts](https://flake.parts/) a tool which allows composing nixos modules in a modular way.
Here's how to set up Clan using `nix flakes` and `flake-parts`.
## 1. Update Your Flake Inputs
To begin, you'll need to add `flake-parts` as a new dependency in your flake's inputs. This is alongside the already existing dependencies, such as `clan-core` and `nixpkgs`. Here's how you can update your `flake.nix` file:
```nix
# flake.nix
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
# New flake-parts input
flake-parts.url = "github:hercules-ci/flake-parts";
flake-parts.inputs.nixpkgs-lib.follows = "nixpkgs";
clan-core = {
url = "git+https://git.clan.lol/clan/clan-core";
inputs.nixpkgs.follows = "nixpkgs"; # Needed if your configuration uses nixpkgs unstable.
# New
inputs.flake-parts.follows = "flake-parts";
};
}
```
## 2. Import Clan-Core Flake Module
After updating your flake inputs, the next step is to import the `clan-core` flake module. This will make the [clan options](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix) available within `mkFlake`.
```nix
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } (
{
#
imports = [
inputs.clan-core.flakeModules.default
];
}
);
```
### 3. Configure Clan Settings and Define Machines
Configure your clan settings and define machine configurations.
Below is a guide on how to structure this in your flake.nix:
```nix
outputs = inputs@{ flake-parts, clan-core, ... }:
flake-parts.lib.mkFlake { inherit inputs; } ({self, pkgs, ...}: {
# We define our own systems below. you can still use this to add system specific outputs to your flake.
# See: https://flake.parts/getting-started
systems = [];
# import clan-core modules
imports = [
clan-core.flakeModules.default
];
# Define your clan
clan = {
# Clan wide settings. (Required)
clanName = ""; # Ensure to choose a unique name.
machines = {
jon = {
imports = [
./machines/jon/configuration.nix
# ... more modules
];
nixpkgs.hostPlatform = "x86_64-linux";
clanCore.machineIcon = null; # Optional, a path to an image file
# Set this for clan commands use ssh i.e. `clan machines update`
clan.networking.targetHost = pkgs.lib.mkDefault "root@jon";
# remote> lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT
clan.diskLayouts.singleDiskExt4 = {
device = "/dev/disk/by-id/nvme-eui.e8238fa6bf530001001b448b4aec2929";
};
# There needs to be exactly one controller per clan
clan.networking.zerotier.controller.enable = true;
};
};
};
});
```
For detailed information about configuring `flake-parts` and the available options within Clan,
refer to the Clan module documentation located [here](https://git.clan.lol/clan/clan-core/src/branch/main/flakeModules/clan.nix).
## Whats next?
- [Configure Machines](configure.md): Customize machine configuration
- [Deploying](machines.md): Deploying a Machine configuration
---

View File

@@ -0,0 +1,149 @@
# Installer
We offer a dedicated installer to assist remote installations.
In this tutorial we will guide you through building and flashing it to a bootable USB drive.
## Creating and Using the **Clan Installer**
### Step 0. Prerequisites
- [x] A free USB Drive with at least 1.5GB (All data on it will be lost)
- [x] Linux/NixOS Machine with Internet
### Step 1. Identify the USB Flash Drive
1. Insert your USB flash drive into your computer.
2. Identify your flash drive with `lsblk`:
```shellSession
lsblk
```
```{.console, .no-copy}
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS
sdb 8:0 1 117,2G 0 disk
└─sdb1 8:1 1 117,2G 0 part /run/media/qubasa/INTENSO
nvme0n1 259:0 0 1,8T 0 disk
├─nvme0n1p1 259:1 0 512M 0 part /boot
└─nvme0n1p2 259:2 0 1,8T 0 part
└─luks-f7600028-9d83-4967-84bc-dd2f498bc486 254:0 0 1,8T 0 crypt /nix/store
```
!!! Info "In this case the USB device is `sdb`"
3. Ensure all partitions on the drive are unmounted. Replace `sdb1` in the command below with your device identifier (like `sdc1`, etc.):
```shellSession
sudo umount /dev/sdb1
```
### Step 2. Download the Installer
```shellSession
wget https://github.com/nix-community/nixos-images/releases/download/nixos-unstable/nixos-installer-x86_64-linux.iso
```
### Step 3. Flash the Installer to the USB Drive
!!! Danger "Specifying the wrong device can lead to unrecoverable data loss."
The `dd` utility will erase the disk. Make sure to specify the correct device (`of=...`)
For example if the USB device is `sdb` use `of=/dev/sdb`.
Use the `dd` utility to write the NixOS installer image to your USB drive:
```shellSession
sudo dd bs=4M conv=fsync oflag=direct status=progress if=./nixos-installer-x86_64-linux.iso of=/dev/sd<X>
```
### Step 4. Boot and Connect to your network
After writing the installer to the USB drive, use it to boot the target machine.
!!! info
Plug it into the target machine and select the USB drive as a temporary boot device.
??? tip "Here you can find the key combinations for selection used by most vendors."
- **Dell**: F12 (Boot Menu), F2/Del (BIOS Setup)
- **HP**: F9 (Boot Menu), Esc (Startup Menu)
- **Lenovo**: F12 (ThinkPad Boot Menu), F2/Fn+F2/Novo Button (IdeaPad Boot Menu/BIOS Setup)
- **Acer**: F12 (Boot Menu), F2/Del (BIOS Setup)
- **Asus**: F8/Esc (Boot Menu), F2/Del (BIOS Setup)
- **Toshiba**: F12/F2 (Boot Menu), Esc then F12 (Alternate Method)
- **Sony**: F11/Assist Button (Boot Menu/Recovery Options)
- **Samsung**: F2/F12/Esc (Boot Menu), F2 (BIOS Setup)
- **MSI**: F11 (Boot Menu), Del (BIOS Setup)
- **Apple**: Option (Alt) Key (Boot Menu for Mac)
- If your hardware was not listed read the manufacturers instructions how to enter the boot Menu/BIOS Setup.
**During Boot**
Select `NixOS` to boot into the clan installer.
**After Booting**
For deploying your configuration the machine needs to be connected via LAN (recommended).
For connecting via Wifi, please consult the [guide below](#optional-connect-to-wifi).
---
## Whats next?
- [Configure Machines](configure.md): Customize machine configuration
- [Deploying](machines.md): Deploying a Machine configuration
- [WiFi](#optional-connect-to-wifi): Guide for connecting to Wifi.
---
## (Optional) Connect to Wifi
If you don't have access via LAN the Installer offers support for connecting via Wifi.
```shellSession
iwctl
```
This will enter `iwd`
```{.console, .no-copy}
[iwd]#
```
Now run the following command to connect to your Wifi:
```shellSession
# Identify your network device.
device list
# Replace 'wlan0' with your wireless device name
# Find your Wifi SSID.
station wlan0 scan
station wlan0 get-networks
# Replace your_ssid with the Wifi SSID
# Connect to your network.
station wlan0 connect your_ssid
# Verify you are connected
station wlan0 show
```
If the connection was successful you should see something like this:
```{.console, .no-copy}
State connected
Connected network FRITZ!Box (Your router device)
IPv4 address 192.168.188.50 (Your new local ip)
```
Press `ctrl-d` to exit `IWD`.
!!! Important
Press `ctrl-d` **again** to update the displayed QR code and connection information.
You're all set up

View File

@@ -0,0 +1,213 @@
# Deploy Machine
Integrating a new machine into your Clan environment is an easy yet flexible process, allowing for a straight forward management of multiple NixOS configurations.
We'll walk you through adding a new computer to your Clan.
## Installing a New Machine
Clan CLI, in conjunction with [nixos-anywhere](https://github.com/nix-community/nixos-anywhere), provides a seamless method for installing NixOS on various machines.
This process involves preparing a suitable hardware and disk partitioning configuration and ensuring the target machine is accessible via SSH.
### Step 0. Prerequisites
=== "**Physical Hardware**"
- [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 [configuration guide](./configure.md)
- [x] **Initialized secrets**: See [secrets](secrets.md) for how to initialize your secrets.
- [x] **USB Flash Drive**: See [Clan Installer](installer.md)
!!! Steps
1. Create a NixOS installer image and transfer it to a bootable USB drive as described in the [installer](./installer.md).
2. Boot the target machine and connect it to a network that makes it reachable from your setup computer.
=== "**Baremetal Machines**"
- [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 [configuration guide](./configure.md)
- [x] **Initialized secrets**: See [secrets](secrets.md) for how to initialize your secrets.
!!! Steps
- Any cloud machine if it is reachable via SSH and supports `kexec`.
Confirm the machine is reachable via SSH from your setup computer.
```bash
ssh root@<your_target_machine_ip>
```
### Step 1. Deploy the machine
**Finally deployment time!** Use the following command to build and deploy the image via SSH onto your machine.
=== "**SSH access**"
Replace `<target_host>` with the **target computers' ip address**:
```bash
clan machines install my-machine <target_host>
```
!!!note
Building and deploying time will depend on hardware and connection speed.
=== "**Image Installer**"
This method makes use of the image installers of [nixos-images](https://github.com/nix-community/nixos-images).
See how to prepare the installer for use [here](./installer.md).
The installer will randomly generate a password and local addresses on boot, then run ssh with these preconfigured.
The installer shows it's deployment relevant information in two formats, a text form, as well as a QR code.
???example "An example view of a booted installer."
This is an example of the booted installer.
```{ .bash .annotate }
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ ┌───────────────────────────┐ │
│ │███████████████████████████│ # This is the QR Code (1) │
│ │██ ▄▄▄▄▄ █▀▄█▀█▀▄█ ▄▄▄▄▄ ██│ │
│ │██ █ █ █▀▄▄▄█ ▀█ █ █ ██│ │
│ │██ █▄▄▄█ █▀▄ ▀▄▄▄█ █▄▄▄█ ██│ │
│ │██▄▄▄▄▄▄▄█▄▀ ▀▄▀▄█▄▄▄▄▄▄▄██│ │
│ │███▀▀▀ █▄▄█ ▀▄ ▄▀▄█ ███│ │
│ │██▄██▄▄█▄▄▀▀██▄▀ ▄▄▄ ▄▀█▀██│ │
│ │██ ▄▄▄▄▄ █▄▄▄▄ █ █▄█ █▀ ███│ │
│ │██ █ █ █ █ █ ▄▄▄ ▄▀▀ ██│ │
│ │██ █▄▄▄█ █ ▄ ▄ ▄ ▀█ ▄███│ │
│ │██▄▄▄▄▄▄▄█▄▄▄▄▄▄█▄▄▄▄▄█▄███│ │
│ │███████████████████████████│ │
│ └───────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │Root password: cheesy-capital-unwell # password (2) │ │
│ │Local network addresses: │ │
│ │enp1s0 UP 192.168.178.169/24 metric 1024 fe80::21e:6ff:fe45:3c92/64 │ │
│ │enp2s0 DOWN │ │
│ │wlan0 DOWN # connect to wlan (3) │ │
│ │Onion address: 6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion │ │
│ │Multicast DNS: nixos-installer.local │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ Press 'Ctrl-C' for console access │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
```
1. This is not an actual QR code, because it is displayed rather poorly on text sites.
This would be the actual content of this specific QR code prettified:
```json
{
"pass": "cheesy-capital-unwell",
"tor": "6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion",
"addrs": [
"2001:9e8:347:ca00:21e:6ff:fe45:3c92"
]
}
```
To generate the actual QR code, that would be displayed use:
```shellSession
echo '{"pass":"cheesy-capital-unwell","tor":"6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion","addrs":["2001:9e8:347:ca00:21e:6ff:fe45:3c92"]}' | nix run nixpkgs#qrencode -- -s 2 -m 2 -t utf8
```
2. The root password for the installer medium.
This password is autogenerated and meant to be easily typeable.
3. See how to connect the installer medium to wlan [here](./installer.md#optional-connect-to-wifi).
4. :man_raising_hand: I'm a code annotation! I can contain `code`, __formatted
text__, images, ... basically anything that can be written in Markdown.
!!!tip
We recommend using KDE Connect for sharing the deployment information from the QR code with the deploying machine.
The QR code can be used to deploy either with an image, that is decoded on the fly, or it's contained json information.
With the path to a `json` string, or the string itself:
```terminal
clan machines install [MACHINE] --json [JSON]
```
With the path to an image containing the relevant QR code:
```terminal
clan machines install [MACHINE] --png [PATH]
```
!!! success
Your machine is all set up. 🎉 🚀
---
## What's next ?
- [**Update a Machine**](#update-your-machines): Learn how to update an existing machine?
Coming Soon:
- **Join Your Machines in a Private Network:**: Stay tuned for steps on linking all your machines into a secure mesh network with Clan.
---
## Update Your Machines
Clan CLI enables you to remotely update your machines over SSH. This requires setting up a target address for each target machine.
### Setting the Target Host
Replace `host_or_ip` with the actual hostname or IP address of your target machine:
```bash
clan config --machine my-machine clan.networking.targetHost root@host_or_ip
```
!!! warning
The use of `root@` in the target address implies SSH access as the `root` user.
Ensure that the root login is secured and only used when necessary.
### Updating Machine Configurations
Execute the following command to update the specified machine:
```bash
clan machines update my-machine
```
You can also update all configured machines simultaneously by omitting the machine name:
```bash
clan machines update
```
### Setting a Build Host
If the machine does not have enough resources to run the NixOS evaluation or build itself,
it is also possible to specify a build host instead.
During an update, the cli will ssh into the build host and run `nixos-rebuild` from there.
```bash
clan config --machine my-machine clan.networking.buildHost root@host_or_ip
```
### Excluding a machine from `clan machine update`
To exclude machines from being updated when running `clan machines update` without any machines specified,
one can set the `clan.deployment.requireExplicitUpdate` option to true:
```bash
clan config --machine my-machine clan.deployment.requireExplicitUpdate true
```
This is useful for machines that are not always online or are not part of the regular update cycle.
---
# TODO:
* TODO: How to join others people zerotier
* `services.zerotier.joinNetworks = [ "network-id" ]`
* Controller needs to approve over webinterface or cli

View File

@@ -0,0 +1,95 @@
# Overlay Networks
This guide provides detailed instructions for configuring
[ZeroTier VPN](https://zerotier.com) within Clan. Follow the
outlined steps to set up a machine as a VPN controller (`<CONTROLLER>`) and to
include a new machine into the VPN.
## 1. Setting Up the VPN Controller
The VPN controller is initially essential for providing configuration to new
peers. Once addresses are allocated, the controller's continuous operation is not essential.
### Instructions
1. **Designate a Machine**: Label a machine as the VPN controller in the clan,
referred to as `<CONTROLLER>` henceforth in this guide.
1. **Add Configuration**: Input the following configuration to the NixOS
configuration of the controller machine:
```nix
clan.networking.zerotier.controller = {
enable = true;
public = true;
};
```
1. **Update the Controller Machine**: Execute the following:
```bash
$ clan machines update <CONTROLLER>
```
Your machine is now operational as the VPN controller.
## 2. Integrating a New Machine to the VPN
To introduce a new machine to the VPN, adhere to the following steps:
### Instructions:
1. **Update Configuration**: On the new machine, incorporate the following to its
configuration, substituting `<CONTROLLER>` with the controller machine name:
```nix
{ config, ... }: {
clan.networking.zerotier.networkId = builtins.readFile (config.clanCore.clanDir + "/machines/<CONTROLLER>/facts/zerotier-network-id");
}
```
1. **Update the New Machine**: Execute:
```bash
$ clan machines update <NEW_MACHINE>
```
Replace `<NEW_MACHINE>` with the designated new machine name.
1. **Retrieve the ZeroTier ID**: On the `new_machine`, execute:
```bash
$ sudo zerotier-cli info
```
Example Output:
```{.console, .no-copy}
200 info d2c71971db 1.12.1 OFFLINE
```
, where `d2c71971db` is the ZeroTier ID.
1. **Authorize the New Machine on the Controller**: On the controller machine,
execute:
```bash
$ sudo zerotier-members allow <ID>
```
Substitute `<ID>` with the ZeroTier ID obtained previously.
1. **Verify Connection**: On the `new_machine`, re-execute:
```bash
$ sudo zerotier-cli info
```
The status should now be "ONLINE":
```{.console, .no-copy}
200 info d2c71971db 1.12.1 ONLINE
```
!!! success "Congratulations!"
The new machine is now part of the VPN, and the ZeroTier
configuration on NixOS within the Clan project is complete.
## Decision
We chose zerotier because in our tests it was the easiest solution to bootstrap. You can selfhost a controller and the controller doesn't need to be globally reachable.
In the future we plan to add additional network technologies like tinc, head/tailscale, yggdrassil and mycelium.
## Specification
By default all machines within one clan are connected via the chosen network technology.
```
Clan
Node A
<-> (zerotier / mycelium / ...)
Node B
```
If you select multiple network technologies at the same time. e.g. (zerotier + yggdrassil)
One of them is the primary network and the above statement holds for the primary network.

View File

@@ -1,69 +1,151 @@
# Managing Secrets with Clan
# Secrets / Facts
Clan enables encryption of secrets within a Clan flake, ensuring secure sharing among users.
This documentation will guide you through managing secrets with the Clan CLI,
which utilizes the [sops](https://github.com/getsops/sops) format and
integrates with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
Clan enables encryption of secrets (such as passwords & keys) ensuring security and ease-of-use among users.
## 1. Generating Keys and Creating Secrets
Clan utilizes the [sops](https://github.com/getsops/sops) format and integrates with [sops-nix](https://github.com/Mic92/sops-nix) on NixOS machines.
To begin, generate a key pair:
This documentation will guide you through managing secrets with the Clan CLI
```shellSession
$ clan secrets key generate
## 1. Initializing Secrets
### Create Your Master Keypair
To get started, you'll need to create **Your master keypair**.
!!! info
Don't worry — if you've already made one before, this step won't change or overwrite it.
```bash
clan secrets key generate
```
**Output**:
```
```{.console, .no-copy}
Public key: age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7
Generated age private key at '/home/joerg/.config/sops/age/keys.txt' for your user.
Generated age private key at '/home/joerg/.config/sops/age/keys.txt' for your user. Please back it up on a secure location or you will lose access to your secrets.
Also add your age public key to the repository with 'clan secrets users add youruser age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace you
user with your user name)
Also add your age public key to the repository with 'clan secrets users add YOUR_USER age1wkth7uhpkl555g40t8hjsysr20drq286netu8zptw50lmqz7j95sw2t3l7' (replace YOUR_USER with your actual username)
```
⚠️ **Important**: Backup the generated private key securely, or risk losing access to your secrets.
!!! warning
Make sure to keep a safe backup of the private key you've just created.
If it's lost, you won't be able to get to your secrets anymore because they all need the master key to be unlocked.
Next, add your public key to the Clan flake repository:
!!! note
It's safe to add any secrets created by the clan CLI and placed in your repository to version control systems like `git`.
```shellSession
$ clan secrets users add <your_username> <your_public_key>
### Add Your Public Key
```bash
clan secrets users add <your_username> <your_public_key>
```
Doing so creates this structure in your Clan flake:
!!! note
Choose the same username as on your Setup/Source Machine that you use to control the deployment with.
```
Once run this will create the following files:
```{.console, .no-copy}
sops/
└── users/
└── <your_username>/
└── key.json
```
Now, to set your first secret:
## 2. Adding Machine Keys
```shellSession
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
```bash
$ clan secrets machines list
```
For existing machines, add their keys:
```bash
$ clan secrets machines add <machine_name> <age_key>
```
### Advanced
To fetch an age key from an SSH host key:
```bash
$ ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
```
## 3. Assigning Access
By default, secrets are encrypted for your key. To specify which users and machines can access a secret:
```bash
$ clan secrets set --machine <machine1> --machine <machine2> --user <user1> --user <user2> <secret_name>
```
You can add machines/users to existing secrets without modifying the secret:
```bash
$ clan secrets machines add-secret <machine_name> <secret_name>
```
## 4. Adding Secrets
```bash
$ clan secrets set mysecret
Paste your secret:
```
Note: As you type your secret, keypresses won't be displayed. Press Enter to save the secret.
!!! note
As you type your secret won't be displayed. Press Enter to save the secret.
Retrieve the stored secret:
## 5. Retrieving Stored Secrets
```shellSession
```bash
$ clan secrets get mysecret
```
And list all secrets like this:
### List all Secrets
```shellSession
```bash
$ clan secrets list
```
## 6. Groups
Clan CLI makes it easy to manage access by allowing you to create groups.
All users within a group inherit access to all secrets of the group.
This feature eases the process of handling permissions for multiple users.
Here's how to get started:
1. **Creating Groups**:
Assign users to a new group, e.g., `admins`:
```bash
$ clan secrets groups add admins <username>
```
2. **Listing Groups**:
```bash
$ clan secrets groups list
```
3. **Assigning Secrets to Groups**:
```bash
$ clan secrets groups add-secret <group_name> <secret_name>
```
## Further
Secrets in the repository follow this structure:
```
```{.console, .no-copy}
sops/
├── secrets/
│ └── <secret_name>/
@@ -73,73 +155,15 @@ sops/
```
The content of the secret is stored encrypted inside the `secret` file under `mysecret`.
By default, secrets are encrypted with your key to ensure readability.
## 2. Adding Machine Keys
New machines in Clan come with age keys stored in `./sops/machines/<machine_name>`. To list these machines:
```shellSession
$ clan secrets machines list
```
For existing machines, add their keys:
```shellSession
$ clan secrets machines add <machine_name> <age_key>
```
To fetch an age key from an SSH host key:
```shellSession
$ ssh-keyscan <domain_name> | nix shell nixpkgs#ssh-to-age -c ssh-to-age
```
## 3. Assigning Access
By default, secrets are encrypted for your key. To specify which users and machines can access a secret:
```shellSession
$ clan secrets set --machine <machine1> --machine <machine2> --user <user1> --user <user2> <secret_name>
```
You can add machines/users to existing secrets without modifying the secret:
```shellSession
$ clan secrets machines add-secret <machine_name> <secret_name>
```
## 4. Utilizing Groups
For convenience, Clan CLI allows group creation to simplify access management. Here's how:
1. **Creating Groups**:
Assign users to a new group, e.g., `admins`:
```shellSession
$ clan secrets groups add admins <username>
```
2. **Listing Groups**:
```shellSession
$ clan secrets groups list
```
3. **Assigning Secrets to Groups**:
```shellSession
$ clan secrets groups add-secret <group_name> <secret_name>
```
# NixOS integration
### NixOS integration
A NixOS machine will automatically import all secrets that are encrypted for the
current machine. At runtime it will use the host key to decrypt all secrets into
a in-memory, non-persistent filesystem using
[sops-nix](https://github.com/Mic92/sops-nix). In your nixos configuration you
can get a path to secrets like this `config.sops.secrets.<name>.path`. Example:
an in-memory, non-persistent filesystem using [sops-nix](https://github.com/Mic92/sops-nix).
In your nixos configuration you can get a path to secrets like this `config.sops.secrets.<name>.path`. For example:
```nix
{ config, ...}: {
@@ -155,19 +179,18 @@ can get a path to secrets like this `config.sops.secrets.<name>.path`. Example:
See the [readme](https://github.com/Mic92/sops-nix) of sops-nix for more
examples.
# Importing existing sops-based keys / sops-nix
### Migration: Importing existing sops-based keys / sops-nix
`clan secrets` stores each secrets in a single file, whereas [sops](https://github.com/Mic92/sops-nix)
commonly allows to put all secrets in a yaml or json documents.
`clan secrets` stores each secret in a single file, whereas [sops](https://github.com/Mic92/sops-nix) commonly allows to put all secrets in a yaml or json document.
If you already happend to use sops-nix, you can migrate by using the `clan secrets import-sops` command by importing these documents:
If you already happened to use sops-nix, you can migrate by using the `clan secrets import-sops` command by importing these files:
```shellSession
```bash
% clan secrets import-sops --prefix matchbox- --group admins --machine matchbox nixos/matchbox/secrets/secrets.yaml
```
This will create secrets for each secret found in `nixos/matchbox/secrets/secrets.yaml` in a ./sops folder of your repository.
Each member of the group `admins` will be able
This will create secrets for each secret found in `nixos/matchbox/secrets/secrets.yaml` in a `./sops` folder of your repository.
Each member of the group `admins` in this case will be able to decrypt the secrets with their respective key.
Since our clan secret module will auto-import secrets that are encrypted for a particular nixos machine,
you can now remove `sops.secrets.<secrets> = { };` unless you need to specify more options for the secret like owner/group of the secret file.

113
docs/site/index.md Normal file
View File

@@ -0,0 +1,113 @@
# Getting Started
Welcome to your simple guide on starting a new Clan project.
## What's Inside
We've put together a straightforward guide to help you out:
- [**Starting with a New Clan Project**](#starting-with-a-new-clan-project): Create a new Clan from scratch.
- [**Integrating Clan using Flake-Parts**](getting-started/flake-parts.md)
---
## **Starting with a New Clan Project**
Create your own clan with these initial steps.
### Prerequisites
#### Linux
Clan depends on nix installed on your system. Run the following command to install nix.
```bash
curl --proto '=https' --tlsv1.2 -sSf -L https://install.determinate.systems/nix | sh -s -- install
```
#### NixOS
If you run NixOS the `nix` binary is already installed.
You will also need to enable the `flakes` and `nix-commands` experimental features.
```bash
# /etc/nix/nix.conf or ~/.config/nix/nix.conf
experimental-features = nix-command flakes
```
#### Other
Clan doesn't offer dedicated support for other operating systems yet.
### Step 1: Add Clan CLI to Your Shell
Add the Clan CLI into your development workflow:
```bash
nix shell git+https://git.clan.lol/clan/clan-core#clan-cli
```
### Step 2: Initialize Your Project
Set the foundation of your Clan project by initializing it as follows:
```bash
clan flakes create my-clan
```
This command creates the `flake.nix` and `.clan-flake` files for your project.
### Step 3: Verify the Project Structure
Ensure that all project files exist by running:
```bash
cd my-clan
tree
```
This should yield the following:
``` { .console .no-copy }
.
├── flake.nix
├── machines
│   ├── jon
│   │   ├── configuration.nix
│   │   └── hardware-configuration.nix
│   └── sara
│   ├── configuration.nix
│   └── hardware-configuration.nix
└── modules
└── shared.nix
5 directories, 6 files
```
```bash
clan machines list
```
``` { .console .no-copy }
jon
sara
```
!!! success
You just successfully bootstrapped your first clan directory.
---
### What's Next?
- [**Machine Configuration**](getting-started/configure.md): Declare behavior and configuration of machines.
- [**Deploy Machines**](getting-started/machines.md): Learn how to deploy to any remote machine.
- [**Installer**](getting-started/installer.md): Setting up new computers remotely is easy with an USB stick.
- [**Check out our Templates**](templates/index.md)
---

BIN
docs/site/static/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,24 @@
# Templates
We provide some starting templates you can easily use one of those via `nix flakes`.
They showcase best practices and guide you through setting up and using Clan's modules
I.e. To use the `new-clan` template run the following command:
```bash
nix flake init -t git+https://git.clan.lol/clan/clan-core#new-clan
```
## Available Templates
We offer the following templates:
To initialize a clan with one of those run:
```bash
nix flake init -t git+https://git.clan.lol/clan/clan-core#[TEMPLATE_NAME]
```
Substitute `[TEMPLATE_NAME]` with the name of the template.
- **new-clan**: Perfect for beginners, this template shows you how to link two machines in a basic setup.

42
flake.lock generated
View File

@@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1707524024,
"narHash": "sha256-HmumZ8FuWAAYZrWUKm3N4G4h8nmZ5VUVX+vXLmCJNKM=",
"lastModified": 1712356478,
"narHash": "sha256-kTcEtrQIRnexu5lAbLsmUcfR2CrmsACF1s3ZFw1NEVA=",
"owner": "nix-community",
"repo": "disko",
"rev": "d07de570ba05cec2807d058daaa044f6955720c7",
"rev": "0a17298c0d96190ef3be729d594ba202b9c53beb",
"type": "github"
},
"original": {
@@ -27,11 +27,11 @@
]
},
"locked": {
"lastModified": 1706830856,
"narHash": "sha256-a0NYyp+h9hlb7ddVz4LUn1vT/PLwqfrWYcHMvFB1xYg=",
"lastModified": 1712014858,
"narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "b253292d9c0a5ead9bc98c4e9a26c6312e27d69f",
"rev": "9126214d0a59633752a136528f5f3b9aa8565b7d",
"type": "github"
},
"original": {
@@ -42,11 +42,11 @@
},
"nixlib": {
"locked": {
"lastModified": 1693701915,
"narHash": "sha256-waHPLdDYUOHSEtMKKabcKIMhlUOHPOOPQ9UyFeEoovs=",
"lastModified": 1711846064,
"narHash": "sha256-cqfX0QJNEnge3a77VnytM0Q6QZZ0DziFXt6tSCV8ZSc=",
"owner": "nix-community",
"repo": "nixpkgs.lib",
"rev": "f5af57d3ef9947a70ac86e42695231ac1ad00c25",
"rev": "90b1a963ff84dc532db92f678296ff2499a60a87",
"type": "github"
},
"original": {
@@ -63,11 +63,11 @@
]
},
"locked": {
"lastModified": 1707405218,
"narHash": "sha256-ZQ366Oo8WJbCqXAZET7N0Sz6RQ3G2IbqVtxQRSa3SXc=",
"lastModified": 1712191720,
"narHash": "sha256-xXtSSnVHURHsxLQO30dzCKW5NJVGV/umdQPmFjPFMVA=",
"owner": "nix-community",
"repo": "nixos-generators",
"rev": "843e2f04c716092797ffa4ce14c446adce2f09ef",
"rev": "0c15e76bed5432d7775a22e8d22059511f59d23a",
"type": "github"
},
"original": {
@@ -78,11 +78,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1707639604,
"narHash": "sha256-J5ipSdfkbYcYaH3Js2dUf3Of94BWStapdmxpW5wwH1U=",
"lastModified": 1712468661,
"narHash": "sha256-n2gVVBs+rV+HzPv/N3QQv5cdAXqSkjmaObvfeMqnw2c=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bdc57436da855500d44e9c1ce7450c0772e1cfa1",
"rev": "298edc8f1e0dfffce67f50375c9f5952e04a6d02",
"type": "github"
},
"original": {
@@ -110,11 +110,11 @@
"nixpkgs-stable": []
},
"locked": {
"lastModified": 1707620614,
"narHash": "sha256-gfAoB9dGzBu62NoAoM945aok7+6M+LFu+nvnGwAsTp4=",
"lastModified": 1712458908,
"narHash": "sha256-DMgBS+jNHDg8z3g9GkwqL8xTKXCRQ/0FGsAyrniVonc=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "2eb7c4ba3aa75e2660fd217eb1ab64d5b793608e",
"rev": "39191e8e6265b106c9a2ba0cfd3a4dafe98a31c6",
"type": "github"
},
"original": {
@@ -130,11 +130,11 @@
]
},
"locked": {
"lastModified": 1707300477,
"narHash": "sha256-qQF0fEkHlnxHcrKIMRzOETnRBksUK048MXkX0SOmxvA=",
"lastModified": 1711963903,
"narHash": "sha256-N3QDhoaX+paWXHbEXZapqd1r95mdshxToGowtjtYkGI=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "ac599dab59a66304eb511af07b3883114f061b9d",
"rev": "49dc4a92b02b8e68798abd99184f228243b6e3ac",
"type": "github"
},
"original": {

View File

@@ -2,7 +2,9 @@
description = "clan.lol base operating system";
nixConfig.extra-substituters = [ "https://cache.clan.lol" ];
nixConfig.extra-trusted-public-keys = [ "cache.clan.lol-1:3KztgSAB5R1M+Dz7vzkBGzXdodizbgLXGXKXlcQLA28=" ];
nixConfig.extra-trusted-public-keys = [
"cache.clan.lol-1:3KztgSAB5R1M+Dz7vzkBGzXdodizbgLXGXKXlcQLA28="
];
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable-small";
@@ -20,8 +22,11 @@
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
};
outputs = inputs @ { flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } ({ lib, ... }: {
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } (
{ ... }:
{
systems = [
"x86_64-linux"
"aarch64-linux"
@@ -29,34 +34,19 @@
];
imports = [
./checks/flake-module.nix
./devShell.nix
./formatter.nix
./templates/flake-module.nix
./clanModules/flake-module.nix
./pkgs/flake-module.nix
./flakeModules/flake-module.nix
(import ./flakeModules/clan.nix inputs.self)
./devShell.nix
# TODO: migrate this @davHau
# ./docs/flake-module
./docs/nix/flake-module.nix
./formatter.nix
./lib/flake-module.nix
./nixosModules/flake-module.nix
{
options.flake = flake-parts.lib.mkSubmoduleOptions {
clanInternals = lib.mkOption {
type = lib.types.submodule {
options = {
all-machines-json = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
};
machines = lib.mkOption {
type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified);
};
machinesFunc = lib.mkOption {
type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified);
};
};
};
};
};
}
./pkgs/flake-module.nix
./templates/flake-module.nix
];
});
}
);
}

75
flakeModules/clan.nix Normal file
View File

@@ -0,0 +1,75 @@
clan-core:
{
config,
lib,
flake-parts-lib,
inputs,
self,
...
}:
let
inherit (lib) mkOption types;
buildClan = import ../lib/build-clan {
inherit lib clan-core;
inherit (inputs) nixpkgs;
};
cfg = config.clan;
in
{
options.clan = {
directory = mkOption {
type = types.path;
description = "The directory containing the clan subdirectory";
default = self; # default to the directory of the flake
};
specialArgs = mkOption {
type = types.attrsOf types.raw;
default = { };
description = "Extra arguments to pass to nixosSystem i.e. useful to make self available";
};
machines = mkOption {
type = types.attrsOf types.raw;
default = { };
description = "Allows to include machine-specific modules i.e. machines.\${name} = { ... }";
};
clanName = mkOption {
type = types.str;
description = "Needs to be (globally) unique, as this determines the folder name where the flake gets downloaded to.";
};
clanIcon = mkOption {
type = types.nullOr types.path;
default = null;
description = "A path to an icon to be used for the clan, should be the same for all machines";
};
pkgsForSystem = mkOption {
type = types.functionTo types.raw;
default = _system: null;
description = "A map from arch to pkgs, if specified this nixpkgs will be only imported once for each system.";
};
};
options.flake = flake-parts-lib.mkSubmoduleOptions {
clanInternals = lib.mkOption {
type = lib.types.submodule {
options = {
all-machines-json = lib.mkOption { type = lib.types.attrsOf lib.types.unspecified; };
machines = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); };
machinesFunc = lib.mkOption { type = lib.types.attrsOf (lib.types.attrsOf lib.types.unspecified); };
};
};
};
};
config = {
flake = buildClan {
inherit (cfg)
directory
specialArgs
machines
clanName
clanIcon
pkgsForSystem
;
};
};
_file = __curPos.file;
}

View File

@@ -0,0 +1,7 @@
{ self, config, ... }:
{
flake.flakeModules = {
clan = import ./clan.nix self;
default = config.flake.flakeModules.clan;
};
}

View File

@@ -1,20 +1,17 @@
{ lib
, inputs
, ...
}: {
imports = [
inputs.treefmt-nix.flakeModule
];
perSystem = { self', pkgs, ... }: {
{ lib, inputs, ... }:
{
imports = [ inputs.treefmt-nix.flakeModule ];
perSystem =
{ self', pkgs, ... }:
{
treefmt.projectRootFile = "flake.nix";
treefmt.flakeCheck = true;
treefmt.flakeFormatter = true;
treefmt.programs.shellcheck.enable = true;
treefmt.programs.mypy.enable = true;
treefmt.programs.mypy.directories = {
"pkgs/clan-cli".extraPythonPackages = self'.packages.clan-cli.pytestDependencies;
"pkgs/clan-vm-manager".extraPythonPackages = self'.packages.clan-vm-manager.propagatedBuildInputs;
"pkgs/clan-cli".extraPythonPackages = self'.packages.clan-cli.testDependencies;
"pkgs/clan-vm-manager".extraPythonPackages =
self'.packages.clan-vm-manager.externalTestDeps ++ self'.packages.clan-cli.testDependencies;
};
treefmt.settings.formatter.nix = {
@@ -25,18 +22,22 @@
# First deadnix
${lib.getExe pkgs.deadnix} --edit "$@"
# Then nixpkgs-fmt
${lib.getExe pkgs.nixpkgs-fmt} "$@"
${lib.getExe pkgs.nixfmt-rfc-style} "$@"
''
"--" # this argument is ignored by bash
];
includes = [ "*.nix" ];
excludes = [
# Was copied from nixpkgs. Keep diff minimal to simplify upstreaming.
"pkgs/builders/script-writers.nix"
];
};
treefmt.settings.formatter.python = {
command = "sh";
options = [
"-eucx"
''
${lib.getExe pkgs.ruff} --fix "$@"
${lib.getExe pkgs.ruff} check --fix "$@"
${lib.getExe pkgs.ruff} format "$@"
''
"--" # this argument is ignored by bash

View File

@@ -1,36 +1,51 @@
{ clan-core, nixpkgs, lib }:
{ directory # The directory containing the machines subdirectory
, specialArgs ? { } # Extra arguments to pass to nixosSystem i.e. useful to make self available
, machines ? { } # allows to include machine-specific modules i.e. machines.${name} = { ... }
, clanName # Needs to be (globally) unique, as this determines the folder name where the flake gets downloaded to.
, clanIcon ? null # A path to an icon to be used for the clan, should be the same for all machines
{
clan-core,
nixpkgs,
lib,
}:
{
directory, # The directory containing the machines subdirectory
specialArgs ? { }, # Extra arguments to pass to nixosSystem i.e. useful to make self available
machines ? { }, # allows to include machine-specific modules i.e. machines.${name} = { ... }
clanName, # Needs to be (globally) unique, as this determines the folder name where the flake gets downloaded to.
clanIcon ? null, # A path to an icon to be used for the clan, should be the same for all machines
pkgsForSystem ? (_system: null), # A map from arch to pkgs, if specified this nixpkgs will be only imported once for each system.
# This improves performance, but all nipxkgs.* options will be ignored.
}:
let
machinesDirs = lib.optionalAttrs (builtins.pathExists "${directory}/machines") (builtins.readDir (directory + /machines));
machinesDirs = lib.optionalAttrs (builtins.pathExists "${directory}/machines") (
builtins.readDir (directory + /machines)
);
machineSettings = machineName:
machineSettings =
machineName:
# CLAN_MACHINE_SETTINGS_FILE allows to override the settings file temporarily
# This is useful for doing a dry-run before writing changes into the settings.json
# Using CLAN_MACHINE_SETTINGS_FILE requires passing --impure to nix eval
if builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE" != ""
then builtins.fromJSON (builtins.readFile (builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE"))
if builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE" != "" then
builtins.fromJSON (builtins.readFile (builtins.getEnv "CLAN_MACHINE_SETTINGS_FILE"))
else
lib.optionalAttrs (builtins.pathExists "${directory}/machines/${machineName}/settings.json")
(builtins.fromJSON
(builtins.readFile (directory + /machines/${machineName}/settings.json)));
lib.optionalAttrs (builtins.pathExists "${directory}/machines/${machineName}/settings.json") (
builtins.fromJSON (builtins.readFile (directory + /machines/${machineName}/settings.json))
);
# Read additional imports specified via a config option in settings.json
# This is not an infinite recursion, because the imports are discovered here
# before calling evalModules.
# It is still useful to have the imports as an option, as this allows for type
# checking and easy integration with the config frontend(s)
machineImports = machineSettings:
map
(module: clan-core.clanModules.${module})
(machineSettings.clanImports or [ ]);
machineImports =
machineSettings: map (module: clan-core.clanModules.${module}) (machineSettings.clanImports or [ ]);
# TODO: remove default system once we have a hardware-config mechanism
nixosConfiguration = { system ? "x86_64-linux", name, pkgs ? null, extraConfig ? { } }: nixpkgs.lib.nixosSystem {
nixosConfiguration =
{
system ? "x86_64-linux",
name,
pkgs ? null,
extraConfig ? { },
}:
nixpkgs.lib.nixosSystem {
modules =
let
settings = machineSettings name;
@@ -41,7 +56,9 @@ let
clan-core.nixosModules.clanCore
extraConfig
(machines.${name} or { })
({
(
{
networking.hostName = lib.mkDefault name;
clanCore.clanName = clanName;
clanCore.clanIcon = clanIcon;
clanCore.clanDir = directory;
@@ -53,11 +70,13 @@ let
type = "path";
path = lib.mkDefault nixpkgs;
};
} // lib.optionalAttrs (pkgs != null) {
nixpkgs.pkgs = lib.mkForce pkgs;
})
}
// lib.optionalAttrs (pkgs != null) { nixpkgs.pkgs = lib.mkForce pkgs; }
)
];
inherit specialArgs;
specialArgs = {
inherit clan-core;
} // specialArgs;
};
allMachines = machinesDirs // machines;
@@ -75,17 +94,38 @@ let
# This instantiates nixos for each system that we support:
# configPerSystem = <system>.<machine>.nixosConfiguration
# We need this to build nixos secret generators for each system
configsPerSystem = builtins.listToAttrs
(builtins.map
(system: lib.nameValuePair system
(lib.mapAttrs (name: _: nixosConfiguration { inherit name system; }) allMachines))
supportedSystems);
configsPerSystem = builtins.listToAttrs (
builtins.map (
system:
lib.nameValuePair system (
lib.mapAttrs (
name: _:
nixosConfiguration {
inherit name system;
pkgs = pkgsForSystem system;
}
) allMachines
)
) supportedSystems
);
configsFuncPerSystem = builtins.listToAttrs
(builtins.map
(system: lib.nameValuePair system
(lib.mapAttrs (name: _: args: nixosConfiguration (args // { inherit name system; })) allMachines))
supportedSystems);
configsFuncPerSystem = builtins.listToAttrs (
builtins.map (
system:
lib.nameValuePair system (
lib.mapAttrs (
name: _: args:
nixosConfiguration (
args
// {
inherit name system;
pkgs = pkgsForSystem system;
}
)
) allMachines
)
) supportedSystems
);
in
{
inherit nixosConfigurations;
@@ -93,8 +133,11 @@ in
clanInternals = {
machines = configsPerSystem;
machinesFunc = configsFuncPerSystem;
all-machines-json = lib.mapAttrs
(system: configs: nixpkgs.legacyPackages.${system}.writers.writeJSON "machines.json" (lib.mapAttrs (_: m: m.config.system.clan.deployment.data) configs))
configsPerSystem;
all-machines-json = lib.mapAttrs (
system: configs:
nixpkgs.legacyPackages.${system}.writers.writeJSON "machines.json" (
lib.mapAttrs (_: m: m.config.system.clan.deployment.data) configs
)
) configsPerSystem;
};
}

View File

@@ -1,4 +1,9 @@
{ lib, clan-core, nixpkgs, ... }:
{
lib,
clan-core,
nixpkgs,
...
}:
{
jsonschema = import ./jsonschema { inherit lib; };

View File

@@ -1,11 +1,11 @@
{ lib
, inputs
, self
, ...
}: {
imports = [
./jsonschema/flake-module.nix
];
{
lib,
inputs,
self,
...
}:
{
imports = [ ./jsonschema/flake-module.nix ];
flake.lib = import ./default.nix {
inherit lib;
inherit (inputs) nixpkgs;

View File

@@ -1,15 +1,18 @@
{ lib ? import <nixpkgs/lib>
, excludedTypes ? [
{
lib ? import <nixpkgs/lib>,
excludedTypes ? [
"functionTo"
"package"
]
],
}:
let
# remove _module attribute from options
clean = opts: builtins.removeAttrs opts [ "_module" ];
# throw error if option type is not supported
notSupported = option: lib.trace option throw ''
notSupported =
option:
lib.trace option throw ''
option type '${option.type.name}' ('${option.type.description}') not supported by jsonschema converter
location: ${lib.concatStringsSep "." option.loc}
'';
@@ -20,23 +23,29 @@ let
filterExcludedAttrs = lib.filterAttrs (_name: opt: !isExcludedOption opt);
allBasicTypes =
[ "boolean" "integer" "number" "string" "array" "object" "null" ];
allBasicTypes = [
"boolean"
"integer"
"number"
"string"
"array"
"object"
"null"
];
in
rec {
# parses a nixos module to a jsonschema
parseModule = module:
parseModule =
module:
let
evaled = lib.evalModules {
modules = [ module ];
};
evaled = lib.evalModules { modules = [ module ]; };
in
parseOptions evaled.options;
# parses a set of evaluated nixos options to a jsonschema
parseOptions = options':
parseOptions =
options':
let
options = filterExcludedAttrs (clean options');
# parse options to jsonschema properties
@@ -44,22 +53,20 @@ rec {
# TODO: figure out how to handle if prop.anyOf is used
isRequired = prop: !(prop ? default || prop.type or null == "object");
requiredProps = lib.filterAttrs (_: prop: isRequired prop) properties;
required = lib.optionalAttrs (requiredProps != { }) {
required = lib.attrNames requiredProps;
};
required = lib.optionalAttrs (requiredProps != { }) { required = lib.attrNames requiredProps; };
in
# return jsonschema
required // {
required
// {
type = "object";
inherit properties;
};
# parses and evaluated nixos option to a jsonschema property definition
parseOption = option:
parseOption =
option:
let
default = lib.optionalAttrs (option ? default) {
inherit (option) default;
};
default = lib.optionalAttrs (option ? default) { inherit (option) default; };
description = lib.optionalAttrs (option ? description) {
description = option.description.text or option.description;
};
@@ -67,177 +74,217 @@ rec {
# either type
# TODO: if all nested optiosn are excluded, the parent sould be excluded too
if option.type.name or null == "either"
if
option.type.name or null == "either"
# return jsonschema property definition for either
then
let
optionsList' = [
{ type = option.type.nestedTypes.left; _type = "option"; loc = option.loc; }
{ type = option.type.nestedTypes.right; _type = "option"; loc = option.loc; }
{
type = option.type.nestedTypes.left;
_type = "option";
loc = option.loc;
}
{
type = option.type.nestedTypes.right;
_type = "option";
loc = option.loc;
}
];
optionsList = filterExcluded optionsList';
in
default // description // {
anyOf = map parseOption optionsList;
}
default // description // { anyOf = map parseOption optionsList; }
# handle nested options (not a submodule)
else if ! option ? _type
then parseOptions option
else if !option ? _type then
parseOptions option
# throw if not an option
else if option._type != "option" && option._type != "option-type"
then throw "parseOption: not an option"
else if option._type != "option" && option._type != "option-type" then
throw "parseOption: not an option"
# parse nullOr
else if option.type.name == "nullOr"
else if
option.type.name == "nullOr"
# return jsonschema property definition for nullOr
then
let
nestedOption =
{ type = option.type.nestedTypes.elemType; _type = "option"; loc = option.loc; };
nestedOption = {
type = option.type.nestedTypes.elemType;
_type = "option";
loc = option.loc;
};
in
default // description // {
anyOf =
[{ type = "null"; }]
++ (
lib.optional (! isExcludedOption nestedOption)
(parseOption nestedOption)
);
default
// description
// {
anyOf = [
{ type = "null"; }
] ++ (lib.optional (!isExcludedOption nestedOption) (parseOption nestedOption));
}
# parse bool
else if option.type.name == "bool"
else if
option.type.name == "bool"
# return jsonschema property definition for bool
then default // description // {
type = "boolean";
}
then
default // description // { type = "boolean"; }
# parse float
else if option.type.name == "float"
else if
option.type.name == "float"
# return jsonschema property definition for float
then default // description // {
type = "number";
}
then
default // description // { type = "number"; }
# parse int
else if (option.type.name == "int" || option.type.name == "positiveInt")
else if
(option.type.name == "int" || option.type.name == "positiveInt")
# return jsonschema property definition for int
then default // description // {
type = "integer";
}
then
default // description // { type = "integer"; }
# parse string
else if option.type.name == "str"
else if
option.type.name == "str"
# return jsonschema property definition for string
then default // description // {
type = "string";
}
then
default // description // { type = "string"; }
# parse string
else if option.type.name == "path"
else if
option.type.name == "path"
# return jsonschema property definition for path
then default // description // {
type = "string";
}
then
default // description // { type = "string"; }
# parse anything
else if option.type.name == "anything"
else if
option.type.name == "anything"
# return jsonschema property definition for anything
then default // description // {
type = allBasicTypes;
}
then
default // description // { type = allBasicTypes; }
# parse unspecified
else if option.type.name == "unspecified"
else if
option.type.name == "unspecified"
# return jsonschema property definition for unspecified
then default // description // {
type = allBasicTypes;
}
then
default // description // { type = allBasicTypes; }
# parse raw
else if option.type.name == "raw"
else if
option.type.name == "raw"
# return jsonschema property definition for raw
then default // description // {
type = allBasicTypes;
}
then
default // description // { type = allBasicTypes; }
# parse enum
else if option.type.name == "enum"
else if
option.type.name == "enum"
# return jsonschema property definition for enum
then default // description // {
enum = option.type.functor.payload;
}
then
default // description // { enum = option.type.functor.payload; }
# parse listOf submodule
else if option.type.name == "listOf" && option.type.functor.wrapped.name == "submodule"
else if
option.type.name == "listOf" && option.type.functor.wrapped.name == "submodule"
# return jsonschema property definition for listOf submodule
then default // description // {
then
default
// description
// {
type = "array";
items = parseOptions (option.type.functor.wrapped.getSubOptions option.loc);
}
# parse list
else if (option.type.name == "listOf")
else if
(option.type.name == "listOf")
# return jsonschema property definition for list
then
let
nestedOption = { type = option.type.functor.wrapped; _type = "option"; loc = option.loc; };
nestedOption = {
type = option.type.functor.wrapped;
_type = "option";
loc = option.loc;
};
in
default // description // {
default
// description
// {
type = "array";
}
// (lib.optionalAttrs (! isExcludedOption nestedOption) {
items = parseOption nestedOption;
})
// (lib.optionalAttrs (!isExcludedOption nestedOption) { items = parseOption nestedOption; })
# parse list of unspecified
else if
(option.type.name == "listOf")
&& (option.type.functor.wrapped.name == "unspecified")
(option.type.name == "listOf") && (option.type.functor.wrapped.name == "unspecified")
# return jsonschema property definition for list
then default // description // {
type = "array";
}
then
default // description // { type = "array"; }
# parse attrsOf submodule
else if option.type.name == "attrsOf" && option.type.nestedTypes.elemType.name == "submodule"
else if
option.type.name == "attrsOf" && option.type.nestedTypes.elemType.name == "submodule"
# return jsonschema property definition for attrsOf submodule
then default // description // {
then
default
// description
// {
type = "object";
additionalProperties = parseOptions (option.type.nestedTypes.elemType.getSubOptions option.loc);
}
# parse attrs
else if option.type.name == "attrs"
else if
option.type.name == "attrs"
# return jsonschema property definition for attrs
then default // description // {
then
default
// description
// {
type = "object";
additionalProperties = true;
}
# parse attrsOf
# TODO: if nested option is excluded, the parent sould be excluded too
else if option.type.name == "attrsOf" || option.type.name == "lazyAttrsOf"
else if
option.type.name == "attrsOf" || option.type.name == "lazyAttrsOf"
# return jsonschema property definition for attrs
then
let
nestedOption = { type = option.type.nestedTypes.elemType; _type = "option"; loc = option.loc; };
nestedOption = {
type = option.type.nestedTypes.elemType;
_type = "option";
loc = option.loc;
};
in
default // description // {
default
// description
// {
type = "object";
additionalProperties =
if ! isExcludedOption nestedOption
then parseOption { type = option.type.nestedTypes.elemType; _type = "option"; loc = option.loc; }
else false;
if !isExcludedOption nestedOption then
parseOption {
type = option.type.nestedTypes.elemType;
_type = "option";
loc = option.loc;
}
else
false;
}
# parse submodule
else if option.type.name == "submodule"
else if
option.type.name == "submodule"
# return jsonschema property definition for submodule
# then (lib.attrNames (option.type.getSubOptions option.loc).opt)
then parseOptions (option.type.getSubOptions option.loc)
then
parseOptions (option.type.getSubOptions option.loc)
# throw error if option type is not supported
else notSupported option;
else
notSupported option;
}

View File

@@ -1,7 +1,6 @@
/*
An example nixos module declaring an interface.
*/
{ lib, ... }: {
# An example nixos module declaring an interface.
{ lib, ... }:
{
options = {
# str
name = lib.mkOption {
@@ -44,7 +43,11 @@
# list of str
kernelModules = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ "nvme" "xhci_pci" "ahci" ];
default = [
"nvme"
"xhci_pci"
"ahci"
];
description = "A list of enabled kernel modules";
};
};

View File

@@ -1,5 +1,7 @@
{
perSystem = { pkgs, ... }: {
perSystem =
{ pkgs, ... }:
{
checks = {
# check if the `clan config` example jsonschema and data is valid

View File

@@ -1,6 +1,7 @@
# run these tests via `nix-unit ./test.nix`
{ lib ? (import <nixpkgs> { }).lib
, slib ? import ./. { inherit lib; }
{
lib ? (import <nixpkgs> { }).lib,
slib ? import ./. { inherit lib; },
}:
{
parseOption = import ./test_parseOption.nix { inherit lib slib; };

View File

@@ -1,21 +1,25 @@
# tests for the nixos options to jsonschema converter
# run these tests via `nix-unit ./test.nix`
{ lib ? (import <nixpkgs> { }).lib
, slib ? import ./. { inherit lib; }
{
lib ? (import <nixpkgs> { }).lib,
slib ? import ./. { inherit lib; },
}:
let
description = "Test Description";
evalType = type: default:
evalType =
type: default:
let
evaledConfig = lib.evalModules {
modules = [{
modules = [
{
options.opt = lib.mkOption {
inherit type;
inherit default;
inherit description;
};
}];
}
];
};
in
evaledConfig.options.opt;
@@ -25,11 +29,7 @@ in
testNoDefaultNoDescription =
let
evaledConfig = lib.evalModules {
modules = [{
options.opt = lib.mkOption {
type = lib.types.bool;
};
}];
modules = [ { options.opt = lib.mkOption { type = lib.types.bool; }; } ];
};
in
{
@@ -42,7 +42,8 @@ in
testDescriptionIsAttrs =
let
evaledConfig = lib.evalModules {
modules = [{
modules = [
{
options.opt = lib.mkOption {
type = lib.types.bool;
description = {
@@ -50,7 +51,8 @@ in
text = description;
};
};
}];
}
];
};
in
{
@@ -112,7 +114,11 @@ in
testEnum =
let
default = "foo";
values = [ "foo" "bar" "baz" ];
values = [
"foo"
"bar"
"baz"
];
in
{
expr = slib.parseOption (evalType (lib.types.enum values) default);
@@ -124,7 +130,11 @@ in
testListOfInt =
let
default = [ 1 2 3 ];
default = [
1
2
3
];
in
{
expr = slib.parseOption (evalType (lib.types.listOf lib.types.int) default);
@@ -139,14 +149,26 @@ in
testListOfUnspecified =
let
default = [ 1 2 3 ];
default = [
1
2
3
];
in
{
expr = slib.parseOption (evalType (lib.types.listOf lib.types.unspecified) default);
expected = {
type = "array";
items = {
type = [ "boolean" "integer" "number" "string" "array" "object" "null" ];
type = [
"boolean"
"integer"
"number"
"string"
"array"
"object"
"null"
];
};
inherit default description;
};
@@ -154,7 +176,11 @@ in
testAttrs =
let
default = { foo = 1; bar = 2; baz = 3; };
default = {
foo = 1;
bar = 2;
baz = 3;
};
in
{
expr = slib.parseOption (evalType (lib.types.attrs) default);
@@ -167,7 +193,11 @@ in
testAttrsOfInt =
let
default = { foo = 1; bar = 2; baz = 3; };
default = {
foo = 1;
bar = 2;
baz = 3;
};
in
{
expr = slib.parseOption (evalType (lib.types.attrsOf lib.types.int) default);
@@ -182,7 +212,11 @@ in
testLazyAttrsOfInt =
let
default = { foo = 1; bar = 2; baz = 3; };
default = {
foo = 1;
bar = 2;
baz = 3;
};
in
{
expr = slib.parseOption (evalType (lib.types.lazyAttrsOf lib.types.int) default);
@@ -286,7 +320,10 @@ in
inherit description;
};
};
default = { foo.opt = false; bar.opt = true; };
default = {
foo.opt = false;
bar.opt = true;
};
in
{
expr = slib.parseOption (evalType (lib.types.attrsOf (lib.types.submodule subModule)) default);
@@ -315,7 +352,10 @@ in
inherit description;
};
};
default = [{ opt = false; } { opt = true; }];
default = [
{ opt = false; }
{ opt = true; }
];
in
{
expr = slib.parseOption (evalType (lib.types.listOf (lib.types.submodule subModule)) default);
@@ -358,7 +398,15 @@ in
expr = slib.parseOption (evalType lib.types.anything default);
expected = {
inherit default description;
type = [ "boolean" "integer" "number" "string" "array" "object" "null" ];
type = [
"boolean"
"integer"
"number"
"string"
"array"
"object"
"null"
];
};
};
@@ -370,7 +418,15 @@ in
expr = slib.parseOption (evalType lib.types.unspecified default);
expected = {
inherit default description;
type = [ "boolean" "integer" "number" "string" "array" "object" "null" ];
type = [
"boolean"
"integer"
"number"
"string"
"array"
"object"
"null"
];
};
};
@@ -382,7 +438,15 @@ in
expr = slib.parseOption (evalType lib.types.raw default);
expected = {
inherit default description;
type = [ "boolean" "integer" "number" "string" "array" "object" "null" ];
type = [
"boolean"
"integer"
"number"
"string"
"array"
"object"
"null"
];
};
};
}

View File

@@ -1,14 +1,13 @@
# tests for the nixos options to jsonschema converter
# run these tests via `nix-unit ./test.nix`
{ lib ? (import <nixpkgs> { }).lib
, slib ? import ./. { inherit lib; }
{
lib ? (import <nixpkgs> { }).lib,
slib ? import ./. { inherit lib; },
}:
let
evaledOptions =
let
evaledConfig = lib.evalModules {
modules = [ ./example-interface.nix ];
};
evaledConfig = lib.evalModules { modules = [ ./example-interface.nix ]; };
in
evaledConfig.options;
in
@@ -21,11 +20,7 @@ in
testParseNestedOptions =
let
evaled = lib.evalModules {
modules = [{
options.foo.bar = lib.mkOption {
type = lib.types.bool;
};
}];
modules = [ { options.foo.bar = lib.mkOption { type = lib.types.bool; }; } ];
};
in
{
@@ -34,7 +29,9 @@ in
properties = {
foo = {
properties = {
bar = { type = "boolean"; };
bar = {
type = "boolean";
};
};
required = [ "bar" ];
type = "object";

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBIbwIVnLy+uoDZ6uK/OCc1QK46SIGeC3mVc85dqLYQw lass@ignavia

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBIbwIVnLy+uoDZ6uK/OCc1QK46SIGeC3mVc85dqLYQw lass@ignavia

View File

@@ -1,11 +1,12 @@
{ lib, ... }:
{
imports = [
./state.nix
];
imports = [ ./state.nix ];
options.clanCore.backups = {
providers = lib.mkOption {
type = lib.types.attrsOf (lib.types.submodule ({ name, ... }: {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.str;
@@ -17,29 +18,27 @@
list = lib.mkOption {
type = lib.types.str;
description = ''
script to list backups
Command to list backups.
'';
};
restore = lib.mkOption {
type = lib.types.str;
description = ''
script to restore a backup
should take an optional service name as argument
gets ARCHIVE_ID, LOCATION, JOB and FOLDERS as environment variables
ARCHIVE_ID is the id of the backup
LOCATION is the remote identifier of the backup
JOB is the job name of the backup
FOLDERS is a colon separated list of folders to restore
Command to restore a backup.
The name of the backup and the folders to restore will be
set as environment variables NAME and FOLDERS respectively.
'';
};
create = lib.mkOption {
type = lib.types.str;
description = ''
script to start a backup
Command to start a backup
'';
};
};
}));
}
)
);
default = { };
description = ''
Configured backup providers which are used by this machine

View File

@@ -1,9 +1,9 @@
{
imports = [
./backups.nix
./facts
./manual.nix
./imports.nix
./meshnamed
./metadata.nix
./networking.nix
./nix-settings.nix
@@ -11,7 +11,6 @@
./outputs.nix
./packages.nix
./schema.nix
./secrets
./vm.nix
./wayland-proxy-virtwl.nix
./zerotier

View File

@@ -0,0 +1,167 @@
{ config, lib, ... }:
{
imports = [
(lib.mkRemovedOptionModule [
"clanCore"
"secretsPrefix"
] "secretsPrefix was only used by the sops module and the code is now integrated in there")
(lib.mkRenamedOptionModule
[
"clanCore"
"secretStore"
]
[
"clanCore"
"facts"
"secretStore"
]
)
(lib.mkRemovedOptionModule [
"clanCore"
"secretsDirectory"
] "clancore.secretsDirectory was removed. Use clanCore.facts.secretPathFunction instead")
(lib.mkRenamedOptionModule
[
"clanCore"
"secretsUploadDirectory"
]
[
"clanCore"
"facts"
"secretUploadDirectory"
]
)
];
options.clanCore.secrets = lib.mkOption {
visible = false;
default = { };
type = lib.types.attrsOf (
lib.types.submodule (service: {
options = {
name = lib.mkOption {
type = lib.types.str;
default = service.config._module.args.name;
description = ''
Namespace of the service
'';
};
generator = lib.mkOption {
type = lib.types.submodule (
{ ... }:
{
options = {
path = lib.mkOption {
type = lib.types.listOf (lib.types.either lib.types.path lib.types.package);
default = [ ];
description = ''
Extra paths to add to the PATH environment variable when running the generator.
'';
};
prompt = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
prompt text to ask for a value.
This value will be passed to the script as the environment variable $prompt_value.
'';
};
script = lib.mkOption {
type = lib.types.str;
description = ''
Script to generate the secret.
The script will be called with the following variables:
- facts: path to a directory where facts can be stored
- secrets: path to a directory where secrets can be stored
The script is expected to generate all secrets and facts defined in the module.
'';
};
};
}
);
};
secrets = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (secret: {
options =
{
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
};
path = lib.mkOption {
type = lib.types.path;
description = ''
path to a secret which is generated by the generator
'';
default = config.clanCore.facts.secretPathFunction secret;
defaultText = lib.literalExpression "config.clanCore.facts.secretPathFunction secret";
};
}
// lib.optionalAttrs (config.clanCore.facts.secretStore == "sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clanCore.sops.defaultGroups;
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
};
})
);
description = ''
path where the secret is located in the filesystem
'';
};
facts = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (fact: {
options = {
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the fact
'';
default = fact.config._module.args.name;
};
path = lib.mkOption {
type = lib.types.path;
description = ''
path to a fact which is generated by the generator
'';
default =
config.clanCore.clanDir
+ "/machines/${config.clanCore.machineName}/facts/${fact.config._module.args.name}";
defaultText = lib.literalExpression "\${config.clanCore.clanDir}/machines/\${config.clanCore.machineName}/facts/\${fact.config._module.args.name}";
};
value = lib.mkOption {
defaultText = lib.literalExpression "\${config.clanCore.clanDir}/\${fact.config.path}";
type = lib.types.nullOr lib.types.str;
default =
if builtins.pathExists fact.config.path then lib.strings.fileContents fact.config.path else null;
};
};
})
);
};
};
})
);
};
config = lib.mkIf (config.clanCore.secrets != { }) {
clanCore.facts.services = lib.mapAttrs' (
name: service:
lib.warn "clanCore.secrets.${name} is deprecated, use clanCore.facts.services.${name} instead" (
lib.nameValuePair name ({
secret = service.secrets;
public = service.facts;
generator = service.generator;
})
)
) config.clanCore.secrets;
};
}

View File

@@ -0,0 +1,222 @@
{
config,
lib,
pkgs,
...
}:
{
options.clanCore.facts = {
secretStore = lib.mkOption {
type = lib.types.enum [
"sops"
"password-store"
"vm"
"custom"
];
default = "sops";
description = ''
method to store secret facts
custom can be used to define a custom secret fact store.
'';
};
secretModule = lib.mkOption {
type = lib.types.str;
internal = true;
description = ''
the python import path to the secret module
'';
};
secretUploadDirectory = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
The directory where secrets are uploaded into, This is backend specific.
'';
};
secretPathFunction = lib.mkOption {
type = lib.types.raw;
description = ''
The function to use to generate the path for a secret.
The default function will use the path attribute of the secret.
The function will be called with the secret submodule as an argument.
'';
};
publicStore = lib.mkOption {
type = lib.types.enum [
"in_repo"
"vm"
"custom"
];
default = "in_repo";
description = ''
method to store public facts.
custom can be used to define a custom public fact store.
'';
};
publicModule = lib.mkOption {
type = lib.types.str;
internal = true;
description = ''
the python import path to the public module
'';
};
publicDirectory = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
};
services = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (service: {
options = {
name = lib.mkOption {
type = lib.types.str;
default = service.config._module.args.name;
description = ''
Namespace of the service
'';
};
generator = lib.mkOption {
type = lib.types.submodule (
{ config, ... }:
{
options = {
path = lib.mkOption {
type = lib.types.listOf (lib.types.either lib.types.path lib.types.package);
default = [ ];
description = ''
Extra paths to add to the PATH environment variable when running the generator.
'';
};
prompt = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = null;
description = ''
prompt text to ask for a value.
This value will be passed to the script as the environment variable $prompt_value.
'';
};
script = lib.mkOption {
type = lib.types.str;
description = ''
Shell script snippet to generate the secrets and facts.
The script has access to the following environment variables:
- facts: path to a directory where facts can be stored
- secrets: path to a directory where secrets can be stored
The script is expected to generate all secrets and facts defined for this service.
'';
};
finalScript = lib.mkOption {
type = lib.types.str;
readOnly = true;
internal = true;
default = ''
set -eu -o pipefail
export PATH="${lib.makeBinPath config.path}:${pkgs.coreutils}/bin"
# prepare sandbox user
mkdir -p /etc
cp ${
pkgs.runCommand "fake-etc" { } ''
export PATH="${pkgs.coreutils}/bin"
mkdir -p $out
cp /etc/* $out/
''
}/* /etc/
${config.script}
'';
};
};
}
);
};
secret = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (secret: {
options =
{
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the secret
'';
default = secret.config._module.args.name;
};
path = lib.mkOption {
type = lib.types.str;
description = ''
path to a secret which is generated by the generator
'';
default = config.clanCore.facts.secretPathFunction secret;
};
}
// lib.optionalAttrs (config.clanCore.facts.secretModule == "clan_cli.facts.secret_modules.sops") {
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = config.clanCore.sops.defaultGroups;
description = ''
Groups to decrypt the secret for. By default we always use the user's key.
'';
};
};
})
);
description = ''
path where the secret is located in the filesystem
'';
};
public = lib.mkOption {
default = { };
type = lib.types.attrsOf (
lib.types.submodule (fact: {
options = {
name = lib.mkOption {
type = lib.types.str;
description = ''
name of the public fact
'';
default = fact.config._module.args.name;
};
path = lib.mkOption {
type = lib.types.path;
description = ''
path to a fact which is generated by the generator
'';
defaultText = lib.literalExpression "\${config.clanCore.clanDir}/machines/\${config.clanCore.machineName}/facts/\${fact.config.name}";
default =
config.clanCore.clanDir + "/machines/${config.clanCore.machineName}/facts/${fact.config.name}";
};
value = lib.mkOption {
defaultText = lib.literalExpression "\${config.clanCore.clanDir}/\${fact.config.path}";
type = lib.types.nullOr lib.types.str;
default =
if builtins.pathExists fact.config.path then lib.strings.fileContents fact.config.path else null;
};
};
})
);
};
};
})
);
};
};
imports = [
./compat.nix
./secret/sops.nix
./secret/password-store.nix
./secret/vm.nix
./public/in_repo.nix
./public/vm.nix
];
}

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