Compare commits

...

422 Commits

Author SHA1 Message Date
pinpox
956281ba38 Remove clanModules 2025-08-18 14:34:05 +02:00
clan-bot
3fb8b6587d Merge pull request 'Update nixpkgs-dev in devFlake' (#4791) from update-devFlake-nixpkgs-dev into main 2025-08-17 00:08:28 +00:00
clan-bot
6aee353b43 Update nixpkgs-dev in devFlake 2025-08-17 00:01:48 +00:00
hsjobeki
e109361e81 Merge pull request 'clanModules: remove unused code' (#4785) from clean-dead-code into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4785
2025-08-16 11:03:16 +00:00
Johannes Kirschbauer
3c34f81a44 inventory/tests: remove unused tests 2025-08-16 12:56:30 +02:00
Johannes Kirschbauer
72e7c2e9b9 clanModules: cleanup some more unused code 2025-08-16 12:56:30 +02:00
Johannes Kirschbauer
03968d8fbc api/inventory: remove leaked schemas 2025-08-16 12:56:30 +02:00
Johannes Kirschbauer
2f27b3941e lib/inventory: limit access to defined keys 2025-08-16 12:56:30 +02:00
clan-bot
e9dc5b9ba6 Merge pull request 'Update nixpkgs-dev in devFlake' (#4787) from update-devFlake-nixpkgs-dev into main 2025-08-16 10:07:46 +00:00
clan-bot
e4ef885cd5 Update nixpkgs-dev in devFlake 2025-08-16 10:01:45 +00:00
Johannes Kirschbauer
9fe457ebd5 lib/clanModules: update nix_models 2025-08-16 11:59:16 +02:00
Johannes Kirschbauer
4a51aa9316 clanModules: remove unused test code 2025-08-16 11:58:55 +02:00
Johannes Kirschbauer
308a10d6e6 clanModules: remove unused code 2025-08-16 11:48:13 +02:00
clan-bot
90f513a08f Merge pull request 'Update nixpkgs' (#4784) from update-nixpkgs into main 2025-08-16 00:21:23 +00:00
clan-bot
4ddc61d132 Update nixpkgs 2025-08-16 00:01:27 +00:00
clan-bot
fc0088e9ea Merge pull request 'Update nix-darwin' (#4783) from update-nix-darwin into main 2025-08-15 20:16:14 +00:00
clan-bot
71094f7fa1 Update nix-darwin 2025-08-15 20:00:52 +00:00
clan-bot
a8516cf9c6 Merge pull request 'Update nixpkgs-dev in devFlake' (#4782) from update-devFlake-nixpkgs-dev into main 2025-08-15 15:08:18 +00:00
clan-bot
a89e2f877a Update nixpkgs-dev in devFlake 2025-08-15 15:01:50 +00:00
Mic92
ed78e49c47 Merge pull request 'vms/inspect: mark test as pure' (#4781) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4781
2025-08-15 11:54:46 +00:00
Jörg Thalheim
3ef0a7919d vms/inspect: mark test as pure 2025-08-15 13:31:27 +02:00
Jörg Thalheim
36812d5f95 test_vars_deployment: simplify test to just start one vm 2025-08-15 13:30:30 +02:00
Mic92
f5bcdb4ba0 Merge pull request 'flakes/inspect: mark test as pure' (#4779) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4779
2025-08-15 11:28:22 +00:00
Jörg Thalheim
b69ad0eca5 backups/list: mark as pure 2025-08-15 13:10:41 +02:00
Jörg Thalheim
b221c29694 flakes/inspect: mark test as pure 2025-08-15 13:08:30 +02:00
Luis Hebendanz
7dc7f09173 Merge pull request 'clanServices: telegraf -> add basic auth' (#4777) from Qubasa/clan-core:basic_auth_telegraf into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4777
2025-08-15 11:07:44 +00:00
Mic92
ec3d224e1d Merge pull request 'tests_secrets_generate: mark as pure' (#4766) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4766
2025-08-15 11:06:47 +00:00
Luis Hebendanz
00c5312080 Merge pull request 'docs: Revamp Getting Started guide for clarity and usability' (#4776) from scriptogre/clan-core:update-getting-started-docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4776
2025-08-15 11:04:52 +00:00
Qubasa
7811a56d2b clanServices: telegraf -> add basic auth
treefmt
2025-08-15 18:02:31 +07:00
Jörg Thalheim
e9401177b7 installation: make sure target host is actually down 2025-08-15 12:51:20 +02:00
Jörg Thalheim
ef56258e8b impure-checks: reduce to 6 jobs 2025-08-15 12:51:20 +02:00
Jörg Thalheim
c4d9b39a17 tests_secrets_generate: mark as pure 2025-08-15 12:51:20 +02:00
Mic92
1f59b75c20 Merge pull request 'Delete old files when deploying docs' (#4775) from deploy-docs-delete into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4775
2025-08-15 10:24:10 +00:00
scriptogre
6b6da7b897 docs: Revamp and simplify Getting Started guide 2025-08-15 13:19:39 +03:00
pinpox
4391c19ee9 Delete old files when deploying docs 2025-08-15 12:04:46 +02:00
hsjobeki
eb993b7060 Merge pull request 'ui/vars: add more vars to install story' (#4747) from ui-install-3 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4747
2025-08-15 09:14:46 +00:00
Johannes Kirschbauer
08cb6993a8 install/progress: display usb-stick 2025-08-15 11:10:57 +02:00
Johannes Kirschbauer
872f640211 install/assets: init usb-stick png image 2025-08-15 11:04:10 +02:00
Johannes Kirschbauer
c58f7c573d ui/install: clean up design 2025-08-15 11:04:09 +02:00
Johannes Kirschbauer
7b807a0745 ui/vars: add more vars to install story 2025-08-15 11:04:09 +02:00
pinpox
62805c66ff Merge pull request 'Add monitoring service' (#4756) from monitoring-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4756
2025-08-15 08:57:36 +00:00
pinpox
30b737ae1f init telegraph service 2025-08-15 10:54:39 +02:00
Luis Hebendanz
cc41185f98 Merge pull request 'flake.py: Error messages are now always ClanSelectErrors. Improved error messages' (#4773) from Qubasa/clan-core:improve_select_error into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4773
2025-08-15 06:50:46 +00:00
Qubasa
606aae7212 flake.py: Error messages are now always ClanSelectErrors. Improved error messages
flake.py: Fix unbound variable

flake.py: Fix test_create.py test
2025-08-15 13:46:12 +07:00
clan-bot
c31d884dc7 Merge pull request 'Update nixpkgs' (#4772) from update-nixpkgs into main 2025-08-15 05:22:06 +00:00
clan-bot
f546ce82f6 Update nixpkgs 2025-08-15 05:01:35 +00:00
clan-bot
b173bc37f5 Merge pull request 'Update nixpkgs' (#4771) from update-nixpkgs into main 2025-08-15 00:18:55 +00:00
clan-bot
0c20cfb34a Update nixpkgs 2025-08-15 00:01:25 +00:00
clan-bot
6c096a276d Merge pull request 'Update nixpkgs-dev in devFlake' (#4770) from update-devFlake-nixpkgs-dev into main 2025-08-14 20:08:03 +00:00
clan-bot
b7436b5b7f Update nixpkgs-dev in devFlake 2025-08-14 20:01:49 +00:00
hsjobeki
a84ab5d4bf Merge pull request 'exports: rename special args' (#4765) from exports-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4765
2025-08-14 16:11:07 +00:00
Johannes Kirschbauer
a82ecbcbff docs: update docs for exports 2025-08-14 18:01:19 +02:00
Mic92
4ae3abe8c2 Merge pull request 'Update nixpkgs-dev in devFlake' (#4669) from update-devFlake-nixpkgs-dev into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4669
2025-08-14 16:01:05 +00:00
Johannes Kirschbauer
90c7951704 exports: expose in special args or 'perInstance' and 'perMachine' 2025-08-14 17:58:23 +02:00
Johannes Kirschbauer
116ff37156 exports: rename special args 2025-08-14 17:58:23 +02:00
clan-bot
f11df276a9 Update nixpkgs-dev in devFlake 2025-08-14 15:57:22 +00:00
Mic92
d44b43a937 Merge pull request 'test_machines_cli: remove more tests from the impure set' (#4764) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4764
2025-08-14 15:22:01 +00:00
Jörg Thalheim
716b74bc02 test_machines_cli: remove more tests from the impure set 2025-08-14 17:14:35 +02:00
Mic92
c85969c2b4 Merge pull request 'chore: remove spurious folder' (#4763) from orga into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4763
2025-08-14 15:11:51 +00:00
Johannes Kirschbauer
edb7dcc154 chore: remove spurious folder 2025-08-14 17:06:02 +02:00
Mic92
3586b4f48c Merge pull request 'clan-cli/machines/list: mark test as pure' (#4761) from no-impure-machines into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4761
2025-08-14 14:59:10 +00:00
Jörg Thalheim
9cdc6a27b6 test_copy_from_nixstore_symlink: drop test.
seems a bit overkill to have a test for two lines of python code...
2025-08-14 16:53:39 +02:00
Mic92
ceecdc0eef Merge pull request 'clan-cli/flash: remove impure tests' (#4757) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4757
2025-08-14 14:41:12 +00:00
Jörg Thalheim
96014c02c5 clan-cli/templates: mark tests as pure 2025-08-14 16:35:25 +02:00
Jörg Thalheim
810a2c67f9 clan-cli/machines/list: mark test as pure 2025-08-14 16:33:21 +02:00
Jörg Thalheim
fbb28afb2f clan-cli/flash: make tests runnable in sandbox 2025-08-14 16:23:22 +02:00
hsjobeki
a6ef38dadd Merge pull request 'vars: move generator class and bound methods into seperate module' (#4734) from generator-class into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4734
2025-08-14 14:17:14 +00:00
Mic92
328e0b20ac Merge pull request 'machines/list: make tests pure' (#4759) from no-impure-list into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4759
2025-08-14 14:07:51 +00:00
brianmcgee
7e77505316 Merge pull request 'fix(ui): host file input max width' (#4760) from fix/host-file-input-max-width into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4760
2025-08-14 14:01:34 +00:00
Brian McGee
245453b461 fix(ui): host file input max width 2025-08-14 14:57:26 +01:00
Jörg Thalheim
21e6a01cf3 machines/list: make tests pure 2025-08-14 15:54:00 +02:00
brianmcgee
302adf6f41 Merge pull request 'chore(ui): general cleanup' (#4758) from chore/cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4758
2025-08-14 13:32:36 +00:00
Brian McGee
f754b88ae4 chore(ui): general cleanup 2025-08-14 14:28:23 +01:00
Mic92
34d27e6bab Merge pull request 'clan-vm-manager: don't mark test_is_local as impure' (#4755) from no-impure into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4755
2025-08-14 13:12:59 +00:00
Jörg Thalheim
5817713e39 clan-vm-manager: don't mark test_is_local as impure.
should just work without it
2025-08-14 15:09:33 +02:00
clan-bot
cc283e88c9 Merge pull request 'Update disko' (#4700) from update-disko into main 2025-08-14 12:33:03 +00:00
clan-bot
1bb9f4741d Update disko 2025-08-14 12:12:27 +00:00
clan-bot
0d26e991e6 Merge pull request 'Update nuschtos in devFlake' (#4674) from update-devFlake-nuschtos into main 2025-08-14 12:11:19 +00:00
gitea-actions[bot]
961beda3e5 Update nuschtos in devFlake 2025-08-14 14:07:34 +02:00
clan-bot
0a8a1d4354 Merge pull request 'Update nixpkgs' (#4667) from update-nixpkgs into main 2025-08-14 12:05:03 +00:00
clan-bot
daf8d8e80d Update nixpkgs 2025-08-14 14:02:09 +02:00
Mic92
011b2a5872 Merge pull request 'update-flake-inputs: set different author' (#4753) from macos-ci into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4753
2025-08-14 11:35:09 +00:00
Jörg Thalheim
da06babcc2 update-flake-inputs: set different author 2025-08-14 13:30:22 +02:00
Mic92
c43eeb68a5 Merge pull request 'macos: don't build devShell until CI error is fixed' (#4752) from macos-ci into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4752
2025-08-14 11:27:30 +00:00
Jörg Thalheim
5e485a37f5 macos: don't build devShell until CI error is fixed 2025-08-14 13:05:02 +02:00
pinpox
ce902bed0a Merge pull request 'Remove clanModules (again)' (#4387) from remove-modules-new into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4387
2025-08-14 10:39:23 +00:00
pinpox
a5d401b715 Update migration status table 2025-08-14 12:29:27 +02:00
pinpox
2637496059 zt-tcp-relay: drop 2025-08-14 12:03:47 +02:00
pinpox
87c8a4549b re-add table with migration status 2025-08-14 12:02:40 +02:00
pinpox
35e5f4a42a Remove clanModules
- Removes clanModules in favor of the new clanServices
- Adds a warning and link to the migration guide
2025-08-14 12:02:40 +02:00
pinpox
e4949755d7 Merge pull request 'Migrate matrix-synapse to clan services' (#4684) from migrate-matrix-synapse into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4684
2025-08-14 10:01:14 +00:00
pinpox
b239c5bd88 Migrate matrix-synapse to clan services 2025-08-14 11:54:52 +02:00
Johannes Kirschbauer
4312e3fc2f vars: move generator class and bound methods into seperate module 2025-08-14 11:05:42 +02:00
hsjobeki
62ef90e959 Merge pull request 'codeowners: remove @lopter due to inactivity' (#4742) from codeowners into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4742
2025-08-13 17:48:08 +00:00
hsjobeki
7fdbd2e3eb Merge pull request 'dirs: remove unused conditional import' (#4736) from import-cleanup-dirs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4736
2025-08-13 17:46:19 +00:00
hsjobeki
7daebd5ee0 Merge pull request 'networking: remove unused conditional import' (#4737) from networking-import into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4737
2025-08-13 17:46:04 +00:00
hsjobeki
cc8dd0564b Merge pull request 'askpass: use protocol as interface' (#4739) from interface-askpass into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4739
2025-08-13 17:43:01 +00:00
Johannes Kirschbauer
23e52954c9 codeowners: remove @lopter due to inactivity 2025-08-13 19:41:47 +02:00
hsjobeki
4717d1f149 Merge pull request 'lib/Remote: Unify class method _parse_ssh_uri with class file' (#4733) from imports-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4733
2025-08-13 17:40:36 +00:00
Johannes Kirschbauer
e28f280036 vars: remove unused conditional import 2025-08-13 19:24:53 +02:00
Johannes Kirschbauer
6fa2a977df askpass: use protocol as interface
Avoids a cyclic dependency on the Remote class
Strips down the dependency closure by explizitly declaring what functions it needs
2025-08-13 19:21:18 +02:00
Johannes Kirschbauer
65dba2508f dirs: remove unused conditional import 2025-08-13 19:04:32 +02:00
Johannes Kirschbauer
9884643070 networking: remove unused conditional import 2025-08-13 19:03:35 +02:00
Johannes Kirschbauer
5083992f7b lib: remove unused TYPE_CHECKING 2025-08-13 18:26:57 +02:00
Johannes Kirschbauer
6bd8839128 lib/Remote: Unify class method _parse_ssh_uri with class file 2025-08-13 18:26:28 +02:00
clan-bot
765bdb262a Merge pull request 'Update clan-core-for-checks in devFlake' (#4731) from update-devFlake-clan-core-for-checks into main 2025-08-13 15:22:38 +00:00
gitea-actions[bot]
05c00fbe82 Update clan-core-for-checks in devFlake 2025-08-13 15:01:35 +00:00
clan-bot
7e97734797 Merge pull request 'Update clan-core-for-checks in devFlake' (#4727) from update-devFlake-clan-core-for-checks into main 2025-08-13 13:57:32 +00:00
gitea-actions[bot]
6384c4654e Update clan-core-for-checks in devFlake 2025-08-13 13:54:09 +00:00
DavHau
72d3ad09a4 vars: refactor - pass Machine objects to run_generators 2025-08-13 12:45:47 +00:00
DavHau
a535450ec0 vars: refactor - unify get_generators and _get_closure 2025-08-13 12:45:47 +00:00
Mic92
aaeb616f82 Merge pull request 'Drop update-private-flake-inputs ci action' (#4730) from init-wireguard-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4730
2025-08-13 12:42:59 +00:00
Jörg Thalheim
434edeaae1 drop update-private-flake-inputs 2025-08-13 14:35:43 +02:00
Mic92
a4efd3cb16 Merge pull request 'update-sops-nix2' (#4719) from update-sops-nix2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4719
2025-08-13 12:34:37 +00:00
Jörg Thalheim
13131ccd6e docs/wireguard: put requirements at the top 2025-08-13 14:34:15 +02:00
hsjobeki
3a8309b01f Merge pull request 'UI/install: add loading animation' (#4723) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4723
2025-08-13 12:19:23 +00:00
Johannes Kirschbauer
10065a7c8f UI/install: add loading to button 2025-08-13 14:15:52 +02:00
Johannes Kirschbauer
176b54e29d UI/Button: move state out of the button 2025-08-13 14:15:29 +02:00
Jörg Thalheim
be048d8307 morph/flash: use patched clan-core-for-checks
the other one doesn't override flake.lock
2025-08-13 11:41:09 +00:00
gitea-actions[bot]
52fcab30e7 Update sops-nix 2025-08-13 11:41:09 +00:00
Mic92
d3b423328f Merge pull request 'Add wireguard service module' (#3354) from init-wireguard-service into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/3354
2025-08-13 10:55:48 +00:00
Jörg Thalheim
1177e84dcc vars/generate: print the files that were found when files are missing
this helps fixing typos in the generator scripts
2025-08-13 12:29:52 +02:00
pinpox
414952dfa3 Add wireguard service module 2025-08-13 12:29:52 +02:00
DavHau
24194011ac vars: refactor - remove unnecessary return values
The boolean return value signaling if anything was ran or not isn't that useful. We are not doing anything with it.
2025-08-13 12:54:05 +07:00
DavHau
4f78a8ff94 Merge pull request 'networking_3' (#4507) from networking_3 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4507
2025-08-13 05:20:03 +00:00
DavHau
068b5d4c1e install: fix error message when target host not specified 2025-08-13 12:04:14 +07:00
DavHau
adccef4757 install: fix torify package not available 2025-08-13 12:04:14 +07:00
Qubasa
980d94d47d clan_cli: Improve cli message if no networks present 2025-08-13 12:04:14 +07:00
lassulus
a50b25eea2 clan-cli network: refactor, use new networking in ssh and install commands 2025-08-13 12:04:14 +07:00
lassulus
017989841d refactor: remove DeployInfo class and use Network/Remote directly
- Remove DeployInfo class entirely, replacing with direct Remote usage
- Update parse_qr_json_to_networks to return dict with network and remote
- Refactor all code to work with Remote lists instead of DeployInfo
- Add get_remote_for_machine context manager for network connections
- Update tests to use new Network/Remote structure
2025-08-13 12:04:14 +07:00
lassulus
c14a5fcc69 refactor: move ssh/upload.py from cli to lib
Move the upload module to clan_lib to better organize SSH-related
utilities. Updated all imports across the codebase.
2025-08-13 12:04:14 +07:00
clan-bot
4f60345ba7 Merge pull request 'Update clan-core-for-checks in devFlake' (#4726) from update-devFlake-clan-core-for-checks into main 2025-08-13 00:21:42 +00:00
gitea-actions[bot]
ece48d3b5f Update clan-core-for-checks in devFlake 2025-08-13 00:01:32 +00:00
clan-bot
4eea8d24f0 Merge pull request 'Update clan-core-for-checks in devFlake' (#4725) from update-devFlake-clan-core-for-checks into main 2025-08-12 20:26:23 +00:00
gitea-actions[bot]
49099df3fb Update clan-core-for-checks in devFlake 2025-08-12 20:01:32 +00:00
Johannes Kirschbauer
62ccba9fb5 ui/install: test connection 2025-08-12 21:04:18 +02:00
Johannes Kirschbauer
0b44770f1f UI/install: add loading animation 2025-08-12 20:45:55 +02:00
hsjobeki
61c3d7284a Merge pull request 'pkgs/clan/lib(install): implement separate nixos-anywhere install phases' (#4710) from ke-install-phases into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4710
2025-08-12 15:34:15 +00:00
clan-bot
44b1be5ed4 Merge pull request 'Update clan-core-for-checks in devFlake' (#4717) from update-devFlake-clan-core-for-checks into main 2025-08-12 15:30:32 +00:00
Jörg Thalheim
88871bea69 clan_lib/flash: remove trailing whitespace 2025-08-12 17:14:52 +02:00
Johannes Kirschbauer
5141ea047c install: init secrets 2025-08-12 17:11:58 +02:00
gitea-actions[bot]
ff6a03a646 Update clan-core-for-checks in devFlake 2025-08-12 15:01:31 +00:00
Johannes Kirschbauer
bc379c985d ui/install: update storybook mock data 2025-08-12 16:35:34 +02:00
Johannes Kirschbauer
69d8b029d6 ui/install: fix alignment of some steps 2025-08-12 16:35:34 +02:00
Johannes Kirschbauer
f3617b0407 ui/vars: sanitize generator and prompt field names 2025-08-12 16:35:34 +02:00
Johannes Kirschbauer
a5205681cc ui/select: fix z-index of trigger 2025-08-12 16:35:34 +02:00
Johannes Kirschbauer
9880847d43 install: add progress to ui 2025-08-12 16:35:34 +02:00
a-kenji
8aa88b22ab pkgs/clan/lib(install): implement separate nixos-anywhere install phases
Split the `nixos-anywhere` phases into it's components,
so we provide the user with better feedback.

Closes: #4682
2025-08-12 16:35:34 +02:00
brianmcgee
ff979eba61 Merge pull request 'ui/integrate-clan-tags-machine-detail' (#4716) from ui/integrate-clan-tags-machine-detail into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4716
2025-08-12 14:20:27 +00:00
Brian McGee
5d1abbd303 feat(ui): integrate tags info from field schema into tags section 2025-08-12 15:16:59 +01:00
Brian McGee
92e9bb2ed8 feat(ui): integrate list_tags api call into machine detail 2025-08-12 14:46:43 +01:00
brianmcgee
ea75c9bfa9 Merge pull request 'feat(ui): add small and transparent variants for Alert component' (#4713) from feat/small-variant-for-alert into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4713
Reviewed-by: hsjobeki <hsjobeki@gmail.com>
2025-08-12 12:04:31 +00:00
hsjobeki
2adf65482d Merge pull request 'feat(api): add list_inventory_tags' (#4692) from feat/machine-tags-writeability into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4692
2025-08-12 11:33:49 +00:00
DavHau
5684ddf104 vars: health check also for API not just cli 2025-08-12 11:28:02 +00:00
Johannes Kirschbauer
f74e444120 api/tags: add docs 2025-08-12 13:19:11 +02:00
Johannes Kirschbauer
0ef57bfc8e api/tags: add init.py for pytest 2025-08-12 13:07:36 +02:00
Brian McGee
8f43af3c48 feat(ui): add transparent option for Alert component 2025-08-12 11:52:38 +01:00
Brian McGee
eeaec583cb feat(ui): add small variant for Alert component 2025-08-12 11:52:37 +01:00
Johannes Kirschbauer
a9d1ff83f2 api/tags: split list into options and non-configurable tags 2025-08-12 12:41:15 +02:00
DavHau
89cb22147c Revert "machines update: support --target-host localhost"
This reverts commit a2818d4946cc66a08b9dd7a1ab95dc48ea708fe3.

Setting `--target-host localhost` breaks with:
sudo: no askpass program specified, try setting SUDO_ASKPASS
2025-08-12 17:39:40 +07:00
Jörg Thalheim
1006fc755e clanTest/vars-executor: add debugging to finalScript 2025-08-12 12:38:47 +02:00
clan-bot
f100177df3 Merge pull request 'Update clan-core-for-checks in devFlake' (#4709) from update-devFlake-clan-core-for-checks into main 2025-08-12 10:26:57 +00:00
Johannes Kirschbauer
cbd3b08296 api/tags: add from all possible sources 2025-08-12 11:05:10 +01:00
Brian McGee
2608bee30a feat(api): add list_inventory_tags 2025-08-12 11:05:10 +01:00
gitea-actions[bot]
a29459a384 Update clan-core-for-checks in devFlake 2025-08-12 10:01:30 +00:00
DavHau
1abdd45821 vars: add doc comments for fix() and health_check() 2025-08-12 09:13:54 +00:00
brianmcgee
b058fcc8eb Merge pull request 'fix(ui): swap colors for inverted/non-inverted in Divider component' (#4696) from fix/invert-default-color-scheme-divider into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4696
2025-08-12 09:09:20 +00:00
Brian McGee
24ae95a007 fix(ui): swap colors for inverted/non-inverted in Divider component
Fixes #4602
2025-08-12 10:00:40 +01:00
brianmcgee
39510b613f Merge pull request 'fix color=inherit in typography component' (#4693) from fix/typography-color-inherit into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4693
2025-08-12 09:00:20 +00:00
Brian McGee
dcdab61d13 feat(ui): improve color=inherit example in typography story 2025-08-12 09:56:26 +01:00
hsjobeki
f86fe07b63 Merge pull request 'fix/commit-mono-woff2' (#4695) from fix/commit-mono-woff2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4695
2025-08-12 07:51:57 +00:00
Brian McGee
84bf9fe3cf fix(ui): load CommitMono via woff2 instead of OTF
Fixes #4611
2025-08-12 07:48:21 +00:00
Luis Hebendanz
9737ce51b1 Merge pull request 'Fix clan select hiding error messages' (#4704) from Qubasa/clan-core:clan_select_error_msg into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4704
2025-08-12 07:46:35 +00:00
Qubasa
3c1c6c1942 flake.py: Add a custom error message for missing clan export
test_clan_create_api: Fix check for SelectCmdError
2025-08-12 14:41:26 +07:00
Qubasa
0904c9da60 flake.py: Don't hide error messages 2025-08-12 14:18:19 +07:00
Luis Hebendanz
73e03c21f7 Merge pull request 'templates: Fix missing export of clan = clan.config;' (#4703) from Qubasa/clan-core:fix_templates2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4703
2025-08-12 07:05:07 +00:00
Qubasa
743f05a1b5 templates: Fix missing export of clan = clan.config; 2025-08-12 13:50:09 +07:00
DavHau
e28b8dc944 vars: refactor - health checks on multiple generators 2025-08-12 13:12:49 +07:00
clan-bot
8d871aafe8 Merge pull request 'Update clan-core-for-checks in devFlake' (#4701) from update-devFlake-clan-core-for-checks into main 2025-08-12 05:25:52 +00:00
DavHau
26559ff88b Merge pull request 'machines update: support --target-host localhost' (#4623) from jfly/clan-core:localhost-as-target-host-without-ssh into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4623
2025-08-12 05:10:53 +00:00
gitea-actions[bot]
b39aead1db Update clan-core-for-checks in devFlake 2025-08-12 05:01:29 +00:00
DavHau
caae6c7a55 docs: improve wording on getting-started
I found the header text to be confusing at places:
- `at least one machine to push to`: Pushing what? Where? DO I ned a git server? Do you mean installing?

-> I re-phrased the text

Also removed the tree command, as this is not available on most systems by default
2025-08-12 11:33:28 +07:00
DavHau
df90fb20a0 clan-lib/hosts: reintroduce test for localhost 2025-08-12 10:18:55 +07:00
clan-bot
d6577ec05d Merge pull request 'Update clan-core-for-checks in devFlake' (#4698) from update-devFlake-clan-core-for-checks into main 2025-08-12 00:17:53 +00:00
gitea-actions[bot]
9a66170aa1 Update clan-core-for-checks in devFlake 2025-08-12 00:01:27 +00:00
clan-bot
3effd8fd9a Merge pull request 'Update clan-core-for-checks in devFlake' (#4697) from update-devFlake-clan-core-for-checks into main 2025-08-11 20:18:06 +00:00
hsjobeki
86d6b42f4c Merge pull request 'api/machines: add tests for tags readOnly' (#4694) from readonly-tags into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4694
2025-08-11 20:09:25 +00:00
gitea-actions[bot]
5e2ffa9491 Update clan-core-for-checks in devFlake 2025-08-11 20:01:27 +00:00
Mic92
ba58d6d91a Merge pull request 'devFlake: switch back to main' (#4691) from update-nixpkgs-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4691
2025-08-11 16:44:31 +00:00
Jörg Thalheim
38e2d00bbc flash test: enable useNixStoreImage
we had some weird corruption, this hopefully helps. Unclear if it's
slower..
2025-08-11 18:23:28 +02:00
Johannes Kirschbauer
4f29f2e2ca api/machines: add tests for tags readOnly 2025-08-11 18:07:02 +02:00
Jörg Thalheim
5c23e24315 devFlake: switch back to main 2025-08-11 18:02:56 +02:00
Johannes Kirschbauer
1009c61c9f api/machines: use get_value_by_path utility for nested dict access 2025-08-11 17:49:25 +02:00
hsjobeki
0817f83b0b Merge pull request 'api/machines: expose readonly tags' (#4690) from readonly-tags into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4690
2025-08-11 15:40:42 +00:00
Mic92
4f191f3ebe Merge pull request 'Bump nixpkgs + ci fixes' (#4688) from update-nixpkgs-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4688
2025-08-11 15:35:55 +00:00
Johannes Kirschbauer
9f48b7a2fa inventory: rename 'unmerge-lists' to 'list_difference' 2025-08-11 17:35:31 +02:00
Johannes Kirschbauer
b17466c84b api/machines: expose readonly tags 2025-08-11 17:30:35 +02:00
Jörg Thalheim
d2814efcde update: sort precached vars 2025-08-11 17:18:01 +02:00
Jörg Thalheim
6a5a83f57a devFlake: switch to clan-core-for-checks to this branch 2025-08-11 17:17:27 +02:00
Jörg Thalheim
9e9ab22c37 skip private inputs again 2025-08-11 17:16:34 +02:00
gitea-actions[bot]
2840d3a5fc Update nixpkgs 2025-08-11 17:16:34 +02:00
clan-bot
a305f98586 Merge pull request 'Update clan-core-for-checks in devFlake' (#4689) from update-devFlake-clan-core-for-checks into main 2025-08-11 15:13:45 +00:00
hsjobeki
96fe387399 Merge pull request 'api: init notification queue' (#4678) from ui-notify into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4678
2025-08-11 15:13:42 +00:00
gitea-actions[bot]
d022f26c2c Update clan-core-for-checks in devFlake 2025-08-11 15:01:28 +00:00
Johannes Kirschbauer
d1f5a8e263 ui/install: set fixed dimensions for modal 2025-08-11 17:00:20 +02:00
Mic92
a6a5c1e21d Merge pull request 'zt-tcp-relay: 2023-07-11 -> 2025-07-03' (#4687) from zt-tcp-relay into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4687
2025-08-11 14:27:35 +00:00
Jörg Thalheim
f1867bdd7a zt-tcp-relay: 2023-07-11 -> 2025-07-03 2025-08-11 16:23:10 +02:00
DavHau
ee8e44d255 vars/generators: refactor - identify generators by name + machine
This brings us one step closer towards re-generating over multiple machines reliably
2025-08-11 21:02:55 +07:00
Mic92
f730f4fa06 Merge pull request 'make clan-core-for-checks a dev flake input' (#4247) from private-flake-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4247
2025-08-11 13:45:22 +00:00
Jörg Thalheim
567570e89c make clan-core-for-checks a dev flake input 2025-08-11 15:36:40 +02:00
Johannes Kirschbauer
54797dd5f5 ui/install: hook up notification bus 2025-08-11 15:30:55 +02:00
Johannes Kirschbauer
c70c588c1c ui/api: init message bus subscriber hooks 2025-08-11 15:24:41 +02:00
Johannes Kirschbauer
bb6fab1168 api: init notification queue 2025-08-11 15:24:41 +02:00
Johannes Kirschbauer
0859a86ce0 ui/api: simplify types in api 2025-08-11 15:24:41 +02:00
hsjobeki
1524dc963e Merge pull request 'ui/install: hook up {cancel, close} method' (#4685) from install-cancel into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4685
2025-08-11 13:24:26 +00:00
Johannes Kirschbauer
eebd3fa4ec ui/install: hook up {cancel, close} method 2025-08-11 15:15:00 +02:00
brianmcgee
a1ff794d57 Merge pull request 'feat: ui/machine-detail-writeability' (#4577) from ui/machine-detail-writeability into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4577
2025-08-11 11:40:30 +00:00
pinpox
6693cda465 Merge pull request 'Refactor admin module' (#4681) from fix-admin-service-split into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4681
2025-08-11 11:36:24 +00:00
Brian McGee
bf0691587d feat(ui): integrate machine writeability 2025-08-11 12:34:00 +01:00
brianmcgee
deecb966ce Merge pull request 'wip(ui): MachineTags component and tags section in machine detail pane' (#4560) from ui/machine-tags into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4560
2025-08-11 11:31:11 +00:00
Brian McGee
2d2d9c9dca chore(ui): remove some console.log statements 2025-08-11 12:21:36 +01:00
Brian McGee
e0e16de144 feat(ui): MachineTags component and tags section in machine detail pane 2025-08-11 12:21:33 +01:00
pinpox
75c60a6103 Refactor admin module 2025-08-11 13:13:24 +02:00
pinpox
1373670dfc Merge pull request 'Migrate dyndns to clanServices' (#4390) from migrate-dyndns into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4390
2025-08-11 10:23:02 +00:00
pinpox
03b13e9ed4 Migrate dyndns to clanServices 2025-08-11 12:19:21 +02:00
pinpox
a79027c312 Merge pull request 'Improve hello-world example service' (#4679) from better-hello into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4679
2025-08-11 10:16:18 +00:00
pinpox
bdcdf4e788 Merge branch 'main' into better-hello 2025-08-11 10:11:42 +00:00
pinpox
e3ed9d7b4b Improve hello-world example service 2025-08-11 12:03:04 +02:00
Mic92
ddf2b57b3f Merge pull request 'install: precache vars' (#4680) from install-vars into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4680
2025-08-11 10:02:33 +00:00
Jörg Thalheim
5ab3a164c8 install: precache vars 2025-08-11 11:51:06 +02:00
DavHau
073027f7c6 vars/generate: refactor - mark private as private 2025-08-11 11:46:25 +07:00
DavHau
d0374c0d7c vars/keygen: add --no-interactive flags
This is useful to force on-interactive mode with automatic key selection. In unit tests this is necessary. When debugging a test on a real terminal interactive mode is not desired
2025-08-11 11:29:25 +07:00
clan-bot
6137701532 Merge pull request 'Update Clan Core for Checks' (#4675) from update-clan-core-for-checks into main 2025-08-11 03:03:57 +00:00
clan-bot
1560c5f8cf Update pinned clan-core for checks 2025-08-11 02:51:46 +00:00
Kenji Berthold
5d884cecc2 Merge pull request 'formatter: init sizelint' (#4673) from kenji/init-sizelint into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4673
2025-08-10 21:57:10 +00:00
a-kenji
8a3cade082 formatter: init sizelint 2025-08-10 23:50:34 +02:00
Kenji Berthold
10b4389309 Merge pull request 'chore(inputs): bump treefmt-nix' (#4672) from kenji/ke-bump-treefmt into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4672
2025-08-10 21:49:12 +00:00
a-kenji
2879c72a89 chore(inputs): bump treefmt-nix
Flake lock file updates:

• Updated input 'treefmt-nix':
    'github:numtide/treefmt-nix/1298185c05a56bff66383a20be0b41a307f52228?narHash=sha256-B%2B3g9%2B76KlGe34Yk9za8AF3RL%2BlnbHXkLiVHLjYVOAc%3D' (2025-08-06)
  → 'github:numtide/treefmt-nix/7d81f6fb2e19bf84f1c65135d1060d829fae2408?narHash=sha256-2vX8QjO5lRsDbNYvN9hVHXLU6oMl%2BV/PsmIiJREG4rE%3D' (2025-08-10)
2025-08-10 23:41:48 +02:00
clan-bot
547e912c4e Merge pull request 'Update treefmt-nix in devFlake' (#4671) from update-devFlake-treefmt-nix into main 2025-08-10 20:28:18 +00:00
Kenji Berthold
87125f1ff7 Merge branch 'main' into update-devFlake-treefmt-nix 2025-08-10 20:25:17 +00:00
pinpox
804f606384 Merge pull request 'Migrate localbackup to clanServices' (#4656) from migrate-localbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4656
2025-08-10 20:14:27 +00:00
gitea-actions[bot]
997c7de942 Update treefmt-nix in devFlake 2025-08-10 20:06:20 +00:00
hsjobeki
e7323999f2 Merge pull request 'Sops: generate key should always 'generate' a key pair when beeing called' (#4664) from sops-keys into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4664
2025-08-10 12:09:47 +00:00
Johannes Kirschbauer
31d3997358 Secrets: fix tests 2025-08-10 13:06:42 +02:00
Johannes Kirschbauer
62b748624d Secrets: allow to generate additional keys with --new 2025-08-10 13:04:34 +02:00
Johannes Kirschbauer
29f440a482 Sops: generate key should always 'generate' a key pair when beeing called
Check if you want to generate a new key as a caller
2025-08-10 13:04:34 +02:00
clan-bot
f15fd1be52 Merge pull request 'Update Clan Core for Checks' (#4662) from update-clan-core-for-checks into main 2025-08-10 02:59:55 +00:00
clan-bot
beaacf81c6 Update pinned clan-core for checks 2025-08-10 02:51:46 +00:00
pinpox
1ae023f4bf Remove old backup test 2025-08-10 00:56:36 +02:00
hsjobeki
9becd4e0c4 Merge pull request 'Vars: remove spurious 'fake_prompt' with mocked method' (#4659) from cleaner into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4659
2025-08-09 22:53:18 +00:00
Johannes Kirschbauer
454b09a67e Vars: remove unused return 2025-08-10 00:19:08 +02:00
Johannes Kirschbauer
787781c2ad Vars: remove spurious 'fake_prompt' with mocked method 2025-08-10 00:18:01 +02:00
hsjobeki
469c6ba42d Merge pull request 'UI: Resolve some more install blockers' (#4657) from feat-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4657
2025-08-09 18:12:35 +00:00
hsjobeki
21f335fa15 Merge pull request 'fix: remove spurious test file' (#4658) from cleaner into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4658
2025-08-09 18:08:30 +00:00
Johannes Kirschbauer
d98b76e734 fix: remove spurious test file 2025-08-09 20:04:11 +02:00
Johannes Kirschbauer
e2cb1fd83f UI/install: run generators 2025-08-09 20:02:06 +02:00
Johannes Kirschbauer
91646b323a API/generators: adjust filtering to match cli logic 2025-08-09 19:58:23 +02:00
Johannes Kirschbauer
121548ffb7 UI/onboarding: init admin instance 2025-08-09 19:56:23 +02:00
Johannes Kirschbauer
966a3ee919 UI/queries: init generators query 2025-08-09 19:56:23 +02:00
Johannes Kirschbauer
d007b0f1b3 API/generators: expose display attribute of prompts 2025-08-09 19:56:23 +02:00
Johannes Kirschbauer
034982bff2 API/modules: init create_service_instance endpoint 2025-08-09 19:56:04 +02:00
pinpox
7c37bddeea Add localbackup clan service 2025-08-09 19:52:41 +02:00
Kenji Berthold
c1a87e5c6a Merge pull request 'pkgs/clan/lib(directory): Add API function to query the configured directory' (#4655) from kenji/ke-add-clan-dir-api into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4655
2025-08-09 15:29:55 +00:00
a-kenji
e5bea3d49a pkgs/clan/lib(directory): Add API function to query the configured directory
Similar to the implementation in #4526
Co-authored-by: Mayeu <m@mayeu.me>
2025-08-09 15:39:43 +02:00
hsjobeki
40682972ef Merge pull request 'UI/install: add configure disk' (#4653) from feat-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4653
2025-08-09 11:55:56 +00:00
Johannes Kirschbauer
6035455cba Root-password: add display attributes 2025-08-09 13:48:32 +02:00
Johannes Kirschbauer
9be53a9a63 UI/install: add configure disk 2025-08-09 13:48:06 +02:00
Kenji Berthold
29ec9dbe26 Merge pull request 'pkgs/clan/lib: Handle basecase of directory functionality' (#4654) from kenji/ke-add-directory into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4654
2025-08-09 11:12:23 +00:00
a-kenji
a1874c940e pkgs/cli/lib: Fix api test 2025-08-09 12:48:13 +02:00
a-kenji
d115705cb4 pkgs/clan/lib/directory: Improve error message formatting 2025-08-09 12:32:18 +02:00
a-kenji
eceb6eb999 pkgs/clan/lib: Handle basecase of directory functionality 2025-08-09 12:30:28 +02:00
hsjobeki
d25cace522 Merge pull request 'Host: convert to proctocol to avoid forced inheritance' (#4647) from host-protocol into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4647
2025-08-09 09:29:09 +00:00
hsjobeki
3c6567e67d Merge pull request 'Zerotier: make networkId nullable' (#4652) from install-fixing into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4652
2025-08-09 09:22:23 +00:00
Johannes Kirschbauer
628e45293e Update: avoid mutating and shadowing arguments 2025-08-09 11:18:50 +02:00
Johannes Kirschbauer
954c14513a Zerotier: make networkId nullable
This prevents vars from evaluating if the var doesn't exist
Bootstrapping deadlock
2025-08-09 11:17:16 +02:00
clan-bot
cb8a01d448 Merge pull request 'Update Clan Core for Checks' (#4651) from update-clan-core-for-checks into main 2025-08-09 03:00:19 +00:00
clan-bot
8e53e42b74 Update pinned clan-core for checks 2025-08-09 02:51:46 +00:00
Kenji Berthold
ed596a57f0 Merge pull request 'templates(flake-parts-minimal): Fix erroneous removal' (#4648) from kenji/ke-fix-templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4648
2025-08-08 23:07:00 +00:00
a-kenji
b6bccd218a templates(flake-parts-minimal): Fix erroneous removal 2025-08-09 00:56:21 +02:00
Johannes Kirschbauer
1df9b6e97d Remote: set default for commance_prefix 2025-08-08 22:48:19 +02:00
Johannes Kirschbauer
58fa7ac32b Host: convert to proctocol to avoid forced inheritance 2025-08-08 22:33:05 +02:00
hsjobeki
110d1d4921 Merge pull request 'UI/Install workflow: integrate api until hardware report' (#4646) from ui-more into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4646
2025-08-08 19:23:00 +00:00
hsjobeki
46aee098c4 Merge pull request 'API: add sane defaults to some endpoints' (#4645) from readonly into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4645
2025-08-08 19:08:02 +00:00
Johannes Kirschbauer
9d6735e8c4 Ui/install: machine targetHost & hw_report steps 2025-08-08 21:04:39 +02:00
Johannes Kirschbauer
47c94c51b6 UI: finish up create installer subflow 2025-08-08 21:03:53 +02:00
Johannes Kirschbauer
1eb567682c API/ts: fix empty object is not nullish 2025-08-08 21:03:03 +02:00
Johannes Kirschbauer
fcd83e7a60 Machine: add install button 2025-08-08 21:02:30 +02:00
Johannes Kirschbauer
af4b00408a UI/queries: add machine hw query 2025-08-08 21:01:24 +02:00
Johannes Kirschbauer
aaff3b9b38 UI/queries: remove unused argument 2025-08-08 21:01:03 +02:00
Johannes Kirschbauer
c13741602c UI/select: make z-index adjustable 2025-08-08 20:59:55 +02:00
Johannes Kirschbauer
6cbe221f44 UI/modal: fix styling bugs 2025-08-08 20:58:53 +02:00
Johannes Kirschbauer
3cf8f605d5 flash: default keymap and lang 2025-08-08 20:56:45 +02:00
Johannes Kirschbauer
cc07e0ea44 update hw config: add nixos-facter as default 2025-08-08 20:56:15 +02:00
Johannes Kirschbauer
ccb9340478 Host: add None as default to command_prefix 2025-08-08 20:55:54 +02:00
Mic92
df096fe53b Merge pull request 'switch to flake-compat for private flake' (#4639) from flake-compat into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4639
2025-08-08 13:14:07 +00:00
Jörg Thalheim
f248cc91ad switch to flake-compat for private flake 2025-08-08 15:06:57 +02:00
Jeremy Fleischman
1129862293 machines update: support --target-host localhost
This is basically
<af7ce9b8ed>,
but with support for deploying locally.

This failed to install secrets to `/var/lib/sops-nix`. That's because
our `LocalHost` didn't have support for sudo yet. I fixed that.
2025-08-08 12:42:26 +00:00
lassulus
e2cb75784c Merge pull request 'Add default bootstrapNodes for data-mesher service' (#4555) from fix-4424 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4555
Reviewed-by: lassulus <clanlol@lassul.us>
2025-08-08 12:24:51 +00:00
pinpox
a8d48b22f8 Add default bootstrapnodes for data-mesher service 2025-08-08 11:18:08 +02:00
hsjobeki
c0f2bcf751 Merge pull request 'API/Machine: refactor api returns readonly' (#4627) from readonly into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4627
2025-08-08 08:54:49 +00:00
Johannes Kirschbauer
20c23fa64b API/Machine: refactor api returns readonly 2025-08-08 10:44:32 +02:00
clan-bot
23573e16c4 Merge pull request 'Update flake-parts' (#4620) from update-flake-parts into main 2025-08-08 07:18:42 +00:00
gitea-actions[bot]
eaee4e8cad Update flake-parts 2025-08-08 17:08:03 +10:00
clan-bot
10e43a8884 Merge pull request 'Update nixpkgs' (#4443) from update-nixpkgs into main 2025-08-08 05:57:37 +00:00
Michael Hoang
dc1cd03717 Merge pull request 'cli: fix missing newline in error message' (#4634) from push-lnmsprtyuntw into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4634
2025-08-08 05:30:05 +00:00
Michael Hoang
a71a5880c1 treewide: reformat 2025-08-08 15:28:37 +10:00
gitea-actions[bot]
6b137f21de Update nixpkgs 2025-08-08 15:28:37 +10:00
Michael Hoang
fbc14bf20f Merge pull request 'docs: fix command in Secrets guide' (#4635) from push-mxkpvktxwypw into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4635
2025-08-08 05:25:38 +00:00
Michael Hoang
2f2f3b6898 cli: fix missing newline in error message 2025-08-08 15:19:19 +10:00
Michael Hoang
3ae0f37bcb docs: fix command in Secrets guide 2025-08-08 15:16:58 +10:00
clan-bot
e49d432542 Merge pull request 'Update Clan Core for Checks' (#4633) from update-clan-core-for-checks into main 2025-08-08 03:00:34 +00:00
clan-bot
76955533cf Update pinned clan-core for checks 2025-08-08 02:51:46 +00:00
hsjobeki
d0ebc75135 Merge pull request 'ui/install: hook up stepper store and api' (#4626) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4626
2025-08-07 14:21:21 +00:00
Johannes Kirschbauer
40503306d1 cli/flash: fixup types 2025-08-07 16:09:36 +02:00
hsjobeki
da99407e74 Merge pull request 'Vars: rename classmethod to get_machine_generators' (#4629) from vars-fixing into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4629
2025-08-07 13:50:38 +00:00
Johannes Kirschbauer
915178765b Vars: rename classmethod to get_machine_generators 2025-08-07 15:31:17 +02:00
Johannes Kirschbauer
518de45d41 ui/install: hook up stepper store and api 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
7d23189c1c ui/intall: extend stories to mock router and api 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
eec55f73a2 ui/stepper: add stepper store to hook 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
484d274c3c ui/queries: add required flash data queries 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
a4b20f9167 UI/queries: migrate existing queries to useApiClient 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
dc7291c62b UI/api: add api client provider
This allows to switch out the used api backend for testing purposes.
Or for different plattforms
2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
a814a44bc6 UI/Select: add async option loading 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
86a6177126 UI/useClan: add error debugging 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
4536a5b4f5 clan/flash: provide defaults for verbose flash options 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
a9cfda9acb dirs: add local path to clan_core flake in dirs 2025-08-07 13:46:07 +02:00
Johannes Kirschbauer
b9f60218d7 UI/install: create installer improve wording 2025-08-07 13:46:07 +02:00
clan-bot
f69e28a133 Merge pull request 'Update Clan Core for Checks' (#4625) from update-clan-core-for-checks into main 2025-08-07 03:00:25 +00:00
clan-bot
1968230c28 Update pinned clan-core for checks 2025-08-07 02:51:46 +00:00
clan-bot
9cad074732 Merge pull request 'Update treefmt-nix' (#4621) from update-treefmt-nix into main 2025-08-06 15:20:13 +00:00
gitea-actions[bot]
4859a9ab7c Update treefmt-nix 2025-08-06 15:01:29 +00:00
hsjobeki
b53ecdc89d Merge pull request 'UI/install: add machine progress, minor stepper fixes' (#4619) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4619
2025-08-06 14:49:30 +00:00
Johannes Kirschbauer
19603e1a1c UI/install: add machine progress 2025-08-06 16:44:30 +02:00
Johannes Kirschbauer
7d20f3a33b UI/install: create installer improve wording 2025-08-06 16:43:48 +02:00
Johannes Kirschbauer
fa03c190f8 UI/install: split initial choice 2025-08-06 16:43:24 +02:00
Johannes Kirschbauer
65101ad55a UI/steps: make step footer next text customizable 2025-08-06 16:42:45 +02:00
Johannes Kirschbauer
e5db3e269b UI/stepper: hooks add helper to more typesafe define steps 2025-08-06 16:42:03 +02:00
Johannes Kirschbauer
073750e4c5 clanServices: update description of generators that can be left empty 2025-08-06 16:41:11 +02:00
DavHau
8bafbcb295 machines update: use 'localhost' for local build 2025-08-06 19:06:20 +07:00
hsjobeki
dbef6ced77 Merge pull request 'cubes and lighting: refinements on coloring of cubes and lighting to fit with design' (#4617) from ui/3d-cubes-refinement into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4617
2025-08-06 10:47:00 +00:00
Timo
65e7f9e6ca cubes and lighting: refinements on coloring of cubes and lighting to fit with design 2025-08-06 12:33:53 +02:00
Mic92
e1062ed97c Merge pull request 'docs/update: mention build-host local and uploading flake inputs' (#4614) from local-build into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4614
2025-08-06 10:18:28 +00:00
Jörg Thalheim
2eb1a56d8f update.md: mention build-host local and uploading flake inputs 2025-08-06 12:14:35 +02:00
clan-bot
0f499fc651 Merge pull request 'Update Clan Core for Checks' (#4608) from update-clan-core-for-checks into main 2025-08-06 03:00:32 +00:00
clan-bot
bcb7a1aa60 Update pinned clan-core for checks 2025-08-06 02:51:47 +00:00
Mic92
273c83ec27 Merge pull request 'update/flake-upload: use ssh-ng:// for nix copy' (#4597) from local-build into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4597
2025-08-05 20:47:23 +00:00
clan-bot
c74d7857da Merge pull request 'Update flake-parts' (#4607) from update-flake-parts into main 2025-08-05 20:12:05 +00:00
gitea-actions[bot]
11405966c6 Update flake-parts 2025-08-05 20:00:50 +00:00
hsjobeki
220839598d Merge pull request 'UI/install: bootstrap visuals for {createImage, Installer}' (#4605) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4605
2025-08-05 17:34:14 +00:00
Jörg Thalheim
44dcfa7844 rename --fetch-local to --upload-inputs 2025-08-05 19:31:29 +02:00
Jörg Thalheim
98f685f3ca update/flake-upload: set correct remote-program for macOS targets 2025-08-05 19:31:29 +02:00
Johannes Kirschbauer
9e43285ba8 UI/install: bootstrap steps for {DiskSchema, Vars, Summary} 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
c0bc0417a6 UI/install: fix metaHeader reactive 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
c90b69d499 UI/install: clean up create steps 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
0240acdf3e UI/modal: move common styling into meta header 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
92726ecebc UI/install: installer steps bootstrap visuals {TargetHost,hw_report} 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
b8e9546762 UI/install: bootstrap visuals for createInstaller 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
2039f034b1 UI/steps: minor layout fixes 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
0a329f43a8 UI/Modal: add 'disablePadding' 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
bde0a2845c UI/LoadingBar: allow injecting props 2025-08-05 19:29:06 +02:00
Johannes Kirschbauer
af3c6282c9 UI/Alert: make description optional 2025-08-05 19:29:06 +02:00
hsjobeki
73ab4d2a6e Merge pull request 'ui/install: add disk selection step to image create' (#4598) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4598
2025-08-05 16:16:54 +00:00
Johannes Kirschbauer
cc269c4f58 ui/install: add disk selection step to image create 2025-08-05 16:22:44 +02:00
Johannes Kirschbauer
20021a92ea ui/next-button: fix interface should extend button 2025-08-05 16:22:02 +02:00
Johannes Kirschbauer
7b54e9b033 ui/loading-bar: move into component 2025-08-05 16:20:56 +02:00
hsjobeki
7971eceb74 Merge pull request 'UI: extend components to prepare install workflows' (#4576) from install-ui into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4576
2025-08-05 13:36:31 +00:00
Johannes Kirschbauer
49a5763f69 Install: split steps into files 2025-08-05 15:32:43 +02:00
Johannes Kirschbauer
10694e58c8 install: use typed stepper 2025-08-05 15:10:38 +02:00
Johannes Kirschbauer
0d919c4fce hooks/stepper: add generic stepper hook 2025-08-05 15:09:29 +02:00
Johannes Kirschbauer
8cccf757a8 Fix: modal header slot was renamed to metaHeader 2025-08-05 13:52:03 +02:00
Johannes Kirschbauer
80c8cc8628 HostFileInput: allow overriding placeholder 2025-08-05 13:48:49 +02:00
Johannes Kirschbauer
ab63f0d7a4 divider: add extra class prop 2025-08-05 13:48:49 +02:00
Johannes Kirschbauer
06e0461ec9 Modal: add metaHeader slot, fix border styling 2025-08-05 13:48:49 +02:00
Johannes Kirschbauer
60ba00dd8f Select: add simple select dropdown for single select 2025-08-05 13:48:49 +02:00
Johannes Kirschbauer
90ef55f040 Label: add support for kobalte select 2025-08-05 13:48:49 +02:00
Johannes Kirschbauer
de81a5d810 Modal: prepare for install flow 2025-08-05 13:48:49 +02:00
Mic92
3fe65f1f12 Merge pull request 'machines update: support local build' (#4515) from local-build into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4515
2025-08-05 11:28:50 +00:00
Jörg Thalheim
6bb998f9dd update/flake-upload: use ssh-ng:// for nix copy
I had concurrency issues with `nix copy` and the ssh:// protocol when
using a machine both as the build host/target host (for different
machines), where it make the result path partially available to a
different update command thread.
2025-08-05 13:26:34 +02:00
DavHau
af7ce9b8ed machines update: support local build
Now the user can pass `--build-host local`, to select the local machine as a build host, in which case no ssh is used.

This means the admin machine does not necessarily have ssh set up to itself, which was confusing for many users.

Also this makes it easier to re-use a well configured nix remote build setup which is only available on the local machine. Eg if `--build-host local` nix' defaults for remote builds on that machine will be utilized.
2025-08-05 13:16:59 +02:00
DavHau
b74193514d ssh: refactor callers to use new Host interface 2025-08-05 13:16:59 +02:00
DavHau
c33fd4e504 ssh: Introduce LocalHost vs. Remote via Host interface
Motivation: local builds and deployments without ssh

Add a new interface `Host` which is implemented bei either `Remote` or `Localhost`

This simplifies all interactions with hosts. THe caller does ot need to know if the Host is remote or local in mot cases anymore
2025-08-05 13:16:59 +02:00
pinpox
65f3cb562a Merge pull request 'Reduce targetHost warning level' (#4594) from fix-target-warning into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4594
2025-08-05 09:55:30 +00:00
Mic92
355ff648d7 Merge pull request 'consistently use tarball urls in documentation' (#4589) from no-git-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4589
Reviewed-by: pinpox <clan@pablo.tools>
2025-08-05 09:55:15 +00:00
pinpox
f314eb04d6 Reduce targetHost warning level
The documentation currently lists setting targetHost in the NixOS
configuration as a slower, but valid option. Especially for dynamic
values, this is the recommended way but it results in a lot of annyoing
warnings.

This lowers the warning level, so it will only get printed on --debug
2025-08-05 11:52:06 +02:00
clan-bot
ebe206cdc0 Merge pull request 'Update Clan Core for Checks' (#4593) from update-clan-core-for-checks into main 2025-08-05 09:02:50 +00:00
clan-bot
2a138d3248 Update pinned clan-core for checks 2025-08-05 08:53:28 +00:00
Kenji Berthold
77810b1d4f Merge pull request 'clanServices: migrate syncthing module to clanServices' (#4558) from ke-migrate-clan-module-syncthing into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4558
2025-08-05 08:25:07 +00:00
a-kenji
77c840c9ba services/syncthing: Add basic usage documentation 2025-08-05 10:00:30 +02:00
a-kenji
9df7e6df1e services/syncthing: Add eval-test 2025-08-05 10:00:30 +02:00
a-kenji
a5e51f658d clanServices: migrate syncthing module to clanServices
Migrate the syncthing module from `clanModules` to `clanServices`.
2025-08-05 10:00:01 +02:00
clan-bot
98d5b3651b Merge pull request 'Update sops-nix' (#4591) from update-sops-nix into main 2025-08-04 20:12:26 +00:00
gitea-actions[bot]
713a1a550e Update sops-nix 2025-08-04 20:01:21 +00:00
Jörg Thalheim
d51d656391 consistently use tarball urls in documentation
otherwise users not using our templates will find themselves missing
git.
2025-08-04 11:20:14 +02:00
lassulus
0f79af697e Merge pull request 'simplify select debug output logic, add better error messages' (#4582) from select-debug into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4582
2025-08-02 20:55:31 +00:00
lassulus
0119fc06ca clan-cli select: show if select is cached or not 2025-08-02 21:26:39 +02:00
lassulus
5361261bd5 clan select: better error 2025-08-02 17:59:12 +02:00
lassulus
86e7bcc389 clan select: simplify select logging 2025-08-02 17:19:35 +02:00
clan-bot
79281aba90 Merge pull request 'Update flake-parts' (#4581) from update-flake-parts into main 2025-08-02 00:13:08 +00:00
gitea-actions[bot]
dade91c292 Update flake-parts 2025-08-02 00:00:52 +00:00
clan-bot
d285a0e716 Merge pull request 'Update treefmt-nix' (#4579) from update-treefmt-nix into main 2025-08-01 20:13:21 +00:00
gitea-actions[bot]
a97128db17 Update treefmt-nix 2025-08-01 20:01:25 +00:00
brianmcgee
ff7b49be5f Merge pull request 'feat: ui/auto-resizing-textarea' (#4562) from ui/auto-resizing-textarea into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4562
2025-08-01 09:40:33 +00:00
Luis Hebendanz
0b816a2672 Merge pull request 'Fix getting-started guide' (#4545) from Qubasa/clan-core:migrate-dyndns into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4545
2025-08-01 08:30:09 +00:00
hsjobeki
e6ec331da0 Merge pull request 'vars: add display attribute submodule for customisable ux' (#4559) from vars-display into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4559
Reviewed-by: DavHau <d.hauer.it@gmail.com>
2025-08-01 07:55:07 +00:00
Qubasa
0b05b0b1ec docs: review fixups
docs: review fixups

docs: review fixups

docs: fixup links in cli

docs: fixup links in cli
2025-08-01 14:53:31 +07:00
Michael Hoang
efd9beba15 Merge pull request 'docs: macOS' (#4563) from push-xptxwrqwvymq into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4563
2025-08-01 05:49:35 +00:00
Michael Hoang
dc03a9183f docs: macOS 2025-08-01 15:45:41 +10:00
Johannes Kirschbauer
ab3158ca07 vars/decrypt_dependencies: simplify 2025-08-01 04:01:43 +00:00
Brian McGee
75a1f7b67f feat(ui): auto-resizing textarea 2025-07-31 18:50:39 +01:00
brianmcgee
d453720a57 Merge pull request 'feat(ui): add tooltips for general section in machine detail pane' (#4561) from feat/machine-detail-tooltips into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4561
2025-07-31 17:48:27 +00:00
Brian McGee
a4331cc109 feat(ui): add tooltips for general section in machine detail pane 2025-07-31 18:38:56 +01:00
hsjobeki
434ce1af49 Merge pull request 'vars/list: doogfood get_machines into cli' (#4549) from vars-dog into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4549
2025-07-31 17:19:42 +00:00
Johannes Kirschbauer
488ee1ae63 users/display: add display properties 2025-07-31 16:45:20 +02:00
Johannes Kirschbauer
fc2e619046 vars: add display attribute submodule for customizable ux 2025-07-31 16:35:15 +02:00
Johannes Kirschbauer
cf6c3604ca generators_from_flake: vars always bind to store 2025-07-31 16:16:36 +02:00
hsjobeki
a3ea62caba Merge pull request 'docs: add vars/gaph doc-strings' (#4554) from vars-docs-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4554
2025-07-31 13:37:29 +00:00
Johannes Kirschbauer
e2e4837b29 docs: add vars/gaph doc-strings 2025-07-31 15:26:22 +02:00
Johannes Kirschbauer
96fc3d409a vars/list: untangle generators_from_flake and get_generators 2025-07-31 15:17:57 +02:00
Johannes Kirschbauer
392f244361 vars/list: doogfood get_machines into cli
This is important otherwise cli diverges from api
2025-07-31 14:02:50 +02:00
Qubasa
d2529704d5 docs: Split up getting-started guide in a Physical and Virtual installation, and properly document how to install on non-NixOS machines
docs: git add docs
2025-07-31 17:06:44 +07:00
Qubasa
62a3503987 clan-lib: Always set a static private key for nixos-anywhere, to make --phases work properly 2025-07-31 17:06:00 +07:00
Qubasa
c39aa89e29 docs: Add a nixos-anywhere debugging hint 2025-07-31 17:06:00 +07:00
557 changed files with 11713 additions and 11441 deletions

View File

@@ -1,28 +0,0 @@
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
env:
CI_BOT_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
run: |
export GIT_AUTHOR_NAME=clan-bot GIT_AUTHOR_EMAIL=clan-bot@clan.lol GIT_COMMITTER_NAME=clan-bot GIT_COMMITTER_EMAIL=clan-bot@clan.lol
git commit -am "Update pinned clan-core for checks"
# Use shared PR creation script
export PR_BRANCH="update-clan-core-for-checks"
export PR_TITLE="Update Clan Core for Checks"
export PR_BODY="This PR updates the pinned clan-core flake input that is used for checks."
./.gitea/workflows/create-pr.sh

View File

@@ -19,8 +19,11 @@ jobs:
uses: Mic92/update-flake-inputs-gitea@main uses: Mic92/update-flake-inputs-gitea@main
with: with:
# Exclude private flakes and update-clan-core checks flake # Exclude private flakes and update-clan-core checks flake
exclude-patterns: "checks/impure/flake.nix"
exclude-patterns: "devFlake/private/flake.nix,checks/impure/flake.nix"
auto-merge: true auto-merge: true
git-author-name: "clan-bot"
git-committer-name: "clan-bot"
git-author-email: "clan-bot@clan.lol"
git-committer-email: "clan-bot@clan.lol"
gitea-token: ${{ secrets.CI_BOT_TOKEN }} gitea-token: ${{ secrets.CI_BOT_TOKEN }}
github-token: ${{ secrets.CI_BOT_GITHUB_TOKEN }} github-token: ${{ secrets.CI_BOT_GITHUB_TOKEN }}

View File

@@ -1,40 +0,0 @@
name: "Update private flake inputs"
on:
repository_dispatch:
workflow_dispatch:
schedule:
- cron: "0 3 * * *" # Run daily at 3 AM
jobs:
update-private-flake:
runs-on: nix
steps:
- uses: actions/checkout@v4
with:
submodules: true
- name: Update private flake inputs
run: |
# Update the private flake lock file
cd devFlake/private
nix flake update
cd ../..
# Update the narHash
bash ./devFlake/update-private-narhash
- name: Create pull request
env:
CI_BOT_TOKEN: ${{ secrets.CI_BOT_TOKEN }}
run: |
export GIT_AUTHOR_NAME=clan-bot GIT_AUTHOR_EMAIL=clan-bot@clan.lol GIT_COMMITTER_NAME=clan-bot GIT_COMMITTER_EMAIL=clan-bot@clan.lol
# Check if there are any changes
if ! git diff --quiet; then
git add devFlake/private/flake.lock devFlake/private.narHash
git commit -m "Update dev flake"
# Use shared PR creation script
export PR_BRANCH="update-dev-flake"
export PR_TITLE="Update dev flake"
export PR_BODY="This PR updates the dev flake inputs and corresponding narHash."
else
echo "No changes detected in dev flake inputs"
fi

1
.gitignore vendored
View File

@@ -39,7 +39,6 @@ select
# Generated files # Generated files
pkgs/clan-app/ui/api/API.json pkgs/clan-app/ui/api/API.json
pkgs/clan-app/ui/api/API.ts pkgs/clan-app/ui/api/API.ts
pkgs/clan-app/ui/api/Inventory.ts
pkgs/clan-app/ui/api/modules_schemas.json pkgs/clan-app/ui/api/modules_schemas.json
pkgs/clan-app/ui/api/schema.json pkgs/clan-app/ui/api/schema.json
pkgs/clan-app/ui/.fonts pkgs/clan-app/ui/.fonts

View File

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

View File

@@ -1,210 +0,0 @@
{ self, ... }:
{
clan.machines.test-backup = {
imports = [ self.nixosModules.test-backup ];
fileSystems."/".device = "/dev/null";
boot.loader.grub.device = "/dev/null";
};
clan.inventory.services = {
borgbackup.test-backup = {
roles.client.machines = [ "test-backup" ];
roles.server.machines = [ "test-backup" ];
};
};
flake.nixosModules = {
test-backup =
{
pkgs,
lib,
...
}:
let
dependencies =
[
pkgs.stdenv.drvPath
]
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{
imports = [
# Do not import inventory modules. They should be configured via 'clan.inventory'
#
# TODO: Configure localbackup via inventory
self.clanModules.localbackup
];
# Borgbackup overrides
services.borgbackup.repos.test-backups = {
path = "/var/lib/borgbackup/test-backups";
authorizedKeys = [ (builtins.readFile ../assets/ssh/pubkey) ];
};
clan.borgbackup.destinations.test-backup.repo = lib.mkForce "borg@machine:.";
clan.core.networking.targetHost = "machine";
networking.hostName = "machine";
programs.ssh.knownHosts = {
machine.hostNames = [ "machine" ];
machine.publicKey = builtins.readFile ../assets/ssh/pubkey;
};
services.openssh = {
enable = true;
settings.UsePAM = false;
settings.UseDns = false;
hostKeys = [
{
path = "/root/.ssh/id_ed25519";
type = "ed25519";
}
];
};
users.users.root.openssh.authorizedKeys.keyFiles = [ ../assets/ssh/pubkey ];
# This is needed to unlock the user for sshd
# Because we use sshd without setuid binaries
users.users.borg.initialPassword = "hello";
systemd.tmpfiles.settings."vmsecrets" = {
"/root/.ssh/id_ed25519" = {
C.argument = "${../assets/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/ssh.id_ed25519" = {
C.argument = "${../assets/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/borgbackup/borgbackup.ssh" = {
C.argument = "${../assets/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/borgbackup/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = {
mode = "0400";
user = "root";
};
};
};
clan.core.facts.secretStore = "vm";
clan.core.vars.settings.secretStore = "vm";
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ];
environment.etc.install-closure.source = "${closureInfo}/store-paths";
nix.settings = {
substituters = lib.mkForce [ ];
hashed-mirrors = null;
connect-timeout = lib.mkForce 3;
flake-registry = pkgs.writeText "flake-registry" ''{"flakes":[],"version":2}'';
};
system.extraDependencies = dependencies;
clan.core.state.test-backups.folders = [ "/var/test-backups" ];
clan.core.state.test-service = {
preBackupScript = ''
touch /var/test-service/pre-backup-command
'';
preRestoreScript = ''
touch /var/test-service/pre-restore-command
'';
postRestoreScript = ''
touch /var/test-service/post-restore-command
'';
folders = [ "/var/test-service" ];
};
fileSystems."/mnt/external-disk" = {
device = "/dev/vdb"; # created in tests with virtualisation.emptyDisks
autoFormat = true;
fsType = "ext4";
options = [
"defaults"
"noauto"
];
};
clan.localbackup.targets.hdd = {
directory = "/mnt/external-disk";
preMountHook = ''
touch /run/mount-external-disk
'';
postUnmountHook = ''
touch /run/unmount-external-disk
'';
};
};
};
perSystem =
{ pkgs, ... }:
let
clanCore = self.checks.x86_64-linux.clan-core-for-checks;
in
{
checks = pkgs.lib.mkIf pkgs.stdenv.isLinux {
nixos-test-backups = self.clanLib.test.containerTest {
name = "nixos-test-backups";
nodes.machine = {
imports =
[
self.nixosModules.clanCore
# Some custom overrides for the backup tests
self.nixosModules.test-backup
]
++
# import the inventory generated nixosModules
self.clan.clanInternals.inventoryClass.machines.test-backup.machineImports;
clan.core.settings.directory = ./.;
};
testScript = ''
import json
start_all()
# dummy data
machine.succeed("mkdir -p /var/test-backups /var/test-service")
machine.succeed("echo testing > /var/test-backups/somefile")
# create
machine.succeed("clan backups create --debug --flake ${clanCore} test-backup")
machine.wait_until_succeeds("! systemctl is-active borgbackup-job-test-backup >&2")
machine.succeed("test -f /run/mount-external-disk")
machine.succeed("test -f /run/unmount-external-disk")
# list
backup_id = json.loads(machine.succeed("borg-job-test-backup list --json"))["archives"][0]["archive"]
out = machine.succeed("clan backups list --debug --flake ${clanCore} test-backup").strip()
print(out)
assert backup_id in out, f"backup {backup_id} not found in {out}"
localbackup_id = "hdd::/mnt/external-disk/snapshot.0"
assert localbackup_id in out, "localbackup not found in {out}"
## borgbackup restore
machine.succeed("rm -f /var/test-backups/somefile")
machine.succeed(f"clan backups restore --debug --flake ${clanCore} test-backup borgbackup 'test-backup::borg@machine:.::{backup_id}' >&2")
assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
machine.succeed("test -f /var/test-service/pre-restore-command")
machine.succeed("test -f /var/test-service/post-restore-command")
machine.succeed("test -f /var/test-service/pre-backup-command")
## localbackup restore
machine.succeed("rm -rf /var/test-backups/somefile /var/test-service/ && mkdir -p /var/test-service")
machine.succeed(f"clan backups restore --debug --flake ${clanCore} test-backup localbackup '{localbackup_id}' >&2")
assert machine.succeed("cat /var/test-backups/somefile").strip() == "testing", "restore failed"
machine.succeed("test -f /var/test-service/pre-restore-command")
machine.succeed("test -f /var/test-service/post-restore-command")
machine.succeed("test -f /var/test-service/pre-backup-command")
'';
} { inherit pkgs self; };
};
};
}

View File

@@ -1,51 +0,0 @@
(
{ ... }:
{
name = "borgbackup";
nodes.machine =
{ self, pkgs, ... }:
{
imports = [
self.clanModules.borgbackup
self.nixosModules.clanCore
{
services.openssh.enable = true;
services.borgbackup.repos.testrepo = {
authorizedKeys = [ (builtins.readFile ../assets/ssh/pubkey) ];
};
}
{
clan.core.settings.directory = ./.;
clan.core.state.testState.folders = [ "/etc/state" ];
environment.etc.state.text = "hello world";
systemd.tmpfiles.settings."vmsecrets" = {
"/etc/secrets/borgbackup/borgbackup.ssh" = {
C.argument = "${../assets/ssh/privkey}";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/borgbackup/borgbackup.repokey" = {
C.argument = builtins.toString (pkgs.writeText "repokey" "repokey12345");
z = {
mode = "0400";
user = "root";
};
};
};
# clan.core.facts.secretStore = "vm";
clan.core.vars.settings.secretStore = "vm";
clan.borgbackup.destinations.test.repo = "borg@localhost:.";
}
];
};
testScript = ''
start_all()
machine.systemctl("start --wait borgbackup-job-test.service")
assert "machine-test" in machine.succeed("BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK=yes /run/current-system/sw/bin/borg-job-test list")
'';
}
)

View File

@@ -1,6 +1,6 @@
{ fetchgit }: { fetchgit }:
fetchgit { fetchgit {
url = "https://git.clan.lol/clan/clan-core.git"; url = "https://git.clan.lol/clan/clan-core.git";
rev = "ba8a80eccf091fc7f99aef3895e31617d3813d20"; rev = "5d884cecc2585a29b6a3596681839d081b4de192";
sha256 = "189srg4mc5y3prapm8day0x0wpibbqc72hrnl61agsmiq7cfmbkd"; sha256 = "09is1afmncamavb2q88qac37vmsijxzsy1iz1vr6gsyjq2rixaxc";
} }

View File

@@ -2,6 +2,7 @@
self, self,
lib, lib,
inputs, inputs,
privateInputs ? { },
... ...
}: }:
let let
@@ -33,7 +34,6 @@ in
in in
getClanCoreTestModules getClanCoreTestModules
++ filter pathExists [ ++ filter pathExists [
./backups/flake-module.nix
./devshell/flake-module.nix ./devshell/flake-module.nix
./flash/flake-module.nix ./flash/flake-module.nix
./impure/flake-module.nix ./impure/flake-module.nix
@@ -93,17 +93,15 @@ in
# Base Tests # Base Tests
nixos-test-secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs; nixos-test-secrets = self.clanLib.test.baseTest ./secrets nixosTestArgs;
nixos-test-borgbackup-legacy = self.clanLib.test.baseTest ./borgbackup-legacy nixosTestArgs;
nixos-test-wayland-proxy-virtwl = self.clanLib.test.baseTest ./wayland-proxy-virtwl nixosTestArgs; nixos-test-wayland-proxy-virtwl = self.clanLib.test.baseTest ./wayland-proxy-virtwl nixosTestArgs;
# Container Tests # Container Tests
nixos-test-container = self.clanLib.test.containerTest ./container nixosTestArgs; nixos-test-container = self.clanLib.test.containerTest ./container nixosTestArgs;
nixos-test-zt-tcp-relay = self.clanLib.test.containerTest ./zt-tcp-relay nixosTestArgs;
nixos-test-matrix-synapse = self.clanLib.test.containerTest ./matrix-synapse nixosTestArgs;
nixos-test-user-firewall-iptables = self.clanLib.test.containerTest ./user-firewall/iptables.nix nixosTestArgs; nixos-test-user-firewall-iptables = self.clanLib.test.containerTest ./user-firewall/iptables.nix nixosTestArgs;
nixos-test-user-firewall-nftables = self.clanLib.test.containerTest ./user-firewall/nftables.nix nixosTestArgs; nixos-test-user-firewall-nftables = self.clanLib.test.containerTest ./user-firewall/nftables.nix nixosTestArgs;
service-dummy-test = import ./service-dummy-test nixosTestArgs; service-dummy-test = import ./service-dummy-test nixosTestArgs;
wireguard = import ./wireguard nixosTestArgs;
service-dummy-test-from-flake = import ./service-dummy-test-from-flake nixosTestArgs; service-dummy-test-from-flake = import ./service-dummy-test-from-flake nixosTestArgs;
}; };
@@ -113,6 +111,8 @@ in
"dont-depend-on-repo-root" "dont-depend-on-repo-root"
]; ];
# Temporary workaround: Filter out docs package and devshell for aarch64-darwin due to CI builder hangs
# TODO: Remove this filter once macOS CI builder is updated
flakeOutputs = flakeOutputs =
lib.mapAttrs' ( lib.mapAttrs' (
name: config: lib.nameValuePair "nixos-${name}" config.config.system.build.toplevel name: config: lib.nameValuePair "nixos-${name}" config.config.system.build.toplevel
@@ -120,8 +120,18 @@ in
// lib.mapAttrs' ( // lib.mapAttrs' (
name: config: lib.nameValuePair "darwin-${name}" config.config.system.build.toplevel name: config: lib.nameValuePair "darwin-${name}" config.config.system.build.toplevel
) (self.darwinConfigurations or { }) ) (self.darwinConfigurations or { })
// lib.mapAttrs' (n: lib.nameValuePair "package-${n}") packagesToBuild // lib.mapAttrs' (n: lib.nameValuePair "package-${n}") (
// lib.mapAttrs' (n: lib.nameValuePair "devShell-${n}") self'.devShells if system == "aarch64-darwin" then
lib.filterAttrs (n: _: n != "docs" && n != "deploy-docs" && n != "docs-options") packagesToBuild
else
packagesToBuild
)
// lib.mapAttrs' (n: lib.nameValuePair "devShell-${n}") (
if system == "aarch64-darwin" then
lib.filterAttrs (n: _: n != "docs") self'.devShells
else
self'.devShells
)
// lib.mapAttrs' (name: config: lib.nameValuePair "home-manager-${name}" config.activation-script) ( // lib.mapAttrs' (name: config: lib.nameValuePair "home-manager-${name}" config.activation-script) (
self'.legacyPackages.homeConfigurations or { } self'.legacyPackages.homeConfigurations or { }
); );
@@ -129,35 +139,8 @@ in
nixosTests nixosTests
// flakeOutputs // flakeOutputs
// { // {
# TODO: Automatically provide this check to downstream users to check their modules
clan-modules-json-compatible =
let
allSchemas = lib.mapAttrs (
_n: m:
let
schema =
(self.clanLib.evalService {
modules = [ m ];
prefix = [
"checks"
system
];
}).config.result.api.schema;
in
schema
) self.clan.modules;
in
pkgs.runCommand "combined-result"
{
schemaFile = builtins.toFile "schemas.json" (builtins.toJSON allSchemas);
}
''
mkdir -p $out
cat $schemaFile > $out/allSchemas.json
'';
clan-core-for-checks = pkgs.runCommand "clan-core-for-checks" { } '' clan-core-for-checks = pkgs.runCommand "clan-core-for-checks" { } ''
cp -r ${pkgs.callPackage ./clan-core-for-checks.nix { }} $out cp -r ${privateInputs.clan-core-for-checks} $out
chmod -R +w $out chmod -R +w $out
cp ${../flake.lock} $out/flake.lock cp ${../flake.lock} $out/flake.lock

View File

@@ -50,7 +50,8 @@
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.toplevel self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.toplevel
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript
self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript.drvPath self.nixosConfigurations."test-flash-machine-${pkgs.hostPlatform.system}".config.system.build.diskoScript.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in in
{ {
@@ -60,6 +61,10 @@
nodes.target = { nodes.target = {
virtualisation.emptyDiskImages = [ 4096 ]; virtualisation.emptyDiskImages = [ 4096 ];
virtualisation.memorySize = 4096; virtualisation.memorySize = 4096;
virtualisation.useNixStoreImage = true;
virtualisation.writableStore = true;
environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ]; environment.systemPackages = [ self.packages.${pkgs.system}.clan-cli ];
environment.etc."install-closure".source = "${closureInfo}/store-paths"; environment.etc."install-closure".source = "${closureInfo}/store-paths";
@@ -78,8 +83,8 @@
start_all() start_all()
# Some distros like to automount disks with spaces # 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('mkdir -p "/mnt/with spaces" && mkfs.ext4 /dev/vdc && mount /dev/vdc "/mnt/with spaces"')
machine.succeed("clan flash write --debug --flake ${self.checks.x86_64-linux.clan-core-for-checks} --yes --disk main /dev/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/vdc test-flash-machine-${pkgs.hostPlatform.system}")
''; '';
} { inherit pkgs self; }; } { inherit pkgs self; };
}; };

View File

@@ -40,7 +40,7 @@
jobs=$(nproc) jobs=$(nproc)
# Spawning worker in pytest is relatively slow, so we limit the number of jobs to 13 # Spawning worker in pytest is relatively slow, so we limit the number of jobs to 13
# (current number of impure tests) # (current number of impure tests)
jobs="$((jobs > 13 ? 13 : jobs))" jobs="$((jobs > 6 ? 6 : jobs))"
nix develop "$ROOT#clan-cli" -c bash -c "TMPDIR=/tmp python -m pytest -n $jobs -m impure ./clan_cli $@" nix develop "$ROOT#clan-cli" -c bash -c "TMPDIR=/tmp python -m pytest -n $jobs -m impure ./clan_cli $@"

View File

@@ -1,6 +1,7 @@
{ {
self, self,
lib, lib,
privateInputs,
... ...
}: }:
@@ -151,14 +152,15 @@
let let
closureInfo = pkgs.closureInfo { closureInfo = pkgs.closureInfo {
rootPaths = [ rootPaths = [
self.checks.x86_64-linux.clan-core-for-checks privateInputs.clan-core-for-checks
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.toplevel
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.initialRamdisk self.clanInternals.machines.${pkgs.hostPlatform.system}.test-install-machine-with-system.config.system.build.initialRamdisk
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.build.diskoScript
pkgs.stdenv.drvPath pkgs.stdenv.drvPath
pkgs.bash.drvPath pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
}; };
in in
pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) { pkgs.lib.mkIf (pkgs.stdenv.isLinux && !pkgs.stdenv.isAarch64) {
@@ -239,7 +241,7 @@
target.shutdown() target.shutdown()
except BrokenPipeError: except BrokenPipeError:
# qemu has already exited # qemu has already exited
pass target.connected = False
# Create a new machine instance that boots from the installed system # Create a new machine instance that boots from the installed system
installed_machine = create_test_machine(target, "${pkgs.qemu_test}", name="after_install") installed_machine = create_test_machine(target, "${pkgs.qemu_test}", name="after_install")

View File

@@ -159,7 +159,8 @@ let
pkgs.stdenv.drvPath pkgs.stdenv.drvPath
pkgs.bash.drvPath pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
}; };
in in

View File

@@ -1,83 +0,0 @@
(
{ pkgs, ... }:
{
name = "matrix-synapse";
nodes.machine =
{
config,
self,
lib,
...
}:
{
imports = [
self.clanModules.matrix-synapse
self.nixosModules.clanCore
{
clan.core.settings.directory = ./.;
services.nginx.virtualHosts."matrix.clan.test" = {
enableACME = lib.mkForce false;
forceSSL = lib.mkForce false;
};
clan.nginx.acme.email = "admins@clan.lol";
clan.matrix-synapse = {
server_tld = "clan.test";
app_domain = "matrix.clan.test";
};
clan.matrix-synapse.users.admin.admin = true;
clan.matrix-synapse.users.someuser = { };
clan.core.facts.secretStore = "vm";
clan.core.vars.settings.secretStore = "vm";
clan.core.vars.settings.publicStore = "in_repo";
# because we use systemd-tmpfiles to copy the secrets, we need to a separate systemd-tmpfiles call to provision them.
boot.postBootCommands = "${config.systemd.package}/bin/systemd-tmpfiles --create /etc/tmpfiles.d/00-vmsecrets.conf";
systemd.tmpfiles.settings."00-vmsecrets" = {
# run before 00-nixos.conf
"/etc/secrets" = {
d.mode = "0700";
z.mode = "0700";
};
"/etc/secrets/matrix-synapse/synapse-registration_shared_secret" = {
f.argument = "supersecret";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/matrix-password-admin/matrix-password-admin" = {
f.argument = "matrix-password1";
z = {
mode = "0400";
user = "root";
};
};
"/etc/secrets/matrix-password-someuser/matrix-password-someuser" = {
f.argument = "matrix-password2";
z = {
mode = "0400";
user = "root";
};
};
};
}
];
};
testScript = ''
start_all()
machine.wait_for_unit("matrix-synapse")
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 8008")
machine.wait_until_succeeds("${pkgs.curl}/bin/curl -Ssf -L http://localhost/_matrix/static/ -H 'Host: matrix.clan.test'")
machine.systemctl("restart matrix-synapse >&2") # check if user creation is idempotent
machine.execute("journalctl -u matrix-synapse --no-pager >&2")
machine.wait_for_unit("matrix-synapse")
machine.succeed("${pkgs.netcat}/bin/nc -z -v ::1 8008")
machine.succeed("${pkgs.curl}/bin/curl -Ssf -L http://localhost/_matrix/static/ -H 'Host: matrix.clan.test'")
'';
}
)

View File

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

View File

@@ -35,7 +35,8 @@
pkgs.stdenv.drvPath pkgs.stdenv.drvPath
pkgs.stdenvNoCC pkgs.stdenvNoCC
self.nixosConfigurations.test-morph-machine.config.system.build.toplevel self.nixosConfigurations.test-morph-machine.config.system.build.toplevel
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in in

View File

@@ -16,7 +16,6 @@ nixosLib.runTest (
# This tests the compatibility of the inventory # This tests the compatibility of the inventory
# With the test framework # With the test framework
# - legacy-modules
# - clan.service modules # - clan.service modules
name = "service-dummy-test-from-flake"; name = "service-dummy-test-from-flake";
@@ -37,9 +36,6 @@ nixosLib.runTest (
start_all() start_all()
admin1.wait_for_unit("multi-user.target") admin1.wait_for_unit("multi-user.target")
peer1.wait_for_unit("multi-user.target") peer1.wait_for_unit("multi-user.target")
# Provided by the legacy module
print(admin1.succeed("systemctl status dummy-service"))
print(peer1.succeed("systemctl status dummy-service"))
# peer1 should have the 'hello' file # peer1 should have the 'hello' file
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.not-a-secret.path}") peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.not-a-secret.path}")

View File

@@ -15,12 +15,6 @@
meta.name = "foo"; meta.name = "foo";
machines.peer1 = { }; machines.peer1 = { };
machines.admin1 = { }; machines.admin1 = { };
services = {
legacy-module.default = {
roles.peer.machines = [ "peer1" ];
roles.admin.machines = [ "admin1" ];
};
};
instances."test" = { instances."test" = {
module.name = "new-service"; module.name = "new-service";
@@ -28,9 +22,6 @@
roles.peer.machines.peer1 = { }; roles.peer.machines.peer1 = { };
}; };
modules = {
legacy-module = ./legacy-module;
};
}; };
modules.new-service = { modules.new-service = {

View File

@@ -1,10 +0,0 @@
---
description = "Set up dummy-module"
categories = ["System"]
features = [ "inventory" ]
[constraints]
roles.admin.min = 1
roles.admin.max = 1
---

View File

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

View File

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

View File

@@ -1,34 +0,0 @@
{ config, ... }:
{
systemd.services.dummy-service = {
enable = true;
description = "Dummy service";
wantedBy = [ "multi-user.target" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
script = ''
generated_password_path="${config.clan.core.vars.generators.dummy-generator.files.generated-password.path}"
if [ ! -f "$generated_password_path" ]; then
echo "Generated password file not found: $generated_password_path"
exit 1
fi
host_id_path="${config.clan.core.vars.generators.dummy-generator.files.host-id.path}"
if [ ! -e "$host_id_path" ]; then
echo "Host ID file not found: $host_id_path"
exit 1
fi
'';
};
# TODO: add and prompt and make it work in the test framework
clan.core.vars.generators.dummy-generator = {
files.host-id.secret = false;
files.generated-password.secret = true;
script = ''
echo $RANDOM > "$out"/host-id
echo $RANDOM > "$out"/generated-password
'';
};
}

View File

@@ -15,7 +15,6 @@ nixosLib.runTest (
# This tests the compatibility of the inventory # This tests the compatibility of the inventory
# With the test framework # With the test framework
# - legacy-modules
# - clan.service modules # - clan.service modules
name = "service-dummy-test"; name = "service-dummy-test";
@@ -24,12 +23,6 @@ nixosLib.runTest (
inventory = { inventory = {
machines.peer1 = { }; machines.peer1 = { };
machines.admin1 = { }; machines.admin1 = { };
services = {
legacy-module.default = {
roles.peer.machines = [ "peer1" ];
roles.admin.machines = [ "admin1" ];
};
};
instances."test" = { instances."test" = {
module.name = "new-service"; module.name = "new-service";
@@ -37,9 +30,6 @@ nixosLib.runTest (
roles.peer.machines.peer1 = { }; roles.peer.machines.peer1 = { };
}; };
modules = {
legacy-module = ./legacy-module;
};
}; };
modules.new-service = { modules.new-service = {
_class = "clan.service"; _class = "clan.service";
@@ -78,9 +68,6 @@ nixosLib.runTest (
start_all() start_all()
admin1.wait_for_unit("multi-user.target") admin1.wait_for_unit("multi-user.target")
peer1.wait_for_unit("multi-user.target") peer1.wait_for_unit("multi-user.target")
# Provided by the legacy module
print(admin1.succeed("systemctl status dummy-service"))
print(peer1.succeed("systemctl status dummy-service"))
# peer1 should have the 'hello' file # peer1 should have the 'hello' file
peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.not-a-secret.path}") peer1.succeed("cat ${nodes.peer1.clan.core.vars.generators.new-service.files.not-a-secret.path}")

View File

@@ -35,6 +35,13 @@
services.openssh.enable = true; services.openssh.enable = true;
services.openssh.settings.PasswordAuthentication = false; services.openssh.settings.PasswordAuthentication = false;
users.users.root.openssh.authorizedKeys.keys = [ (builtins.readFile ../assets/ssh/pubkey) ]; users.users.root.openssh.authorizedKeys.keys = [ (builtins.readFile ../assets/ssh/pubkey) ];
services.openssh.knownHosts.localhost.publicKeyFile = ../assets/ssh/pubkey;
services.openssh.hostKeys = [
{
path = ../assets/ssh/privkey;
type = "ed25519";
}
];
security.sudo.wheelNeedsPassword = false; security.sudo.wheelNeedsPassword = false;
boot.consoleLogLevel = lib.mkForce 100; boot.consoleLogLevel = lib.mkForce 100;
@@ -99,12 +106,14 @@
let let
closureInfo = pkgs.closureInfo { closureInfo = pkgs.closureInfo {
rootPaths = [ rootPaths = [
self.checks.x86_64-linux.clan-core-for-checks self.packages.${pkgs.system}.clan-cli
self.checks.${pkgs.system}.clan-core-for-checks
self.clanInternals.machines.${pkgs.hostPlatform.system}.test-update-machine.config.system.build.toplevel self.clanInternals.machines.${pkgs.hostPlatform.system}.test-update-machine.config.system.build.toplevel
pkgs.stdenv.drvPath pkgs.stdenv.drvPath
pkgs.bash.drvPath pkgs.bash.drvPath
pkgs.buildPackages.xorg.lndir pkgs.buildPackages.xorg.lndir
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs);
}; };
in in
self.clanLib.test.containerTest { self.clanLib.test.containerTest {
@@ -151,14 +160,6 @@
machine_config_path = os.path.join(flake_dir, "machines", "test-update-machine", "configuration.nix") machine_config_path = os.path.join(flake_dir, "machines", "test-update-machine", "configuration.nix")
os.makedirs(os.path.dirname(machine_config_path), exist_ok=True) os.makedirs(os.path.dirname(machine_config_path), exist_ok=True)
with open(machine_config_path, "w") as f:
f.write("""
{
environment.etc."update-successful".text = "ok";
}
""")
# Run clan update command
# Note: update command doesn't accept -i flag, SSH key must be in ssh-agent # Note: update command doesn't accept -i flag, SSH key must be in ssh-agent
# Start ssh-agent and add the key # Start ssh-agent and add the key
agent_output = subprocess.check_output(["${pkgs.openssh}/bin/ssh-agent", "-s"], text=True) agent_output = subprocess.check_output(["${pkgs.openssh}/bin/ssh-agent", "-s"], text=True)
@@ -172,6 +173,90 @@
subprocess.run(["${pkgs.openssh}/bin/ssh-add", ssh_conn.ssh_key], check=True) subprocess.run(["${pkgs.openssh}/bin/ssh-add", ssh_conn.ssh_key], check=True)
##############
print("TEST: update with --build-host local")
with open(machine_config_path, "w") as f:
f.write("""
{
environment.etc."update-build-local-successful".text = "ok";
}
""")
# rsync the flake into the container
os.environ["PATH"] = f"{os.environ['PATH']}:${pkgs.openssh}/bin"
subprocess.run(
[
"${pkgs.rsync}/bin/rsync",
"-a",
"--delete",
"-e",
"ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no",
f"{str(flake_dir)}/",
f"root@192.168.1.1:/flake",
],
check=True
)
# allow machine to ssh into itself
subprocess.run([
"ssh",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
f"root@192.168.1.1",
"mkdir -p /root/.ssh && chmod 700 /root/.ssh && echo \"$(cat \"${../assets/ssh/privkey}\")\" > /root/.ssh/id_ed25519 && chmod 600 /root/.ssh/id_ed25519",
], check=True)
# install the clan-cli package into the container's Nix store
subprocess.run(
[
"${pkgs.nix}/bin/nix",
"copy",
"--to",
"ssh://root@192.168.1.1",
"--no-check-sigs",
f"${self.packages.${pkgs.system}.clan-cli}",
"--extra-experimental-features", "nix-command flakes",
"--from", f"{os.environ["TMPDIR"]}/store"
],
check=True,
env={
**os.environ,
"NIX_SSHOPTS": "-o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no",
},
)
# Run ssh on the host to run the clan update command via --build-host local
subprocess.run([
"ssh",
"-o", "UserKnownHostsFile=/dev/null",
"-o", "StrictHostKeyChecking=no",
f"root@192.168.1.1",
"${self.packages.${pkgs.system}.clan-cli}/bin/clan",
"machines",
"update",
"--debug",
"--flake", "/flake",
"--host-key-check", "none",
"--upload-inputs", # Use local store instead of fetching from network
"--build-host", "localhost",
"test-update-machine",
"--target-host", f"root@localhost",
], check=True)
# Verify the update was successful
machine.succeed("test -f /etc/update-build-local-successful")
##############
print("TEST: update with --target-host")
with open(machine_config_path, "w") as f:
f.write("""
{
environment.etc."target-host-update-successful".text = "ok";
}
""")
# Run clan update command # Run clan update command
subprocess.run([ subprocess.run([
"${self.packages.${pkgs.system}.clan-cli-full}/bin/clan", "${self.packages.${pkgs.system}.clan-cli-full}/bin/clan",
@@ -180,16 +265,18 @@
"--debug", "--debug",
"--flake", flake_dir, "--flake", flake_dir,
"--host-key-check", "none", "--host-key-check", "none",
"--fetch-local", # Use local store instead of fetching from network "--upload-inputs", # Use local store instead of fetching from network
"test-update-machine", "test-update-machine",
"--target-host", f"root@192.168.1.1:{ssh_conn.host_port}", "--target-host", f"root@192.168.1.1:{ssh_conn.host_port}",
], check=True) ], check=True)
# Verify the update was successful # Verify the update was successful
machine.succeed("test -f /etc/update-successful") machine.succeed("test -f /etc/target-host-update-successful")
# Test update with --build-host
# Update configuration again to test build-host functionality ##############
print("TEST: update with --build-host")
# Update configuration again
with open(machine_config_path, "w") as f: with open(machine_config_path, "w") as f:
f.write(""" f.write("""
{ {
@@ -205,24 +292,7 @@
"--debug", "--debug",
"--flake", flake_dir, "--flake", flake_dir,
"--host-key-check", "none", "--host-key-check", "none",
"--fetch-local", # Use local store instead of fetching from network "--upload-inputs", # Use local store instead of fetching from network
"--build-host", f"root@192.168.1.1:{ssh_conn.host_port}",
"test-update-machine",
"--target-host", f"root@192.168.1.1:{ssh_conn.host_port}",
], check=True)
# Verify the second update was successful
machine.succeed("test -f /etc/build-host-update-successful")
# Run clan update command with --build-host
subprocess.run([
"${self.packages.${pkgs.system}.clan-cli-full}/bin/clan",
"machines",
"update",
"--debug",
"--flake", flake_dir,
"--host-key-check", "none",
"--fetch-local", # Use local store instead of fetching from network
"--build-host", f"root@192.168.1.1:{ssh_conn.host_port}", "--build-host", f"root@192.168.1.1:{ssh_conn.host_port}",
"test-update-machine", "test-update-machine",
"--target-host", f"root@192.168.1.1:{ssh_conn.host_port}", "--target-host", f"root@192.168.1.1:{ssh_conn.host_port}",

View File

@@ -0,0 +1,115 @@
{
pkgs,
nixosLib,
clan-core,
lib,
...
}:
nixosLib.runTest (
{ ... }:
let
machines = [
"controller1"
"controller2"
"peer1"
"peer2"
"peer3"
];
in
{
imports = [
clan-core.modules.nixosTest.clanTest
];
hostPkgs = pkgs;
name = "wireguard";
clan = {
directory = ./.;
modules."@clan/wireguard" = import ../../clanServices/wireguard/default.nix;
inventory = {
machines = lib.genAttrs machines (_: { });
instances = {
/*
wg-test-one
controller2 controller1
peer2 peer1 peer3
*/
wg-test-one = {
module.name = "@clan/wireguard";
module.input = "self";
roles.controller.machines."controller1".settings = {
endpoint = "192.168.1.1";
};
roles.controller.machines."controller2".settings = {
endpoint = "192.168.1.2";
};
roles.peer.machines = {
peer1.settings.controller = "controller1";
peer2.settings.controller = "controller2";
peer3.settings.controller = "controller1";
};
};
# TODO: Will this actually work with conflicting ports? Can we re-use interfaces?
#wg-test-two = {
# module.name = "@clan/wireguard";
# roles.controller.machines."controller1".settings = {
# endpoint = "192.168.1.1";
# port = 51922;
# };
# roles.peer.machines = {
# peer1 = { };
# };
#};
};
};
};
testScript = ''
start_all()
# Show all addresses
machines = [peer1, peer2, peer3, controller1, controller2]
for m in machines:
m.systemctl("start network-online.target")
for m in machines:
m.wait_for_unit("network-online.target")
m.wait_for_unit("systemd-networkd.service")
print("\n\n" + "="*60)
print("STARTING PING TESTS")
print("="*60)
for m1 in machines:
for m2 in machines:
if m1 != m2:
print(f"\n--- Pinging from {m1.name} to {m2.name}.wg-test-one ---")
m1.wait_until_succeeds(f"ping -c1 {m2.name}.wg-test-one >&2")
'';
}
)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:zDF0RiBqaawpg+GaFkuLPomJ01Xu+lgY5JfUzaIk2j03XkCzIf8EMrmn6pRtBP3iUjPBm+gQSTQk6GHTONrixA5hRNyETV+UgQw=,iv:zUUCAGZ0cz4Tc2t/HOjVYNsdnrAOtid/Ns5ak7rnyCk=,tag:z43WtNSue4Ddf7AVu21IKA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBlY1NEdjAzQm5RMFZWY3BJ\nclp6c01FdlZFK3dOSDB4cHc1NTdwMXErMFJFCnIrRVFNZEFYOG1rVUhFd2xsbTJ2\nVkJHNmdOWXlOcHJoQ0QzM1VyZmxmcGcKLS0tIFk1cEx4dFdvNGRwK1FWdDZsb1lR\nV2d1RFZtNzZqVFdtQ1FzNStEcEgyUUkKx8tkxqJz/Ko3xgvhvd6IYiV/lRGmrY13\nUZpYWR9tsQwZAR9dLjCyVU3JRuXeGB1unXC1CO0Ff3R0A/PuuRHh+g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:37Z",
"mac": "ENC[AES256_GCM,data:8RGOUhZ2LGmC9ugULwHDgdMrtdo9vzBm3BJmL4XTuNJKm0NlKfgNLi1E4n9DMQ+kD4hKvcwbiUcwSGE8jZD6sm7Sh3bJi/HZCoiWm/O/OIzstli2NNDBGvQBgyWZA5H+kDjZ6aEi6icNWIlm5gsty7KduABnf5B3p0Bn5Uf5Bio=,iv:sGZp0XF+mgocVzAfHF8ATdlSE/5zyz5WUSRMJqNeDQs=,tag:ymYVBRwF5BOSAu5ONU2qKw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:dHM7zWzqnC1QLRKYpbI2t63kOFnSaQy6ur9zlkLQf17Q03CNrqUsZtdEbwMnLR3llu7eVMhtvVRkXjEkvn3leb9HsNFmtk/DP70=,iv:roEZsBFqRypM106O5sehTzo7SySOJUJgAR738rTtOo8=,tag:VDd9/6uU0SAM7pWRLIUhUQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKTEVYUmVGbUtOcHZ4cnc3\nKzNETnlxaVRKYTI3eWVHdEoyc3l2SnhsZ1J3CnB2RnZrOXM5Uml6TThDUlZjY25J\nbkJ6eUZ2ckN1NWpNUU9IaE93UDJQdlEKLS0tIC95ZDhkU0R1VHhCdldxdW4zSmps\nN3NqL1cvd05hRTRPdDA3R2pzNUFFajgKS+DJH14fH9AvEAa3PoUC1jEqKAzTmExN\nl32FeHTHbGMo1PKeaFm+Eg0WSpAmFE7beBunc5B73SW30ok6x4FcQw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:47Z",
"mac": "ENC[AES256_GCM,data:77EnuBQyguvkCtobUg8/6zoLHjmeGDrSBZuIXOZBMxdbJjzhRg++qxQjuu6t0FoWATtz7u4Y3/jzUMGffr/N5HegqSq0D2bhv7AqJwBiVaOwd80fRTtM+YiP/zXsCk52Pj/Gadapg208bDPQ1BBDOyz/DrqZ7w//j+ARJjAnugI=,iv:IuTDmJKZEuHXJXjxrBw0gP2t6vpxAYEqbtpnVbavVCY=,tag:4EnpX6rOamtg1O+AaEQahQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:wcSsqxTKiMAnzPwxs5DNjcSdLyjVQ9UOrZxfSbOkVfniwx6F7xz6dLNhaDq7MHQ0vRWpg28yNs7NHrp52bYFnb/+eZsis46WiCw=,iv:B4t1lvS2gC601MtsmZfEiEulLWvSGei3/LSajwFS9Vs=,tag:hnRXlZyYEFfLJUrw1SqbSQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAybUgya2VEdzMvRG1hdkpu\nM2pGNmcyVmcvYVZ1ZjJlY3A1bXFUUUtkMTI0CmJoRFZmejZjN2UxUXNuc1k5WnE2\nNmxIcnpNQ1lJZ3ZKSmhtSlVURXJTSUUKLS0tIGU4Wi9yZ3VYekJkVW9pNWFHblFk\na0gzbTVKUWdSam1sVjRUaUlTdVd5YWMKntRc9yb9VPOTMibp8QM5m57DilP01N/X\nPTQaw8oI40znnHdctTZz7S+W/3Te6sRnkOhFyalWmsKY0CWg/FELlA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:58Z",
"mac": "ENC[AES256_GCM,data:8nq+ugkUJxE24lUIySySs/cAF8vnfqr936L/5F0O1QFwNrbpPmKRXkuwa6u0V+187L2952Id20Fym4ke59f3fJJsF840NCKDwDDZhBZ20q9GfOqIKImEom/Nzw6D0WXQLUT3w8EMyJ/F+UaJxnBNPR6f6+Kx4YgStYzCcA6Ahzg=,iv:VBPktEz7qwWBBnXE+xOP/EUVy7/AmNCHPoK56Yt/ZNc=,tag:qXONwOLFAlopymBEf5p4Sw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:4d3ri0EsDmWRtA8vzvpPRLMsSp4MIMKwvtn0n0pRY05uBPXs3KcjnweMPIeTE1nIhqnMR2o2MfLah5TCPpaFax9+wxIt74uacbg=,iv:0LBAldTC/hN4QLCxgXTl6d9UB8WmUTnj4sD2zHQuG2w=,tag:zr/RhG/AU4g9xj9l2BprKw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvV0JnZDhlU1piU1g2cng0\ncytKOEZ6WlZlNGRGUjV3MmVMd2Nzc0ZwelgwCjBGdThCUGlXbVFYdnNoZWpJZ3Vm\nc2xkRXhxS09vdzltSVoxLzhFSVduak0KLS0tIE5DRjJ6cGxiVlB1eElHWXhxN1pJ\nYWtIMDMvb0Z6akJjUzlqeEFsNHkxL2cKpghv/QegnXimeqd9OPFouGM//jYvoVmw\n2d4mLT2JSMkEhpfGcqb6vswhdJfCiKuqr2B4bqwAnPMaykhsm8DFRQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:20:08Z",
"mac": "ENC[AES256_GCM,data:BzlQVAJ7HzcxNPKB3JhabqRX/uU0EElj172YecjmOflHnzz/s9xgfdAfJK/c53hXlX4LtGPnubH7a8jOolRq98zmZeBYE27+WLs2aN7Ufld6mYk90/i7u4CqR+Fh2Kfht04SlUJCjnS5A9bTPwU9XGRHJ0BiOhzTuSMUJTRaPRM=,iv:L50K5zc1o99Ix9nP0pb9PRH+VIN2yvq7JqKeVHxVXmc=,tag:XFLkSCsdbTPxbasDYYxcFQ==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:qfLm6+g1vYnESCik9uyBeKsY6Ju2Gq3arnn2I8HHNO67Ri5BWbOQTvtz7WT8/q94RwVjv8SGeJ/fsJSpwLSrJSbqTZCPAnYwzzQ=,iv:PnA9Ao8RRELNhNQYbaorstc0KaIXRU7h3+lgDCXZFHk=,tag:VeLgYQYwqthYihIoQTwYiA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBNWVVQaDJFd0N3WHptRC9Z\nZTgxTWh5bnU1SkpqRWRXZnhPaFhpSVJmVEhrCjFvdHFYenNWaFNrdXlha09iS2xj\nOTZDcUNkcHkvTDUwNjM4Z3gxUkxreUEKLS0tIE5oY3Q2bWhsb2FSQTVGTWVSclJw\nWllrelRwT3duYjJJbTV0d3FwU1VuNlkK2eN3fHFX/sVUWom8TeZC9fddqnSCsC1+\nJRCZsG46uHDxqLcKIfdFWh++2t16XupQYk3kn+NUR/aMc3fR32Uwjw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:20:18Z",
"mac": "ENC[AES256_GCM,data:nUwsPcP1bsDjAHFjQ1NlVkTwyZY4B+BpzNkMx9gl0rE14j425HVLtlhlLndhRp+XMpnDldQppLAAtSdzMsrw8r5efNgTRl7cu4Fy/b9cHt84k7m0aou5lrGus9SV1bM7/fzC9Xm7CSXBcRzyDGVsKC6UBl1rx+ybh7HyAN05XSo=,iv:It57H+zUUNPkoN1D8sYwyZx5zIFIga7mydhGUHYBCGE=,tag:mBQdYqUpjPknbYa13qESyw==,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 @@
../../../../../../sops/machines/controller1

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:noe913+28JWkoDkGGMu++cc1+j5NPDoyIhWixdsowoiVO3cTWGkZ88SUGO5D,iv:ynYMljwqMcBdk8RpVcw/2Jflg2RCF28r4fKUgIAF8B4=,tag:+TsXDJgfUhKgg4iQVXKKlQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBhYVRReTZBQ05GYmVBVjhS\nNXM5aFlhVzZRaVl6UHl6S3JnMC9Sb1dwZ1ZjCmVuS2dEVExYZWROVklUZWFCSnM2\nZnlxbVNseTM2c0Q0TjhsT3NzYmtqREUKLS0tIHBRTFpvVGt6d1cxZ2lFclRsUVhZ\nZDlWaG9PcXVrNUZKaEgxWndjUDVpYjgKt0eOhAgcYdkg9JSEakx4FjChLTn3pis+\njOkuGd4JfXMKcwC7vJV5ygQBxzVJSBw+RucP7sYCBPK0m8Voj94ntw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1rnkc2vmrupy9234clyu7fpur5kephuqs3v7qauaw5zeg00jqjdasefn3cc",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6MFJqNHNraG9DSnJZMFdz\ndU8zVXNTamxROFd1dWtuK2RiekhPdHhleVhFCi8zNWJDNXJMRUlDdjc4Q0UycTIz\nSGFGSmdnNU0wZWlDaTEwTzBqWjh6SFkKLS0tIEJOdjhOMDY2TUFLb3RPczNvMERx\nYkpSeW5VOXZvMlEvdm53MDE3aUFTNjgKyelSTjrTIR9I3rJd3krvzpsrKF1uGs4J\n4MtmQj0/3G+zPYZVBx7b3HF6B3f1Z7LYh05+z7nCnN/duXyPnDjNcg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:37Z",
"mac": "ENC[AES256_GCM,data:+DmIkPG/H6tCtf8CvB98E1QFXv08QfTcCB3CRsi+XWnIRBkryRd/Au9JahViHMdK7MED8WNf84NWTjY2yH4y824/DjI8XXNMF1iVMo0CqY42xbVHtUuhXrYeT+c8CyEw+M6zfy1jC0+Bm3WQWgagz1G6A9SZk3D2ycu0N08+axA=,iv:kwBjTYebIy5i2hagAajSwwuKnSkrM9GyrnbeQXB2e/w=,tag:EgKJ5gVGYj1NGFUduxLGfg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1 @@
lQfR7GhivN87XoXruTGOPjVPhNu1Brt//wyc3pdwE20=

View File

@@ -0,0 +1 @@
7470bb5c79df224a9b7f5a2259acd2e46db763c27e24cb3416c8b591cb328077

View File

@@ -0,0 +1 @@
fd51:19c1:3b:f700

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:2kehACgvNgoYGPwnW7p86BR0yUu689Chth6qZf9zoJtuTY9ATS68dxDyBc5S,iv:qb2iDUtExegTeN3jt6SA8RnU61W5GDDhn56QXiQT4gw=,tag:pSGPICX5p6qlZ1WMVoIEYQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBSTTR5TDY4RE9VYmlCK1dL\nWkVRcVZqVDlsbmQvUlJmdzF2b1Z1S0k3NngwCkFWNzRVaERtSmFsd0o2aFJOb0ZX\nSU9yUnVaNi9IUjJWeGRFcEpDUXo5WkEKLS0tIEczNkxiYnJsTWRoLzFhQVF1M21n\nWnZEdGV1N2N5d1FZQkJUQ1IrdGFLblkKPTpha2bxS8CCAMXWTDKX/WOcdvggaP3Y\nqewyahDNzb4ggP+LNKp55BtwFjdvoPoq4BpYOOgMRbQMMk+H1o9WFw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1t2hhg99d4p2yymuhngcy5ccutp8mvu7qwvg5cdhck303h9e7ha9qnlt635",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBYcEZ6Tzk3M0pkV0tOdTBj\nenF2a0tHNnhBa0NrazMwV1VBbXBZR3pzSHpvCnBZOEU0VlFHS1FHcVpTTDdPczVV\nV0RFSlZ0VmIzWGoydEdKVXlIUE9OOEkKLS0tIFZ0cWVBR1loeVlWa2c4U3oweXE2\ncm1ja0JCS3U5Nk41dlAzV2NabDc2bDQKdgCDNnpRZlFPnEGlX6fo0SQX4yOB+E6r\ntnSwofR3xxZvkyme/6JJU5qBZXyCXEAhKMRkFyvJANXzMJAUo/Osow==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:48Z",
"mac": "ENC[AES256_GCM,data:e3EkL8vwRhLsec83Zi9DE3PKT+4RwgiffpN4QHcJKTgmDW6hzizWc5kAxbNWGJ9Qqe6sso2KY7tc+hg1lHEsmzjCbg153p8h+7lVI2XT6adi/CS8WZ2VpeL+0X9zDQCjqHmrESZAYFBdkLqO4jucdf0Pc3CKKD+N3BDDTwSUvHM=,iv:xvR7dJL8sdYen00ovrYT8PNxhB9XxSWDSRz1IK23I/o=,tag:OyhAvllBgfAp3eGeNpR/Nw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1 @@
5Z7gbLFbXpEFfomW2pKyZBpZN5xvUtiqrIL0GVfNtQ8=

View File

@@ -0,0 +1 @@
c3672fdb9fb31ddaf6572fc813cf7a8fe50488ef4e9d534c62d4f29da60a1a99

View File

@@ -0,0 +1 @@
fd51:19c1:c1:aa00

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:b+akw85T3D9xc75CPLHucR//k7inpxKDvgpR8tCNKwNDRVjVHjcABhfZNLXW,iv:g11fZE8UI0MVh9GKdjR6leBlxa4wN7ZubozXG/VlBbw=,tag:0YkzWCW3zJ3Mt3br/jmTYw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1jts52rzlqcwjc36jkp56a7fmjn3czr7kl9ta2spkfzhvfama33sqacrzzd",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBXWkJUR0pIa2xOSEw2dThm\nYlNuOHZCVW93Wkc5LzE4YmpUTHRkZlk3ckc4CnN4M3ZRMWNFVitCT3FyWkxaR0di\nb0NmSXFhRHJmTWg0d05OcWx1LytscEEKLS0tIEtleTFqU3JrRjVsdHpJeTNuVUhF\nWEtnOVlXVXRFamFSak5ia2F2b0JiTzAKlhOBZvZ4AN+QqAYQXvd6YNmgVS4gtkWT\nbV3bLNTgwtrDtet9NDHM8vdF+cn5RZxwFfgmTbDEow6Zm8EXfpxj/g==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6YVYyQkZqMTJYQTlyRG5Y\nbnJ2UkE1TS9FZkpSa2tQbk1hQjViMi9OcGk0CjFaZUdjU3JtNzh0bDFXdTdUVW4x\nanFqZHZjZjdzKzA2MC8vTWh3Uy82UGcKLS0tIDhyOFl3UGs3czdoMlpza3UvMlB1\nSE90MnpGc05sSCtmVWg0UVNVdmRvN2MKHlCr4U+7bsoYb+2fgT4mEseZCEjxrtLu\n55sR/4YH0vqMnIBnLTSA0e+WMrs3tQfseeJM5jY/ZNnpec1LbxkGTg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:19:58Z",
"mac": "ENC[AES256_GCM,data:gEoEC9D2Z7k5F8egaY1qPXT5/96FFVsyofSBivQ28Ir/9xHX2j40PAQrYRJUWsk/GAUMOyi52Wm7kPuacw+bBcdtQ0+MCDEmjkEnh1V83eZ/baey7iMmg05uO92MYY5o4e7ZkwzXoAeMCMcfO0GqjNvsYJHF1pSNa+UNDj+eflw=,iv:dnIYpvhAdvUDe9md53ll42krb0sxcHy/toqGc7JFxNA=,tag:0WkZU7GeKMD1DQTYaI+1dg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1 @@
juK7P/92N2t2t680aLIRobHc3ts49CsZBvfZOyIKpUc=

View File

@@ -0,0 +1 @@
b36142569a74a0de0f9b229f2a040ae33a22d53bef5e62aa6939912d0cda05ba

View File

@@ -0,0 +1 @@
6987:50a0:9b93:4337

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:apX2sLwtq6iQgLJslFwiRMNBUe0XLzLQbhKfmb2pKiJG7jGNHUgHJz3Ls4Ca,iv:HTDatm3iD5wACTkkd3LdRNvJfnfg75RMtn9G6Q7Fqd4=,tag:Mfehlljnes5CFD1NJdk27A==,type:str]",
"sops": {
"age": [
{
"recipient": "age12nqnp0zd435ckp5p0v2fv4p2x4cvur2mnxe8use2sx3fgy883vaq4ae75e",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBVZzFyMUZsd2V2VWxOUmhP\nZE8yZTc4Q0RkZisxR25NemR1TzVDWmJZVjBVClA1MWhsU0xzSG16aUx3cWFWKzlG\nSkxrT09OTkVqLzlWejVESE1QWHVJaFkKLS0tIGxlaGVuWU43RXErNTB3c3FaUnM3\nT0N5M253anZkbnFkZWw2VHA0eWhxQW8Kd1PMtEX1h0Hd3fDLMi++gKJkzPi9FXUm\n+uYhx+pb+pJM+iLkPwP/q6AWC7T0T4bHfekkdzxrbsKMi73x/GrOiw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBqVzRIMWdlNjVwTURyMFkv\nSUhiajZkZVNuWklRYit6cno4UzNDa2szOFN3CkQ2TWhHb25pbmR1MlBsRXNLL2lx\ncVZ3c3BsWXN2aS9UUVYvN3I4S0xUSmMKLS0tIE5FV0U5aXVUZk9XL0U0Z2ZSNGd5\nbU9zY3IvMlpSNVFLYkRNQUpUYVZOWFUK7j4Otzb8CJTcT7aAj9/irxHEDXh1HkTg\nzz7Ho8/ZncNtaCVHlHxjTgVW9d5aIx8fSsV9LRCFwHMtNzvwj1Nshg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:20:08Z",
"mac": "ENC[AES256_GCM,data:e7WNVEz78noHBiz6S3A6qNfop+yBXB3rYN0k4GvaQKz3b99naEHuqIF8Smzzt4XrbbiPKu2iLa5ddLBlqqsi32UQUB8JS9TY7hvW8ol+jpn0VxusGCXW9ThdDEsM/hXiPyr331C73zTvbOYI1hmcGMlJL9cunVRO9rkMtEqhEfo=,iv:6zt7wjIs1y5xDHNK+yLOwoOuUpY7/dOGJGT6UWAFeOg=,tag:gzFTgoxhoLzUV0lvzOhhfg==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1 @@
XI9uSaQRDBCb82cMnGzGJcbqRfDG/IXZobyeL+kV03k=

View File

@@ -0,0 +1 @@
360f9fce4a984eb87ce2a673eb5341ecb89c0f62126548d45ef25ff5243dd646

View File

@@ -0,0 +1 @@
3b21:3ced:003e:89b3

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:Gluvjes/3oH5YsDq00JDJyJgoEFcj56smioMArPSt309MDGExYX2QsCzeO1q,iv:oBBJRDdTj/1dWEvzhdFKQ2WfeCKyavKMLmnMbqnU5PM=,tag:2WNFxKz2dWyVcybpm5N4iw==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBtQWpjRmhZTFdPa2VSZkFN\nbUczMlY5bDBmMTdoMy8xcWxMaXpWVitMZGdjCnRWb2Y3eGpHU1hmNHRJVFBqbU5w\nVEZGdUIrQXk0U0dUUEZ6bE5EMFpTRHMKLS0tIGpYSmZmQThJUTlvTHpjc05ZVlM4\nQWhTOWxnUHZnYlJ3czE3ZUJ0L3ozWTQK3a7N0Zpzo4sUezYveqvKR49RUdJL23eD\n+cK5lk2xbtj+YHkeG+dg7UlHfDaicj0wnFH1KLuWmNd1ONa6eQp3BQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1sglr4zp34drjfydzeweq43fz3uwpul3hkh53lsfa9drhuzwmkqyqn5jegp",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA3a2FOWlVsSkdnendrYmUz\ndEpuL1hZSWNFTUtDYm14S3V1aW9KS3hsazJRCkp2SkFFbi9hbGJpNks1MlNTL0s5\nTk5pcUMxaEJobkcvWmRGeU9jMkdNdzAKLS0tIDR6M0Y5eE1ETHJJejAzVW1EYy9v\nZCtPWHJPUkhuWnRzSGhMUUtTa280UmMKXvtnxyop7PmRvTOFkV80LziDjhGh93Pf\nYwhD/ByD/vMmr21Fd6PVHOX70FFT30BdnMc1/wt7c/0iAw4w4GoQsA==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-08-13T09:20:18Z",
"mac": "ENC[AES256_GCM,data:3nXMTma0UYXCco+EM8UW45cth7DVMboFBKyesL86GmaG6OlTkA2/25AeDrtSVO13a5c2jC6yNFK5dE6pSe5R9f0BoDF7d41mgc85zyn+LGECNWKC6hy6gADNSDD6RRuV1S3FisFQl1F1LD8LiSWmg/XNMZzChNlHYsCS8M+I84g=,iv:pu5VVXAVPmVoXy0BJ+hq5Ar8R0pZttKSYa4YS+dhDNc=,tag:xp1S/4qExnxMTGwhfLJrkA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1 @@
t6qN4VGLR+VMhrBDNKQEXZVyRsEXs1/nGFRs5DI82F8=

View File

@@ -0,0 +1 @@
e3facc99b73fe029d4c295f71829a83f421f38d82361cf412326398175da162a

View File

@@ -0,0 +1 @@
e42b:bf85:33f4:f0b1

View File

@@ -1,24 +0,0 @@
(
{ pkgs, ... }:
{
name = "zt-tcp-relay";
nodes.machine =
{ self, ... }:
{
imports = [
self.nixosModules.clanCore
self.clanModules.zt-tcp-relay
{
clan.core.settings.directory = ./.;
}
];
};
testScript = ''
start_all()
machine.wait_for_unit("zt-tcp-relay.service")
out = machine.succeed("${pkgs.netcat}/bin/nc -z -v localhost 4443")
print(out)
'';
}
)

View File

@@ -1,5 +0,0 @@
---
description = "Convenient Administration for the Clan App"
categories = ["Utility"]
features = [ "inventory", "deprecated" ]
---

View File

@@ -1,3 +0,0 @@
{
imports = [ ./roles/default.nix ];
}

View File

@@ -1,30 +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 = {
warnings = [
"The clan.admin module is deprecated and will be removed on 2025-07-15.
Please migrate to user-maintained configuration or the new equivalent clan services
(https://docs.clan.lol/reference/clanServices)."
];
users.users.root.openssh.authorizedKeys.keys = builtins.attrValues config.clan.admin.allowedKeys;
};
}

View File

@@ -1,8 +0,0 @@
---
description = "Set up automatic upgrades"
categories = ["System"]
features = [ "inventory", "deprecated" ]
---
Whether to periodically upgrade NixOS to the latest version. If enabled, a
systemd timer will run `nixos-rebuild switch --upgrade` once a day.

View File

@@ -1,32 +0,0 @@
{
config,
lib,
...
}:
let
cfg = config.clan.auto-upgrade;
in
{
options.clan.auto-upgrade = {
flake = lib.mkOption {
type = lib.types.str;
description = "Flake reference";
};
};
config = {
warnings = [
"The clan.auto-upgrade module is deprecated and will be removed on 2025-07-15.
Please migrate to user-maintained configuration or the new equivalent clan services
(https://docs.clan.lol/reference/clanServices)."
];
system.autoUpgrade = {
inherit (cfg) flake;
enable = true;
dates = "02:00";
randomizedDelaySec = "45min";
};
};
}

View File

@@ -1,16 +0,0 @@
---
description = "Statically configure borgbackup with sane defaults."
---
!!! Danger "Deprecated"
Use [borgbackup](borgbackup.md) instead.
Don't use borgbackup-static through [inventory](../../concepts/inventory.md).
This module implements the `borgbackup` backend and implements sane defaults
for backup management through `borgbackup` for members of the clan.
Configure target machines where the backups should be sent to through `targets`.
Configure machines that should be backuped either through `includeMachines`
which will exclusively add the included machines to be backuped, or through
`excludeMachines`, which will add every machine except the excluded machine to the backup.

View File

@@ -1,104 +0,0 @@
{ lib, config, ... }:
let
dir = config.clan.core.settings.directory;
machineDir = dir + "/machines/";
in
{
imports = [ ../borgbackup ];
options.clan.borgbackup-static = {
excludeMachines = lib.mkOption {
type = lib.types.listOf lib.types.str;
example = lib.literalExpression "[ config.clan.core.settings.machine.name ]";
default = [ ];
description = ''
Machines that should not be backuped.
Mutually exclusive with includeMachines.
If this is not empty, every other machine except the targets in the clan will be backuped by this module.
If includeMachines is set, only the included machines will be backuped.
'';
};
includeMachines = lib.mkOption {
type = lib.types.listOf lib.types.str;
example = lib.literalExpression "[ config.clan.core.settings.machine.name ]";
default = [ ];
description = ''
Machines that should be backuped.
Mutually exclusive with excludeMachines.
'';
};
targets = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
description = ''
Machines that should act as target machines for backups.
'';
};
};
config.services.borgbackup.repos =
let
machines = builtins.readDir machineDir;
borgbackupIpMachinePath = machines: machineDir + machines + "/facts/borgbackup.ssh.pub";
filteredMachines =
if ((builtins.length config.clan.borgbackup-static.includeMachines) != 0) then
lib.filterAttrs (name: _: (lib.elem name config.clan.borgbackup-static.includeMachines)) machines
else
lib.filterAttrs (name: _: !(lib.elem name config.clan.borgbackup-static.excludeMachines)) machines;
machinesMaybeKey = lib.mapAttrsToList (
machine: _:
let
fullPath = borgbackupIpMachinePath machine;
in
if builtins.pathExists fullPath then machine else null
) filteredMachines;
machinesWithKey = lib.filter (x: x != null) machinesMaybeKey;
hosts = builtins.map (machine: {
name = machine;
value = {
path = "/var/lib/borgbackup/${machine}";
authorizedKeys = [ (builtins.readFile (borgbackupIpMachinePath machine)) ];
};
}) machinesWithKey;
in
lib.mkIf
(builtins.any (
target: target == config.clan.core.settings.machine.name
) config.clan.borgbackup-static.targets)
(if (builtins.listToAttrs hosts) != null then builtins.listToAttrs hosts else { });
config.clan.borgbackup.destinations =
let
destinations = builtins.map (d: {
name = d;
value = {
repo = "borg@${d}:/var/lib/borgbackup/${config.clan.core.settings.machine.name}";
};
}) config.clan.borgbackup-static.targets;
in
lib.mkIf (builtins.any (
target: target == config.clan.core.settings.machine.name
) config.clan.borgbackup-static.includeMachines) (builtins.listToAttrs destinations);
config.assertions = [
{
assertion =
!(
((builtins.length config.clan.borgbackup-static.excludeMachines) != 0)
&& ((builtins.length config.clan.borgbackup-static.includeMachines) != 0)
);
message = ''
The options:
config.clan.borgbackup-static.excludeMachines = [${builtins.toString config.clan.borgbackup-static.excludeMachines}]
and
config.clan.borgbackup-static.includeMachines = [${builtins.toString config.clan.borgbackup-static.includeMachines}]
are mutually exclusive.
Use excludeMachines to exclude certain machines and backup the other clan machines.
Use include machines to only backup certain machines.
'';
}
];
config.warnings = lib.optional (
builtins.length config.clan.borgbackup-static.targets > 0
) "The borgbackup-static module is deprecated use the service via the inventory interface instead.";
}

View File

@@ -1,14 +0,0 @@
---
description = "Efficient, deduplicating backup program with optional compression and secure encryption."
categories = ["System"]
features = [ "inventory", "deprecated" ]
---
BorgBackup (short: Borg) gives you:
- Space efficient storage of backups.
- Secure, authenticated encryption.
- Compression: lz4, zstd, zlib, lzma or none.
- Mountable backups with FUSE.
- Easy installation on multiple platforms: Linux, macOS, BSD, …
- Free software (BSD license).
- Backed by a large and active open-source community.

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/client.nix ];
}

View File

@@ -1,210 +0,0 @@
{
config,
lib,
pkgs,
...
}:
let
# Instances might be empty, if the module is not used via the inventory
instances = config.clan.inventory.services.borgbackup or { };
# roles = { ${role_name} :: { machines :: [string] } }
allServers = lib.foldlAttrs (
acc: _instanceName: instanceConfig:
acc
++ (
if builtins.elem machineName instanceConfig.roles.client.machines then
instanceConfig.roles.server.machines
else
[ ]
)
) [ ] instances;
machineName = config.clan.core.settings.machine.name;
cfg = config.clan.borgbackup;
preBackupScript = ''
declare -A preCommandErrors
${lib.concatMapStringsSep "\n" (
state:
lib.optionalString (state.preBackupCommand != null) ''
echo "Running pre-backup command for ${state.name}"
if ! /run/current-system/sw/bin/${state.preBackupCommand}; then
preCommandErrors["${state.name}"]=1
fi
''
) (lib.attrValues config.clan.core.state)}
if [[ ''${#preCommandErrors[@]} -gt 0 ]]; then
echo "pre-backup commands failed for the following services:"
for state in "''${!preCommandErrors[@]}"; do
echo " $state"
done
exit 1
fi
'';
in
{
options.clan.borgbackup.destinations = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ name, ... }:
{
options = {
name = lib.mkOption {
type = lib.types.strMatching "^[a-zA-Z0-9._-]+$";
default = name;
description = "the name of the backup job";
};
repo = lib.mkOption {
type = lib.types.str;
description = "the borgbackup repository to backup to";
};
rsh = lib.mkOption {
type = lib.types.str;
default = "ssh -i ${
config.clan.core.vars.generators.borgbackup.files."borgbackup.ssh".path
} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o IdentitiesOnly=Yes";
defaultText = "ssh -i \${config.clan.core.vars.generators.borgbackup.files.\"borgbackup.ssh\".path} -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null";
description = "the rsh to use for the backup";
};
};
}
)
);
default = { };
description = ''
destinations where the machine should be backuped to
'';
};
options.clan.borgbackup.exclude = lib.mkOption {
type = lib.types.listOf lib.types.str;
example = [ "*.pyc" ];
default = [ ];
description = ''
Directories/Files to exclude from the backup.
Use * as a wildcard.
'';
};
config = {
warnings = [
"The clan.borgbackup module is deprecated and will be removed on 2025-07-15.
Please migrate to user-maintained configuration or the new equivalent clan services
(https://docs.clan.lol/reference/clanServices)."
];
# Destinations
clan.borgbackup.destinations =
let
destinations = builtins.map (serverName: {
name = serverName;
value = {
repo = "borg@${serverName}:/var/lib/borgbackup/${machineName}";
};
}) allServers;
in
(builtins.listToAttrs destinations);
# Derived from the destinations
systemd.services = lib.mapAttrs' (
_: dest:
lib.nameValuePair "borgbackup-job-${dest.name}" {
# since borgbackup mounts the system read-only, we need to run in a
# ExecStartPre script, so we can generate additional files.
serviceConfig.ExecStartPre = [
''+${pkgs.writeShellScript "borgbackup-job-${dest.name}-pre-backup-commands" preBackupScript}''
];
}
) cfg.destinations;
services.borgbackup.jobs = lib.mapAttrs (_: dest: {
paths = lib.unique (
lib.flatten (map (state: state.folders) (lib.attrValues config.clan.core.state))
);
exclude = cfg.exclude;
repo = dest.repo;
environment.BORG_RSH = dest.rsh;
compression = "auto,zstd";
startAt = "*-*-* 01:00:00";
persistentTimer = true;
encryption = {
mode = "repokey";
passCommand = "cat ${config.clan.core.vars.generators.borgbackup.files."borgbackup.repokey".path}";
};
prune.keep = {
within = "1d"; # Keep all archives from the last day
daily = 7;
weekly = 4;
monthly = 0;
};
}) cfg.destinations;
environment.systemPackages = [
(pkgs.writeShellApplication {
name = "borgbackup-create";
runtimeInputs = [ config.systemd.package ];
text = ''
${lib.concatMapStringsSep "\n" (dest: ''
systemctl start borgbackup-job-${dest.name}
'') (lib.attrValues cfg.destinations)}
'';
})
(pkgs.writeShellApplication {
name = "borgbackup-list";
runtimeInputs = [ pkgs.jq ];
text = ''
(${
lib.concatMapStringsSep "\n" (
dest:
# we need yes here to skip the changed url verification
''echo y | /run/current-system/sw/bin/borg-job-${dest.name} list --json | jq '[.archives[] | {"name": ("${dest.name}::${dest.repo}::" + .name)}]' ''
) (lib.attrValues cfg.destinations)
}) | jq -s 'add // []'
'';
})
(pkgs.writeShellApplication {
name = "borgbackup-restore";
runtimeInputs = [ pkgs.gawk ];
text = ''
cd /
IFS=':' read -ra FOLDER <<< "''${FOLDERS-}"
job_name=$(echo "$NAME" | awk -F'::' '{print $1}')
backup_name=''${NAME#"$job_name"::}
if [[ ! -x /run/current-system/sw/bin/borg-job-"$job_name" ]]; then
echo "borg-job-$job_name not found: Backup name is invalid" >&2
exit 1
fi
echo y | /run/current-system/sw/bin/borg-job-"$job_name" extract "$backup_name" "''${FOLDER[@]}"
'';
})
];
clan.core.vars.generators.borgbackup = {
files."borgbackup.ssh.pub".secret = false;
files."borgbackup.ssh" = { };
files."borgbackup.repokey" = { };
migrateFact = "borgbackup";
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
pkgs.xkcdpass
];
script = ''
ssh-keygen -t ed25519 -N "" -C "" -f "$out"/borgbackup.ssh
xkcdpass -n 4 -d - > "$out"/borgbackup.repokey
'';
};
clan.core.backups.providers.borgbackup = {
list = "borgbackup-list";
create = "borgbackup-create";
restore = "borgbackup-restore";
};
};
}

View File

@@ -1,63 +0,0 @@
{ config, lib, ... }:
let
dir = config.clan.core.settings.directory;
machineDir = dir + "/vars/per-machine/";
machineName = config.clan.core.settings.machine.name;
# Instances might be empty, if the module is not used via the inventory
#
# Type: { ${instanceName} :: { roles :: Roles } }
# Roles :: { ${role_name} :: { machines :: [string] } }
instances = config.clan.inventory.services.borgbackup or { };
allClients = lib.foldlAttrs (
acc: _instanceName: instanceConfig:
acc
++ (
if (builtins.elem machineName instanceConfig.roles.server.machines) then
instanceConfig.roles.client.machines
else
[ ]
)
) [ ] instances;
in
{
options = {
clan.borgbackup.directory = lib.mkOption {
type = lib.types.str;
default = "/var/lib/borgbackup";
description = ''
The directory where the borgbackup repositories are stored.
'';
};
};
config.services.borgbackup.repos =
let
borgbackupIpMachinePath = machine: machineDir + machine + "/borgbackup/borgbackup.ssh.pub/value";
machinesMaybeKey = builtins.map (
machine:
let
fullPath = borgbackupIpMachinePath machine;
in
if builtins.pathExists fullPath then
machine
else
lib.warn ''
Machine ${machine} does not have a borgbackup key at ${fullPath},
run `clan vars generate ${machine}` to generate it.
'' null
) allClients;
machinesWithKey = lib.filter (x: x != null) machinesMaybeKey;
hosts = builtins.map (machine: {
name = machine;
value = {
path = "${config.clan.borgbackup.directory}/${machine}";
authorizedKeys = [ (builtins.readFile (borgbackupIpMachinePath machine)) ];
};
}) machinesWithKey;
in
if (builtins.listToAttrs hosts) != [ ] then builtins.listToAttrs hosts else { };
}

View File

@@ -1,10 +0,0 @@
---
description = "Set up data-mesher"
categories = ["System"]
features = [ "inventory" ]
[constraints]
roles.admin.min = 1
roles.admin.max = 1
---

View File

@@ -1,19 +0,0 @@
lib: {
machines =
config:
let
instanceNames = builtins.attrNames config.clan.inventory.services.data-mesher;
instanceName = builtins.head instanceNames;
dataMesherInstances = config.clan.inventory.services.data-mesher.${instanceName};
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
in
rec {
admins = dataMesherInstances.roles.admin.machines or [ ];
signers = dataMesherInstances.roles.signer.machines or [ ];
peers = dataMesherInstances.roles.peer.machines or [ ];
bootstrap = uniqueStrings (admins ++ signers);
};
}

View File

@@ -1,58 +0,0 @@
{ lib, config, ... }:
let
cfg = config.clan.data-mesher;
dmLib = import ../lib.nix lib;
in
{
imports = [
../shared.nix
];
options.clan.data-mesher = {
network = {
tld = lib.mkOption {
type = lib.types.str;
default = (config.networking.domain or "clan");
description = "Top level domain to use for the network";
};
hostTTL = lib.mkOption {
type = lib.types.str;
default = "672h"; # 28 days
example = "24h";
description = "The TTL for hosts in the network, in the form of a Go time.Duration";
};
};
};
config = {
warnings = [
"The clan.admin module is deprecated and will be removed on 2025-07-15.
Please migrate to user-maintained configuration or the new equivalent clan services
(https://docs.clan.lol/reference/clanServices)."
];
services.data-mesher.initNetwork =
let
# for a given machine, read it's public key and remove any new lines
readHostKey =
machine:
let
path = "${config.clan.core.settings.directory}/vars/per-machine/${machine}/data-mesher-host-key/public_key/value";
in
builtins.elemAt (lib.splitString "\n" (builtins.readFile path)) 1;
in
{
enable = true;
keyPath = config.clan.core.vars.generators.data-mesher-network-key.files.private_key.path;
tld = cfg.network.tld;
hostTTL = cfg.network.hostTTL;
# admin and signer host public keys
signingKeys = builtins.map readHostKey (dmLib.machines config).bootstrap;
};
};
}

View File

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

View File

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

View File

@@ -1,152 +0,0 @@
{
config,
lib,
...
}:
let
cfg = config.clan.data-mesher;
dmLib = import ./lib.nix lib;
# the default bootstrap nodes are any machines with the admin or signers role
# we iterate through those machines, determining an IP address for them based on their VPN
# currently only supports zerotier
defaultBootstrapNodes = builtins.foldl' (
urls: name:
let
ipPath = "${config.clan.core.settings.directory}/vars/per-machine/${name}/zerotier/zerotier-ip/value";
in
if builtins.pathExists ipPath then
let
ip = builtins.readFile ipPath;
in
urls ++ [ "[${ip}]:${builtins.toString cfg.network.port}" ]
else
urls
) [ ] (dmLib.machines config).bootstrap;
in
{
options.clan.data-mesher = {
bootstrapNodes = lib.mkOption {
type = lib.types.nullOr (lib.types.listOf lib.types.str);
default = null;
description = ''
A list of bootstrap nodes that act as an initial gateway when joining
the cluster.
'';
example = [
"192.168.1.1:7946"
"192.168.1.2:7946"
];
};
network = {
interface = lib.mkOption {
type = lib.types.str;
description = ''
The interface over which cluster communication should be performed.
All the ip addresses associate with this interface will be part of
our host claim, including both ipv4 and ipv6.
This should be set to an internal/VPN interface.
'';
example = "tailscale0";
};
port = lib.mkOption {
type = lib.types.port;
default = 7946;
description = ''
Port to listen on for cluster communication.
'';
};
};
};
config = {
services.data-mesher = {
enable = true;
openFirewall = true;
settings = {
log_level = "warn";
state_dir = "/var/lib/data-mesher";
# read network id from vars
network.id = config.clan.core.vars.generators.data-mesher-network-key.files.public_key.value;
host = {
names = [ config.networking.hostName ];
key_path = config.clan.core.vars.generators.data-mesher-host-key.files.private_key.path;
};
cluster = {
port = cfg.network.port;
join_interval = "30s";
push_pull_interval = "30s";
interface = cfg.network.interface;
bootstrap_nodes = if cfg.bootstrapNodes == null then defaultBootstrapNodes else cfg.bootstrapNodes;
};
http.port = 7331;
http.interface = "lo";
};
};
# Generate host key.
clan.core.vars.generators.data-mesher-host-key = {
files =
let
owner = config.users.users.data-mesher.name;
in
{
private_key = {
inherit owner;
};
public_key.secret = false;
};
runtimeInputs = [
config.services.data-mesher.package
];
script = ''
data-mesher generate keypair \
--public-key-path "$out"/public_key \
--private-key-path "$out"/private_key
'';
};
clan.core.vars.generators.data-mesher-network-key = {
# generated once per clan
share = true;
files =
let
owner = config.users.users.data-mesher.name;
in
{
private_key = {
inherit owner;
};
public_key.secret = false;
};
runtimeInputs = [
config.services.data-mesher.package
];
script = ''
data-mesher generate keypair \
--public-key-path "$out"/public_key \
--private-key-path "$out"/private_key
'';
};
};
}

View File

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

View File

@@ -1,3 +0,0 @@
{
imports = [ ./roles/default.nix ];
}

View File

@@ -1,153 +0,0 @@
{
config,
pkgs,
...
}:
{
warnings = [
"The clan.deltachat module is deprecated and will be removed on 2025-07-15.
Please migrate to user-maintained configuration or the new equivalent clan services
(https://docs.clan.lol/reference/clanServices)."
];
networking.firewall.interfaces."zt+".allowedTCPPorts = [ 25 ]; # smtp with other hosts
environment.systemPackages = [ pkgs.deltachat-desktop ];
services.maddy =
let
domain = "${config.clan.core.settings.machine.name}.local";
in
{
enable = true;
primaryDomain = domain;
config = ''
# Minimal configuration with TLS disabled, adapted from upstream example
# configuration here https://github.com/foxcpp/maddy/blob/master/maddy.conf
# Do not use this in unencrypted networks!
auth.pass_table local_authdb {
table sql_table {
driver sqlite3
dsn credentials.db
table_name passwords
}
}
storage.imapsql local_mailboxes {
driver sqlite3
dsn imapsql.db
}
table.chain local_rewrites {
optional_step regexp "(.+)\+(.+)@(.+)" "$1@$3"
optional_step static {
entry postmaster postmaster@$(primary_domain)
}
optional_step file /etc/maddy/aliases
}
msgpipeline local_routing {
destination postmaster $(local_domains) {
modify {
replace_rcpt &local_rewrites
}
deliver_to &local_mailboxes
}
default_destination {
reject 550 5.1.1 "User doesn't exist"
}
}
smtp tcp://[::]:25 {
limits {
all rate 20 1s
all concurrency 10
}
dmarc yes
check {
require_mx_record
dkim
spf
}
source $(local_domains) {
reject 501 5.1.8 "Use Submission for outgoing SMTP"
}
default_source {
destination postmaster $(local_domains) {
deliver_to &local_routing
}
default_destination {
reject 550 5.1.1 "User doesn't exist"
}
}
}
submission tcp://[::1]:587 {
limits {
all rate 50 1s
}
auth &local_authdb
source $(local_domains) {
check {
authorize_sender {
prepare_email &local_rewrites
user_to_email identity
}
}
destination postmaster $(local_domains) {
deliver_to &local_routing
}
default_destination {
modify {
dkim $(primary_domain) $(local_domains) default
}
deliver_to &remote_queue
}
}
default_source {
reject 501 5.1.8 "Non-local sender domain"
}
}
target.remote outbound_delivery {
limits {
destination rate 20 1s
destination concurrency 10
}
mx_auth {
dane
mtasts {
cache fs
fs_dir mtasts_cache/
}
local_policy {
min_tls_level encrypted
min_mx_level none
}
}
}
target.queue remote_queue {
target &outbound_delivery
autogenerated_msg_domain $(primary_domain)
bounce {
destination postmaster $(local_domains) {
deliver_to &local_routing
}
default_destination {
reject 550 5.0.0 "Refusing to send DSNs to non-local addresses"
}
}
}
imap tcp://[::1]:143 {
auth &local_authdb
storage &local_mailboxes
}
'';
ensureAccounts = [ "user@${domain}" ];
ensureCredentials = {
"user@${domain}".passwordFile = pkgs.writeText "dummy" "foobar";
};
};
}

View File

@@ -1,5 +0,0 @@
---
description = "Generates a uuid for use in disk device naming"
features = [ "inventory" ]
categories = [ "System" ]
---

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,36 +0,0 @@
{
pkgs,
...
}:
{
config = {
warnings = [
''
The clan.disk-id module is deprecated and will be removed on 2025-07-15.
For migration see: https://docs.clan.lol/guides/migrations/disk-id/
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!! Please migrate. Otherwise you may not be able to boot your system after that date. !!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
''
];
clan.core.vars.generators.disk-id = {
files.diskId.secret = false;
runtimeInputs = [
pkgs.coreutils
pkgs.bash
];
script = ''
uuid=$(bash ${./uuid4.sh})
# Remove the hyphens from the UUID
uuid_no_hyphens=$(echo -n "$uuid" | tr -d '-')
echo -n "$uuid_no_hyphens" > "$out/diskId"
'';
};
};
}

View File

@@ -1,20 +0,0 @@
#!/usr/bin/env bash
# Read 16 bytes from /dev/urandom
uuid=$(dd if=/dev/urandom bs=1 count=16 2>/dev/null | od -An -tx1 | tr -d ' \n')
# Break the UUID into pieces and apply the required modifications
byte6=${uuid:12:2}
byte8=${uuid:16:2}
# Construct the correct version and variant
hex_byte6=$(printf "%x" $((0x$byte6 & 0x0F | 0x40)))
hex_byte8=$(printf "%x" $((0x$byte8 & 0x3F | 0x80)))
# Rebuild the UUID with the correct fields
uuid_v4="${uuid:0:12}${hex_byte6}${uuid:14:2}${hex_byte8}${uuid:18:14}"
# Format the UUID correctly 8-4-4-4-12
uuid_formatted="${uuid_v4:0:8}-${uuid_v4:8:4}-${uuid_v4:12:4}-${uuid_v4:16:4}-${uuid_v4:20:12}"
echo -n "$uuid_formatted"

View File

@@ -1,6 +0,0 @@
---
description = "A dynamic DNS service to update domain IPs"
---
To understand the possible options that can be set visit the documentation of [ddns-updater](https://github.com/qdm12/ddns-updater?tab=readme-ov-file#versioned-documentation)

View File

@@ -1,257 +0,0 @@
{
config,
pkgs,
lib,
...
}:
let
name = "dyndns";
cfg = config.clan.${name};
# We dedup secrets if they have the same provider + base domain
secret_id = opt: "${name}-${opt.provider}-${opt.domain}";
secret_path =
opt: config.clan.core.vars.generators."${secret_id opt}".files."${secret_id opt}".path;
# We check that a secret has not been set in extraSettings.
extraSettingsSafe =
opt:
if (builtins.hasAttr opt.secret_field_name opt.extraSettings) then
throw "Please do not set ${opt.secret_field_name} in extraSettings, it is automatically set by the dyndns module."
else
opt.extraSettings;
/*
We go from:
{home.example.com:{value:{domain:example.com,host:home, provider:namecheap}}}
To:
{settings: [{domain: example.com, host: home, provider: namecheap, password: dyndns-namecheap-example.com}]}
*/
service_config = {
settings = builtins.catAttrs "value" (
builtins.attrValues (
lib.mapAttrs (_: opt: {
value =
(extraSettingsSafe opt)
// {
domain = opt.domain;
provider = opt.provider;
}
// {
"${opt.secret_field_name}" = secret_id opt;
};
}) cfg.settings
)
);
};
secret_generator = _: opt: {
name = secret_id opt;
value = {
share = true;
migrateFact = "${secret_id opt}";
prompts.${secret_id opt} = {
type = "hidden";
persist = true;
};
};
};
in
{
options.clan.${name} = {
server = {
enable = lib.mkEnableOption "dyndns webserver";
domain = lib.mkOption {
type = lib.types.str;
description = "Domain to serve the webservice on";
};
port = lib.mkOption {
type = lib.types.int;
default = 54805;
description = "Port to listen on";
};
};
period = lib.mkOption {
type = lib.types.int;
default = 5;
description = "Domain update period in minutes";
};
settings = lib.mkOption {
type = lib.types.attrsOf (
lib.types.submodule (
{ ... }:
{
options = {
provider = lib.mkOption {
example = "namecheap";
type = lib.types.str;
description = "The dyndns provider to use";
};
domain = lib.mkOption {
type = lib.types.str;
example = "example.com";
description = "The top level domain to update.";
};
secret_field_name = lib.mkOption {
example = [
"password"
"api_key"
];
type = lib.types.enum [
"password"
"token"
"api_key"
"secret_api_key"
];
default = "password";
description = "The field name for the secret";
};
# TODO: Ideally we would create a gigantic list of all possible settings / types
# optimally we would have a way to generate the options from the source code
extraSettings = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = { };
description = ''
Extra settings for the provider.
Provider specific settings: https://github.com/qdm12/ddns-updater#configuration
'';
};
};
}
)
);
default = [ ];
description = "Configuration for which domains to update";
};
};
imports = [
../nginx
];
config = lib.mkMerge [
(lib.mkIf (cfg.settings != { }) {
clan.core.vars.generators = lib.mapAttrs' secret_generator cfg.settings;
users.groups.${name} = { };
users.users.${name} = {
group = name;
isSystemUser = true;
description = "User for ${name} service";
home = "/var/lib/${name}";
createHome = true;
};
services.nginx = lib.mkIf cfg.server.enable {
enable = true;
virtualHosts = {
"${cfg.server.domain}" = {
forceSSL = true;
enableACME = true;
locations."/" = {
proxyPass = "http://localhost:${toString cfg.server.port}";
};
};
};
};
systemd.services.${name} = {
path = [ ];
description = "Dynamic DNS updater";
after = [ "network.target" ];
wantedBy = [ "multi-user.target" ];
environment = {
MYCONFIG = "${builtins.toJSON service_config}";
SERVER_ENABLED = if cfg.server.enable then "yes" else "no";
PERIOD = "${toString cfg.period}m";
LISTENING_ADDRESS = ":${toString cfg.server.port}";
};
serviceConfig =
let
pyscript =
pkgs.writers.writePython3Bin "generate_secret_config.py"
{
libraries = [ ];
doCheck = false;
}
''
import json
from pathlib import Path
import os
cred_dir = Path(os.getenv("CREDENTIALS_DIRECTORY"))
config_str = os.getenv("MYCONFIG")
def get_credential(name):
secret_p = cred_dir / name
with open(secret_p, 'r') as f:
return f.read().strip()
config = json.loads(config_str)
print(f"Config: {config}")
for attrset in config["settings"]:
if "password" in attrset:
attrset['password'] = get_credential(attrset['password'])
elif "token" in attrset:
attrset['token'] = get_credential(attrset['token'])
elif "secret_api_key" in attrset:
attrset['secret_api_key'] = get_credential(attrset['secret_api_key'])
elif "api_key" in attrset:
attrset['api_key'] = get_credential(attrset['api_key'])
else:
raise ValueError(f"Missing secret field in {attrset}")
# create directory data if it does not exist
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
with open(tmp_config_path, 'w') as f:
f.write(json.dumps(config, indent=4))
# 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
for file in data_dir.iterdir():
file.chmod(0o660)
'';
in
{
ExecStartPre = lib.getExe pyscript;
ExecStart = lib.getExe pkgs.ddns-updater;
LoadCredential = lib.mapAttrsToList (_: opt: "${secret_id opt}:${secret_path opt}") cfg.settings;
User = name;
Group = name;
NoNewPrivileges = true;
PrivateTmp = true;
ProtectSystem = "strict";
ReadOnlyPaths = "/";
PrivateDevices = "yes";
ProtectKernelModules = "yes";
ProtectKernelTunables = "yes";
WorkingDirectory = "/var/lib/${name}";
ReadWritePaths = [
"/proc/self"
"/var/lib/${name}"
];
Restart = "always";
RestartSec = 60;
};
};
})
];
}

View File

@@ -1,5 +0,0 @@
---
description = "A modern IRC server"
categories = ["Social"]
features = [ "inventory", "deprecated" ]
---

View File

@@ -1,3 +0,0 @@
{
imports = [ ./roles/default.nix ];
}

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