Compare commits

...

232 Commits

Author SHA1 Message Date
Johannes Kirschbauer
9fa017bc7b Docs: init empty migration guide with references 2025-05-12 22:26:35 +02:00
Johannes Kirschbauer
c25910c796 Feat: print better error if module was migrated 2025-05-12 22:26:35 +02:00
Johannes Kirschbauer
0d417bf098 Fix: update test and docs 2025-05-12 22:26:35 +02:00
pinpox
7609a9d0d7 Remove admin UI interface 2025-05-12 22:26:35 +02:00
pinpox
9b1a4e8219 migrate admin module 2025-05-12 22:26:35 +02:00
Mic92
ef4b5cc9d5 Merge pull request 'checks/mumble: make delays between keyboard clicks more robust' (#3578) from mumble-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3578
2025-05-12 13:39:21 +00:00
Jörg Thalheim
bea10f7bc8 checks/mumble: disable on x86_64-linux for now 2025-05-12 15:32:52 +02:00
Jörg Thalheim
e8608ac830 checks/mumble: make delays between keyboard clicks more robust 2025-05-12 15:10:29 +02:00
kenji
2ecedb6535 Merge pull request 'clan/vars: Fix vars help hyperlink' (#3577) from kenji/clan-core:ke-docs-vars-cli into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3577
2025-05-12 13:08:13 +00:00
a-kenji
96fb6c39f4 clan/vars: Fix vars help hyperlink 2025-05-12 14:55:34 +02:00
hsjobeki
6e26d31ac6 Merge pull request 'Refactor(inventory/constraints): use explizit dependency injections instead of specialArgs' (#3553) from hsjobeki/clan-core:clan-services into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3553
2025-05-12 12:26:45 +00:00
Johannes Kirschbauer
77ec1e9e48 Feat(inventory/manifest): vendor {description, categories} from 'clanModules' 2025-05-12 14:19:04 +02:00
renovate[bot]
ea8b1aa34c chore(deps): lock file maintenance 2025-05-12 14:05:14 +02:00
Mic92
2bd9141d2d Merge pull request 'pinned-clan-core' (#3574) from pinned-clan-core into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3574
2025-05-12 12:02:58 +00:00
Jörg Thalheim
f788313e97 morph: don't depend on clan-core 2025-05-12 13:56:10 +02:00
Jörg Thalheim
89b70ffa6f checks/backup: depend on pinned clan core 2025-05-12 13:52:21 +02:00
Mic92
ed1692574f Merge pull request 'ci/update-clan-core-for-checks: bump gitea-create-pull-request' (#3573) from bump-update-flake into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3573
2025-05-12 11:46:01 +00:00
Jörg Thalheim
1106c50924 ci/update-clan-core-for-checks: bump gitea-create-pull-request 2025-05-12 13:41:16 +02:00
Mic92
e99e47da10 Merge pull request 'use a clan-core snapshots for ci tests' (#3572) from misc-fixes-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3572
2025-05-12 11:26:31 +00:00
Jörg Thalheim
67def050fd use a clan-core snapshots for ci tests
We currently have to re-run our integration tests a lot because they are
depending on the whole repository. This pull request changes locks the
clan-core used for vm tests. This has the caveat that we might not run
the latest NixOS machine of our profiles. On the upside we can test
behaviour against an older clan-core version and capture breakages and
make it backwards compatible. If we actually want to test the latest
version, the PR that changes the exposed flake api, could also bump the
clan-core snapshot.
2025-05-12 13:21:25 +02:00
Jörg Thalheim
c0d2787dee docs/testing: update to latest api 2025-05-12 13:03:06 +02:00
Mic92
ecc327277c Merge pull request 'Data-mesher: don't set owner for public vars' (#3571) from misc-fixes-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3571
2025-05-12 10:27:05 +00:00
Mic92
0064a8bfbc Merge pull request 'Add /bin/sh to bubblewrap sandbox' (#3551) from jfly/clan-core:bin-sh-in-sandbox into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3551
2025-05-12 10:07:56 +00:00
Jörg Thalheim
1e8b9def2a data-mesher: don't set owner for public_key 2025-05-12 12:06:05 +02:00
Jörg Thalheim
f0983ede5e move single dont-depend-on-repo-root check into checks
Doesn't seem to be a pattern yet with a single check.
2025-05-12 12:06:05 +02:00
Jörg Thalheim
10bc9e3e44 vars: improve warnings for non-public secrets 2025-05-12 12:06:05 +02:00
DavHau
556fd8845e Merge pull request 'GUI/machines: enable grid view by default' (#3570) from DavHau/clan-core:dave into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3570
2025-05-12 08:52:03 +00:00
DavHau
fab079af71 GUI/machines: enable grid view by default 2025-05-12 15:41:31 +07:00
DavHau
0370c1cf02 Merge pull request 'vars: cleanup sops file module' (#3569) from DavHau/clan-core:dave into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3569
2025-05-12 08:40:35 +00:00
DavHau
aa557f3a96 vars: cleanup sops file module 2025-05-12 15:30:23 +07:00
DavHau
e8699e68b5 Merge pull request 'gui/vars: fix vars screen doesn't appear on update' (#3567) from DavHau/clan-core:dave into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3567
2025-05-12 07:23:51 +00:00
hsjobeki
f8f31d430d Merge pull request 'Docs: update 'clan.service' examples' (#3568) from hsjobeki/clan-core:docs-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3568
2025-05-12 07:23:41 +00:00
DavHau
3d345e0bca gui/vars: fix vars screen doesn't appear on update 2025-05-12 13:52:16 +07:00
Michael Hoang
80711fcf72 Merge pull request 'cli: allow age-plugin-1p' (#3565) from push-uzmrpnklrmxw into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3565
2025-05-12 06:47:42 +00:00
Michael Hoang
35684090e3 cli: allow age-plugin-1p 2025-05-12 16:36:24 +10:00
renovate[bot]
8069b137f3 chore(deps): update data-mesher digest to 2666bb1 2025-05-12 00:50:11 +00:00
renovate[bot]
2fba6b15e8 chore(deps): update data-mesher digest to 20e20ac 2025-05-11 22:30:11 +00:00
renovate[bot]
cddee0ca86 chore(deps): update data-mesher digest to 61da4b5 2025-05-11 19:30:10 +00:00
renovate[bot]
0f3ab641d9 chore(deps): update treefmt-nix digest to 708ec80 2025-05-11 19:00:11 +00:00
Johannes Kirschbauer
d5f90b2730 Docs: update 'clan.service' examples 2025-05-11 15:46:16 +02:00
renovate[bot]
54335221d8 chore(deps): update data-mesher digest to f664c98 2025-05-11 11:30:21 +00:00
renovate[bot]
76b13476a5 chore(deps): update treefmt-nix digest to 4819332 2025-05-11 11:10:10 +00:00
Johannes Kirschbauer
bbed94d6de Refactor(inventory/manifest): move into seperate file 2025-05-10 13:58:21 +02:00
Johannes Kirschbauer
23a5c845b0 Refactor(inventory/constraints): use explizit dependency injections instead of specialArgs 2025-05-10 13:42:47 +02:00
Michael Hoang
b933dcf2e2 Merge pull request 'cli: fix machines update not outputting stdout of nixos-rebuild' (#3552) from push-zmlxvwnvrpuk into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3552
2025-05-10 07:15:23 +00:00
Michael Hoang
8a755fff8c cli: fix machines update not outputting stdout of nixos-rebuild 2025-05-10 17:02:56 +10:00
Jeremy Fleischman
5726dd1010 Add /bin/sh to bubblewrap sandbox
I ran into this error when trying to run `opendkim-genkey` in a vars
generator:

```console
=========================================================================== Command ===========================================================================
nix \
    --extra-experimental-features 'nix-command flakes' \
    shell \
    --inputs-from /nix/store/9r3ddw80dz4qzci9pj57ppbh6gy2pgv9-clan-cli/lib/python3.12/site-packages/clan_cli/nixpkgs \
    'nixpkgs#bash' \
    'nixpkgs#bubblewrap' \
    -c bwrap \
    --unshare-all --tmpfs \
    / \
    --ro-bind /nix/store \
    /nix/store \
    --dev /dev \
    --bind /tmp/nix-shell.ClOjgJ/vars-kh4qrnas \
    /tmp/nix-shell.ClOjgJ/vars-kh4qrnas \
    --chdir / \
    --bind /proc \
    /proc \
    --uid 1000 \
    --gid 1000 \
    -- bash \
    -c /nix/store/p0089w4y1w3h535g7ipv4jl4r6mb2hs2-generator-dkim-playground.jflei.com.mail

=========================================================================== Stderr ============================================================================
perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = (unset),
	LC_ALL = (unset),
	LC_CTYPE = (unset),
	LC_NUMERIC = (unset),
	LC_COLLATE = (unset),
	LC_TIME = (unset),
	LC_MESSAGES = (unset),
	LC_MONETARY = (unset),
	LC_ADDRESS = (unset),
	LC_IDENTIFICATION = (unset),
	LC_MEASUREMENT = (unset),
	LC_PAPER = (unset),
	LC_TELEPHONE = (unset),
	LC_NAME = (unset),
	LANG = "en_US.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").
Can't exec "/bin/sh": No such file or directory at /nix/store/nfawbww80p1hgpymfgq1vq8wqlak75yh-opendkim-2.11.0-Beta2/sbin/.opendkim-genkey-wrapped line 139.
.opendkim-genkey-wrapped: openssl died with signal %d
127
Return Code: 1

1 hosts failed with an error. Check the logs above
```

As we allow `/bin/sh` in the nix build sandbox, I assume we're OK
allowing it here as well?
2025-05-09 18:33:08 -07:00
Luis Hebendanz
b306c748b8 Merge pull request 'clan-cli: Use machine object everywhere instead of name + flake' (#3541) from Qubasa/clan-core:replace_machine_name_with_machine_obj2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3541
2025-05-09 14:01:25 +00:00
Qubasa
2682581c09 clan-cli: Use machine object everywhere instead of name + flake 2025-05-09 13:13:14 +02:00
renovate[bot]
a0a5827157 chore(deps): update disko digest to 85555d2 2025-05-08 18:40:10 +00:00
hsjobeki
8638861a87 Merge pull request 'Refactor(inventory/modules): add support for local clan.modules and migrate all checks' (#3547) from hsjobeki/clan-core:clan-services into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3547
2025-05-08 15:50:26 +00:00
Johannes Kirschbauer
c5a28e2655 fix: make sure legacyModules dont end up in localModules for inventory.instances 2025-05-08 17:38:28 +02:00
Johannes Kirschbauer
0af36d0a4d Refactor(inventory/modules): add support for local clan.modules and migrate all checks 2025-05-08 17:17:46 +02:00
Mic92
34b63ca1d5 Merge pull request 'chore(deps): update nix-darwin digest to 6cb36e8' (#3544) from renovate/nix-darwin-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3544
2025-05-08 14:49:18 +00:00
renovate[bot]
e24a6e23ad chore(deps): update nix-darwin digest to 6cb36e8 2025-05-08 14:40:13 +00:00
Mic92
fd7ccaca1a Merge pull request 'clan evaluation warnings for clan.inventory.modules' (#3546) from improve-container into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3546
2025-05-08 14:38:13 +00:00
Jörg Thalheim
4251d5ee0b clan evaluation warnings for clan.inventory.modules 2025-05-08 16:29:23 +02:00
Mic92
0a8839bcc0 Merge pull request 'Prettify nspawn output' (#3545) from improve-container into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3545
2025-05-08 14:28:35 +00:00
pinpox
cb41aaafa1 Prettify nspawn output 2025-05-08 16:20:29 +02:00
Qubasa
9867b6a894 clan-cli: Fix clan not finding vendored packages when running from git repo 2025-05-08 12:31:21 +02:00
Qubasa
7459566c2b clan-cli: remove useless run_no_stdout function 2025-05-08 12:30:16 +02:00
renovate[bot]
1c08d6dd25 chore(deps): update disko digest to 6bb82b7 2025-05-08 09:30:10 +00:00
renovate[bot]
14f4d65c47 chore(deps): update disko digest to c4fe2d1 2025-05-08 02:50:10 +00:00
renovate[bot]
43159cc2f0 chore(deps): update disko digest to 78d6a13 2025-05-07 18:10:11 +00:00
hsjobeki
9d8ebfd267 Merge pull request 'chore: deprecate usage of inventory.modules in favor of clan.modules' (#3314) from hsjobeki/clan-core:clan-services into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3314
2025-05-07 17:21:19 +00:00
Johannes Kirschbauer
1e379f6fa7 chore: deprecate usage of inventory.modules in favor of clan.modules 2025-05-07 19:12:07 +02:00
Mic92
b32a7749cf Merge pull request 'clan-cli: Refactor the API to use the Flake object' (#3539) from Qubasa/clan-core:Qubasa-replace_machine_name_with_machine_obj into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3539
2025-05-07 16:57:32 +00:00
Qubasa
153da50d6f clan-cli: Refactor the API to use the Flake object 2025-05-07 16:43:50 +00:00
hsjobeki
dd3bb314fd Merge pull request 'Feat(modules): display clan.service modules' (#3537) from hsjobeki/clan-core:module-list into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3537
2025-05-07 15:33:49 +00:00
Mic92
687f26eef1 Merge pull request 'chore(deps): update data-mesher digest to 4347dfb' (#3538) from renovate/data-mesher-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3538
2025-05-07 14:53:57 +00:00
Johannes Kirschbauer
afdb08643d fix(tests/modules): list_modules returns moduleSets" 2025-05-07 16:46:13 +02:00
renovate[bot]
0946d4316e chore(deps): update data-mesher digest to 4347dfb 2025-05-07 16:42:17 +02:00
hsjobeki
462c0764b9 Merge pull request 'feat(UI): design fixups in {machineList, machineItem, machineDetails, sidebar, sidebarHeader, button, sidebar}' (#3528) from amunsen/clan-core:ui-improvements into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3528
2025-05-07 14:23:49 +00:00
Timo
a748a27ddc fixes after npm run check 2025-05-07 16:12:35 +02:00
Johannes Kirschbauer
baf686e83f Feat(modules): display clan.service modules 2025-05-07 16:03:39 +02:00
Timo
03ddce83b7 machine-list:loading skeleton 2025-05-07 15:31:44 +02:00
Timo
45eb73680d sidebar-header: updates design 2025-05-07 15:31:44 +02:00
Timo
7d39d49b30 flash install: fixes form layout 2025-05-07 15:31:42 +02:00
Timo
698a39fafb tailwind: updates color values 2025-05-07 15:30:37 +02:00
Timo
b633db4f8e machine-details: updates form layout 2025-05-07 15:30:01 +02:00
Timo
7b9d18f9eb machine-item: adds border to thumb 2025-05-07 15:28:44 +02:00
Timo
51950329a3 machine-item: updates design and unifies 2025-05-07 15:28:44 +02:00
Timo
16256440e6 button component: introduces button-ghost dedicated styles 2025-05-07 15:28:44 +02:00
Timo
dfbb860898 sidebar component: removes pseudo marker 2025-05-07 15:28:44 +02:00
Jörg Thalheim
444fc3f820 Revert "Merge pull request 'clan-cli: Refactor the API to use the Flake object' (#3531) from Qubasa/clan-core:replace_machine_name_with_machine_obj into main"
This reverts commit 572ce8885f, reversing
changes made to 0bee027251.
2025-05-07 15:24:57 +02:00
Mic92
572ce8885f Merge pull request 'clan-cli: Refactor the API to use the Flake object' (#3531) from Qubasa/clan-core:replace_machine_name_with_machine_obj into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3531
2025-05-07 13:21:13 +00:00
Mic92
0bee027251 Merge pull request 'Flake: remove unused variable and mark other fields as non-init' (#3535) from cleanup-flake into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3535
2025-05-07 13:20:10 +00:00
Mic92
334367c3f7 Merge pull request 'chore(deps): update data-mesher digest to a454b9f' (#3532) from renovate/data-mesher-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3532
2025-05-07 13:18:25 +00:00
renovate[bot]
2371a5fa78 chore(deps): update data-mesher digest to a454b9f 2025-05-07 13:00:09 +00:00
Mic92
4792d8b1e3 Merge pull request 'Fix debug command to attach to container' (#3534) from container-debug into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3534
2025-05-07 12:56:33 +00:00
pinpox
ace0328a14 Fix debug command to attach to container 2025-05-07 14:41:18 +02:00
Jörg Thalheim
66c2d54961 Flake: remove unused variable and mark other fields as non-init 2025-05-07 14:40:22 +02:00
renovate[bot]
e18efdd48f Update data-mesher digest to c14644b 2025-05-07 11:20:09 +00:00
DavHau
8b652866c7 Merge pull request 'GUI: initialize support for vars prompts' (#3529) from DavHau/clan-core:gui-prompts into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3529
2025-05-07 11:15:32 +00:00
Qubasa
7129c38675 clan-cli: Refactor the API to use the Flake object 2025-05-07 13:12:48 +02:00
DavHau
caacf65dc0 GUI: initialize support for vars prompts
... for now only when updating a machine (not when installing)

Whenever the user clicks on the update button in the machine view, and only if user input is needed for some missing vars, the user will be forwarded to a vars page.
2025-05-07 18:06:35 +07:00
kenji
f8723ab897 Merge pull request 'vars/interface: Fix typo' (#3522) from kenji/clan-core:ke-vars-typo into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3522
2025-05-06 19:48:08 +00:00
a-kenji
b877df4c6e vars/interface: Fix typo 2025-05-06 19:48:08 +00:00
kenji
bf04eabc21 Merge pull request 'container-test-driver: Fix test naming' (#3521) from kenji/clan-core:ke-vmctn into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3521
2025-05-06 19:47:53 +00:00
a-kenji
5149ed9318 container-test-driver: Fix test naming
Fix the container test naming, as this otherwise can be very confusing.
2025-05-06 19:47:53 +00:00
hsjobeki
4d84180dd9 Merge pull request 'api-1' (#3524) from hsjobeki/clan-core:api-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3524
2025-05-06 17:08:02 +00:00
hsjobeki
7571fdef74 Merge pull request 'Refactor(machine/class): use frozen dataclass for class 'machine'' (#3520) from hsjobeki/clan-core:api-cleanup-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3520
2025-05-06 17:07:51 +00:00
Johannes Kirschbauer
7d55511d6f fix(services): features.API set to true and readOnly 2025-05-06 18:58:40 +02:00
Johannes Kirschbauer
cbd7157cfc feat(modules): derive module list from inputs and local modules 2025-05-06 18:57:54 +02:00
kenji
25faba4795 Merge pull request 'adr/2: Fix typo' (#3523) from kenji/clan-core:ke-adr-fix-typo into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3523
2025-05-06 16:33:19 +00:00
a-kenji
0f0bab7976 adr/2: Fix typo 2025-05-06 18:23:45 +02:00
hsjobeki
f0e18bbdfb Merge pull request 'Refactor(machine/install): don't mutate the machine class during installation' (#3519) from hsjobeki/clan-core:api-cleanup-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3519
2025-05-06 15:21:21 +00:00
Johannes Kirschbauer
6d4db71ea3 Refactor(machine/class): use frozen dataclass for class 'machine' 2025-05-06 17:12:52 +02:00
Johannes Kirschbauer
b21c98db7f Refactor(machine/install): don't mutate the machine class during installation 2025-05-06 17:09:37 +02:00
hsjobeki
df3fe00b8a Merge pull request 'Refactor(machine/update): cleanup dataflow and logic conditions to be intuitive' (#3518) from hsjobeki/clan-core:api-cleanup-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3518
2025-05-06 15:02:05 +00:00
Johannes Kirschbauer
7371085c05 Refactor(machine/update): cleanup dataflow and logic conditions to be intuitive 2025-05-06 16:49:32 +02:00
Mic92
6804327bca Merge pull request 'Host: actual setup ssh controlmaster' (#3515) from fix-control-master into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3515
2025-05-06 11:21:05 +00:00
Jörg Thalheim
ec76d5f8e5 only apply ssh control master to local ssh connection 2025-05-06 13:11:30 +02:00
Jörg Thalheim
864cdf33a7 Host: actual setup ssh controlmaster
before we were not entering the context manager
2025-05-06 13:11:30 +02:00
Mic92
e6dbccd8e5 Merge pull request 'Add CODEOWNERS and tag @lopter as a reviewer on vars and secrets changes' (#3508) from lopter/clan-core:lo-vars-codeowner into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3508
2025-05-06 10:48:46 +00:00
hsjobeki
30ac51b313 Merge pull request 'chore(API): cleanup remove unnused functions' (#3516) from hsjobeki/clan-core:api-cleanup-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3516
2025-05-06 10:42:37 +00:00
Johannes Kirschbauer
00b12c2c51 chore(API): cleanup remove unnused functions 2025-05-06 12:29:11 +02:00
kenji
085d726217 Merge pull request 'container-test-driver/nsenter: Improve printing of command' (#3514) from kenji/clan-core:ke-nsenter-pprint into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3514
2025-05-06 10:11:20 +00:00
a-kenji
3e65a76dfe container-test-driver/nsenter: Improve printing of command
Improves printing of `nsenter` command, so that it can easier be copied.
2025-05-06 10:11:20 +00:00
Mic92
929632049e Merge pull request 'fix clan machines update with build-host' (#3512) from build-host into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3512
2025-05-06 09:56:48 +00:00
Jörg Thalheim
0d1e642dfd fix build_host set if it doesn't exist 2025-05-06 09:56:58 +02:00
Mic92
8af68cbd9d Merge pull request 'fix incorrect target host when build host is set' (#3511) from ssh-foo into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3511
2025-05-06 07:54:40 +00:00
Jörg Thalheim
a44fee9eab fix incorrect target host when build host is set 2025-05-06 09:54:08 +02:00
Mic92
b27f34aed3 Merge pull request 'decisions: propose an ADR to formalize the ADR numbering process' (#3507) from lopter/clan-core:lo-adr-numbering-process into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3507
2025-05-06 07:32:41 +00:00
Jörg Thalheim
cd23c9ff41 fix incorrect target host when build host is set 2025-05-06 09:26:59 +02:00
Louis Opter
852a673839 Add CODEOWNERS and tag @lopter as a reviewer on vars and secrets changes
Since I am working in those areas through [ADR-7], I would like to know
when they get changed, and possibly have a say.

[ADR-7]: https://git.clan.lol/clan/clan-core/pulls/3196
2025-05-05 23:40:11 +00:00
Louis Opter
763a403e9f decisions: propose an ADR to formalize the ADR numbering process 2025-05-05 23:22:31 +00:00
renovate[bot]
78f8a080a8 chore(deps): update sops-nix digest to e93ee1d 2025-05-05 22:50:09 +00:00
Luis Hebendanz
af2a00bde3 Merge pull request 'clan-cli: fix bubblewrap not finding bash when IN_NIX_SANDBOX=1 if prev environment doesn't have it in PATH' (#3503) from Qubasa/clan-core:fix_bubblewrap_bash_path into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3503
2025-05-05 21:07:22 +00:00
Luis Hebendanz
47c44ec7ec Merge pull request 'clan-cli: add test_create in clan_lib test folder' (#3501) from Qubasa/clan-core:api_vm_test into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3501
2025-05-05 20:29:57 +00:00
Qubasa
1f66e90db1 clan-cli: fix bubblewrap not finding bash when IN_NIX_SANDBOX=1 if prev environment doesn't have it in PATH 2025-05-05 22:19:17 +02:00
hsjobeki
89fbf723ca Merge pull request 'API(cli): add method to Flake class to allow calling nix functions' (#3502) from hsjobeki/clan-core:improvements-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3502
2025-05-05 20:16:28 +00:00
Qubasa
548fdfb877 clan-cli: add test_create in clan_lib test folder 2025-05-05 22:16:02 +02:00
Johannes Kirschbauer
e44d34ef99 feat(clanLib): init evalServiceSchema 2025-05-05 21:55:29 +02:00
Johannes Kirschbauer
acc6797c22 API(cli): add method to Flake class to allow calling nix functions 2025-05-05 21:46:20 +02:00
Johannes Kirschbauer
9fbd943f44 API(clanInternals): add 'evalServiceSchema' endpoint 2025-05-05 21:46:20 +02:00
Johannes Kirschbauer
d42d9ad943 tests: add error prefix for json schema in checks 2025-05-05 21:46:16 +02:00
renovate[bot]
3c16ccdb38 chore(deps): update nixpkgs digest to ed30f8a 2025-05-05 16:10:18 +00:00
renovate[bot]
7b9e431da7 chore(deps): update data-mesher digest to d63db16 2025-05-05 15:50:11 +00:00
Mic92
05388c9c7e Merge pull request 'Log nsenter command on container tests' (#3498) from log-nsenter into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3498
2025-05-05 12:01:08 +00:00
pinpox
fe36aa4161 Log nsenter command on container tests 2025-05-05 13:00:11 +02:00
DavHau
6829c7f2dd vars: improve API of generate_vars_for_machine
receive list of generator names as an argument instead of generator objects
2025-05-05 15:55:04 +07:00
renovate[bot]
aa2e8eef88 chore(deps): update data-mesher digest to 0b5ff29 2025-05-05 08:10:11 +00:00
renovate[bot]
9e07064ec5 chore(deps): update nixpkgs digest to 6b1c028 2025-05-05 07:30:25 +00:00
renovate[bot]
305a361f56 chore(deps): lock file maintenance 2025-05-05 02:20:11 +00:00
renovate[bot]
db32e99082 chore(deps): update disko digest to 7b63642 2025-05-04 20:50:09 +00:00
Mic92
50ac0266f5 Merge pull request 'bind ssh controlmaster to live time of CLI' (#3491) from ssh-refactoring into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3491
2025-05-04 14:45:13 +00:00
Jörg Thalheim
b01691cb64 bind ssh controlmaster to live time of CLI 2025-05-04 16:28:14 +02:00
Mic92
44b237d9be Merge pull request 'test vars permissions in dummy-test' (#3490) from non-secret-var into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3490
2025-05-04 13:07:39 +00:00
Jörg Thalheim
f8bbd91c4a vars: warn if mode/owner/user is used on non-secret var 2025-05-04 14:59:22 +02:00
Jörg Thalheim
401de330f8 clanTest: remove unneeded parantheses 2025-05-04 14:59:22 +02:00
Jörg Thalheim
51da7ed5e8 vars: fix defaultText 2025-05-04 14:59:22 +02:00
Jörg Thalheim
e170cc2641 test vars permissions in dummy-test 2025-05-04 14:59:22 +02:00
Jörg Thalheim
8434f0fc35 fix ssh control master check (#3488)
Co-authored-by: pinpox <git@pablo.tools>
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3488
Co-authored-by: Jörg Thalheim <joerg@thalheim.io>
Co-committed-by: Jörg Thalheim <joerg@thalheim.io>
2025-05-04 12:49:53 +00:00
Mic92
d6bbb42dda Merge pull request 'Revert "Merge pull request 'Fix deploying with sudo + password' (#3470) from target-host into main"' (#3489) from revert-sudo into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3489
2025-05-04 11:40:28 +00:00
Jörg Thalheim
6539a6a24f Revert "Merge pull request 'Fix deploying with sudo + password' (#3470) from target-host into main"
This reverts commit 8a849eb90f, reversing
changes made to 3b5c22ebcf.
2025-05-04 13:37:39 +02:00
Mic92
8a849eb90f Merge pull request 'Fix deploying with sudo + password' (#3470) from target-host into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3470
2025-05-04 11:36:39 +00:00
Jörg Thalheim
15f691d5aa tests_secrets_cli: improve assertion message for pgp key 2025-05-04 10:51:49 +02:00
Jörg Thalheim
82949237b7 fix terminal output when terminal is put into interactive mode 2025-05-04 10:51:49 +02:00
Jörg Thalheim
7abb8bb662 update: fix sudo password prompt 2025-05-04 10:51:49 +02:00
Jörg Thalheim
f4d34b1326 fix upload when sudo prompts are needed 2025-05-04 10:51:49 +02:00
Mic92
3b5c22ebcf Merge pull request 'Miscellaneous ssh fixes.' (#3487) from misc-fixes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3487
2025-05-04 08:51:31 +00:00
Mic92
a2ce48f8cc Merge pull request 'update_hardware_config: use host.run rather than adhoc ssh command' (#3486) from control-master into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3486
2025-05-04 08:47:34 +00:00
Jörg Thalheim
f6899166c7 cmd: don't shadow time module 2025-05-04 10:39:50 +02:00
Jörg Thalheim
f5277c989a Host: always set needs_user_terminal for ssh commands, only override prefix if given by user 2025-05-04 10:39:39 +02:00
Jörg Thalheim
03731a2a67 run_local: allow stdin to be a file descriptor 2025-05-04 10:39:28 +02:00
Jörg Thalheim
091a56f57d update_hardware_config: use host.run rather than adhoc ssh command 2025-05-04 10:30:46 +02:00
Jörg Thalheim
7351f7994c rename connect_ssh_shell to interactive_ssh
better name than secure shell shell
2025-05-04 10:28:43 +02:00
Jörg Thalheim
5770ea036c move password/tor_socks into Host attributes
we set those parameters usually just once.
2025-05-04 10:28:43 +02:00
Mic92
0d537a146e Merge pull request 'configure ControlMaster and ControlPath for SSH connections' (#3485) from control-master into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3485
2025-05-04 07:59:13 +00:00
Jörg Thalheim
c430ff6253 configure ControlMaster and ControlPath for SSH connections
This should speed up deployments by not having to reconnect to the server on each command
2025-05-04 09:48:37 +02:00
Mic92
f3f4ebfc71 Merge pull request 'facts/sops: no longer upload age key' (#3484) from facts-no-age-upload into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3484
2025-05-04 07:40:05 +00:00
Jörg Thalheim
b79446f97e facts/sops: no longer upload age key
The vars backend already does this for us.
This avoids duplicated work.
2025-05-04 09:29:29 +02:00
Mic92
6d75a5596e Merge pull request 'chore(deps): update nixpkgs digest to f21e454' (#3445) from renovate/nixpkgs-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3445
2025-05-04 07:16:50 +00:00
Mic92
2d97119a3b Merge pull request 'Avoid a few cases of chmod-after-creation' (#3438) from tangential/clan-core:it-s_a_race into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3438
2025-05-04 07:08:43 +00:00
Jörg Thalheim
d0ff114f6b disable age-plugin-se for now on aarch64-linuxql
disable
2025-05-04 09:07:06 +02:00
Mic92
20ab5a67c1 Merge pull request 'clanCore/vars/sops: only copy required secrets to store' (#3457) from vdbe/clan-core:clanCore/vars/sops/only-copy-used into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3457
2025-05-04 06:41:37 +00:00
vdbe
d445a353d5 clanCore/vars/sops: add sops & switch to builtins.path 2025-05-04 08:08:58 +02:00
vdbe
b08a2bdb75 clanCore/vars/sops: only copy required secrets to store
Create a store path per in repo secret/var to be copied, this prevents
unused secrets from being leaked.

For example the `root-password` generator contains both the hashed and
unhashed password but only the hash is used.
2025-05-04 08:08:58 +02:00
renovate[bot]
10fd3f6e43 chore(deps): update nixpkgs digest to f21e454 2025-05-04 06:00:13 +00:00
Mic92
e8c85e3237 Merge pull request 'Set terminal on nix flake update/archive' (#3468) from fix-shell-on-copy into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3468
2025-05-04 05:59:58 +00:00
Mic92
6aa3ec66d8 Merge pull request 'don't depend on git for flake inputs' (#3483) from no-git into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3483
2025-05-04 05:48:10 +00:00
Mic92
b767a4a09c Merge pull request 'morph: speed up test by enabling useNixStoreImage' (#3481) from morph into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3481
2025-05-04 05:40:50 +00:00
Jörg Thalheim
b0bd209638 don't depend on git for flake inputs
This makes migration of an existing machine without git installed
easier:

fixes:
https://git.clan.lol/clan/clan-core/issues/3465#issuecomment-28189
2025-05-04 07:30:49 +02:00
Jörg Thalheim
b187d9b3d2 morph: speed up test by enabling useNixStoreImage 2025-05-04 07:29:31 +02:00
renovate[bot]
83d8c3d2f3 chore(deps): update data-mesher digest to 6544fb9 2025-05-03 21:00:09 +00:00
DavHau
1ce482f8f7 GUI/devshell: hot reload python API
This change speeds up the development workflow on the GUI when modifying the python api

The GUI started from the devshell already hot reloads itself on any change of the typescript codebase.

But python api changes were not caught bu the hot reload and required a reload of the devshell which is slow.

This change implements a custom vite plugin to also listen to changes coming from the clan-cli python code and re-generate the python-ts api on any change.
2025-05-03 19:22:16 +07:00
renovate[bot]
8803b3e0b5 chore(deps): update data-mesher digest to 642de25 2025-05-03 08:50:09 +00:00
renovate[bot]
9b66af37eb chore(deps): update data-mesher digest to 13026a9 2025-05-03 08:10:09 +00:00
DavHau
9186961ccb GUI/vars: add endpoints for getting prompts and generating vars 2025-05-03 14:44:51 +07:00
DavHau
ca594bbe95 refactor(vars): move migration logic to extra file 2025-05-03 07:33:11 +00:00
renovate[bot]
5454076df7 Update nix-darwin digest to 760a11c 2025-05-03 07:00:13 +00:00
DavHau
f8e7292bc4 GUI: generate sops key when creating clan 2025-05-03 13:00:27 +07:00
renovate[bot]
2ddb38a434 Update treefmt-nix digest to 29ec502 2025-05-02 20:40:11 +00:00
pinpox
a99c832ed9 Set terminal on nix flake update/archive
When using resident SSH-keys (-sk), e.g. from a Yubikey that require a
Pin, a terminal is needed to be able to enter it during deployment.
2025-05-02 15:41:29 +02:00
Mic92
12882ed68d Merge pull request 'Update data-mesher digest to 80b8ba4' (#3469) from renovate/data-mesher-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3469
2025-05-02 13:31:17 +00:00
renovate[bot]
134c545782 Update data-mesher digest to 80b8ba4 2025-05-02 13:20:10 +00:00
renovate[bot]
7889192b7c Update data-mesher digest to ba46584 2025-05-02 03:40:09 +00:00
brianmcgee
05a18baecb Merge pull request 'clan-cli select: fix returning early on list select' (#3464) from select-lists-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3464
2025-05-01 16:06:31 +00:00
lassulus
e6ebca8588 clan-cli select: fix returning early on list select 2025-05-02 00:16:21 +09:00
renovate[bot]
fcf1c683c5 Update data-mesher digest to 9d10655 2025-05-01 13:30:09 +00:00
Mic92
db215a48b5 Merge pull request 'correct capitilization for targetHost in error message' (#3461) from target-host into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3461
2025-05-01 13:21:42 +00:00
Mic92
1df62bd2f2 Merge pull request 'clan_cli flake caching: fix caching of store files' (#3458) from select-store-caching into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3458
2025-05-01 13:12:05 +00:00
Jörg Thalheim
ea1c8b9503 correct capitilization for targetHost in error message 2025-05-01 15:11:05 +02:00
renovate[bot]
511b107511 chore(deps): update data-mesher digest to 2327a7e 2025-05-01 06:50:09 +00:00
lassulus
47bcec69ab clan_cli flake caching: fix caching of store files 2025-05-01 13:40:12 +09:00
renovate[bot]
47203d849e chore(deps): update data-mesher digest to c74c5ed 2025-04-30 16:10:09 +00:00
hsjobeki
7b4b700c33 Merge pull request 'Refactor(inventory): move prio 'introspection' into inventoryClass to minimize the 'clanInternals' api' (#3440) from hsjobeki/clan-core:ui-fixups into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3440
2025-04-30 10:24:34 +00:00
kenji
69d394088b Merge pull request 'docs/reference: Improve wording of reference overview' (#3454) from kenji/clan-core:ke-docs-improve-reference into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3454
2025-04-30 10:19:12 +00:00
a-kenji
4c1e346cf2 docs/reference: Improve wording of reference overview
There is no value in calling it "automatically extracted" - but it is
potentially misleading.
2025-04-30 10:19:12 +00:00
hsjobeki
be9a43c50b Merge pull request 'fix(clan-app): Misc ui styling fixes' (#3451) from amunsen/clan-core:ui-fixes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3451
2025-04-30 10:18:42 +00:00
Johannes Kirschbauer
049d41f35c Fix: fix sidebar marker for webkit 2025-04-30 12:05:51 +02:00
kenji
055bd1edd5 Merge pull request 'clanModules/password: Fix vars documentation' (#3453) from kenji/clan-core:ke-fix-vars-docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3453
2025-04-30 10:05:22 +00:00
a-kenji
9ae44db29c clanModules/password: Fix vars documentation 2025-04-30 11:55:23 +02:00
Johannes Kirschbauer
17a6eda4b1 Fix: remove unused classNames 2025-04-30 11:43:29 +02:00
Timo
6beba157fe modules page: improves design cohesiveness of module components 2025-04-30 11:16:10 +02:00
Timo
a14dcf4adb form component: unify values and improve cohesiveness of overall design within dyn-form component 2025-04-30 11:14:19 +02:00
Timo
9bc23690a3 form components: adds general fieldset component and accordion component 2025-04-30 11:13:32 +02:00
Timo
5b0334adda button component: adds button-group component 2025-04-30 11:12:06 +02:00
Timo
45639c0d4f button component: moves dark style button into dedicated style classes 2025-04-30 11:09:03 +02:00
Timo
dfa861428f button component: orders classes and properties, moves tailwind classes to dedicates css file for better DOM readability 2025-04-30 11:09:03 +02:00
Timo
f15cd773c5 sidebarListItem: fixed active states to be displayed in ui 2025-04-30 11:09:03 +02:00
Timo
1a24a05034 general layout: removes drawer-component and adjusts font sizes in sidebar 2025-04-30 11:09:01 +02:00
Johannes Kirschbauer
e07551cecf Refactor(inventory): move prio 'introspection' into inventoryClass to minimize the 'clanInternals' api 2025-04-30 11:02:58 +02:00
DavHau
1f4b526e42 ci-performance: remove self reference from installation test 2025-04-30 15:53:18 +07:00
DavHau
8a4fe1405a gui: make update machine work
Also fix error when age plugins not defined
2025-04-30 15:28:49 +07:00
DavHau
f7e0345ab3 app: open welcome page if clan doesn't exist
Previously if a user started the app and the last opened clan directory does not exist anymore, it would still show the clan screen but without any machines.

This changes catches this case and throws the user back to the clan selection page
2025-04-30 14:48:05 +07:00
Mic92
11afc1faef Merge pull request 'chore(deps): update data-mesher digest to 517092d' (#3441) from renovate/data-mesher-digest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3441
2025-04-30 06:48:06 +00:00
renovate[bot]
c0964e1b22 chore(deps): update data-mesher digest to 517092d 2025-04-30 06:40:11 +00:00
DavHau
f8c5b178a4 add select file that shouldn't exist but does to gitignore 2025-04-30 13:28:19 +07:00
DavHau
93090b74e5 ci performance: add check to ensure nothing depends on the whole repo
Since this project is an ever growing monorepo, having derivations depending on the whole repo leads to bad CI performance, as the cache is busted on every commit.

-> We never want any derivations depend on the whole repo

...except: the test that tests that nothing depends on the whole repo, which is added by this commit.

For now only add this check to packages to allow contributors to build it locally.
We might want to add it to the CI later once all occurrences are fixed.
2025-04-30 13:17:33 +07:00
Jonathan Thiessen
839f8fb347 Avoid a few cases of chmod-after-creation 2025-04-28 17:11:21 -07:00
216 changed files with 10183 additions and 5064 deletions

View File

@@ -0,0 +1,29 @@
name: "Update pinned clan-core for checks"
on:
repository_dispatch:
workflow_dispatch:
schedule:
- cron: "51 2 * * *"
jobs:
update-pinned-clan-core:
runs-on: nix
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Update clan-core for checks
run: nix run .#update-clan-core-for-checks
- name: Create pull request
run: |
git commit -am ""
git push origin HEAD:update-clan-core-for-checks
curl -X POST \
-H "Authorization: token $GITEA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"head": "update-clan-core-branch",
"base": "main",
"title": "Automated Update: Clan Core",
"body": "This PR updates the pinned clan-core for checks."
}' \
"${GITEA_SERVER_URL}/api/v1/repos/${GITEA_OWNER}/${GITEA_REPO}/pulls"

7
.gitignore vendored
View File

@@ -14,8 +14,12 @@ example_clan
nixos.qcow2
**/*.glade~
/docs/out
/pkgs/clan-cli/clan_cli/select
**/.local.env
# MacOS stuff
**/.DS_store
# dream2nix
.dream2nix
@@ -39,3 +43,6 @@ repo
node_modules
dist
.webui
# TODO: remove after bug in select is fixed
select

2
CODEOWNERS Normal file
View File

@@ -0,0 +1,2 @@
nixosModules/clanCore/vars/.* @lopter
pkgs/clan-cli/clan_cli/(secrets|vars)/.* @lopter

64
checks/admin/default.nix Normal file
View File

@@ -0,0 +1,64 @@
{
pkgs,
self,
clanLib,
...
}:
let
public-key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAII6zj7ubTg6z/aDwRNwvM/WlQdUocMprQ8E92NWxl6t+ test@test";
in
clanLib.test.makeTestClan {
inherit pkgs self;
nixosTest = (
{ ... }:
{
name = "admin";
clan = {
directory = ./.;
modules."@clan/admin" = ../../clanServices/admin/default.nix;
inventory = {
machines.client = { };
machines.server = { };
instances = {
ssh-test-one = {
module.name = "@clan/admin";
roles.default.machines."server".settings = {
allowedKeys.testkey = public-key;
};
};
};
};
};
nodes = {
client.environment.etc.private-test-key.source = ./private-test-key;
server = {
services.openssh = {
enable = true;
settings.UsePAM = false;
};
};
};
testScript = ''
start_all()
machines = [client, server]
for m in machines:
m.systemctl("start network-online.target")
for m in machines:
m.wait_for_unit("network-online.target")
client.succeed(f"ssh -F /dev/null -i /etc/private-test-key -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o BatchMode=yes root@server true &>/dev/null")
'';
}
);
}

View File

@@ -0,0 +1,8 @@
-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
QyNTUxOQAAACCOs4+7m04Os/2g8ETcLzP1pUHVKHDKa0PBPdjVsZerfgAAAJDXdRkm13UZ
JgAAAAtzc2gtZWQyNTUxOQAAACCOs4+7m04Os/2g8ETcLzP1pUHVKHDKa0PBPdjVsZerfg
AAAECIgb2FQcgBKMniA+6zm2cwGre60ATu3Sg1GivgAqVJlI6zj7ubTg6z/aDwRNwvM/Wl
QdUocMprQ8E92NWxl6t+AAAAC3BpbnBveEBraXdpAQI=
-----END OPENSSH PRIVATE KEY-----

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:ET/FggP6t7L60krfVRvtMjv++xr3zqRsJ58AfnPS1zjTovV5tE9RgnboGY1ieS7fCs4VOL2S6ELtwV1+BTLDQX9s0c5A9cKqjnc=,iv:6EQ6DOqxUdHcOziTxf8kl0sp1Pggu720s5BJ8zA9Je0=,tag:hQMPWaWb4igqDYjwNehlqQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRWjhuZkgwNEZTL3JXZHFE\nTC9jSXJGcVd2bnkvOE1qV0d6TzNobFZobndvCmF1UmhVUWtKeVVwS29NY21ONkRn\nZU5sM01kTU9rQVNENi9paUFWbERoWnMKLS0tIEdjZzgwQjFtWlVtRGZwdW9GY0FK\nSER1TTFNVGxFa0ZrclR4MitWVERiSGMK9DNLzlJZelcpP0klwSDMggTAy5ZVOmsZ\niuu8dXMSdIeTd7l8rpZZN27BaKUm8yEDpUmot5Vq9rbZl6SO3ncX+A==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-07T11:45:41Z",
"mac": "ENC[AES256_GCM,data:m8eTnPtMzrooEah43mvjwHxQIwR/aq+A1wYyG/rQ75COq/TQepfMiDSrCJKW8x+OKmN/3HZs1b9k659jNNMF+RtMag0+/ovTmr7PQux3IkzWl+R2kU3Y7WDOMweBKY3mTMu6reICE1YVME8vJwhDDbA5JCXJv64rkTz2tfGt4CQ=,iv:/vrwJyEVsfm1cUK//TesY24Makt8YI8mwx5GIhn4038=,tag:H2tS9ohvWJ4TWB6LghcZNg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

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

View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICVVQjCEuryZii1LmJyjx9DX44eJh3qwTTEWlahYONsz nixbld@kiwi

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:yH7IQixe4nudnK4QOsr7VYoJ1YrVLP0Ufvgu7TNWSJnc55khKZHvQiDIlxzCIrAyMgUYwPNmrrZn9PZhgjAQZm7/o6SmP91Efb0yWM55o861El6v59yw0fseo3z6xAisjlg3KwTd5KMrRhzT0HzrjLn89SYRVh7DAWK+Cs7HVGvKVJ1E6AWiJmFPXIB7YaqJ7P4jZW9u7bEMCZabsRRqgS8dWXVXw9VS5ll4bNYQY4x5p2eg6e81zdeY2Y9Gbi5ty1Whqpzko2Pvggu6K4zUDXikM4lWggvIXzfrJA7HNE3xzXw94J45woj1y5FVOzn1Ve5kCc8PjVGaJ32poGkZiiD07kd5PxZuyVexREJpgz29lyB6nRJJeau4gpSG1VHOyNdwwBsBBm+zn6v2rlVzJPTlqmCV1+5UKf8JZKziIDFfi/78kSdtaeX+miJJvyDRkqNpQ7htEI0TAS8yQrkjWEIyaPAWQ2Usa8g1UrEftTlGUi/aMC2ob0qTLQQbhNhlSV/dImzI/qRMqSy2RWeS,iv:EuprKOFKzNLZrGlPtU2mEjmtNPNOcuVDbuvrtYyrerc=,tag:ny/q1AMHIQ8OgUNEE0Cc8w==,type:str]",
"sops": {
"age": [
{
"recipient": "age1q4e7nsw5z6mqeqk5u5kug8lwhpq3f276s0t0npwfffwdkfh58gkqxknhjg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBLODFxUjREa2tOYW9xaHYw\nQlhWZ282UVhiOGRndk0xYnlCQWRYR01qS2hJCllySUZyblJmTkgyZXd5bjVINDBo\nbEhIWmxycVdOVW0xTUxkalF5Y1k2bXcKLS0tIGRRS1VqOG5sanh2dXR5a2FGeXRs\nK3ZUdERCdEkvMmt3ZndPZEM3QUxJZzAKutOr9jHPCL86zEdMWJ6YZmplcr4tDAcN\nncQfC5rddYDW+0y/crwepKTa2FZjQheOY7jobZanU19ai521hqDSVw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBxc3NxNGhRYmU3eFNodDZ4\ndnNTeHFnNXBKbUxmNHBjRlFpNG0zdVNpS2d3CjhrOUlSQU5BZVlSdWR3dnNyODZO\nRFBKZWpwWHlOUW03OGlVZlRQUmMrMzQKLS0tIEd6ei9LU3ZFTzlWTUk1c3huS1RQ\nbG1vQzI4ODJkeFcyRnJaQWp1Wk9zSkUKXefMOk/ZT4P6DItfnM82RoOvX4SBn7Fn\nlAoMnSzaRCunDwq7ha05G45gcI2Wjv3urjt0tmdmrmTnFtBSSt23TQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-07T11:45:47Z",
"mac": "ENC[AES256_GCM,data:ORCANHbEX13O+zBVLOYyPxYIr1RS3NybTBb23ES7RbiGhSl2t/TXcfPWU5Smuqee0tfcrxL0u1FELZta4IysySW54JlD2907E9OUJWlQ6seOxADla4TMukW2pwhSsUJ9XfjEwC07zYB0alHzO3pY+LG3OAWzyhAlWzHlB5+WqIA=,iv:As+CjAJxKht0PJs3S2WWzho7UBqaUUltBIrYvlzBAbM=,tag:PSyUKaPZZNCxqd6XLPJSCw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:5Fa0TQN/Whj311JZuVWXnp+2KJaNZPb/TOnP23T+KktulabcBA9go+/F+8wJbsEH2mf6UDq656p6C+kLIvfBFl2O/WwSOhsl23as9TLbgB6gBq73GjyV81VFsnLYNLHKMq+8nfJHM/WekA==,iv:n5vz3q5N6DplLWibdiCcYDdiN7q1VggzPoIYy9r2ZJw=,tag:FoGXrrJfjHZCUVTS2RESmw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1q4e7nsw5z6mqeqk5u5kug8lwhpq3f276s0t0npwfffwdkfh58gkqxknhjg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBheXZvUW9YbjBFMi9mZnVk\ncGFPQzFOZkNPMU1HckhtSGtDWExpWVNYRlV3CjdDaDlSd2wzVnhKZGU0aFY0UnZY\nQStPSkxuSmlyOU9aeUdRaEJ2UTRRSm8KLS0tIFd3SG9YdEU5T2tzNk16b2s1SUNj\nWkh2cng5eWd3ZmxVZDhSR2Y1QnFySDgKGb/t+8NqiSGgmFOJc1NmDYZ+PXlANy8V\nuFwUTeqWAv7pOiGC8oessfyTPaJ7gWjz+XfKV5JVVikK2l3J4eAGxg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWM0daWmxCTjAyQStwQ2lM\nNkcyZW9hRmpDelRJR0VVTWhNTGFuZWhCc1RJCm81ZXowZjBhWGpIQTBhQnZLSmQy\nVUNNYjI0bVpqQ21YZS95TW53OUx1YUkKLS0tIDRUUE1zczBDeFJTOTQyVXVkMkYy\ncVVTN3J6TWtwcXVpM0M5c0gxUXpmV2cKwlWrbGLtkO2+PXKoMoHTV5aJpnfVy3RP\n6i8DDpLPGYfVUtWxHx+L+NmMxmw1AvmKSbdB4Y7aSbBW2mea3j1YCg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-07T11:45:50Z",
"mac": "ENC[AES256_GCM,data:rwdbGOg8l8fWT2GYFx+PgV3oPxt5+NCHJf3PhG3V2lrRMPRisyf1nKwDsYavTuhv+bZC/qo4LrGylcXsHWdkCe/xBX+/jYLMf6nJZPk8BPzfUpiDnEKwRl05qfRfkIDusnQrlBrE+tqtcool65js7hYIzSi92O/hxbzzfsCUpqk=,iv:lUTNJkr6Zh3MQm/h7Ven4N6xVn4VeTXOEKzxd0HSsCk=,tag:Bwbi4HD9vzso6306y7EZOg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:sPh+BuT2we+d/GaMv4zPWc3rPhlMsJQC,iv:VwcHUOMaNiao+R8RBtUINffEUhutktKD6KEWLkFxyp4=,tag:SNVKLjjDv+u5XTVczs2/Uw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBJVWNYRGEwVWxDSmE4bTNL\nRlZPeGZabFZZNGFsMEwzV1ZmT1pqNVk4STMwCkg5UER0Vjk3K1RMazVVYjF3SDc2\ndDZHa3VtYjRiWUJET25weXprc0JNUjAKLS0tIDdVb2xNdWxCcjhpSGtGWDV0d2ti\nZENkZGNpSTNzMVVTZVN0ZktLc2VackEKdexhI37pwcnbZbcy30k9Uo5Z7z3NLqlx\nspxJ87SzEwdStTMhiH1iYf62vcyAOTa4HwfXu97MGVPFNw13/VfgCw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-07T11:45:50Z",
"mac": "ENC[AES256_GCM,data:tZRh8qj7JUnhXCfqCHJKWEFQ8XLtmo/p0C+eFIK+34enxfB5lG5Lq83wBXLa0D/nqrr58z1rLO+UVDOI5LH1jFxARBZZnUKrVJNTDHa5pUnlnVOFEOoc+R0h2E5Xw9OHaq7aDUh4fT9+gNDpguKggI5fS9KqRnmZ4VrpNccjnkw=,iv:2yI25fcWMog91EMD7bYQy3GS30a7gZHnif93MaE3sZo=,tag:tYqa6zssiU3BCFU5xmDYZQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -147,25 +147,7 @@
perSystem =
{ pkgs, ... }:
let
clanCore = self.filter {
include = [
"checks/backups"
"checks/flake-module.nix"
"clanModules/borgbackup"
"clanModules/flake-module.nix"
"clanModules/localbackup"
"clanModules/packages"
"clanModules/single-disk"
"clanModules/zerotier"
"flake.lock"
"flakeModules"
"inventory.json"
"nixosModules"
# Just include everything in 'lib'
# If anything changes in /lib that may affect everything
"lib"
];
};
clanCore = self.checks.x86_64-linux.clan-core-for-checks;
in
{
checks = pkgs.lib.mkIf pkgs.stdenv.isLinux {
@@ -182,11 +164,6 @@
# import the inventory generated nixosModules
self.clanInternals.inventoryClass.machines.test-backup.machineImports;
clan.core.settings.directory = ./.;
environment.systemPackages = [
(pkgs.writeShellScriptBin "foo" ''
echo ${clanCore}
'')
];
};
testScript = ''

View File

@@ -0,0 +1,6 @@
{ fetchgit }:
fetchgit {
url = "https://git.clan.lol/clan/clan-core.git";
rev = "1e8b9def2a021877342491ca1f4c45533a580759";
sha256 = "0f12vwr1abwa1iwjbb5z5xx8jlh80d9njwdm6iaw1z1h2m76xgzc";
}

View File

@@ -0,0 +1,122 @@
{
...
}:
{
perSystem =
{
system,
pkgs,
self',
lib,
...
}:
let
clanCore = self'.packages.clan-core-flake;
clanCoreHash = lib.substring 0 12 (builtins.hashString "sha256" "${clanCore}");
/*
construct a flake for the test which contains a single check which depends
on all checks of clan-core.
*/
testFlakeFile = pkgs.writeText "flake.nix" ''
{
inputs.clan-core.url = path:///to/nowhere;
outputs = {clan-core, ...}:
let
checks =
builtins.removeAttrs
clan-core.checks.${system}
[
"dont-depend-on-repo-root"
"package-dont-depend-on-repo-root"
"package-clan-core-flake"
];
checksOutPaths = map (x: "''${x}") (builtins.attrValues checks);
in
{
checks.${system}.check = builtins.derivation {
name = "all-clan-core-checks";
system = "${system}";
builder = "/bin/sh";
args = ["-c" '''
of outPath in ''${toString checksOutPaths}; do
echo "$outPath" >> $out
done
'''];
};
};
}
'';
in
lib.optionalAttrs (system == "x86_64-linux") {
packages.dont-depend-on-repo-root =
pkgs.runCommand
# append repo hash to this tests name to ensure it gets invalidated on each chain
# This is needed because this test is an FOD (due to networking) and would get cached indefinitely.
"check-dont-depend-on-repo-root-${clanCoreHash}"
{
buildInputs = [
pkgs.nix
pkgs.cacert
pkgs.nix-diff
];
outputHashAlgo = "sha256";
outputHash = "sha256-47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=";
}
''
mkdir clanCore testFlake store
clanCore=$(realpath clanCore)
testFlake=$(realpath testFlake)
# copy clan core flake and make writable
cp -r ${clanCore}/* clanCore/
chmod +w -R clanCore\
# copy test flake and make writable
cp ${testFlakeFile} testFlake/flake.nix
chmod +w -R testFlake
# enable flakes
export NIX_CONFIG="experimental-features = nix-command flakes"
# give nix a $HOME
export HOME=$(realpath ./store)
# override clan-core flake input to point to $clanCore\
echo "locking clan-core to $clanCore"
nix flake lock --override-input clan-core "path://$clanCore" "$testFlake" --store "$HOME"
# evaluate all tests
echo "evaluating all tests for clan core"
nix eval "$testFlake"#checks.${system}.check.drvPath --store "$HOME" --raw > drvPath1 &
# slightly modify clan core
cp -r $clanCore clanCore2
cp -r $testFlake testFlake2
export clanCore2=$(realpath clanCore2)
export testFlake2=$(realpath testFlake2)
touch clanCore2/fly-fpv
# re-evaluate all tests
echo "locking clan-core to $clanCore2"
nix flake lock --override-input clan-core "path://$clanCore2" "$testFlake2" --store "$HOME"
echo "evaluating all tests for clan core with added file"
nix eval "$testFlake2"#checks.${system}.check.drvPath --store "$HOME" --raw > drvPath2
# wait for first nix eval to return as well
while ! grep -q drv drvPath1; do sleep 1; done
# raise error if outputs are different
if [ "$(cat drvPath1)" != "$(cat drvPath2)" ]; then
echo -e "\n\nERROR: Something in clan-core depends on the whole repo" > /dev/stderr
echo -e "See details in the nix-diff below which shows the difference between two evaluations:"
echo -e " 1. Evaluation of clan-core checks without any changes"
echo -e " 1. Evaluation of clan-core checks after adding a file to the top-level of the repo"
echo "nix-diff:"
export NIX_REMOTE="$HOME"
nix-diff $(cat drvPath1) $(cat drvPath2)
exit 1
fi
touch $out
'';
};
}

View File

@@ -26,6 +26,7 @@ clanLib.test.makeTestClan {
roles.admin.machines = [ "admin1" ];
};
};
instances."test" = {
module.name = "new-service";
roles.peer.machines.peer1 = { };
@@ -33,25 +34,33 @@ clanLib.test.makeTestClan {
modules = {
legacy-module = ./legacy-module;
new-service = {
_class = "clan.service";
manifest.name = "new-service";
roles.peer = { };
perMachine = {
nixosModule = {
# This should be generated by:
# ./pkgs/scripts/update-vars.py
clan.core.vars.generators.new-service = {
files.hello = {
secret = false;
deploy = true;
};
script = ''
# This is a dummy script that does nothing
echo "This is a dummy script" > $out/hello
'';
};
};
};
modules.new-service = {
_class = "clan.service";
manifest.name = "new-service";
roles.peer = { };
perMachine = {
nixosModule = {
# This should be generated by:
# nix run .#generate-test-vars -- checks/dummy-inventory-test dummy-inventory-test
clan.core.vars.generators.new-service = {
files.not-a-secret = {
secret = false;
deploy = true;
};
files.a-secret = {
secret = true;
deploy = true;
owner = "nobody";
group = "users";
mode = "0644";
};
script = ''
# This is a dummy script that does nothing
echo -n "not-a-secret" > $out/not-a-secret
echo -n "a-secret" > $out/a-secret
'';
};
};
};
@@ -69,7 +78,15 @@ clanLib.test.makeTestClan {
print(peer1.succeed("systemctl status dummy-service"))
# peer1 should have the 'hello' file
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.hello.path}")
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.not-a-secret.path}")
ls_out = peer1.succeed("ls -la ${nodes.peer1.clan.core.vars.generators.new-service.files.a-secret.path}")
# Check that the file is owned by 'nobody'
assert "nobody" in ls_out, f"File is not owned by 'nobody': {ls_out}"
# Check that the file is in the 'users' group
assert "users" in ls_out, f"File is not in the 'users' group: {ls_out}"
# Check that the file is in the '0644' mode
assert "-rw-r--r--" in ls_out, f"File is not in the '0644' mode: {ls_out}"
'';
}
);

View File

@@ -1,6 +1,6 @@
[
{
"publickey": "age1hd2exjq88h7538y6mvjvexx3u5gp6a03yfn5nj32h2667yyksyaqcuk5qs",
"publickey": "age12yt078p9ewxy2sh0a36nxdpgglv8wqqftmj4dkj9rgy5fuyn4p0q5nje9m",
"type": "age"
}
]

View File

@@ -1,6 +1,6 @@
[
{
"publickey": "age19urkt89q45a2wk6a4yaramzufjtnw6nq2snls0v7hmf7tqf73axsfx50tk",
"publickey": "age12w2ld4vxfyf3hdq2d8la4cu0tye4pq97egvv3me4wary7xkdnq2snh0zx2",
"type": "age"
}
]

View File

@@ -1,15 +1,15 @@
{
"data": "ENC[AES256_GCM,data:hhuFgZcPqht0h3tKxGtheS4GlrVDo4TxH0a9lxgPYj2i12QUmE04rB07A+hu4Z8WNWLYvdM5069mEOZYm3lSeTzBHQPxYZRuVj0=,iv:sA1srRFQqsMlJTAjFcb09tI/Jg2WjOVJL5NZkPwiLoU=,tag:6xXo9FZpmAJw6hCBsWzf8Q==,type:str]",
"data": "ENC[AES256_GCM,data:GPpsUhSzWPtTP8EUNKsobFXjYqDldhkkIH6hBk11RsDLAGWdhVrwcISGbhsWpYhvAdPKA84DB6Zqyh9lL2bLM9//ybC1kzY20BQ=,iv:NrxMLdedT2FCkUAD00SwsAHchIsxWvqe7BQekWuJcxw=,tag:pMDXcMyHnLF2t3Qhb1KolA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBGaGVHeTgrN3dJQ2VITFBM\neWVzbDhjb0pwNUhBUjdUc0p5OTVta1dvSno4ClJxeUc4Z0hiaFRkVlJ1YTA4Lyta\neWdwV005WGYvMUNRVG1qOVdicTk0NUkKLS0tIFQvaDNFS1JMSFlHRXlhc3lsZm03\nYVhDaHNsam5wN1VqdzA3WTZwM1JwV2sKZk/SiZJgjllADdfHLSWuQcU4+LttDpt/\nqqDUATEuqYaALljC/y3COT+grTM2bwGjj6fsfsfiO/EL9iwzD3+7oA==\n-----END AGE ENCRYPTED FILE-----\n"
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBzb2tWb1ExKzdmUTRzaGVj\nK3cyYTBHZTJwVjM1SzUvbHFiMnVhY05iKzFZCnJTSE1VSVdpcUFLSEJuaE1CZzJD\nWjZxYzN2cUltdThNMVRKU3FIb20vUXMKLS0tIFlHQXRIdnMybDZFUVEzWlQrc1dw\nbUxhZURXblhHd0pka0JIK1FTZEVqdUEKI/rfxQRBc+xGRelhswkJQ9GcZs6lzfgy\nuCxS5JI9npdPLQ/131F3b21+sP5YWqks41uZG+vslM1zQ+BlENNhDw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-09T15:10:16Z",
"mac": "ENC[AES256_GCM,data:xuXj4833G6nhvcRo2ekDxz8G5phltmU8h1GgGofH9WndzrqLKeRSqm/n03IHRW0f4F68XxnyAkfvokVh6vW3LRQAFkqIlXz5U4+zFNcaVaPobS5gHTgxsCoTUoalWPvHWtXd50hUVXeAt8rPfTfeveVGja8bOERk8mvwUPxb6h4=,iv:yP1usA9m8tKl6Z/UK9PaVMJlZlF5qpY4EiM4+ByVlik=,tag:8DgoIhLstp3MRki90VfEvw==,type:str]",
"lastmodified": "2025-05-04T12:44:13Z",
"mac": "ENC[AES256_GCM,data:fWxLHXBWolHVxv6Q7utcy6OVLV13ziswrIYyNKiwy1vsU8i7xvvuGO1HlnE+q43D2WuHR53liKq1UHuf1JMrWzTwZ0PYe+CVugtoEtbR2qu3rK/jAkOyMyhmmHzmf6Rp4ZMCzKgZeC/X2bDKY/z0firHAvjWydEyogutHpvtznM=,iv:OQI3FfkLneqbdztAXVQB3UkHwDPK+0hWu5hZ9m8Oczg=,tag:em6GfS2QHsXs391QKPxfmA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.1"
"version": "3.10.2"
}
}

View File

@@ -1,15 +1,15 @@
{
"data": "ENC[AES256_GCM,data:rwPhbayGf6mE1E9NCN+LuL7VfWWOfhoJW6H2tNSoyebtyTpM3GO2jWca1+N7hI0juhNkUk+rIsYQYbCa/5DZQiV0/2Jgu4US1XY=,iv:B5mcaQsDjb6BacxGB4Kk88/qLCpVOjQNRvGN+fgUiEo=,tag:Uz0A8kAF5NzFetbv9yHIjQ==,type:str]",
"data": "ENC[AES256_GCM,data:W3cOkUYL5/YulW2pEISyTlMaA/t7/WBE7BoCdFlqrqgaCL7tG4IV2HgjiPWzIVMs0zvDSaghdEvAIoB4wOf470d1nSWs0/E8SDk=,iv:wXXaZIw3sPY8L/wxsu7+C5v+d3RQRuwxZRP4YLkS8K4=,tag:HeK4okj7O7XDA9JDz2KULw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWY0hKQ1dnV0tMYytDMCtj\nTDV4Zk5NeVN0bCtqaWRQV3d4M0VlcGVZMkhZCm02dHZyOGVlYzJ5Z3FlUWNXMVQ0\nb2ZrTXZQRzRNdzFDeWZCVGhlTS9rMm8KLS0tIEJkY1QwOENRYWw3cjIwd3I0bzdz\nOEtQNm1saE5wNWt2UUVnYlN4NWtGdFkKmWHU5ttZoQ3NZu/zkX5VxfC2sMpSOyod\neb7LRhFqPfo5N1XphJcCqr5QUoZOfnH0xFhZ2lxWUS3ItiRpU4VDwg==\n-----END AGE ENCRYPTED FILE-----\n"
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAxRC83b3dtSVpXcGovNnVs\nTzFka2J2MEFhYkF1ajVrdjMrNUtPWGRObjM4Cm5zSUR5OGw0T0FaL3BaWmR6L29W\nU2syMFIyMUhFRUZpWFpCT28vWko2ZU0KLS0tIFpHK3BjU1V1L0FrMGtwTGFuU3Mz\nRkV5VjI2Vndod202bUR3RWQwNXpmVzQKNk8/y7M62wTIIKqY4r3ZRk5aUCRUfine\n1LUSHMKa2bRe+hR7nS7AF4BGXp03h2UPY0FP5+U5q8XuIj1jfMX8kg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-09T15:10:41Z",
"mac": "ENC[AES256_GCM,data:pab0G2GPjgs59sbiZ8XIV5SdRtq5NPU0yq18FcqiMV8noAL94fyVAY7fb+9HILQWQsEjcykgk9mA2MQ0KpK/XG8+tDQKcBH+F+2aQnw5GJevXmfi7KLTU0P224SNo7EnKlfFruB/+NZ0WBtkbbg1OzekrbplchpSI6BxWz/jASE=,iv:TCj9FCxgfMF2+PJejr67zgGnF+CFS+YeJiejnHbf7j0=,tag:s7r9SqxeqpAkncohYvIQ2Q==,type:str]",
"lastmodified": "2025-05-04T12:44:16Z",
"mac": "ENC[AES256_GCM,data:yTkQeFvKrN1+5FP+yInsaRWSAG+ZGG0uWF3+gVRvzJTFxab8kT2XkAMc+4D7SKgcjsmwBBb77GNoAKaKByhZ92UaCfZ2X66i7ZmYUwLM1NVVmm+xiwwjsh7PJXlZO/70anTzd1evtlZse0jEmRnV5Y0F0M6YqXmuwU+qGUJU2F8=,iv:sy6ozhXonWVruaQfa7pdEoV5GkNZR/UbbINKAPbgWeg=,tag:VMruQ1KExmlMR7TsGNgMlg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.1"
"version": "3.10.2"
}
}

View File

@@ -1,19 +1,19 @@
{
"data": "ENC[AES256_GCM,data:bxM9aYMK,iv:SMNYtk9FSyZ1PIfEzayTKKdCnZWdhcyUEiTwFUNb988=,tag:qJYW4+VQyhF1tGPQPTKlOQ==,type:str]",
"data": "ENC[AES256_GCM,data:T8edCvw=,iv:7/G5xt5fv38I9uFzk7WMIr9xQdz/6lFxqOC+18HBg8Q=,tag:F39Cxbgmzml+lZLsZ59Kmg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1hd2exjq88h7538y6mvjvexx3u5gp6a03yfn5nj32h2667yyksyaqcuk5qs",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAvZDZYYXdpcXVqRFRnQ2Jx\nTFhFWEJTR290cHZhTXZadFFvcHM4MHVIN3lFCmJhOEZrL3g4TFBZVllxdDFZakJn\nR3NxdXo0eE8vTDh3QlhWOFpVZ0lNUHcKLS0tIEE4dkpCalNzaXJ0Qks3VHJSUzZF\nb2N3NGdjNHJnSUN6bW8welZ1VDdJakEKGKZ7nn1p11IyJB6DMxu2HJMvZ+0+5WpE\nPLWh2NlGJO3XrrL4Fw7xetwbqE+QUZPNl/JbEbu4KLIUGLjqk9JDhQ==\n-----END AGE ENCRYPTED FILE-----\n"
"recipient": "age12yt078p9ewxy2sh0a36nxdpgglv8wqqftmj4dkj9rgy5fuyn4p0q5nje9m",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPNUhiYkZWK3dPMHNiRTVM\nRHNvaHFsOFp1c0UxQitwVG0zY01MNDZRV1E4CjEybENoTVIzN29vQ3FtUTRSYmFU\nNXIzQllVSllXRGN2M1B6WXJLdHZSajgKLS0tIDllZ0ZmZUcxMHhDQUpUOEdWbmkv\neUQweHArYTdFSmNteVpuQ3BKdnh0Y0UKs8Hm3D+rXRRfpUVSZM3zYjs6b9z8g10D\nGTkvreUMim4CS22pjdQ3eNA9TGeDXfWXE7XzwXLCb+wVcf7KwbDmvg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHckJCQVFyb21aT1R0d2Rr\nMWxNMHVqcGxabHBmS0RibW9sN0gyZDI1b1dFCnRWUk5LSWdxV3c4RWVZdUtEN1Fv\nRk4xVmwwT2xrdWVERkJXUVVlVXJjTVUKLS0tIC9ERG9KMGxTNEsrbzFHUGRiVUlm\nRi9qakxoc1FOVVV1TkUrckwxRUVnajQKE8ms/np2NMswden3xkjdC8cXccASLOoN\nu+EaEk69UvBvnOg9VBjyPAraIKgNrTc4WWwz+DOBj1pCwVbu9XxUlA==\n-----END AGE ENCRYPTED FILE-----\n"
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKSDhpT3cvck9PenZYVEZH\ndFQreVRBdG93L1dBUGlvYjFWcDlHWUJsZUVBCm9DMTJ4UytiYzlEVHNWdUcwS1ds\nT0dhbzAzNDdmbDBCU0dvL2xNeHpXcGsKLS0tIFArbmpsbzU3WnpJdUt1MGN0L1d0\nV1JkTDJYWUxsbmhTQVNOeVRaSUhTODQKk9Vph2eldS5nwuvVX0SCsxEm4B+sO76Z\ndIjJ3OQxzoZmXMaOOuKHC5U0Y75Qn7eXC43w5KHsl2CMIUYsBGJOZw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-09T15:10:30Z",
"mac": "ENC[AES256_GCM,data:cIwWctUbAFI8TRMxYWy5xqlKDVLMqBIxVv4LInnLqi3AauL0rJ3Z7AxK/wb2dCQM07E1N7YaORNqgUpFC1xo0hObAA8mrPaToPotKDkjua0zuyTUNS1COoraYjZpI/LKwmik/qtk399LMhiC7aHs+IliT9Dd41B8LSMBXwdMldY=,iv:sZ+//BrYH5Ay2JJAGs7K+WfO2ASK82syDlilQjGmgFs=,tag:nY+Af9eQRLwkiHZe85dQ9A==,type:str]",
"lastmodified": "2025-05-04T12:44:14Z",
"mac": "ENC[AES256_GCM,data:6fKrS1eLLUWlHkQpxLFXBRk6f2wa5ADLMViVvYXXGU24ayl9UuNSKrCRHp9cbzhqhti3HdwyNt6TM+2X6qhiiAQanKEB2PF7JRYX74NfNKil9BEDjt5AqqtpSgVv5l7Ku/uSHaPkd2sDmzHsy5Q4bSGxJQokStk1kidrwle+mbc=,iv:I/Aad82L/TCxStM8d8IZICUrwdjRbGx2fuGWqexr21o=,tag:BfgRbGUxhPZzK2fLik1kxA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.1"
"version": "3.10.2"
}
}

View File

@@ -1,19 +1,19 @@
{
"data": "ENC[AES256_GCM,data:ImlGIKxE,iv:UUWxjLNRKJCD2WHNpw8lfvCc8rnXPCqc2pni1ODckjE=,tag:HFCqiv31E9bShIIaAEjF0A==,type:str]",
"data": "ENC[AES256_GCM,data:vp0yW0Gt,iv:FO2cy+UpEl5aRay/LUGu//c82QiVxuKuGSaVh0rGJvc=,tag:vf2RAOPpcRW0HwxHoGy17A==,type:str]",
"sops": {
"age": [
{
"recipient": "age19urkt89q45a2wk6a4yaramzufjtnw6nq2snls0v7hmf7tqf73axsfx50tk",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBpTEROZjh6NjBhSlJSc1Av\nSHhjdkhwVUd3VzBZemhQb3dhMlJXalBmZlFjCkZPYkhZZGVOVTNjUWdFU0s4cWFn\nL2NXbkRCdUlMdElnK2lGbG5iV0w1cHMKLS0tIFREcmxDdHlUNVBFVGRVZSt0c0E5\nbnpHaW1Vb3R3ZFFnZVMxY3djSjJmOU0KIwqCSQf5S9oA59BXu7yC/V6yqvCh88pa\nYgmNyBjulytPh1aAfOuNWIGdIxBpcEf+gFjz3EiJY9Kft3fTmhp2bw==\n-----END AGE ENCRYPTED FILE-----\n"
"recipient": "age12w2ld4vxfyf3hdq2d8la4cu0tye4pq97egvv3me4wary7xkdnq2snh0zx2",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBjaFVNMEd2YUxpSm5XVVRi\nY2ZUc3NTOStJUFNMWWVPQTgxZ2tCK1QrMW1ZCjYwMlA4dkIzSlc0TGtvZjcyK3Bi\nM3pob2JOOFUyeVJ6M2JpaTRCZlc1R0kKLS0tIDJMb1dFcVRWckhwYWNCQng0RlFO\nTkw3OGt4dkFIZVY5aVEzZE5mMzJSM0EKUv8bUqg48L2FfYVUVlpXvyZvPye699of\nG6PcjLh1ZMbNCfnsCzr+P8Vdk/F4J/ifxL66lRGfu2xOLxwciwQ+5Q==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArN3R4TThibjdYbE9TMDE1\naUhuNDlscExjaktIR2VmTk1OMWtVM0NpTUJZClJUNEcwVDlibExWQk84TTNEWFhp\nMjYyZStHc1N0ZTh1S3VTVk45WGxlWWMKLS0tIHFab25LY1R1d1l6NE5XbHJvQ3lj\nNGsxUldFVHQ5RVJERDlGbi9NY29hNWsKENBTcAS/R/dTGRYdaWv5Mc/YG4bkah5w\nb421ZMQF+r4CYnzUqnwivTG8TMRMqJLavfkutE6ZUfJbbLufrTk5Lw==\n-----END AGE ENCRYPTED FILE-----\n"
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBnZ2dDbVhoQngxM3lTSmZF\nUTAwS1lCTGhEMU1GVXpFUzlIUFdqZy9LajF3Ck9mdVpBRjlyVUNhZXZIUFZjUzF1\nNlhFN28vNmwzcUVkNmlzUnpkWjJuZE0KLS0tIHpXVHVlNk9vU1ZPTGRrYStWbmRO\nbDM4U2o1SlEwYWtqOXBqd3BFUTAvMHcKkI8UVd0v+x+ELZ5CoGq9DzlA6DnVNU2r\nrV9wLfbFd7RHxS0/TYZh5tmU42nO3iMYA9FqERQXCtZgXS9KvfqHwQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-09T15:11:04Z",
"mac": "ENC[AES256_GCM,data:JdJzocQZWVprOmZ4Ni04k1tpD1TpFcK5neKy3+0/c3+uPBwjwaMayISKRaa/ILUXlalg60oTqxB4fUFoYVm8KGQVhDwPhO/T1hyYVQqidonrcYfJfCYg00mVSREV/AWqXb7RTnaEBfrdnRJvaAQF9g2qDXGVgzp3eACdlItclv4=,iv:nOw1jQjIWHWwU3SiKpuQgMKXyu8MZYI+zI9UYYd9fCI=,tag:ewUkemIPm/5PkmuUD0EcAQ==,type:str]",
"lastmodified": "2025-05-04T12:44:18Z",
"mac": "ENC[AES256_GCM,data:1ZZ+ZI1JsHmxTov1bRijfol3kTkyheg2o3ivLsMHRhCmScsUry97hQJchF78+y2Izt7avaQEHYn6pVbYt/0rLrSYD7Ru7ITVxXoYHOiN5Qb98masUzpibZjrdyg5nO+LW5/Hmmwsc3yn/+o3IH1AUYpsxlJRdnHHCmoSOFaiFFM=,iv:OQlgmpOTw4ljujNzqwQ5/0Mz8pQpCSUtqRvj3FJAxDs=,tag:foZvdeW7gK9ZVKkWqnlxGA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.1"
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:prFl0EJy8bM=,iv:zITWxf+6Ebk0iB5vhhd7SBQa1HFrIJXm8xpSM+D9I0M=,tag:NZCRMCs1SzNKLBu/KUDKMQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age12w2ld4vxfyf3hdq2d8la4cu0tye4pq97egvv3me4wary7xkdnq2snh0zx2",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB0S0RZRWxaZVZvTUhjdWVL\naU9WZmtEcm1qa2JsRmdvdmZmNENMaWFEVUFRCmdoVnRXSGlpRlFjNmVVbDJ5VnFT\nMnVJUlVnM3lxNmZCRTdoRVJ4NW1oYWcKLS0tIFFNbXBFUk1RWnlUTW1SeG1vYzlM\nVVpEclFVOE9PWWQxVkZ0eEgwWndoRWcKDAOHe+FIxqGsc6LhxMy164qjwG6t2Ei2\nP0FSs+bcKMDpudxeuxCjnDm/VoLxOWeuqkB+9K2vSm2W/c/fHTSbrA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB2VU5jOEpwYUtDVEVFcVpU\nQkExTVZ3ejZHcGo5TG8zdUQwNktoV09WdUZvCmQ0dE1TOWRFbTlxdVd4WWRxd3VF\nQUNTTkNNT3NKYjQ5dEJDY0xVZ3pZVUUKLS0tIDFjajRZNFJZUTdNeS8yN05FMFZU\ncEtjRjhRbGE0MnRLdk10NkFLMkxqencKGzJ66dHluIghH04RV/FccfEQP07yqnfb\n25Hi0XIVJfXBwje4UEyszrWTxPPwVXdQDQmoNKf76Qy2jYqJ56uksw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-05-04T12:44:20Z",
"mac": "ENC[AES256_GCM,data:FIkilsni5kOdNlVwDuLsQ/zExypHRWdqIBQDNWMLTwe8OrsNPkX+KYutUvt9GaSoGv4iDULaMRoizO/OZUNfc2d8XYSdj0cxOG1Joov4GPUcC/UGyNuQneAejZBKolvlnidKZArofnuK9g+lOTANEUtEXUTnx8L+VahqPZayQas=,iv:NAo6sT3L8OOB3wv1pjr3RY2FwXgVmZ4N0F4BEX4YPUY=,tag:zHwmXygyvkdpASZCodQT9Q==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -1 +0,0 @@
This is a dummy script

View File

@@ -0,0 +1 @@
not-a-secret

View File

@@ -14,12 +14,14 @@ in
./installation/flake-module.nix
./morph/flake-module.nix
./nixos-documentation/flake-module.nix
./dont-depend-on-repo-root.nix
];
perSystem =
{
pkgs,
lib,
self',
system,
...
}:
{
@@ -32,33 +34,45 @@ in
inherit self;
inherit (self) clanLib;
};
nixosTests = lib.optionalAttrs (pkgs.stdenv.isLinux) {
# Deltachat is currently marked as broken
# deltachat = import ./deltachat nixosTestArgs;
nixosTests =
lib.optionalAttrs (pkgs.stdenv.isLinux) {
# Deltachat is currently marked as broken
# deltachat = import ./deltachat nixosTestArgs;
# Base Tests
secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs;
borgbackup = self.clanLib.test.baseTest ./borgbackup nixosTestArgs;
wayland-proxy-virtwl = self.clanLib.test.baseTest ./wayland-proxy-virtwl nixosTestArgs;
# Base Tests
secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs;
borgbackup = self.clanLib.test.baseTest ./borgbackup nixosTestArgs;
wayland-proxy-virtwl = self.clanLib.test.baseTest ./wayland-proxy-virtwl nixosTestArgs;
# Container Tests
container = self.clanLib.test.containerTest ./container nixosTestArgs;
zt-tcp-relay = self.clanLib.test.containerTest ./zt-tcp-relay nixosTestArgs;
matrix-synapse = self.clanLib.test.containerTest ./matrix-synapse nixosTestArgs;
postgresql = self.clanLib.test.containerTest ./postgresql nixosTestArgs;
# Container Tests
container = self.clanLib.test.containerTest ./container nixosTestArgs;
zt-tcp-relay = self.clanLib.test.containerTest ./zt-tcp-relay nixosTestArgs;
matrix-synapse = self.clanLib.test.containerTest ./matrix-synapse nixosTestArgs;
postgresql = self.clanLib.test.containerTest ./postgresql nixosTestArgs;
# Clan Tests
mumble = import ./mumble nixosTestArgs;
dummy-inventory-test = import ./dummy-inventory-test nixosTestArgs;
data-mesher = import ./data-mesher nixosTestArgs;
syncthing = import ./syncthing nixosTestArgs;
};
# Clan Tests
dummy-inventory-test = import ./dummy-inventory-test nixosTestArgs;
admin = import ./admin nixosTestArgs;
data-mesher = import ./data-mesher nixosTestArgs;
syncthing = import ./syncthing nixosTestArgs;
}
// lib.optionalAttrs (pkgs.stdenv.hostPlatform.system == "aarch64-linux") {
# for some reason this hangs in an odd place in CI, but it works on my machine ...
# on aarch64-linux it works though
mumble = import ./mumble nixosTestArgs;
};
packagesToBuild = lib.removeAttrs self'.packages [
# exclude the check that checks that nothing depends on the repo root
# We might want to include this later once everything is fixed
"dont-depend-on-repo-root"
];
flakeOutputs =
lib.mapAttrs' (
name: config: lib.nameValuePair "nixos-${name}" config.config.system.build.toplevel
) (lib.filterAttrs (n: _: !lib.hasPrefix "test-" n) self.nixosConfigurations)
// lib.mapAttrs' (n: lib.nameValuePair "package-${n}") self'.packages
// lib.mapAttrs' (n: lib.nameValuePair "package-${n}") packagesToBuild
// 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 { }
@@ -76,7 +90,10 @@ in
schema =
(self.clanLib.inventory.evalClanService {
modules = [ m ];
key = "checks";
prefix = [
"checks"
system
];
}).config.result.api.schema;
in
schema
@@ -90,6 +107,12 @@ in
mkdir -p $out
cat $schemaFile > $out/allSchemas.json
'';
clan-core-for-checks = pkgs.runCommand "clan-core-for-checks" { } ''
cp -r ${pkgs.callPackage ./clan-core-for-checks.nix { }} $out
chmod +w $out/flake.lock
cp ${../flake.lock} $out/flake.lock
'';
};
legacyPackages = {
nixosTests =

View File

@@ -43,6 +43,7 @@
let
dependencies = [
pkgs.disko
pkgs.buildPackages.xorg.lndir
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".pkgs.perlPackages.ConfigIniFiles
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".pkgs.perlPackages.FileSlurp
@@ -80,7 +81,7 @@
# Some distros like to automount disks with spaces
machine.succeed('mkdir -p "/mnt/with spaces" && mkfs.ext4 /dev/vdb && mount /dev/vdb "/mnt/with spaces"')
machine.succeed("clan flash write --debug --flake ${../..} --yes --disk main /dev/vdb test-flash-machine-${pkgs.hostPlatform.system}")
machine.succeed("clan flash write --debug --flake ${self.checks.x86_64-linux.clan-core-for-checks} --yes --disk main /dev/vdb test-flash-machine-${pkgs.hostPlatform.system}")
'';
} { inherit pkgs self; };
};

View File

@@ -8,7 +8,6 @@ let
{ modulesPath, pkgs, ... }:
let
dependencies = [
self
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.toplevel
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.diskoScript
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.clan.deployment.file
@@ -16,6 +15,7 @@ let
pkgs.bash.drvPath
pkgs.nixos-anywhere
pkgs.bubblewrap
pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
@@ -198,7 +198,7 @@ in
installer.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../assets/ssh/privkey} /root/.ssh/id_ed25519")
installer.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new -v nonrootuser@localhost hostname")
installer.succeed("cp -r ${../..} test-flake && chmod -R +w test-flake")
installer.succeed("cp -r ${self.checks.x86_64-linux.clan-core-for-checks} test-flake && chmod -R +w test-flake")
installer.succeed("clan machines install --no-reboot --debug --flake test-flake --yes test-install-machine-without-system --target-host nonrootuser@localhost --update-hardware-config nixos-facter >&2")
installer.shutdown()
@@ -218,7 +218,7 @@ in
installer.start()
installer.succeed("${pkgs.coreutils}/bin/install -Dm 600 ${../assets/ssh/privkey} /root/.ssh/id_ed25519")
installer.wait_until_succeeds("timeout 2 ssh -o StrictHostKeyChecking=accept-new -v nonrootuser@localhost hostname")
installer.succeed("cp -r ${../..} test-flake && chmod -R +w test-flake")
installer.succeed("cp -r ${self.checks.x86_64-linux.clan-core-for-checks} test-flake && chmod -R +w test-flake")
installer.fail("test -f test-flake/machines/test-install-machine/hardware-configuration.nix")
installer.fail("test -f test-flake/machines/test-install-machine/facter.json")

View File

@@ -32,7 +32,6 @@
{ pkgs, ... }:
let
dependencies = [
self
pkgs.stdenv.drvPath
pkgs.stdenvNoCC
self.nixosConfigurations.test-morph-machine.config.system.build.toplevel
@@ -44,14 +43,18 @@
{
environment.etc."install-closure".source = "${closureInfo}/store-paths";
system.extraDependencies = dependencies;
virtualisation.memorySize = 2048;
virtualisation.useNixStoreImage = true;
virtualisation.writableStore = true;
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli-full ];
};
};
testScript = ''
start_all()
actual.fail("cat /etc/testfile")
actual.succeed("env CLAN_DIR=${self} clan machines morph test-morph-template --i-will-be-fired-for-using-this --debug --name test-morph-machine")
actual.succeed("env CLAN_DIR=${self.checks.x86_64-linux.clan-core-for-checks} clan machines morph test-morph-template --i-will-be-fired-for-using-this --debug --name test-morph-machine")
assert actual.succeed("cat /etc/testfile") == "morphed"
'';
} { inherit pkgs self; };

View File

@@ -8,5 +8,8 @@
(modulesPath + "/profiles/minimal.nix")
];
virtualisation.useNixStoreImage = true;
virtualisation.writableStore = true;
clan.core.enableRecommendedDefaults = false;
}

View File

@@ -47,6 +47,20 @@ clanLib.test.makeTestClan {
nodes.peer2 = common;
testScript = ''
import time
import re
def machine_has_text(machine: Machine, regex: str) -> bool:
variants = machine.get_screen_text_variants()
# for debugging
# machine.screenshot(f"/tmp/{machine.name}.png")
for text in variants:
print(f"Expecting '{regex}' in '{text}'")
if re.search(regex, text) is not None:
return True
return False
start_all()
with subtest("Waiting for x"):
@@ -63,41 +77,53 @@ clanLib.test.makeTestClan {
peer2.execute("mumble >&2 &")
with subtest("Wait for Mumble"):
peer1.wait_for_window(r"^Mumble$")
peer2.wait_for_window(r"^Mumble$")
peer1.wait_for_window(r"Mumble")
peer2.wait_for_window(r"Mumble")
with subtest("Wait for certificate creation"):
peer1.wait_for_window(r"^Mumble$")
peer1.sleep(3) # mumble is slow to register handlers
peer1.send_chars("\n")
peer1.send_chars("\n")
peer2.wait_for_window(r"^Mumble$")
peer2.sleep(3) # mumble is slow to register handlers
peer2.send_chars("\n")
peer2.send_chars("\n")
peer1.wait_for_window(r"Mumble")
peer2.wait_for_window(r"Mumble")
with subtest("Wait for server connect"):
peer1.wait_for_window(r"^Mumble Server Connect$")
peer2.wait_for_window(r"^Mumble Server Connect$")
for i in range(20):
time.sleep(1)
peer1.send_chars("\n")
peer1.send_chars("\n")
peer2.send_chars("\n")
peer2.send_chars("\n")
if machine_has_text(peer1, r"Mumble Server Connect") and \
machine_has_text(peer2, r"Mumble Server Connect"):
break
else:
raise Exception("Timeout waiting for certificate creation")
with subtest("Check validity of server certificates"):
peer1.execute("killall .mumble-wrapped")
peer1.sleep(1)
peer1.execute("mumble mumble://peer2 >&2 &")
peer1.wait_for_window(r"^Mumble$")
peer1.sleep(3) # mumble is slow to register handlers
peer1.send_chars("\n")
peer1.send_chars("\n")
peer1.wait_for_text("Connected.")
peer1.wait_for_window(r"Mumble")
for i in range(20):
time.sleep(1)
peer1.send_chars("\n")
peer1.send_chars("\n")
if machine_has_text(peer1, "Connected."):
break
else:
raise Exception("Timeout waiting for certificate creation")
peer2.execute("killall .mumble-wrapped")
peer2.sleep(1)
peer2.execute("mumble mumble://peer1 >&2 &")
peer2.wait_for_window(r"^Mumble$")
peer2.sleep(3) # mumble is slow to register handlers
peer2.send_chars("\n")
peer2.send_chars("\n")
peer2.wait_for_text("Connected.")
peer2.wait_for_window(r"Mumble")
for i in range(20):
time.sleep(1)
peer2.send_chars("\n")
peer2.send_chars("\n")
if machine_has_text(peer2, "Connected."):
break
else:
raise Exception("Timeout waiting for certificate creation")
'';
}
);

View File

@@ -1,6 +0,0 @@
# Dont import this file
# It is only here for backwards compatibility.
# Dont author new modules with this file.
{
imports = [ ./roles/default.nix ];
}

View File

@@ -1,22 +0,0 @@
{ lib, config, ... }:
{
options.clan.admin = {
allowedKeys = lib.mkOption {
default = { };
type = lib.types.attrsOf lib.types.str;
description = "The allowed public keys for ssh access to the admin user";
example = {
"key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD...";
};
};
};
# Bad practice.
# Should we add 'clanModules' to specialArgs?
imports = [
../../sshd
../../root-password
];
config = {
users.users.root.openssh.authorizedKeys.keys = builtins.attrValues config.clan.admin.allowedKeys;
};
}

View File

@@ -105,10 +105,7 @@ in
private_key = {
inherit owner;
};
public_key = {
inherit owner;
secret = false;
};
public_key.secret = false;
};
runtimeInputs = [
@@ -134,10 +131,7 @@ in
private_key = {
inherit owner;
};
public_key = {
inherit owner;
secret = false;
};
public_key.secret = false;
};
runtimeInputs = [

View File

@@ -210,14 +210,18 @@ in
data_dir = Path('data')
data_dir.mkdir(mode=0o770, exist_ok=True)
# Create a temporary config file
# with appropriate permissions
tmp_config_path = data_dir / '.config.json'
tmp_config_path.touch(mode=0o660, exist_ok=False)
# Write the config with secrets back
config_path = data_dir / 'config.json'
with open(config_path, 'w') as f:
with open(tmp_config_path, 'w') as f:
f.write(json.dumps(config, indent=4))
# Set file permissions to read and write
# only by the user and group
config_path.chmod(0o660)
# Move config into place
config_path = data_dir / 'config.json'
tmp_config_path.rename(config_path)
# Set file permissions to read
# and write only by the user and group

View File

@@ -8,7 +8,6 @@ in
{
# only import available files, as this allows to filter the files for tests.
flake.clanModules = filterAttrs (_name: pathExists) {
admin = ./admin;
auto-upgrade = ./auto-upgrade;
borgbackup = ./borgbackup;
borgbackup-static = ./borgbackup-static;

View File

@@ -7,8 +7,12 @@ features = [ "inventory" ]
After the system was installed/deployed the following command can be used to display the root-password:
```bash
clan secrets get {machine_name}-password
clan vars get [machine_name] root-password/root-password
```
See also: [Vars](../../manual/vars-backend.md)
See also: [Facts / Secrets](../../getting-started/secrets.md)
To regenerate the password run:
```
clan vars generate --regenerate [machine_name] --generator root-password
```

View File

@@ -13,9 +13,12 @@ If setting the option prompt to true, the user will be prompted to type in their
After the system was installed/deployed the following command can be used to display the user-password:
```bash
clan secrets get {machine_name}-user-password
clan vars get [machine_name] root-password/root-password
```
See also: [Facts / Secrets](../../getting-started/secrets.md)
See also: [Vars](../../manual/vars-backend.md)
To regenerate the password, delete the password files in the clan directory and redeploy the machine.
To regenerate the password run:
```
clan vars generate --regenerate [machine_name] --generator user-password
```

View File

@@ -0,0 +1,37 @@
{ ... }:
{
_class = "clan.service";
manifest.name = "clan-core/admin";
roles.default = {
interface =
{ lib, ... }:
{
options.allowedKeys = lib.mkOption {
default = { };
type = lib.types.attrsOf lib.types.str;
description = "The allowed public keys for ssh access to the admin user";
example = {
"key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD...";
};
};
};
perInstance =
{ settings, ... }:
{
nixosModule =
{ ... }:
{
imports = [
../../clanModules/sshd
../../clanModules/root-password
];
users.users.root.openssh.authorizedKeys.keys = builtins.attrValues settings.allowedKeys;
};
};
};
}

View File

@@ -1,5 +1,10 @@
{ lib, ... }:
{
imports = [
./hello-world/flake-module.nix
];
clan.modules = {
admin = lib.modules.importApply ./admin/default.nix { };
};
}

View File

@@ -4,7 +4,15 @@
_class = "clan.service";
manifest.name = "clan-core/hello-word";
roles.peer = { };
roles.peer = {
interface =
{ lib, ... }:
{
options.foo = lib.mkOption {
type = lib.types.str;
};
};
};
perMachine =
{ machine, ... }:

View File

@@ -10,9 +10,6 @@ let
};
in
{
clan.inventory.modules = {
hello-world = module;
};
clan.modules = {
hello-world = module;
};
@@ -50,6 +47,7 @@ in
hello-service = import ./tests/vm/default.nix {
inherit module;
inherit self inputs pkgs;
# clanLib is exposed from inputs.clan-core
clanLib = self.clanLib;
};
};

View File

@@ -18,7 +18,7 @@ let
};
# Register the module for the test
inventory.modules.hello-world = module;
modules.hello-world = module;
# Use the module in the test
inventory.instances = {

View File

@@ -14,6 +14,9 @@ clanLib.test.makeTestClan {
clan = {
directory = ./.;
modules = {
hello-service = module;
};
inventory = {
machines.peer1 = { };
@@ -21,10 +24,6 @@ clanLib.test.makeTestClan {
module.name = "hello-service";
roles.peer.machines.peer1 = { };
};
modules = {
hello-service = module;
};
};
};

View File

@@ -19,7 +19,7 @@ We might not be sure whether all of those will exist but the architecture should
## Decision
This leads to the conclusion that we should do `library` centric development.
With the current `clan` python code beeing a library that can be imported to create various tools ontop of it.
With the current `clan` python code being a library that can be imported to create various tools ontop of it.
All **CLI** or **UI** related parts should be moved out of the main library.
*Note: The next person who wants implement any new frontend should do this first. Currently it looks like the TUI is the next one.*

View File

@@ -0,0 +1,47 @@
# ADR Numbering process
## Status
Proposed after some conversation between @lassulus, @Mic92, & @lopter.
## Context
It can be useful to refer to ADRs by their numbers, rather than their full title. To that end, short and sequential numbers are useful.
The issue is that an ADR number is effectively assigned when the ADR is merged, before being merged its number is provisional. Because multiple ADRs can be written at the same time, you end-up with multiple provisional ADRs with the same number, for example this is the third ADR-3:
1. ADR-3-clan-compat: see [#3212];
2. ADR-3-fetching-nix-from-python: see [#3452];
3. ADR-3-numbering-process: this ADR.
This situation makes it impossible to refer to an ADR by its number, and why I (@lopter) went with the arbitrary number 7 in [#3196].
We could solve this problem by using the PR number as the ADR number (@lassulus). The issue is that PR numbers are getting big in clan-core which does not make them easy to remember, or use in conversation and code (@lopter).
Another approach would be to move the ADRs in a different repository, this would reset the counter back to 1, and make it straightforward to keep ADR and PR numbers in sync (@lopter). The issue then is that ADR are not in context with their changes which makes them more difficult to review (@Mic92).
## Decision
A third approach would be to:
1. Commit ADRs before they are approved, so that the next ADR number gets assigned;
1. Open a PR for the proposed ADR;
1. Update the ADR file committed in step 1, so that its markdown contents point to the PR that tracks it.
## Consequences
### ADR have unique and memorable numbers trough their entire life cycle
This makes it easier to refer to them in conversation or in code.
### You need to have commit access to get an ADR number assigned
This makes it more difficult for someone external to the project to contribute an ADR.
### Creating a new ADR requires multiple commits
Maybe a script or CI flow could help with that if it becomes painful.
[#3212]: https://git.clan.lol/clan/clan-core/pulls/3212/
[#3452]: https://git.clan.lol/clan/clan-core/pulls/3452/
[#3196]: https://git.clan.lol/clan/clan-core/pulls/3196/

View File

@@ -58,7 +58,7 @@ nav:
- Autoincludes: manual/adding-machines.md
- Inventory:
- Inventory: manual/inventory.md
- Instances: manual/distributed-services.md
- Services: manual/distributed-services.md
- Secure Boot: manual/secure-boot.md
- Flake-parts: manual/flake-parts.md
- Authoring:
@@ -71,14 +71,16 @@ nav:
- Testing: contributing/testing.md
- Repo Layout: manual/repo-layout.md
- Migrate existing Flakes: manual/migration-guide.md
- Migrate inventory Services: guides/migrate-inventory-services.md
- Reference:
- Overview: reference/index.md
- Clan Modules:
- Overview:
- reference/clanModules/index.md
- reference/clanModules/frontmatter/index.md
# TODO: display the docs of the clan.service modules
# - reference/clanServices/admin.md
# This is the module overview and should stay at the top
- reference/clanModules/admin.md
- reference/clanModules/borgbackup-static.md
- reference/clanModules/data-mesher.md
- reference/clanModules/borgbackup.md

View File

@@ -26,8 +26,7 @@ writeShellScriptBin "deploy-docs" ''
trap "rm -rf $tmpdir" EXIT
if [ -n "''${SSH_HOMEPAGE_KEY-}" ]; then
echo "$SSH_HOMEPAGE_KEY" > "$tmpdir/ssh_key"
chmod 600 "$tmpdir/ssh_key"
( umask 0177 && echo "$SSH_HOMEPAGE_KEY" > "$tmpdir/ssh_key" )
sshExtraArgs="-i $tmpdir/ssh_key"
else
sshExtraArgs=

View File

@@ -12,7 +12,7 @@ We discussed the initial architecture in [01-clan-service-modules](https://git.c
### A Minimal module
First of all we need to register our module into the `inventory.modules` attribute. Make sure to choose a unique name so the module doesn't have a name collision with any of the core modules.
First of all we need to register our module into the `clan.modules` attribute. Make sure to choose a unique name so the module doesn't have a name collision with any of the core modules.
While not required we recommend to prefix your module attribute name.
@@ -22,20 +22,15 @@ i.e. `@hsjobeki/customNetworking`
```nix title="flake.nix"
# ...
outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({
imports = [ inputs.clan-core.flakeModules.default ];
# ...
clan = {
inventory = {
# We could also inline the complete module spec here
# For example
# {...}: { _class = "clan.service"; ... };
modules."@hsjobeki/customNetworking" = import ./service-modules/networking.nix;
};
# If needed: Exporting the module for other people
modules."@hsjobeki/customNetworking" = import ./service-modules/networking.nix;
# We could also inline the complete module spec here
# For example
# {...}: { _class = "clan.service"; ... };
};
})
```
@@ -221,9 +216,6 @@ outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}:
# ...
clan = {
# Register the module
inventory.modules."@hsjobeki/messaging" = lib.importApply ./service-modules/messaging.nix { inherit self; };
# Expose the module for downstream users, 'self' would always point to this flake.
modules."@hsjobeki/messaging" = lib.importApply ./service-modules/messaging.nix { inherit self; };
};
})
@@ -250,7 +242,7 @@ outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}:
# ...
clan = {
# Register the module
inventory.modules."@hsjobeki/messaging" = {
modules."@hsjobeki/messaging" = {
# Create an option 'myClan' and assign it to 'self'
options.myClan = lib.mkOption {
default = self;

View File

@@ -32,7 +32,7 @@ VM tests should be avoided wherever it is possible to implement a cheaper unit t
Existing nixos vm tests in clan-core can be found by using ripgrep:
```shellSession
rg "import.*/lib/test-base.nix"
rg self.clanLib.test.baseTest
```
### Locating definitions of failing VM tests
@@ -50,7 +50,7 @@ example: locating the vm test named `borgbackup`:
```shellSession
$ rg "borgbackup =" ./checks
./checks/flake-module.nix
41: borgbackup = import ./borgbackup nixosTestArgs;
44- wayland-proxy-virtwl = self.clanLib.test.baseTest ./wayland-proxy-virtwl nixosTestArgs;
```
-> the location of that test is `/checks/flake-module.nix` line `41`.
@@ -99,15 +99,15 @@ Basically everything stated under the NixOS VM tests sections applies here, exce
Limitations:
- does not yet support networking
- supports only one machine as of now
- Cannot run in interactive mode, however while the container test runs, it logs a nsenter command that can be used to log into each of the container.
- setuid binaries don't work
### Where to find examples for NixOS container tests
Existing nixos container tests in clan-core can be found by using ripgrep:
```shellSession
rg "import.*/lib/container-test.nix"
rg self.clanLib.test.containerTest
```

View File

@@ -0,0 +1,7 @@
# How to migrate `Inventory.services`
## Further reference
- [Authoring a 'clan.service' module](../authoring/clanServices/index.md)
- [Setting up `inventory.instances`](../manual/distributed-services.md)
- [Inventory Reference](../reference/nix-api/inventory.md)

View File

@@ -1,8 +1,10 @@
# Instances
# Setting up `inventory.instances`
In Clan *distributed services* can be declaratively deployed using the `inventory.instances` attribute
First of all it might be needed to explain what we mean by the term *distributed service*
## What is considered a service?
## What is considered a distributed service?
A **distributed service** is a system where multiple machines work together to provide a certain functionality, abstracting complexity and allowing for declarative configuration and management.

View File

@@ -1,6 +1,6 @@
# :material-api: Overview
This section of the site provides an **automatically extracted** overview of the available options and commands within the Clan Framework.
This section of the site provides an overview of available options and commands within the Clan Framework.
---

56
flake.lock generated
View File

@@ -16,17 +16,15 @@
]
},
"locked": {
"lastModified": 1745889637,
"narHash": "sha256-+BW9rppchFYIiJldD+fZA3MS2OtPNrb8l27SC3GyoSk=",
"ref": "refs/heads/main",
"rev": "11b5673d9c7290a6b96c2b6c6c5be600304f310f",
"revCount": 415,
"type": "git",
"url": "https://git.clan.lol/clan/data-mesher"
"lastModified": 1747008053,
"narHash": "sha256-rob/qftmEuk+/JVGCIrOpv+LWjdmayFtebEKqRZXVAI=",
"rev": "2666bb11f4287cfbdf3b7c5f55231c6b5772a436",
"type": "tarball",
"url": "https://git.clan.lol/api/v1/repos/clan/data-mesher/archive/2666bb11f4287cfbdf3b7c5f55231c6b5772a436.tar.gz"
},
"original": {
"type": "git",
"url": "https://git.clan.lol/clan/data-mesher"
"type": "tarball",
"url": "https://git.clan.lol/clan/data-mesher/archive/main.tar.gz"
}
},
"disko": {
@@ -36,11 +34,11 @@
]
},
"locked": {
"lastModified": 1745812220,
"narHash": "sha256-hotBG0EJ9VmAHJYF0yhWuTVZpENHvwcJ2SxvIPrXm+g=",
"lastModified": 1746729224,
"narHash": "sha256-9R4sOLAK1w3Bq54H3XOJogdc7a6C2bLLmatOQ+5pf5w=",
"owner": "nix-community",
"repo": "disko",
"rev": "d0c543d740fad42fe2c035b43c9d41127e073c78",
"rev": "85555d27ded84604ad6657ecca255a03fd878607",
"type": "github"
},
"original": {
@@ -76,11 +74,11 @@
]
},
"locked": {
"lastModified": 1745816321,
"narHash": "sha256-Gyh/fkCDqVNGM0BWvk+4UAS17w2UI6iwnbQQCmc1TDI=",
"lastModified": 1746708654,
"narHash": "sha256-GeC99gu5H6+AjBXsn5dOhP4/ApuioGCBkufdmEIWPRs=",
"owner": "nix-darwin",
"repo": "nix-darwin",
"rev": "4515dacafb0ccd42e5395aacc49fd58a43027e01",
"rev": "6cb36e8327421c61e5a3bbd08ed63491b616364a",
"type": "github"
},
"original": {
@@ -93,15 +91,13 @@
"locked": {
"lastModified": 1745005516,
"narHash": "sha256-IVaoOGDIvAa/8I0sdiiZuKptDldrkDWUNf/+ezIRhyc=",
"ref": "refs/heads/main",
"rev": "69d8bf596194c5c35a4e90dd02c52aa530caddf8",
"revCount": 40,
"type": "git",
"url": "https://git.clan.lol/clan/nix-select"
"type": "tarball",
"url": "https://git.clan.lol/api/v1/repos/clan/nix-select/archive/69d8bf596194c5c35a4e90dd02c52aa530caddf8.tar.gz"
},
"original": {
"type": "git",
"url": "https://git.clan.lol/clan/nix-select"
"type": "tarball",
"url": "https://git.clan.lol/clan/nix-select/archive/main.tar.gz"
}
},
"nixos-facter-modules": {
@@ -122,10 +118,10 @@
"nixpkgs": {
"locked": {
"lastModified": 315532800,
"narHash": "sha256-+Elxpf3FLkgKfh81xrEjVolpJEn8+fKWqEJ3ZXbAbS4=",
"rev": "29335f23bea5e34228349ea739f31ee79e267b88",
"narHash": "sha256-kgy4FnRFGj62QO3kI6a6glFl8XUtKMylWGybnVCvycM=",
"rev": "b3582c75c7f21ce0b429898980eddbbf05c68e55",
"type": "tarball",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.05pre791229.29335f23bea5/nixexprs.tar.xz"
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.05pre796313.b3582c75c7f2/nixexprs.tar.xz"
},
"original": {
"type": "tarball",
@@ -153,11 +149,11 @@
]
},
"locked": {
"lastModified": 1745310711,
"narHash": "sha256-ePyTpKEJTgX0gvgNQWd7tQYQ3glIkbqcW778RpHlqgA=",
"lastModified": 1746485181,
"narHash": "sha256-PxrrSFLaC7YuItShxmYbMgSuFFuwxBB+qsl9BZUnRvg=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "5e3e92b16d6fdf9923425a8d4df7496b2434f39c",
"rev": "e93ee1d900ad264d65e9701a5c6f895683433386",
"type": "github"
},
"original": {
@@ -188,11 +184,11 @@
]
},
"locked": {
"lastModified": 1745929750,
"narHash": "sha256-k5ELLpTwRP/OElcLpNaFWLNf8GRDq4/eHBmFy06gGko=",
"lastModified": 1746989248,
"narHash": "sha256-uoQ21EWsAhyskNo8QxrTVZGjG/dV4x5NM1oSgrmNDJY=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "82bf32e541b30080d94e46af13d46da0708609ea",
"rev": "708ec80ca82e2bbafa93402ccb66a35ff87900c5",
"type": "github"
},
"original": {

View File

@@ -23,10 +23,10 @@
treefmt-nix.url = "github:numtide/treefmt-nix";
treefmt-nix.inputs.nixpkgs.follows = "nixpkgs";
nix-select.url = "git+https://git.clan.lol/clan/nix-select";
nix-select.url = "https://git.clan.lol/clan/nix-select/archive/main.tar.gz";
data-mesher = {
url = "git+https://git.clan.lol/clan/data-mesher";
url = "https://git.clan.lol/clan/data-mesher/archive/main.tar.gz";
inputs = {
flake-parts.follows = "flake-parts";
nixpkgs.follows = "nixpkgs";
@@ -40,7 +40,6 @@
inputs@{
flake-parts,
nixpkgs,
self,
systems,
...
}:

View File

@@ -37,7 +37,7 @@ let
done
if ! test -e ~/clan-core; then
# git clone https://git.clan.lol/clan/clan-core.git ~/clan-core
cp -rv ${self} clan-core
cp -rv ${self.checks.x86_64-linux.clan-core-for-checks} clan-core
fi
cd clan-core
clan machines morph demo-template --i-will-be-fired-for-using-this

View File

@@ -10,6 +10,11 @@ let
in
{
options = {
_prefix = lib.mkOption {
type = types.listOf types.str;
internal = true;
default = [ ];
};
self = lib.mkOption {
type = types.raw;
default = self;
@@ -160,7 +165,6 @@ in
# Those options are interfaced by the CLI
# We don't specify the type here, for better performance.
inventory = lib.mkOption { type = lib.types.raw; };
inventoryValuesPrios = lib.mkOption { type = lib.types.raw; };
# all exported clan templates from this clan
templates = lib.mkOption { type = lib.types.raw; };
# all exported clan modules from this clan
@@ -169,6 +173,7 @@ in
inventoryFile = lib.mkOption { type = lib.types.raw; };
# The machine 'imports' generated by the inventory per machine
inventoryClass = lib.mkOption { type = lib.types.raw; };
evalServiceSchema = lib.mkOption { };
# clan-core's modules
clanModules = lib.mkOption { type = lib.types.raw; };
source = lib.mkOption { type = lib.types.raw; };

View File

@@ -44,6 +44,10 @@ let
buildInventory {
inherit inventory directory;
flakeInputs = config.self.inputs;
prefix = config._prefix ++ [ "inventoryClass" ];
# TODO: remove inventory.modules, this is here for backwards compatibility
localModuleSet =
lib.filterAttrs (n: _: !inventory._legacyModules ? ${n}) inventory.modules // config.modules;
}
);
@@ -177,6 +181,7 @@ in
# Merge the meta attributes from the buildClan function
{
inventory.modules = clan-core.clanModules;
inventory._legacyModules = clan-core.clanModules;
}
# config.inventory.meta <- config.meta
{ inventory.meta = config.meta; }
@@ -204,20 +209,21 @@ in
inherit inventoryClass;
# Endpoint that can be called to get a service schema
evalServiceSchema = clan-core.clanLib.evalServiceSchema config.self;
# TODO: unify this interface
# We should have only clan.modules. (consistent with clan.templates)
inherit (clan-core) clanModules clanLib;
modules = config.modules;
inherit inventoryFile;
inventoryValuesPrios =
# Temporary workaround
builtins.removeAttrs (clan-core.clanLib.introspection.getPrios { options = inventory.options; })
# tags are freeformType which is not supported yet.
[ "tags" ];
templates = config.templates;
inventory = config.inventory;
# TODO: Remove this in about a month
# It is only here for backwards compatibility for people with older CLI versions
inventoryValuesPrios = inventoryClass.introspection;
meta = config.inventory.meta;
secrets = config.secrets;

View File

@@ -15,10 +15,27 @@ lib.fix (clanLib: {
*/
callLib = file: args: import file ({ inherit lib clanLib; } // args);
# ------------------------------------
buildClan = clanLib.buildClanModule.buildClanWith {
clan-core = self;
inherit nixpkgs nix-darwin;
};
evalServiceSchema =
self:
{
moduleSpec,
flakeInputs ? self.inputs,
localModuleSet ? self.clan.modules,
}:
let
resolvedModule = clanLib.inventory.resolveModule {
inherit moduleSpec flakeInputs localModuleSet;
};
in
(clanLib.inventory.evalClanService {
modules = [ resolvedModule ];
prefix = [ ];
}).config.result.api.schema;
# ------------------------------------
# ClanLib functions
evalClan = clanLib.callLib ./inventory/eval-clan-modules { };

View File

@@ -12,27 +12,38 @@ let
inventory,
directory,
flakeInputs,
prefix ? [ ],
localModuleSet ? { },
}:
(lib.evalModules {
# TODO: remove clanLib from specialArgs
specialArgs = {
inherit clanLib;
};
modules = [
./builder
(lib.modules.importApply ./service-list-from-inputs.nix {
inherit flakeInputs clanLib localModuleSet;
})
{ inherit directory inventory; }
(
# config.distributedServices.allMachines.${name} or [ ];
{ config, ... }:
{
distributedServices = clanLib.inventory.mapInstances {
inherit (config) inventory;
inherit localModuleSet;
inherit flakeInputs;
prefix = prefix ++ [ "distributedServices" ];
};
machines = lib.mapAttrs (_machineName: v: {
machineImports = v;
}) config.distributedServices.allMachines;
}
)
(lib.modules.importApply ./inventory-introspection.nix { inherit clanLib; })
];
}).config;
in

View File

@@ -96,6 +96,12 @@ in
./assertions.nix
];
options = {
_legacyModules = lib.mkOption {
internal = true;
visible = false;
default = { };
};
options = lib.mkOption {
internal = true;
visible = false;
@@ -138,6 +144,28 @@ in
};
```
'';
apply =
moduleSet:
let
allowedNames = lib.attrNames config._legacyModules;
in
if builtins.all (moduleName: builtins.elem moduleName allowedNames) (lib.attrNames moduleSet) then
moduleSet
else
lib.warn ''
`inventory.modules` will be deprecated soon.
Please migrate the following modules into `clan.service` modules
and register them in `clan.modules`
${lib.concatStringsSep "\n" (
map (m: "'${m}'") (lib.attrNames (lib.filterAttrs (n: _v: !builtins.elem n allowedNames) moduleSet))
)}
See: https://docs.clan.lol/manual/distributed-services/
And: https://docs.clan.lol/authoring/clanServices/
'' moduleSet;
};
assertions = lib.mkOption {

View File

@@ -0,0 +1,17 @@
{ clanLib }:
{
config,
options,
lib,
...
}:
{
options.introspection = lib.mkOption {
readOnly = true;
# TODO: use options.inventory instead of the evaluate config attribute
default =
builtins.removeAttrs (clanLib.introspection.getPrios { options = config.inventory.options; })
# tags are freeformType which is not supported yet.
[ "tags" ];
};
}

View File

@@ -0,0 +1,43 @@
{
flakeInputs,
clanLib,
localModuleSet,
}:
{ lib, config, ... }:
let
inspectModule =
inputName: moduleName: module:
let
eval = clanLib.inventory.evalClanService {
modules = [ module ];
prefix = [
inputName
"clan"
"modules"
moduleName
];
};
in
{
manifest = eval.config.manifest;
roles = lib.mapAttrs (_n: _v: { }) eval.config.roles;
};
in
{
options.modulesPerSource = lib.mkOption {
# { sourceName :: { moduleName :: {} }}
default =
let
inputsWithModules = lib.filterAttrs (_inputName: v: v ? clan.modules) flakeInputs;
in
lib.mapAttrs (
inputName: v: lib.mapAttrs (inspectModule inputName) v.clan.modules
) inputsWithModules;
};
options.localModules = lib.mkOption {
default = lib.mapAttrs (inspectModule "self") localModuleSet;
};
}

View File

@@ -1,9 +1,12 @@
{
lib,
config,
resolvedRoles,
instanceName,
moduleName,
allRoles,
}:
{
lib,
config,
...
}:
let
@@ -11,7 +14,7 @@ let
in
{
imports = [
./interface.nix
(lib.modules.importApply ./interface.nix { inherit allRoles; })
# Role assertions
{
config.assertions = lib.foldlAttrs (
@@ -24,7 +27,7 @@ in
"${moduleName}.${instanceName}.roles.${roleName}.min" = {
assertion = memberCount >= roleConstraints.min;
message = ''
The ${moduleName} module requires at least ${builtins.toString roleConstraints.min} members of the '${roleName}' role
The '${moduleName}' module requires at least ${builtins.toString roleConstraints.min} members of the '${roleName}' role
but found '${builtins.toString memberCount}' members within instance '${instanceName}':
${lib.concatLines members}

View File

@@ -1,7 +1,8 @@
{
allRoles,
}:
{
lib,
allRoles,
moduleName,
...
}:
let
@@ -9,12 +10,6 @@ let
rolesAttrs = builtins.groupBy lib.id allRoles;
in
{
options.serviceName = mkOption {
type = types.str;
default = moduleName;
readOnly = true;
visible = false;
};
options.roles = lib.mapAttrs (
_name: _:
mkOption {

View File

@@ -3,7 +3,7 @@ let
services = clanLib.callLib ./distributed-service/inventory-adapter.nix { };
in
{
inherit (services) evalClanService mapInstances;
inherit (services) evalClanService mapInstances resolveModule;
inherit (import ./build-inventory { inherit lib clanLib; }) buildInventory;
interface = ./build-inventory/interface.nix;
# Returns the list of machine names

View File

@@ -1,7 +1,7 @@
# This module enables itself if
# manifest.features.API = true
# It converts the roles.interface to a json-schema
{ clanLib, attrName }:
{ clanLib, prefix }:
let
converter = clanLib.jsonschema {
includeDefaults = true;
@@ -45,7 +45,7 @@ in
To see the evaluation problem run
nix eval .#clanInternals.inventoryClass.distributedServices.importedModulesEvaluated.${attrName}.config.result.api.schema.${roleName}
nix eval .#${lib.concatStringsSep "." prefix}.config.result.api.schema.${roleName}
'';
assertion = (builtins.tryEval (lib.deepSeq config.result.api.schema.${roleName} true)).success;
};

View File

@@ -16,27 +16,73 @@
}:
let
evalClanService =
{ modules, key }:
{ modules, prefix }:
(lib.evalModules {
class = "clan.service";
modules = [
./service-module.nix
# feature modules
(lib.modules.importApply ./api-feature.nix {
inherit clanLib;
attrName = key;
inherit clanLib prefix;
})
] ++ modules;
});
resolveModule =
{
moduleSpec,
flakeInputs,
localModuleSet,
}:
let
# TODO:
resolvedModuleSet =
# If the module.name is self then take the modules defined in the flake
# Otherwise its an external input which provides the modules via 'clan.modules' attribute
if moduleSpec.input == null then
localModuleSet
else
let
input =
flakeInputs.${moduleSpec.input} or (throw ''
Flake doesn't provide input with name '${moduleSpec.input}'
Choose one of the following inputs:
- ${
builtins.concatStringsSep "\n- " (
lib.attrNames (lib.filterAttrs (_name: input: input ? clan) flakeInputs)
)
}
To import a local module from 'clan.modules' remove the 'input' attribute from the module definition
Remove the following line from the module definition:
...
- module.input = "${moduleSpec.input}"
'');
clanAttrs =
input.clan
or (throw "It seems the flake input ${moduleSpec.input} doesn't export any clan resources");
in
clanAttrs.modules;
resolvedModule =
resolvedModuleSet.${moduleSpec.name}
or (throw "flake doesn't provide clan-module with name ${moduleSpec.name}");
in
resolvedModule;
in
{
inherit evalClanService;
inherit evalClanService resolveModule;
mapInstances =
{
# This is used to resolve the module imports from 'flake.inputs'
flakeInputs,
# The clan inventory
inventory,
localModuleSet,
prefix ? [ ],
}:
let
# machineHasTag = machineName: tagName: lib.elem tagName inventory.machines.${machineName}.tags;
@@ -45,42 +91,11 @@ in
importedModuleWithInstances = lib.mapAttrs (
instanceName: instance:
let
# TODO:
resolvedModuleSet =
# If the module.name is self then take the modules defined in the flake
# Otherwise its an external input which provides the modules via 'clan.modules' attribute
if instance.module.input == null then
inventory.modules
else
let
input =
flakeInputs.${instance.module.input} or (throw ''
Flake doesn't provide input with name '${instance.module.input}'
Choose one of the following inputs:
- ${
builtins.concatStringsSep "\n- " (
lib.attrNames (lib.filterAttrs (_name: input: input ? clan) flakeInputs)
)
}
To import a local module from 'inventory.modules' remove the 'input' attribute from the module definition
Remove the following line from the module definition:
...
- module.input = "${instance.module.input}"
'');
clanAttrs =
input.clan
or (throw "It seems the flake input ${instance.module.input} doesn't export any clan resources");
in
clanAttrs.modules;
resolvedModule =
resolvedModuleSet.${instance.module.name}
or (throw "flake doesn't provide clan-module with name ${instance.module.name}");
resolvedModule = resolveModule {
moduleSpec = instance.module;
inherit localModuleSet;
inherit flakeInputs;
};
# Every instance includes machines via roles
# :: { client :: ... }
@@ -138,7 +153,7 @@ in
importedModulesEvaluated = lib.mapAttrs (
module_ident: instances:
evalClanService {
key = module_ident;
prefix = prefix ++ [ module_ident ];
modules =
[
# Import the resolved module.

View File

@@ -0,0 +1,78 @@
{ lib, config, ... }:
let
inherit (lib) mkOption;
inherit (lib) types;
in
{
options = {
name = mkOption {
description = ''
The name of the module
Mainly used to create an error context while evaluating.
This helps backtracking which module was included; And where an error came from originally.
'';
type = types.str;
};
description = mkOption {
type = types.str;
description = ''
A Short description of the module.
'';
defaultText = "Short description";
default = config.name;
};
categories = mkOption {
default = [ "Uncategorized" ];
description = ''
Categories are used for Grouping and searching.
While initial oriented on [freedesktop](https://specifications.freedesktop.org/menu-spec/latest/category-registry.html) the following categories are allowed
'';
type = types.listOf (
types.enum [
"AudioVideo"
"Audio"
"Video"
"Development"
"Education"
"Game"
"Graphics"
"Social"
"Network"
"Office"
"Science"
"System"
"Settings"
"Utility"
"Uncategorized"
]
);
};
features = mkOption {
description = ''
Enable built-in features for the module
See the documentation for each feature:
- API
'';
type = types.submoduleWith {
modules = [
{
options.API = mkOption {
type = types.bool;
# This is read only, because we don't support turning it off yet
readOnly = true;
default = true;
description = ''
Enables automatic API schema conversion for the interface of this module.
'';
};
}
];
};
default = { };
};
};
}

View File

@@ -232,41 +232,7 @@ in
description = "Meta information about this module itself";
type = submoduleWith {
modules = [
{
options = {
name = mkOption {
description = ''
The name of the module
Mainly used to create an error context while evaluating.
This helps backtracking which module was included; And where an error came from originally.
'';
type = types.str;
};
features = mkOption {
description = ''
Enable built-in features for the module
See the documentation for each feature:
- API
'';
type = types.submoduleWith {
modules = [
{
options.API = mkOption {
type = types.bool;
default = false;
description = ''
Enables automatic API schema conversion for the interface of this module.
'';
};
}
];
};
default = { };
};
};
}
./manifest/default.nix
];
};
};

View File

@@ -41,9 +41,13 @@ let
callInventoryAdapter =
inventoryModule:
let
inventory = evalInventory inventoryModule;
in
clanLib.inventory.mapInstances {
flakeInputs = flakeInputsFixture;
inventory = evalInventory inventoryModule;
inherit inventory;
localModuleSet = inventory.modules;
};
in
{

View File

@@ -34,37 +34,60 @@ let
allModules,
}:
lib.evalModules {
specialArgs = {
inherit moduleName resolvedRoles instanceName;
allRoles = getRoles "inventory.modules" allModules moduleName;
};
modules = [
(getFrontmatter allModules.${moduleName} moduleName)
./interface.nix
{
constraints.imports = [
(lib.modules.importApply ../constraints {
inherit moduleName resolvedRoles instanceName;
allRoles = getRoles "inventory.modules" allModules moduleName;
})
];
}
];
};
# For Documentation purposes only
frontmatterOptions =
(lib.evalModules {
specialArgs = {
moduleName = "{moduleName}";
allRoles = [ "{roleName}" ];
};
modules = [
./interface.nix
{
constraints.imports = [
(lib.modules.importApply ../constraints {
moduleName = "{moduleName}";
allRoles = [ "{roleName}" ];
})
];
}
];
}).options;
migratedModules = [ "admin" ];
makeModuleNotFoundError =
serviceName:
if builtins.elem serviceName migratedModules then
''
(Legacy) ClanModule not found: '${serviceName}'.
Please update your configuration to use this module via 'inventory.instances'
See: https://docs.clan.lol/manual/distributed-services/
''
else
''
(Legacy) ClanModule not found: '${serviceName}'.
Make sure the module is added to inventory.modules.${serviceName}
'';
# This is a legacy function
# Old modules needed to define their roles by directory
# This means if this function gets anything other than a string/path it will throw
getRoles =
scope: allModules: serviceName:
_scope: allModules: serviceName:
let
module =
allModules.${serviceName}
or (throw "(Legacy) ClanModule not found: '${serviceName}'. Make sure the module is added to ${scope}");
module = allModules.${serviceName} or (throw (makeModuleNotFoundError serviceName));
moduleType = (lib.typeOf module);
checked =
if

View File

@@ -1,6 +1,5 @@
{
lib,
specialArgs,
...
}:
let
@@ -76,9 +75,8 @@ in
```
'';
type = types.submoduleWith {
inherit specialArgs;
modules = [
../constraints
];
};
};

View File

@@ -92,7 +92,7 @@ in
lib.lazyDerivation {
# lazyDerivation improves performance when only passthru items and/or meta are used.
derivation = hostPkgs.stdenv.mkDerivation {
name = "vm-test-run-${config.name}";
name = "container-test-run-${config.name}";
requiredSystemFeatures = [ "uid-range" ];

View File

@@ -2,9 +2,11 @@ import argparse
import ctypes
import os
import re
import shutil
import subprocess
import time
import types
import uuid
from collections.abc import Callable
from contextlib import _GeneratorContextManager
from dataclasses import dataclass
@@ -13,6 +15,8 @@ from pathlib import Path
from tempfile import TemporaryDirectory
from typing import Any
from colorama import Fore, Style
from .logger import AbstractLogger, CompositeLogger, TerminalLogger
# Load the C library
@@ -187,6 +191,22 @@ class Machine:
if line_pattern.match(line)
)
def nsenter_command(self, command: str) -> list[str]:
return [
"nsenter",
"--target",
str(self.container_pid),
"--mount",
"--uts",
"--ipc",
"--net",
"--pid",
"--cgroup",
"/bin/sh",
"-c",
command,
]
def execute(
self,
command: str,
@@ -228,23 +248,10 @@ class Machine:
"""
# Always run command with shell opts
command = f"set -eo pipefail; source /etc/profile; set -u; {command}"
command = f"set -eo pipefail; source /etc/profile; set -xu; {command}"
proc = subprocess.run(
[
"nsenter",
"--target",
str(self.container_pid),
"--mount",
"--uts",
"--ipc",
"--net",
"--pid",
"--cgroup",
"/bin/sh",
"-c",
command,
],
self.nsenter_command(command),
timeout=timeout,
check=False,
stdout=subprocess.PIPE,
@@ -465,6 +472,43 @@ class Driver:
print(f"Starting {machine.name}")
machine.start()
# Print copy-pastable nsenter command to debug container tests
for machine in self.machines:
nspawn_uuid = uuid.uuid4()
# We lauch a sleep here, so we can pgrep the process cmdline for
# the uuid
sleep = shutil.which("sleep")
assert sleep is not None, "sleep command not found"
machine.execute(
f"systemd-run /bin/sh -c '{sleep} 999999999 && echo {nspawn_uuid}'",
)
print(f"nsenter for {machine.name}:")
print(
" ".join(
[
Style.BRIGHT,
Fore.CYAN,
"sudo",
"nsenter",
"--user",
"--target",
f"$(\\pgrep -f '^/bin/sh.*{nspawn_uuid}')",
"--mount",
"--uts",
"--ipc",
"--net",
"--pid",
"--cgroup",
"/bin/sh",
"-c",
"bash",
Style.RESET_ALL,
]
)
)
def test_symbols(self) -> dict[str, Any]:
general_symbols = {
"start_all": self.start_all,

View File

@@ -22,6 +22,9 @@ in
pkgs,
self,
useContainers ? true,
# Displayed for better error messages, otherwise the placeholder
system ? "<system>",
attrName ? "<check_name>",
...
}:
let
@@ -35,7 +38,7 @@ in
{
imports = [
nixosTest
] ++ lib.optionals (useContainers) [ ./container-test-driver/driver-module.nix ];
] ++ lib.optionals useContainers [ ./container-test-driver/driver-module.nix ];
options = {
clanSettings = mkOption {
default = { };
@@ -60,6 +63,15 @@ in
};
modules = [
clanLib.buildClanModule.flakePartsModule
{
_prefix = [
"checks"
system
attrName
"config"
"clan"
];
}
];
};
};

21
module.nix Normal file
View File

@@ -0,0 +1,21 @@
{ lib, ... }:
{
_class = "clan.service";
manifest.name = "test";
roles.peer.interface =
{ ... }:
{
options.debug = lib.mkOption { default = 1; };
};
roles.peer.perInstance =
{ settings, ... }:
{
nixosModule = {
options.debug = lib.mkOption {
default = settings;
};
};
};
}

View File

@@ -39,9 +39,44 @@ in
type = submodule { imports = [ ./interface.nix ]; };
};
config.system.clan.deployment.data = {
vars = config.clan.core.vars._serialized;
inherit (config.clan.core.networking) targetHost buildHost;
inherit (config.clan.core.deployment) requireExplicitUpdate;
config = {
# check all that all non-secret files have no owner/group/mode set
warnings = lib.foldl' (
warnings: generator:
warnings
++ lib.foldl' (
warnings: file:
warnings
++
lib.optional
(
!file.secret
&& (
file.owner != "root"
|| file.group != (if _class == "darwin" then "wheel" else "root")
|| file.mode != "0400"
)
)
''
The config.clan.core.vars.generators.${generator.name}.files.${file.name} is not secret:
${lib.optionalString (file.owner != "root") ''
The owner is set to ${file.owner}, but should be root.
''}
${lib.optionalString (file.group != (if _class == "darwin" then "wheel" else "root")) ''
The group is set to ${file.group}, but should be ${if _class == "darwin" then "wheel" else "root"}.
''}
${lib.optionalString (file.mode != "0400") ''
The mode is set to ${file.mode}, but should be 0400.
''}
This doesn't work because the file will be added to the nix store
''
) [ ] (lib.attrValues generator.files)
) [ ] (lib.attrValues config.clan.core.vars.generators);
system.clan.deployment.data = {
vars = config.clan.core.vars._serialized;
inherit (config.clan.core.networking) targetHost buildHost;
inherit (config.clan.core.deployment) requireExplicitUpdate;
};
};
}

View File

@@ -39,7 +39,7 @@ in
internal = true;
description = ''
JSON serialization of the generators.
This is read from the python client to generate the specified ressources.
This is read from the python client to generate the specified resources.
'';
default = {
# TODO: We don't support per-machine choice of backends
@@ -241,12 +241,30 @@ in
type = bool;
default = true;
};
flakePath = lib.mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = nullOr str;
default = null;
};
path = lib.mkOption {
description = ''
The path to the file containing the content of the generated value.
This will be set automatically
'';
type = str;
defaultText = ''
builtins.path {
name = "$${generator.config._module.args.name}_$${file.config._module.args.name}";
path = file.config.flakePath;
}
'';
default = builtins.path {
name = "${generator.config._module.args.name}_${file.config._module.args.name}";
path = file.config.flakePath;
};
};
neededFor = lib.mkOption {
description = ''

View File

@@ -11,7 +11,7 @@ in
config.clan.core.vars.settings = mkIf (config.clan.core.vars.settings.publicStore == "in_repo") {
publicModule = "clan_cli.vars.public_modules.in_repo";
fileModule = file: {
path = mkIf (file.config.secret == false) (
flakePath = mkIf (file.config.secret == false) (
if file.config.share then
(
config.clan.core.settings.directory
@@ -25,9 +25,9 @@ in
);
value = mkIf (file.config.secret == false) (
# dynamically adjust priority to allow overriding with mkDefault in case the file is not found
if (pathExists file.config.path) then
if (pathExists file.config.flakePath) then
# if the file is found it should have normal priority
readFile file.config.path
readFile file.config.flakePath
else
# if the file is not found, we want to downgrade the priority, to allow overriding via mkDefault
mkOptionDefault (

View File

@@ -18,7 +18,7 @@ let
config.clan.core.settings.directory
+ "/vars/per-machine/${machineName}/${secret.generator}/${secret.name}/secret";
vars = collectFiles config.clan.core.vars;
vars = collectFiles config.clan.core.vars.generators;
in
{
config.clan.core.vars.settings = lib.mkIf (config.clan.core.vars.settings.secretStore == "sops") {
@@ -49,7 +49,10 @@ in
mode
neededForUsers
;
sopsFile = secretPath secret;
sopsFile = builtins.path {
name = "${secret.generator}_${secret.name}";
path = secretPath secret;
};
format = "binary";
};
}) (builtins.filter (x: builtins.pathExists (secretPath x)) vars)

View File

@@ -13,7 +13,7 @@ in
{
collectFiles =
vars:
generators:
let
relevantFiles =
generator:
@@ -30,7 +30,7 @@ in
inherit (generator) share;
inherit (file) owner group mode;
}) (relevantFiles generator)
) vars.generators
) generators
);
in
allFiles;

View File

@@ -29,6 +29,8 @@ mkShell {
export GIT_ROOT=$(git rev-parse --show-toplevel)
export PKG_ROOT=$GIT_ROOT/pkgs/clan-app
export CLAN_CORE_PATH="$GIT_ROOT"
# Add current package to PYTHONPATH
export PYTHONPATH="$PKG_ROOT''${PYTHONPATH:+:$PYTHONPATH:}"

View File

@@ -6,13 +6,13 @@ from pathlib import Path
from types import ModuleType
# These imports are unused, but necessary for @API.register to run once.
from clan_lib.api import admin, directory, disk, iwd, mdns_discovery, modules
from clan_lib.api import directory, disk, iwd, mdns_discovery, modules
from .arg_actions import AppendOptionAction
from .clan import show, update
# API endpoints that are not used in the cli.
__all__ = ["admin", "directory", "disk", "iwd", "mdns_discovery", "modules", "update"]
__all__ = ["directory", "disk", "iwd", "mdns_discovery", "modules", "update"]
from . import (
backups,

View File

@@ -19,21 +19,23 @@ def create_backup(machine: Machine, provider: str | None = None) -> None:
if not backup_scripts["providers"]:
msg = "No providers specified"
raise ClanError(msg)
for provider in backup_scripts["providers"]:
proc = machine.target_host.run(
[backup_scripts["providers"][provider]["create"]],
)
if proc.returncode != 0:
msg = "failed to start backup"
raise ClanError(msg)
print("successfully started backup")
with machine.target_host() as host:
for provider in backup_scripts["providers"]:
proc = host.run(
[backup_scripts["providers"][provider]["create"]],
)
if proc.returncode != 0:
msg = "failed to start backup"
raise ClanError(msg)
print("successfully started backup")
else:
if provider not in backup_scripts["providers"]:
msg = f"provider {provider} not found"
raise ClanError(msg)
proc = machine.target_host.run(
[backup_scripts["providers"][provider]["create"]],
)
with machine.target_host() as host:
proc = host.run(
[backup_scripts["providers"][provider]["create"]],
)
if proc.returncode != 0:
msg = "failed to start backup"
raise ClanError(msg)

View File

@@ -10,6 +10,7 @@ from clan_cli.completions import (
)
from clan_cli.errors import ClanError
from clan_cli.machines.machines import Machine
from clan_cli.ssh.host import Host
@dataclass
@@ -18,11 +19,11 @@ class Backup:
job_name: str | None = None
def list_provider(machine: Machine, provider: str) -> list[Backup]:
def list_provider(machine: Machine, host: Host, provider: str) -> list[Backup]:
results = []
backup_metadata = machine.eval_nix("config.clan.core.backups")
list_command = backup_metadata["providers"][provider]["list"]
proc = machine.target_host.run(
proc = host.run(
[list_command],
RunOpts(log=Log.NONE, check=False),
)
@@ -48,12 +49,13 @@ def list_provider(machine: Machine, provider: str) -> list[Backup]:
def list_backups(machine: Machine, provider: str | None = None) -> list[Backup]:
backup_metadata = machine.eval_nix("config.clan.core.backups")
results = []
if provider is None:
for _provider in backup_metadata["providers"]:
results += list_provider(machine, _provider)
with machine.target_host() as host:
if provider is None:
for _provider in backup_metadata["providers"]:
results += list_provider(machine, host, _provider)
else:
results += list_provider(machine, provider)
else:
results += list_provider(machine, host, provider)
return results

View File

@@ -8,9 +8,12 @@ from clan_cli.completions import (
)
from clan_cli.errors import ClanError
from clan_cli.machines.machines import Machine
from clan_cli.ssh.host import Host
def restore_service(machine: Machine, name: str, provider: str, service: str) -> None:
def restore_service(
machine: Machine, host: Host, name: str, provider: str, service: str
) -> None:
backup_metadata = machine.eval_nix("config.clan.core.backups")
backup_folders = machine.eval_nix("config.clan.core.state")
@@ -25,7 +28,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
env["FOLDERS"] = ":".join(set(folders))
if pre_restore := backup_folders[service]["preRestoreCommand"]:
proc = machine.target_host.run(
proc = host.run(
[pre_restore],
RunOpts(log=Log.STDERR),
extra_env=env,
@@ -34,7 +37,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
msg = f"failed to run preRestoreCommand: {pre_restore}, error was: {proc.stdout}"
raise ClanError(msg)
proc = machine.target_host.run(
proc = host.run(
[backup_metadata["providers"][provider]["restore"]],
RunOpts(log=Log.STDERR),
extra_env=env,
@@ -44,7 +47,7 @@ def restore_service(machine: Machine, name: str, provider: str, service: str) ->
raise ClanError(msg)
if post_restore := backup_folders[service]["postRestoreCommand"]:
proc = machine.target_host.run(
proc = host.run(
[post_restore],
RunOpts(log=Log.STDERR),
extra_env=env,
@@ -61,18 +64,19 @@ def restore_backup(
service: str | None = None,
) -> None:
errors = []
if service is None:
backup_folders = machine.eval_nix("config.clan.core.state")
for _service in backup_folders:
with machine.target_host() as host:
if service is None:
backup_folders = machine.eval_nix("config.clan.core.state")
for _service in backup_folders:
try:
restore_service(machine, host, name, provider, _service)
except ClanError as e:
errors.append(f"{_service}: {e}")
else:
try:
restore_service(machine, name, provider, _service)
restore_service(machine, host, name, provider, service)
except ClanError as e:
errors.append(f"{_service}: {e}")
else:
try:
restore_service(machine, name, provider, service)
except ClanError as e:
errors.append(f"{service}: {e}")
errors.append(f"{service}: {e}")
if errors:
raise ClanError(
"Restore failed for the following services:\n" + "\n".join(errors)

View File

@@ -1,4 +1,8 @@
from clan_cli.cmd import run
import os
import shutil
from pathlib import Path
from clan_cli.cmd import Log, RunOpts, run
from clan_cli.nix import nix_shell
_works: bool | None = None
@@ -12,6 +16,11 @@ def bubblewrap_works() -> bool:
def _bubblewrap_works() -> bool:
real_bash_path = Path("bash")
if os.environ.get("IN_NIX_SANDBOX"):
bash_executable_path = Path(str(shutil.which("bash")))
real_bash_path = bash_executable_path.resolve()
# fmt: off
cmd = nix_shell(
[
@@ -30,13 +39,10 @@ def _bubblewrap_works() -> bool:
"--gid", "1000",
"--",
# do nothing, just test if bash executes
"bash", "-c", ":"
str(real_bash_path), "-c", ":"
],
)
# fmt: on
try:
run(cmd)
except Exception:
return False
else:
return True
res = run(cmd, RunOpts(log=Log.BOTH, check=False))
return res.returncode == 0

View File

@@ -107,7 +107,7 @@ def create_clan(opts: CreateOptions) -> CreateClanResponse:
response.flake_update = flake_update
if opts.initial:
init_inventory(str(opts.dest), init=opts.initial)
init_inventory(Flake(str(opts.dest)), init=opts.initial)
return response

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