Compare commits

..

326 Commits

Author SHA1 Message Date
pinpox
ba3d57aa63 Merge branch 'main' into update-templates-services-2 2025-07-14 08:32:59 +00:00
pinpox
6ccee60e39 Merge pull request 'Remove clanModules dependencies from admin service' (#4237) from admin-no-modules into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4237
2025-07-14 08:32:27 +00:00
pinpox
463db1537a Remove clanModules dependencies from admin service 2025-07-14 10:26:35 +02:00
Luis Hebendanz
fc4f4987ff Merge pull request 'Simplify flake.select logs, make logs readable again' (#4333) from Qubasa/clan-core:improve_log_output into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4333
2025-07-14 05:14:12 +00:00
Qubasa
e39333abed docs: Document new debug env vars in debugging.md 2025-07-14 12:11:16 +07:00
Qubasa
e407009183 clan-cli: improve log messages further
nix fmt
2025-07-14 12:02:03 +07:00
Qubasa
9ff0215781 clan-cli: Filter out flake select traces to improve debug log visibility 2025-07-14 11:51:35 +07:00
renovate[bot]
84d6400c25 chore(deps): update data-mesher digest to 309e06f 2025-07-14 00:10:13 +00:00
hsjobeki
8c583180ac Merge pull request 'deploy: add warning about disko.nix' (#4330) from docs-3 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4330
2025-07-13 19:29:52 +00:00
Johannes Kirschbauer
1bc6d8c046 deploy: add warning about disko.nix 2025-07-13 21:26:07 +02:00
hsjobeki
b2e424fa2e Merge pull request 'ui/scene: refactor simplify select animation' (#4325) from ui-scene-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4325
2025-07-13 18:56:12 +00:00
Johannes Kirschbauer
1568bb3860 ui/scene: simplify select animation 2025-07-13 20:44:12 +02:00
Johannes Kirschbauer
b549012aa1 ui/scene: rename file 2025-07-13 20:43:35 +02:00
hsjobeki
45594e118b Merge pull request 'clan_cli: move __init__.py into cli.py' (#4323) from cli into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4323
2025-07-13 16:14:21 +00:00
Johannes Kirschbauer
b36abb8fcd clan_cli: add empty __init__.py for relative imports 2025-07-13 18:03:56 +02:00
Johannes Kirschbauer
63b4813c46 clan_cli: rename references 2025-07-13 15:53:10 +02:00
Johannes Kirschbauer
3d103fdb26 clan_cli: move __init__.py into cli.py
This helps to reduce import cycles in python
If ANY python module from clan_cli is imported all the imports of the __init__.py are executed leading to a lot of cycles
2025-07-13 15:52:29 +02:00
hsjobeki
ed470ed2b1 Merge pull request 'api/services: add get_service_module_schema endpoint' (#4324) from lazy-schemas into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4324
2025-07-13 13:07:48 +00:00
Johannes Kirschbauer
4d7aad78ae api/services: add get_service_module_schema 2025-07-13 14:56:57 +02:00
Johannes Kirschbauer
5c0ac5d0cc services: add modules schema to inventoryClass 2025-07-13 14:17:57 +02:00
hsjobeki
4cc149b3c3 Merge pull request 'api/modules: remove redundant localModules' (#4322) from api-modules into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4322
2025-07-13 12:05:11 +00:00
Johannes Kirschbauer
db592a565d instances: create_service_instance init 2025-07-13 13:57:02 +02:00
Johannes Kirschbauer
84865f37b8 lib/modules: list modules consistent argument 2025-07-13 13:57:02 +02:00
Johannes Kirschbauer
21f8a69989 lib/modules: rename 'list_modules' to 'list_service_modules' 2025-07-13 13:57:02 +02:00
Johannes Kirschbauer
fb745beda5 lib/disks: move from api to templates 2025-07-13 13:57:02 +02:00
Johannes Kirschbauer
86db003973 lib/modules: move from api to services module 2025-07-13 13:57:02 +02:00
Johannes Kirschbauer
d9368ec01c api/modules: remove redundant localModules 2025-07-13 11:52:19 +02:00
hsjobeki
f6bf1481f5 Merge pull request 'docs/getting-started: seperate step to add a user' (#4321) from docs-users into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4321
2025-07-13 09:37:17 +00:00
Johannes Kirschbauer
0ac0b422e6 docs/users: add explanation for groups 2025-07-13 11:33:22 +02:00
Johannes Kirschbauer
2ecb9a533d docs/getting-started: seperate step to add a user 2025-07-13 11:31:14 +02:00
Michael Hoang
379d675372 Merge pull request 'users: fix eval when used to manage root' (#4319) from push-qnllumxpxumt into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4319
2025-07-13 02:35:35 +00:00
Michael Hoang
10f89d6612 users: fix eval when used to manage root 2025-07-13 12:30:16 +10:00
hsjobeki
cde9df1536 Merge pull request 'docs/deploy: remove unneeded --update-hardware-config nixos-facter' (#4318) from templates-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4318
2025-07-12 15:51:13 +00:00
Johannes Kirschbauer
8c1587e400 docs/deploy: remove unneeded --update-hardware-config nixos-facter 2025-07-12 17:48:13 +02:00
hsjobeki
e88b05dd9c Merge pull request 'Templates/cli: improve ux and docs' (#4317) from templates-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4317
2025-07-12 15:31:55 +00:00
Johannes Kirschbauer
318cc4b1ec Templates/cli: improve ux and docs 2025-07-12 17:21:23 +02:00
hsjobeki
6ff2e8de94 Merge pull request 'Templates: remove deprecated files' (#4316) from templates-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4316
2025-07-12 15:11:32 +00:00
hsjobeki
346e56191a Merge pull request 'pkgs/clan(templates): Fix template help' (#4315) from ke-fix-template-help into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4315
2025-07-12 15:06:31 +00:00
Johannes Kirschbauer
696e4b984f Templates/flake-parts: remove machines
Users create machines if they need them
2025-07-12 16:59:16 +02:00
Johannes Kirschbauer
de1d0c8747 Templates: remove disko.nix from all templates 2025-07-12 16:58:52 +02:00
Johannes Kirschbauer
86ea1b0a60 Templates: remove shared.nix
- user-password is now part of the new 'users' module (https://docs.clan.lol/reference/clanServices/users/)
- setting 'users.users.user' is not needed and also part of the 'users' module
- services.avahi.enable = true; is not strictly needed can become part of an mdns guide, but shouldnt be part of the default template
2025-07-12 16:58:02 +02:00
hsjobeki
241550921f Merge pull request 'docs/getting-started: refactor and align with new templates' (#4313) from getting-started into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4313
2025-07-12 14:43:29 +00:00
a-kenji
f69dd29f79 pkgs/clan(templates): Fix template help
Currently the template help has the following interface:

```
usage: clan [-h] [SUBCOMMAND]

The clan cli tool

positional arguments:
  {show,backups,b,flakes,f,templates,flash,ssh,secrets,facts,vars,va,machines,m,vms,select,se,state,st}
    show                Show meta information about the clan
    backups (b)         Manage backups of clan machines
    flakes (f)          Create a clan flake inside the current directory
    templates           Subcommands to interact with templates
    flash               Flashes your machine to an USB drive
    ssh                 Ssh to a remote machine
    secrets             Manage secrets
    facts               Manage facts
    vars (va)           Manage vars
    machines (m)        Manage machines and their configuration
    vms                 Manage virtual machines
    select (se)         Select nixos values from the flake
    state (st)          Query state information about machines

options:
  -h, --help            show this help message and exit

Online reference for the clan cli tool: ]8;;https://docs.clan.lol/reference/cli\https://docs.clan.lol/reference/cli]8;;\
For more detailed information, visit: ]8;;https://docs.clan.lol\https://docs.clan.lol]8;;\
```
2025-07-12 16:42:05 +02:00
hsjobeki
648f3ec084 Merge pull request 'pkgs/clan(templates): Add machine completions' (#4312) from ke-templates-machines-add-shell-completions into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4312
2025-07-12 14:40:57 +00:00
Johannes Kirschbauer
f362cfb983 Docs: fix code annotations 2025-07-12 16:40:02 +02:00
Johannes Kirschbauer
66ddc399d0 Docs: fix typos 2025-07-12 16:39:20 +02:00
Johannes Kirschbauer
20a6375c2a Docs: align workflow, remove targetHost before deployment 2025-07-12 16:35:43 +02:00
Johannes Kirschbauer
2882e9e8da Docs: rewrite deployment instructions 2025-07-12 16:35:43 +02:00
Johannes Kirschbauer
2c910f8616 docs: add guide how to create configuration.nix 2025-07-12 16:35:43 +02:00
Johannes Kirschbauer
5e80e0a833 docs: add service update instructions 2025-07-12 16:35:43 +02:00
Johannes Kirschbauer
055cf3d924 docs: add machines update instructions 2025-07-12 16:35:43 +02:00
Johannes Kirschbauer
3d8ddd1be1 docs: create clan update cli instructions 2025-07-12 16:35:41 +02:00
a-kenji
71ee2fcbb6 pkgs/clan(templates): Add machine completions
Add machine completions for the `--to-machine` subcommand
2025-07-12 16:02:51 +02:00
hsjobeki
279df893cc Merge pull request 'cli/create: add interactive name method' (#4310) from getting-started into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4310
2025-07-12 13:27:38 +00:00
Johannes Kirschbauer
ed2663ac7b clan/create: rename path to name argument 2025-07-12 15:16:31 +02:00
Johannes Kirschbauer
c4f67ca44d templates/copy: fix use shutil to copy hidden dot files 2025-07-12 15:08:40 +02:00
kenji
5f8d65bd80 Merge pull request 'pkgs/clan: Fix command typos' (#4309) from kenji/ke-fix-command-typos into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4309
2025-07-12 12:49:57 +00:00
Johannes Kirschbauer
98185217bd templates: add example how to add inventory.machines 2025-07-12 14:49:27 +02:00
Johannes Kirschbauer
876e57e81e cli/create: add interactive name method 2025-07-12 14:12:10 +02:00
hsjobeki
d601237853 Merge pull request 'modules/user: Improve user module' (#4305) from user into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4305
2025-07-12 11:57:44 +00:00
a-kenji
2439d508ef pkgs/clan: Fix command typos 2025-07-12 13:54:37 +02:00
Johannes Kirschbauer
0dd5b284eb Users: add option for regularUser 2025-07-12 13:44:16 +02:00
hsjobeki
a47d65d3ed Merge pull request 'diskId: add migration docs and a big fat warning' (#4307) from disk-migration into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4307
2025-07-12 11:15:51 +00:00
hsjobeki
5484b584f1 Merge pull request 'cli/templates: init apply disk' (#4306) from templates-cli into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4306
2025-07-12 11:15:47 +00:00
Johannes Kirschbauer
461c628a98 diskId: add migration docs and a big fat warning 2025-07-11 20:47:53 +02:00
Johannes Kirschbauer
70454878ff cli/templates: init apply disk 2025-07-11 18:53:54 +02:00
Johannes Kirschbauer
7b6e63d6ca lib/disks: add parameter to disable hardware checking 2025-07-11 18:53:54 +02:00
Johannes Kirschbauer
67eb2274ab cli/machine/hardware: improve error message 2025-07-11 18:53:54 +02:00
Johannes Kirschbauer
794872e235 get_machine: fix error message for not existing machine 2025-07-11 18:53:54 +02:00
Johannes Kirschbauer
7765e7155e lib/copy: fix, copying the content of tempate directory, not the directory itself 2025-07-11 18:53:54 +02:00
Johannes Kirschbauer
3871cb7ab4 Templates: keep clan.nix in sync between default and flake-parts 2025-07-11 16:42:20 +02:00
Johannes Kirschbauer
a4131a0822 Modules/users: add isNormalUser true
NormalUsers get:
- Home directory
- Can login

This is expected for users created through this module. We can make it configurable if the use arises
2025-07-11 16:32:16 +02:00
hsjobeki
02111109f8 Merge pull request 'Vars/helper: remove unneeded wrapper arount collectFiles' (#4304) from vars-angnostic into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4304
2025-07-11 14:31:20 +00:00
Johannes Kirschbauer
3e489d5cff Templates/flake-parts: consistent default clan 2025-07-11 16:19:01 +02:00
Johannes Kirschbauer
2f027cad3c Vars/helper: remove unneeded wrapper arount collectFiles 2025-07-11 16:14:02 +02:00
hsjobeki
16d70c6441 Merge pull request 'templates/flake-parts: remove importing clanModules' (#4300) from templates-2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4300
2025-07-11 13:53:37 +00:00
Johannes Kirschbauer
40bf79e5c6 Template/docs: improve gnome example 2025-07-11 14:56:40 +02:00
Johannes Kirschbauer
c9dc21fb72 Templates/minimal: move name to flake.nix 2025-07-11 14:53:41 +02:00
hsjobeki
9830e711fd Merge pull request 'modules/user: add extraGroups setting with default' (#4301) from user-groups into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4301
2025-07-11 12:51:58 +00:00
hsjobeki
9ab5afb9b9 Merge pull request 'modules: add explicit class constraints' (#4303) from module-classes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4303
2025-07-11 12:51:29 +00:00
Johannes Kirschbauer
b22668629d modules: add explicit class constraints 2025-07-11 14:38:59 +02:00
Johannes Kirschbauer
400c51cdf3 modules/user: improce description, drop default groups 2025-07-11 14:35:28 +02:00
Johannes Kirschbauer
e9275de8d7 modules/user: add extraGroups setting with default 2025-07-11 09:13:59 +02:00
Johannes Kirschbauer
30fbe76e8d templates: remove duplicate logic, update gnome template 2025-07-11 08:57:06 +02:00
Johannes Kirschbauer
c44bf846de templates/flake-parts: remove importing clanModules 2025-07-11 08:46:21 +02:00
Johannes Kirschbauer
cff445229d docs: fix user module prompt description 2025-07-11 08:46:21 +02:00
hsjobeki
2895c18bba Merge pull request 'Docs: improve api docs of {open_file, open_clan_folder}' (#4299) from open-clan into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4299
2025-07-10 16:54:35 +00:00
Johannes Kirschbauer
34abd4b8ce openapi: remove verb {open}, noun {file} 2025-07-10 18:44:34 +02:00
Johannes Kirschbauer
1449ff622f API: rename {open_file, open_clan_folder} into {get_system_file, get_clan_folder} 2025-07-10 18:42:03 +02:00
Johannes Kirschbauer
4d25f29ce7 Docs: improve api docs of {open_file, open_clan_folder} 2025-07-10 18:40:48 +02:00
hsjobeki
fccae71ebb Merge pull request 'UI/App: improve cube scene' (#4298) from ui-scene into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4298
2025-07-10 16:27:49 +00:00
Johannes Kirschbauer
3a1c36e7b0 UI/Cubes: init circle positioning 2025-07-10 18:23:32 +02:00
Johannes Kirschbauer
c12a6cad27 UI/qubescene: add create animation 2025-07-10 17:00:36 +02:00
Johannes Kirschbauer
63ad20b157 UI/qubescene: add delete and reposition animation 2025-07-10 16:53:49 +02:00
Johannes Kirschbauer
d3def537b4 UI/qubescene: dynamically recalculate the positions 2025-07-10 16:49:14 +02:00
Johannes Kirschbauer
456150744d UI/cubescene: init delete cube 2025-07-10 16:45:49 +02:00
pinpox
5528a1af3f Merge pull request 'Add example for data-mesher service usage' (#4297) from data-mesher-docs into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4297
2025-07-10 10:59:12 +00:00
pinpox
8874e0311d Add example for data-mesher service usage 2025-07-10 12:54:04 +02:00
pinpox
c42de173b3 Merge pull request 'Migrate data-mesher to clan service' (#4240) from migrate-data-mesher-services into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4240
Reviewed-by: brianmcgee <brian@bmcgee.ie>
2025-07-10 10:35:48 +00:00
Luis Hebendanz
4d554cad6a Merge pull request 'impl_non_blocking_http' (#4296) from Qubasa/clan-core:impl_non_blocking_http into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4296
2025-07-10 10:32:03 +00:00
pinpox
58a06d2261 Migrate data-mesher to clan service 2025-07-10 12:30:29 +02:00
Qubasa
7e6d94795b clan-app: Make http server non blocking, add tests for the http server and for cancelling tasks 2025-07-10 17:21:18 +07:00
Qubasa
5142794fa3 stash 2025-07-10 16:09:08 +07:00
Qubasa
335f1c7e4c clan-app: Working swagger requests 2025-07-10 16:09:08 +07:00
Luis Hebendanz
4de2df7c86 Merge pull request 'Add check_valid_clan and open_clan_folder api requests' (#4295) from Qubasa/clan-core:impl_open_clan into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4295
2025-07-10 08:14:12 +00:00
Qubasa
3d26214009 clan-lib: Fix @API.register_abstract not throwing correct error when called directly without implementation
clan-app: Fix mypy lint

clan-lib: Mark test as with_core
2025-07-10 15:09:51 +07:00
Qubasa
dd12104e2f clan_lib: Add test for check_valid_clan function 2025-07-10 14:20:02 +07:00
Qubasa
f8ecd4372e clan-app: Implement open_clan_folder api request 2025-07-10 14:19:19 +07:00
Qubasa
0a8c7d9e10 clan-app: Moved thread handling up to the ApiBridge 2025-07-10 12:02:30 +07:00
Michael Hoang
d9e034d878 Merge pull request 'docs: set manifest.readme for services to include README in the docs' (#4294) from push-rlukssmkxtky into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4294
2025-07-10 03:00:36 +00:00
Michael Hoang
230f3ad36c docs: set manifest.readme for services to include README in the docs 2025-07-10 12:55:27 +10:00
renovate[bot]
a18cd40525 chore(deps): update disko digest to 7926429 2025-07-10 02:30:12 +00:00
kenji
1cb1c53dfd Merge pull request 'pkgs/clan: Fix template listing' (#4291) from kenji/ke-template-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4291
2025-07-09 17:40:01 +00:00
a-kenji
2281e61232 pkgs/clan: Fix template listing 2025-07-09 19:29:15 +02:00
hsjobeki
9300fd9dc7 Merge pull request 'refactor: move docs transformOptions to clanLib to reduce rebuilds' (#4259) from self into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4259
2025-07-09 15:31:25 +00:00
hsjobeki
6ad5d8d28c Merge pull request 'openapi: add strict top-level checking' (#4280) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4280
2025-07-09 15:24:45 +00:00
Johannes Kirschbauer
dd1429c89f Docs: fix rendering clan source code url 2025-07-09 17:24:20 +02:00
Jörg Thalheim
8d4099d13d refactor: move docs transformOptions to clanLib to reduce rebuilds
- Add clanLib.docs.stripStorePathsFromDeclarations to deduplicate code
- Update all documentation generation to use the shared function
- This strips store paths from option declarations to prevent options.json
  from rebuilding when only store paths change but content remains the same
- Reduces unnecessary documentation rebuilds when making unrelated changes
2025-07-09 16:59:58 +02:00
Johannes Kirschbauer
e3a882002c openapi: add strict top-level checking 2025-07-09 16:57:06 +02:00
Johannes Kirschbauer
150e070a09 api: rename {list_system_services_mdns, list_system_storage_devices} 2025-07-09 16:51:42 +02:00
lassulus
cf3e5befda Merge pull request 'feat: implement macOS sandboxing for vars generation using sandbox-exec' (#4228) from darwin-sandbox into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4228
2025-07-09 14:37:24 +00:00
Jörg Thalheim
b53ff99248 sandbox_exec: refactor to use context manager for cleanup
Changed sandbox_exec_cmd to return a context manager that automatically
handles profile file cleanup. This ensures the temporary profile is
always removed, even if exceptions occur.
2025-07-09 16:27:04 +02:00
Mic92
0f1b816844 Merge pull request 'bump flake.lock' (#4290) from flakes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4290
2025-07-09 12:53:20 +00:00
Jörg Thalheim
9f1eabd3e1 bump flake.lock 2025-07-09 14:38:23 +02:00
Luis Hebendanz
74489d399a Merge pull request 'clan-app: init clan http api' (#4278) from Qubasa/clan-core:add_middleware_tests into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4278
2025-07-09 11:53:10 +00:00
lassulus
7c11ed1d8d clan-cli: implement macOS sandboxing for vars generation using sandbox-exec
Adds macOS sandboxing support similar to Linux bubblewrap implementation:
- Created clan_lib/sandbox_exec module with sandbox profile creation
- Implemented file system isolation allowing only tmpdir and nix store access
- Added network restrictions (deny outbound except localhost)
- Integrated sandbox-exec command into vars generation on macOS
- Added comprehensive test suite for macOS sandbox functionality
- Fixed working directory handling for generators writing to CWD
2025-07-09 13:51:18 +02:00
Mic92
ac7e082ce4 Merge pull request 'generate_test_vars: fix it' (#4289) from generate_test_vars-fix-it into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4289
2025-07-09 11:49:06 +00:00
Qubasa
c76f7bb020 clan-app: Add swagger redirect 2025-07-09 18:48:00 +07:00
Qubasa
317cd7b5f5 clan-app: Cleaned up http code 2025-07-09 18:45:42 +07:00
Qubasa
3fbf34044a clan-app: Working swagger 2025-07-09 18:34:58 +07:00
kenji
ab7d4409f6 Merge pull request 'pkgs/clan: Fix state list and add regression tests' (#4284) from kenji/ke-test-state-list into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4284
2025-07-09 11:33:59 +00:00
a-kenji
65778cb9fe pkgs/clan: Fix state list and add regression tests
Fix the `clan state list` subcommands, it now correctly propagates the
flake argument.
Also adds regression tests.
2025-07-09 13:22:21 +02:00
Mic92
8180745c50 Merge pull request 'fix build host with sudo' (#4267) from fix-sudo into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4267
2025-07-09 10:03:01 +00:00
Qubasa
4008d2c165 clan-app: Better http architecture 2025-07-09 16:40:49 +07:00
Qubasa
1c269d1eaa clan-app: init clan http api
clan-app: nix fmt
2025-07-09 16:40:49 +07:00
DavHau
84a21d1bab generate_test_vars: fix it 2025-07-09 16:20:37 +07:00
kenji
28d5294292 Merge pull request 'pkgs/clan: Add test for clan flash list' (#4281) from kenji/ke-test-flash into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4281
2025-07-09 09:08:34 +00:00
a-kenji
3a52189ed6 pkgs/clan: Add test for clan flash list
Add a test for `clan flash list`.
This tests the basic functionality, as well as that listing actually
works.
2025-07-09 11:02:24 +02:00
kenji
5c33e02e24 Merge pull request 'pkgs/clan: Add test for clan templates list' (#4282) from kenji/ke-test-templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4282
2025-07-09 08:37:26 +00:00
a-kenji
2aa2145876 pkgs/clan: Add test for clan templates list
Add a test for clan templates list.
This tests the basic functionality, as well as that listing actually
works.
2025-07-09 10:29:29 +02:00
hsjobeki
fa517e1149 Merge pull request 'openapi: improve spec compat with swagger.io' (#4279) from openapi into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4279
2025-07-09 07:52:49 +00:00
Johannes Kirschbauer
6855ab859d api: rename run_blocking_task into run_task_blocking 2025-07-09 09:43:56 +02:00
Johannes Kirschbauer
3828a0cf49 openapi: improve spec compat with swagger.io 2025-07-09 09:40:06 +02:00
hsjobeki
75501a914b Merge pull request 'API Improvements' (#4276) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4276
2025-07-08 21:17:12 +00:00
Johannes Kirschbauer
c9b8bdd6de api/docs: sort resources into tree order 2025-07-08 23:06:20 +02:00
hsjobeki
5a4a7e9158 Merge pull request 'UI: init cubes scene' (#4277) from ui-scene into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4277
2025-07-08 20:40:42 +00:00
Johannes Kirschbauer
83ad0ae836 UI: fix lint 2025-07-08 22:36:14 +02:00
Johannes Kirschbauer
57163cf135 UI: Cubes improve memory usage 2025-07-08 22:33:52 +02:00
Johannes Kirschbauer
13185d005d UI: dispay selected cube base 2025-07-08 22:14:44 +02:00
Johannes Kirschbauer
18a6b57673 UI: Init CubesScene
UI: init cube base scene
2025-07-08 22:14:42 +02:00
kenji
31f2c5106d Merge pull request 'refactor: decouple vars stores from machine instances' (#4269) from davhau/vars-new into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4269
2025-07-08 18:11:03 +00:00
Johannes Kirschbauer
4dfd151cd2 api: rename 'run_machine_deploy' into 'run_machine_update' 2025-07-08 17:21:18 +02:00
Johannes Kirschbauer
8ddd2b607e api/disk_schema: make getter consistent 2025-07-08 17:20:59 +02:00
hsjobeki
b4544b824a Merge pull request 'api/disk_schema: rename getter consistent' (#4274) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4274
2025-07-08 14:43:29 +00:00
hsjobeki
50122c2215 Merge pull request 'docs: disable footer navigation' (#4275) from docs-1 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4275
2025-07-08 14:42:36 +00:00
Johannes Kirschbauer
c65b35edc1 docs: disable footer navigation
This gives the content more space
Especially for plugins (options, developer tabs)
2025-07-08 16:38:33 +02:00
Johannes Kirschbauer
2eb6ee2264 api/disk_schema: make getter consistent 2025-07-08 16:31:51 +02:00
hsjobeki
ec1363aedf Merge pull request 'UI: remove 2d-ui, its broken now since we deleted the symlinked files in #4266' (#4273) from ui-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4273
2025-07-08 14:28:56 +00:00
Johannes Kirschbauer
90495d4157 UI: remove 2d-ui, its broken now since we deleted the symlinked files in #4266 2025-07-08 16:23:30 +02:00
kenji
b8fa4b4677 Merge pull request 'pkgs/cli: Add regression test for clan show' (#4272) from kenji/ke-test-add-show into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4272
2025-07-08 14:01:02 +00:00
a-kenji
ec8effcd46 pkgs/cli: Add regression test for clan show 2025-07-08 15:55:01 +02:00
hsjobeki
09b8e2f49c Merge pull request 'Templates/default: move clan configuration into its own file' (#4262) from templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4262
2025-07-08 13:46:19 +00:00
Johannes Kirschbauer
7fefc8e3b2 Tests: dont expect a hardware-configuration.nix file 2025-07-08 15:34:16 +02:00
Johannes Kirschbauer
62cadb8fbe Docs: mention clan.nix file, which is present in the default template now 2025-07-08 14:58:24 +02:00
Johannes Kirschbauer
f8748d021b tests: dont expect .clan-flake file, it is not strictly required 2025-07-08 14:58:24 +02:00
Jörg Thalheim
f9740909e9 checks/nixos-test-flash: increase ram to workaround gc bug in nix 2025-07-08 14:25:44 +02:00
Jörg Thalheim
b42395234d fix build host with sudo 2025-07-08 14:25:44 +02:00
kenji
b84df095a2 Merge pull request 'templates(minimal): Add .envrc' (#4268) from kenji/ke-template into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4268
2025-07-08 11:58:36 +00:00
DavHau
dbd48a54a3 refactor: decouple vars stores from machine instances
Stores now get machine context from generator objects instead of storing
it internally. This enables future machine-independent generators and
reduces coupling.

- StoreBase.__init__ only takes flake parameter
- Store methods receive machine as explicit parameter
- Fixed all callers to pass machine context
2025-07-08 18:30:16 +07:00
Luis Hebendanz
3b2f0e2029 Merge pull request 'Add middleware interface to clan-app' (#4265) from Qubasa/clan-core:generalize_webview into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4265
2025-07-08 11:16:36 +00:00
Qubasa
639d227055 clan-app: Fix delete tasks
clan-app: Fix delete tasks
2025-07-08 18:11:59 +07:00
a-kenji
7ac4d257d9 templates(minimal): Add .envrc
Add .envrc also to the minimal template to homogenize our templates.
2025-07-08 13:09:04 +02:00
brianmcgee
e45e809553 Merge pull request 'prep-ui-version2' (#4266) from prep-ui-version2 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4266
2025-07-08 10:57:54 +00:00
Qubasa
48c7613556 clan-cli: Add verb 'cancel' to openapi 2025-07-08 17:43:14 +07:00
Brian McGee
fe89d954da fix(ui): display required asterisk in label 2025-07-08 11:41:34 +01:00
Brian McGee
b8604d334b feat(ui): prep V2
Preparation for rebuilding the UI with V2 components.
2025-07-08 11:41:33 +01:00
Qubasa
50cbe3c825 clan-app: Move json.loads to try catch 2025-07-08 17:38:24 +07:00
Qubasa
acab3b8905 clan-app: Ignore ruff errors 2025-07-08 17:32:59 +07:00
Qubasa
eb6166796c clan-app: Generalize architecture for API requests 2025-07-08 17:32:59 +07:00
Qubasa
6d8fd42faa clan-app: Add plug and play middleware interface 2025-07-08 17:32:59 +07:00
Qubasa
494830326d clan-app: Add plug and play middleware interface 2025-07-08 17:32:59 +07:00
Luis Hebendanz
edfad04305 Merge pull request 'fix_ruff_regression' (#4264) from Qubasa/clan-core:fix_ruff_regression into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4264
2025-07-08 10:30:45 +00:00
Qubasa
81d3437ff7 clan-cli: Fix Ruff linting errors
clan-cli: Ruff fixes

ignore noqa lint

fix more ruff issues
2025-07-08 17:25:02 +07:00
Qubasa
d656167cf2 ruff: Ignore TRY301 'raise-within-try' as there are legitimate reasons to do this 2025-07-08 17:23:32 +07:00
Qubasa
49e83954c5 clan-cli: Fix regression in ruff linter, where linter rules got overriden by local pyproject.toml
clan-app: Fix ruff regression where linter rules got overriden by local pyproject.toml
2025-07-08 17:23:32 +07:00
Johannes Kirschbauer
8d1e0353f8 test: don't expect a machines folder 2025-07-08 11:53:20 +02:00
Johannes Kirschbauer
05658589a0 Docs: execute 'clan show' as first step 2025-07-08 10:24:01 +02:00
Johannes Kirschbauer
809a115e58 clan/show: fix cli command 2025-07-08 10:15:35 +02:00
Johannes Kirschbauer
79d8d0707b Templates/default/modules/gnome: Add doc-comment - what the module does, how to use it 2025-07-08 10:06:22 +02:00
Johannes Kirschbauer
b2179c9293 Templates/default: remove predefined machines 2025-07-08 10:05:35 +02:00
Johannes Kirschbauer
e33af96705 Templates/default: move clan configuration into its own file
Doing this with the idea in mind, that flake-parts / default should define the same clan in clan.nix
We can add a CI check to ensure both are the same files
They got desynced in the past and describe completely different clans now
2025-07-08 10:04:17 +02:00
Johannes Kirschbauer
14a221d1d1 Docs: remove 'replaces' sentence; it is not describing any purpose 2025-07-08 10:01:51 +02:00
brianmcgee
9f9ab3de19 Merge pull request 'feat(ui): SidebarPane component' (#4248) from ui/sidebar-pane into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4248
2025-07-08 07:37:47 +00:00
hsjobeki
9739a5ae2b Merge pull request 'templates: rename 'new_clan' to default' (#4244) from templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4244
2025-07-08 07:31:22 +00:00
Mic92
54446d751f Merge pull request 'checks/backup: no longer depend on self' (#4258) from self into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4258
2025-07-07 19:57:30 +00:00
Jörg Thalheim
7bc8e091a5 checks/backup: no longer depend on self 2025-07-07 21:51:51 +02:00
Mic92
3462d458ac Merge pull request 'override-inputs: filter out self' (#4257) from improve-perf into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4257
2025-07-07 19:32:51 +00:00
Jörg Thalheim
bd42d67b0c override-inputs: filter out self 2025-07-07 21:25:33 +02:00
Mic92
d99ca36f9f Merge pull request 'checks/eval-module-clan-vars: optimize to use filtered source' (#4255) from borgbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4255
2025-07-07 19:02:25 +00:00
Jörg Thalheim
57f9cd9eee checks/eval-module-clan-vars: optimize to use filtered source
- Replace self.filter with lib.fileset for more precise filtering
- Remove unnecessary clan-core dependency from the test
- Test only needs lib and pkgs, not the full flake context
- Prevents unnecessary rebuilds when unrelated files change
2025-07-07 20:55:04 +02:00
Mic92
a9ec94b0df Merge pull request 'checks/inventory: optimize eval tests to use filtered sources' (#4254) from borgbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4254
2025-07-07 18:48:58 +00:00
Jörg Thalheim
c64dbceceb checks/inventory: optimize eval tests to use filtered sources
Replace full flake source (self) with minimal filtered filesets to prevent
unnecessary rebuilds when unrelated files change. All three inventory eval
tests now use the same unified fileset containing only necessary files.

This follows the same optimization pattern applied to other eval tests,
significantly reducing rebuild frequency during development.
2025-07-07 20:41:20 +02:00
Mic92
5d924e0c98 Merge pull request 'docs: no longer depend on self' (#4253) from borgbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4253
2025-07-07 18:31:35 +00:00
Jörg Thalheim
6a6688019b docs: no longer depend on self 2025-07-07 20:24:11 +02:00
Mic92
f33172fa73 Merge pull request 'don't rebuild eval tests on each ci run' (#4252) from borgbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4252
2025-07-07 18:13:57 +00:00
Jörg Thalheim
00914311a4 don't rebuild eval tests on each ci run 2025-07-07 20:05:45 +02:00
Mic92
ceeb40d9ac Merge pull request 'checks/borgbackup: don't rebuild on every pull request' (#4251) from borgbackup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4251
2025-07-07 17:44:16 +00:00
Jörg Thalheim
afab33056e checks/borgbackup: don't rebuild on every pull request 2025-07-07 19:35:48 +02:00
Mic92
a5183f4b4c Merge pull request 'avoid shebang in update-private-flake-inputs' (#4250) from fix-devflake-tryeval into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4250
2025-07-07 16:56:21 +00:00
Jörg Thalheim
a686d7523b avoid shebang in update-private-flake-inputs 2025-07-07 18:48:11 +02:00
Mic92
56b784992d Merge pull request 'devFlake: don't load if sources have been filtered out' (#4249) from fix-devflake-tryeval into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4249
2025-07-07 16:47:27 +00:00
Jörg Thalheim
5f723dc376 devFlake: don't load if sources have been filtered out 2025-07-07 18:38:01 +02:00
Brian McGee
1609989734 feat(ui): SidebarPane component
* implement Divider component using Kobalte's Separator
* refine read only state of form components to match the Sidebar Pane design
* introduce a SidebarPane component with sections that can toggle between editing and view states.
2025-07-07 17:31:58 +01:00
Mic92
0c07d5cfe0 Merge pull request 'add dev flake pattern' (#4245) from private-flake into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4245
2025-07-07 16:02:29 +00:00
Jörg Thalheim
9c37ef4cbe add dev flake pattern
This allows us to have dev dependencies which are not propagated to the user.
2025-07-07 15:59:09 +00:00
Jörg Thalheim
783b6a8b06 add gitea action to update private flake inputs 2025-07-07 15:59:09 +00:00
Jörg Thalheim
4f13049ee2 put flake input overrides into a helper function 2025-07-07 15:59:09 +00:00
Johannes Kirschbauer
2f4f303048 create/clan: do initial commit 2025-07-07 15:50:00 +00:00
Johannes Kirschbauer
d02868b950 templates: add .gitignore files to all templates 2025-07-07 15:50:00 +00:00
Johannes Kirschbauer
4f7d82671f Templates: remove 'minimal-flake-parts' 2025-07-07 15:50:00 +00:00
Johannes Kirschbauer
0dce3fc7ec templates: rename 'new_clan' to default 2025-07-07 15:50:00 +00:00
brianmcgee
a635f9c6fe Merge pull request 'ui: Modal component' (#4241) from feat/modal into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4241
2025-07-07 15:16:50 +00:00
Mic92
a8ed1c30e4 Merge pull request 'make treefmt work with git-worktrees' (#4246) from pytest into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4246
2025-07-07 15:07:53 +00:00
Jörg Thalheim
c0c41d52bd make treefmt work with git-worktrees 2025-07-07 16:55:36 +02:00
hsjobeki
bb236bb543 Merge pull request 'Docs: add missing documentation to api functions' (#4243) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4243
2025-07-07 14:02:08 +00:00
Johannes Kirschbauer
d7cf79faa7 openapi: error on missing api function docstring 2025-07-07 15:48:36 +02:00
Johannes Kirschbauer
dab11cb020 docs/api: add docstrings to {list_mdns_services, set_clan_details} 2025-07-07 15:47:14 +02:00
Johannes Kirschbauer
f2cb6fef41 api: remove unused get_directory 2025-07-07 15:45:51 +02:00
Johannes Kirschbauer
655b87ad04 docs/api: add docstrings to {run_machine_install,run_machine_deploy} 2025-07-07 15:41:02 +02:00
Johannes Kirschbauer
d462ae501e docs/api: add docstrings to {check_machine_ssh_login} 2025-07-07 15:38:09 +02:00
Johannes Kirschbauer
59a8c402ba docs/api: add docstrings to {delete_machine} 2025-07-07 15:36:16 +02:00
Johannes Kirschbauer
3b309ea74b docs/api: add docstrings to {get_flash_options, run_machine_flash} 2025-07-07 15:34:49 +02:00
Johannes Kirschbauer
508cd3c784 docs/api: add docstrings to {get_clan_details} 2025-07-07 15:31:06 +02:00
Johannes Kirschbauer
2bff7403df docs/api: add docstrings to {create_clan} 2025-07-07 15:29:19 +02:00
Johannes Kirschbauer
b5a6e809d0 docs/api: add docstrings to {get_generators, run_generators} 2025-07-07 15:22:44 +02:00
Johannes Kirschbauer
ec28c5c307 api/machines: document {get_machine,get_machine_details} 2025-07-07 15:13:23 +02:00
hsjobeki
10f9e5d11b Merge pull request 'api/generators: remove term 'vars' interact purely with 'generators'' (#4242) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4242
2025-07-07 13:04:00 +00:00
Johannes Kirschbauer
b8ba8b79ca api/check_machine_ssh_reachable: add function docs 2025-07-07 15:02:35 +02:00
Johannes Kirschbauer
fd07d02d2d openapi: warn on missing description 2025-07-07 14:52:49 +02:00
Johannes Kirschbauer
2a3d1efc6f api: expose docstring as function description 2025-07-07 14:51:15 +02:00
Johannes Kirschbauer
947e0a5488 openapi: add strict verb checking 2025-07-07 14:35:56 +02:00
Mic92
57b5520143 Merge pull request 'Add missing f to f-string' (#4234) from jfly/clan-core:oops-f-string into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4234
2025-07-07 12:30:20 +00:00
Mic92
9fd1031f4d Merge pull request 'Fix bug? member_id -> member_ip' (#4235) from jfly/clan-core:possible-fix into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4235
2025-07-07 12:30:08 +00:00
Johannes Kirschbauer
c382e8f1f3 api/tasks: rename 'cancel_task' into 'delete_task' 2025-07-07 14:07:53 +02:00
Johannes Kirschbauer
cf92303f31 api/hw: rename 'describe_machine_hardware' into 'get_machine_hardware_summary' 2025-07-07 14:05:57 +02:00
Johannes Kirschbauer
80d0dc9805 api/hw: rename generate_machine_hardware_info into 'run' 2025-07-07 14:04:39 +02:00
Johannes Kirschbauer
4e2cbb188c api/generators: remove term 'vars' interact purely with 'generators' 2025-07-07 13:59:12 +02:00
Brian McGee
eb6460fb40 feat(ui): update playwright to match version in nixpkgs 2025-07-07 12:51:22 +01:00
hsjobeki
155bd36d2b Merge pull request 'api/tasks: prefix impure actions with run' (#4239) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4239
2025-07-07 11:28:07 +00:00
Johannes Kirschbauer
40ea5bf591 api/machine checks: rename, add checkResult 2025-07-07 13:13:00 +02:00
hsjobeki
0cd9c84de0 Merge pull request 'machine/host: degrade into info and add docs' (#4238) from host-info into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4238
Reviewed-by: Luis Hebendanz <consulting@qube.email>
2025-07-07 11:10:05 +00:00
Johannes Kirschbauer
e1ea44a2cc api/clan: rename 'update_clan_meta' -> 'set_clan_details' 2025-07-07 12:51:32 +02:00
Johannes Kirschbauer
7c4865e8b0 api/keygen: add todo comment 2025-07-07 12:49:37 +02:00
Johannes Kirschbauer
b032cd4a29 api/admin: remove maybe_get_admin_public_keys 2025-07-07 12:43:11 +02:00
DavHau
61edc1e06f Refactor StoreBase to take machine name string instead of Machine object
- Updated StoreBase.__init__ to accept machine: str and flake: Flake
- Modified all StoreBase subclasses (in_repo, vm, fs, sops, password_store) to match new signature
- Added select_machine method to Flake class for machine-specific attribute selection
- Updated Machine.select to use the new Flake.select_machine method
- Fixed all test cases to pass machine name and flake to store constructors
- Maintained backward compatibility by keeping the same external API

This reduces coupling between the store system and the Machine class,
making the architecture more modular and flexible.
2025-07-07 10:24:11 +00:00
Johannes Kirschbauer
c369f3b5d1 api/tasks: prefix impure actions with run 2025-07-07 12:09:43 +02:00
hsjobeki
0cc1f072f7 Merge pull request 'api/clan: rename 'show_clan_meta' -> 'get_clan_details'' (#4236) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4236
2025-07-07 10:00:10 +00:00
Johannes Kirschbauer
a2a011a47f machine/host: degrade into info and add docs 2025-07-07 11:52:46 +02:00
Brian McGee
e1796e19e4 feat(ui): refine Fieldset API 2025-07-07 10:51:43 +01:00
Johannes Kirschbauer
972adc7a7c api: chore rename outdated reference 2025-07-07 10:53:32 +02:00
Johannes Kirschbauer
e1b4f296e3 api: rename 'show_mdns' -> 'list_mdns_services' 2025-07-07 10:49:46 +02:00
Johannes Kirschbauer
1cb2156d87 api: rename to get_flash_options 2025-07-07 10:48:14 +02:00
Johannes Kirschbauer
84703fa293 docs: improve docstring for 'list_block_devices' 2025-07-07 10:46:26 +02:00
Johannes Kirschbauer
0e10122d54 api/clan: rename 'show_clan_meta' -> 'get_clan_details' 2025-07-07 10:41:00 +02:00
brianmcgee
ecd731024c Merge pull request 'feat(ui): alert component' (#4199) from ui/alerts into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4199
2025-07-07 08:11:13 +00:00
Jeremy Fleischman
e0da575201 Fix bug? member_id -> member_ip
(I stumbled across this while reading code, I haven't tested this at
all.)
2025-07-07 00:49:45 -07:00
Jeremy Fleischman
3577c689bd Add missing f to f-string 2025-07-07 00:48:32 -07:00
renovate[bot]
885103bfa4 chore(deps): lock file maintenance 2025-07-07 05:40:16 +00:00
Michael Hoang
afc1ca37bd Merge pull request 'cli: don't log every public key we find' (#4233) from push-lynrrnswopmw into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4233
2025-07-07 05:38:03 +00:00
Michael Hoang
4aa536a1bf cli: don't log every public key we find 2025-07-07 15:23:46 +10:00
Michael Hoang
c61dfbf8dd Merge pull request 'treewide: don't generate SSH keys with builder hostname' (#4232) from push-suwrloyoqvlq into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4232
2025-07-07 04:51:21 +00:00
Michael Hoang
e6785fa1d0 treewide: don't generate SSH keys with builder hostname 2025-07-07 14:39:57 +10:00
Michael Hoang
89ea01fd04 Merge pull request 'docs: misc improvements' (#4231) from push-xlwnnlrownnv into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4231
2025-07-07 04:03:33 +00:00
Michael Hoang
a8a08e21e4 clanServices/sshd: add README 2025-07-07 13:54:26 +10:00
Michael Hoang
700f571598 docs: fix highlighting in code block 2025-07-07 13:54:26 +10:00
Michael Hoang
08c15b3d9b docs: remove colon from headings 2025-07-07 13:54:26 +10:00
lassulus
2848b6d5d6 Merge pull request 'vars password-store: fix secret mangling due to string encoding' (#4227) from pass-fix-bytes into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4227
2025-07-07 00:50:58 +00:00
lassulus
ddc1059799 vars password-store: fix secret mangling due to string encoding 2025-07-07 02:35:17 +02:00
renovate[bot]
b690515dd7 Update data-mesher digest to a2166c1 2025-07-07 00:10:13 +00:00
lassulus
e9cef9c7c1 Merge pull request 'rename lingering clan.vars -> clan.core.vars' (#4224) from rip_clan_vars into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4224
2025-07-06 23:33:31 +00:00
lassulus
ca69864a20 rename lingering clan.vars -> clan.core.vars 2025-07-07 00:59:52 +02:00
hsjobeki
5436f284fb Merge pull request 'API: refactor into resource oriented names' (#4223) from api-cleanup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4223
2025-07-06 19:11:31 +00:00
Johannes Kirschbauer
00df032635 vars/api: rename 'get_generators_closure' into 'get_machine_generators' 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
a2c016718a api/hardware: consolidate into 'describe_machine_hardware' 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
d1abebf068 api/inventory: remove 'inventory' from api entirely 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
9635fb03b7 api/flash: refactor into 'list_flash_options' 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
f48c596617 vars/api: rename, unregister some unused vars functions 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
0589c71601 Vars: rename public functions into 'create_machine_vars' 2025-07-06 20:57:42 +02:00
Johannes Kirschbauer
a2c2d73e49 Vars: rename 'keygen' to 'create_secrets_user' 2025-07-06 20:57:42 +02:00
hsjobeki
99b22dfcbf Merge pull request 'Templates/cli: move display command into it own category' (#4222) from clan-templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4222
2025-07-06 18:26:45 +00:00
Johannes Kirschbauer
cd04686663 Docs: update index 2025-07-06 20:06:17 +02:00
Johannes Kirschbauer
2b3e847c28 machine: rename standalone 'get_host' to 'get_machine_host' 2025-07-06 19:47:58 +02:00
Johannes Kirschbauer
d0ec4fd8e6 Templates/cli: move display command into it own category 2025-07-06 19:36:57 +02:00
hsjobeki
bb5c523ac8 Merge pull request 'Templates: remove InputPrio and related classes' (#4221) from clan-templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4221
2025-07-06 17:19:31 +00:00
Johannes Kirschbauer
4df4f5220b Templates: remove InputPrio and related classes 2025-07-06 19:08:45 +02:00
renovate[bot]
a082fd2ed9 Lock file maintenance 2025-07-06 15:00:31 +00:00
hsjobeki
3161c10aa8 Merge pull request 'templates_url: add clan template url test' (#4216) from clan-templates into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4216
2025-07-06 14:54:42 +00:00
Johannes Kirschbauer
7ad8ed1af0 Templates: fix invalid mock flake 2025-07-06 16:43:38 +02:00
Johannes Kirschbauer
94919dc9b8 Fix/ui: update create argument 2025-07-06 15:48:35 +02:00
Johannes Kirschbauer
1502cfa4a7 Templates: migrate clan templates to flake identifiers 2025-07-06 15:37:10 +02:00
Johannes Kirschbauer
cce0207225 Templates: remove outdated check for 'configuration.nix' in machine templates 2025-07-06 15:37:10 +02:00
Johannes Kirschbauer
38f98645ac Templates: replace leftover MachineID, by Machine 2025-07-06 15:37:10 +02:00
Johannes Kirschbauer
74d2ae0619 templates_url: add clan template url test 2025-07-06 15:37:10 +02:00
lassulus
c122201ff2 Merge pull request 'Revert "make host key check an enum instead of an literal type"' (#4220) from revert_host_key_check into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4220
2025-07-06 13:19:00 +00:00
lassulus
e72795904d Revert "make host key check an enum instead of an literal type"
This reverts commit 543c518ed0.
2025-07-06 14:51:19 +02:00
hsjobeki
32ddb4ffa7 Merge pull request 'Templates/list: display templates via exposed nix value' (#4219) from templates-list into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4219
2025-07-06 12:49:58 +00:00
Johannes Kirschbauer
db6220b57b Templates/list: display templates via exposed nix value 2025-07-06 14:37:03 +02:00
lassulus
e929f36f80 Merge pull request 'vars/password-store: replace passBackend option with passPackage' (#4134) from lassulus/passage_compat into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4134
2025-07-06 11:44:27 +00:00
hsjobeki
f71460c4f9 Merge pull request 'clan-cli: fix incorrect field name in deploy warning messages. The warning for missing buildHost/targetHost always showed targetHost in the path, even when buildHost was the missing field.' (#4217) from pr-4215 into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4217
2025-07-06 10:54:55 +00:00
lassulus
8302f3ffde vars/password-store: replace passBackend option with passPackage
The `clan.core.vars.settings.passBackend` option has been replaced with
`clan.vars.password-store.passPackage` to provide better type safety and
clearer configuration.

Changes:
- Remove problematic mkRemovedOptionModule that caused circular dependency
- Add proper option definition with assertion-based migration
- Users setting the old option get clear migration instructions
- Normal evaluation continues to work for users not using the old option

Migration: Replace `clan.core.vars.settings.passBackend = "passage"`
with `clan.vars.password-store.passPackage = pkgs.passage`
2025-07-06 12:46:39 +02:00
lassulus
bd82de6001 fix(flake): handle file paths with line numbers in cache existence check
The is_cached method now correctly handles store paths that have line
numbers appended (e.g., /nix/store/file.nix:123:456). Previously, these
paths would fail the existence check because the exact path with line
numbers doesn't exist as a file.

The fix adds a helper method that:
- First checks if the exact path exists
- If not, and the path contains colons, validates that the suffix
  consists only of numbers (line:column format)
- If valid, strips the line numbers and checks the base file path

This ensures that cached references to specific file locations are
properly validated while avoiding false positives with files that
have colons in their names.
2025-07-06 12:44:15 +02:00
adeci
06613de825 clan-cli: fix incorrect field name in deploy warning messages. The warning for missing buildHost/targetHost always showed targetHost in the path, even when buildHost was the missing field. 2025-07-06 12:44:02 +02:00
hsjobeki
76af63ee1c Merge pull request 'lib/get_host: improve abstraction, turn missconfiguration into a warning' (#4201) from cli-fixup into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4201
2025-07-06 10:38:03 +00:00
Johannes Kirschbauer
3baa43fd87 cli/update: refactor machine selection logic into 'get_machines_for_update' 2025-07-06 12:27:28 +02:00
Johannes Kirschbauer
a6b8ca06ab machines/list: rename helper to instantiate_inventory_to_machines 2025-07-06 12:24:16 +02:00
Johannes Kirschbauer
f7faf2cd63 machines/list: remove duplicate query_machines_by_tags 2025-07-06 12:23:47 +02:00
Johannes Kirschbauer
bff3908bb1 CLI: update requireExplicitUpdate in help 2025-07-06 12:22:25 +02:00
Johannes Kirschbauer
d0613b4030 cli: return validated list from validate_machine_names 2025-07-06 12:22:00 +02:00
Johannes Kirschbauer
52b711667e lib/get_host: improve abstraction, turn missconfiguration into a warning
Motivation: A warning should encourage consistent usage of inventory.machines setting targetHost inside the machine should be considered a custom override

Changing the warning strings to avoid the term 'nix'/'json' both inventory and nixos machines are nix features
2025-07-06 12:08:00 +02:00
lassulus
13d6db98d1 Merge pull request 'better_select_output' (#4213) from better_select_output into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4213
2025-07-06 00:24:06 +00:00
lassulus
195134dd5e clan_cli: better select debug output 2025-07-06 01:17:55 +02:00
lassulus
0670f0ad32 clan_cli flake: remove apply from select, as it will break stuff in horrible ways
Since apply changes the structure of the retuned value, the cache will
be confused about the structure and in subsequent request will use this
wrong structure.

For example: we would use builtins.attrNames on inputs, the flake will
forever think that inputs is a list of strings and will report errors
whenever we try to fetch subkeys from it
2025-07-06 01:17:55 +02:00
lassulus
daf843eeab clan_cli run: add trace runOption to disable verbose traces in debug mode 2025-07-05 19:48:50 +02:00
lassulus
291b742fd7 Merge pull request 'clan_cli machines update: remove caching of sometimes missing pass config' (#4212) from fix_update into main
Reviewed-on: https://git.clan.lol/clan/clan-core/pulls/4212
2025-07-05 17:42:45 +00:00
lassulus
f7d6c23aaa clan_cli machines update: remove caching of sometimes missing pass config
This config value is not set if people don't use pass, it's also at the wrong location
We could cache it with a maybe, but we plan to move it anyway
2025-07-05 18:39:53 +02:00
Brian McGee
1f26135381 feat(ui): alert component 2025-07-04 10:51:18 +01:00
526 changed files with 9225 additions and 17790 deletions

75
.gitea/workflows/create-pr.sh Executable file
View File

@@ -0,0 +1,75 @@
#!/usr/bin/env bash
# Shared script for creating pull requests in Gitea workflows
set -euo pipefail
# Required environment variables:
# - CI_BOT_TOKEN: Gitea bot token for authentication
# - PR_BRANCH: Branch name for the pull request
# - PR_TITLE: Title of the pull request
# - PR_BODY: Body/description of the pull request
if [[ -z "${CI_BOT_TOKEN:-}" ]]; then
echo "Error: CI_BOT_TOKEN is not set" >&2
exit 1
fi
if [[ -z "${PR_BRANCH:-}" ]]; then
echo "Error: PR_BRANCH is not set" >&2
exit 1
fi
if [[ -z "${PR_TITLE:-}" ]]; then
echo "Error: PR_TITLE is not set" >&2
exit 1
fi
if [[ -z "${PR_BODY:-}" ]]; then
echo "Error: PR_BODY is not set" >&2
exit 1
fi
# Push the branch
git push origin "+HEAD:${PR_BRANCH}"
# Create pull request
resp=$(nix run --inputs-from . nixpkgs#curl -- -X POST \
-H "Authorization: token $CI_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"head\": \"${PR_BRANCH}\",
\"base\": \"main\",
\"title\": \"${PR_TITLE}\",
\"body\": \"${PR_BODY}\"
}" \
"https://git.clan.lol/api/v1/repos/clan/clan-core/pulls")
pr_number=$(echo "$resp" | jq -r '.number')
if [[ "$pr_number" == "null" ]]; then
echo "Error creating pull request:" >&2
echo "$resp" | jq . >&2
exit 1
fi
echo "Created pull request #$pr_number"
# Merge when checks succeed
while true; do
resp=$(nix run --inputs-from . nixpkgs#curl -- -X POST \
-H "Authorization: token $CI_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"Do": "merge",
"merge_when_checks_succeed": true,
"delete_branch_after_merge": true
}' \
"https://git.clan.lol/api/v1/repos/clan/clan-core/pulls/$pr_number/merge")
msg=$(echo "$resp" | jq -r '.message')
if [[ "$msg" != "Please try again later" ]]; then
break
fi
echo "Retrying in 2 seconds..."
sleep 2
done
echo "Pull request #$pr_number merge initiated"

View File

@@ -19,35 +19,10 @@ jobs:
run: | 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 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" git commit -am "Update pinned clan-core for checks"
git push origin +HEAD:update-clan-core-for-checks
set -x
resp=$(nix run --inputs-from . nixpkgs#curl -- -X POST \
-H "Authorization: token $CI_BOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"head": "update-clan-core-for-checks",
"base": "main",
"title": "Update Clan Core for Checks",
"body": "This PR updates the pinned clan-core flake input that is used for checks."
}' \
"https://git.clan.lol/api/v1/repos/clan/clan-core/pulls")
pr_number=$(echo "$resp" | jq -r '.number')
# Merge when succeed # Use shared PR creation script
while true; do export PR_BRANCH="update-clan-core-for-checks"
resp=$(nix run --inputs-from . nixpkgs#curl -- -X POST \ export PR_TITLE="Update Clan Core for Checks"
-H "Authorization: token $CI_BOT_TOKEN" \ export PR_BODY="This PR updates the pinned clan-core flake input that is used for checks."
-H "Content-Type: application/json" \
-d '{ ./.gitea/workflows/create-pr.sh
"Do": "merge",
"merge_when_checks_succeed": true,
"delete_branch_after_merge": true
}' \
"https://git.clan.lol/api/v1/repos/clan/clan-core/pulls/$pr_number/merge")
msg=$(echo $resp | jq -r '.message')
if [[ "$msg" != "Please try again later" ]]; then
break
fi
echo "Retrying in 2 seconds..."
sleep 2
done

View File

@@ -0,0 +1,40 @@
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

View File

@@ -19,10 +19,11 @@
... ...
}: }:
let let
dependencies = [ dependencies =
self [
pkgs.stdenv.drvPath pkgs.stdenv.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues self.inputs); ]
++ builtins.map (i: i.outPath) (builtins.attrValues (builtins.removeAttrs self.inputs [ "self" ]));
closureInfo = pkgs.closureInfo { rootPaths = dependencies; }; closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in in
{ {

View File

@@ -47,14 +47,6 @@ nixosLib.runTest (
clientone = clientone =
{ config, pkgs, ... }: { config, pkgs, ... }:
let
dependencies = [
clan-core
pkgs.stdenv.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues clan-core.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{ {
services.openssh.enable = true; services.openssh.enable = true;
@@ -65,15 +57,6 @@ nixosLib.runTest (
environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ]; environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ];
environment.etc.install-closure.source = "${closureInfo}/store-paths";
nix.settings = {
substituters = pkgs.lib.mkForce [ ];
hashed-mirrors = null;
connect-timeout = pkgs.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-backups.folders = [ "/var/test-backups" ];
}; };

View File

@@ -1,89 +0,0 @@
{
pkgs,
nixosLib,
clan-core,
lib,
...
}:
let
machines = [
"admin"
"peer"
"signer"
];
in
nixosLib.runTest (
{ ... }:
{
imports = [
clan-core.modules.nixosTest.clanTest
];
hostPkgs = pkgs;
name = "service-data-mesher";
clan = {
directory = ./.;
inventory = {
machines = lib.genAttrs machines (_: { });
services = {
data-mesher.default = {
roles.peer.machines = [ "peer" ];
roles.admin.machines = [ "admin" ];
roles.signer.machines = [ "signer" ];
};
};
};
};
defaults =
{ config, ... }:
{
environment.systemPackages = [
config.services.data-mesher.package
];
clan.data-mesher.network.interface = "eth1";
clan.data-mesher.bootstrapNodes = [
"[2001:db8:1::1]:7946" # peer1
"[2001:db8:1::2]:7946" # peer2
];
# speed up for testing
services.data-mesher.settings = {
cluster.join_interval = lib.mkForce "2s";
cluster.push_pull_interval = lib.mkForce "5s";
};
};
nodes = {
admin.clan.data-mesher.network.tld = "foo";
};
# TODO Add better test script.
testScript = ''
def resolve(node, success = {}, fail = [], timeout = 60):
for hostname, ips in success.items():
for ip in ips:
node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout)
for hostname in fail:
node.wait_until_fails(f"getent ahosts {hostname}")
start_all()
admin.wait_for_unit("data-mesher")
signer.wait_for_unit("data-mesher")
peer.wait_for_unit("data-mesher")
# check dns resolution
for node in [admin, signer, peer]:
resolve(node, {
"admin.foo": ["2001:db8:1::1", "192.168.1.1"],
"peer.foo": ["2001:db8:1::2", "192.168.1.2"],
"signer.foo": ["2001:db8:1::3", "192.168.1.3"]
})
'';
}
)

View File

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

View File

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

View File

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

View File

@@ -1,20 +0,0 @@
{
"data": "ENC[AES256_GCM,data:7xyb6WoaN7uRWEO8QRkBw7iytP5hFrA94VRi+sy/UhzqT9AyDPmxB/F8ASFsBbzJUwi0Oqd2E1CeIYRoDhG7JHnDyL2bYonz2RQ=,iv:slh3x774m6oTHAXFwcen1qF+jEchOKCyNsJMbNhqXHE=,tag:wtK8H8PZCESPA1vZCd7Ptw==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBPTzZ4RTVNb2I1MTBRMEcy\neU1Eek9GakkydEJBVm9kR3AyY1pEYkorNUYwCkh2WHhNQmc1eWI2cCtEUFFWdzJq\nS0FvQWtoOFkzRVBxVzhuczc0aVprbkkKLS0tIFRLdmpnbzY1Uk9LdklEWnQzZHM2\nVEx3dzhMSnMwaWE0V0J6VTZ5ZVFYMjgKdaICa/hprHxhH89XD7ri0vyTT4rM+Si0\niHcQU4x64dgoJa4gKxgr4k9XncjoNEjJhxL7i/ZNZ5deaaLRn5rKMg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:24:55Z",
"mac": "ENC[AES256_GCM,data:TJWDHGSRBfOCW8Q+t3YxG3vlpf9a5u7B27AamnOk95huqIv0htqWV3RuV7NoOZ5v2ijqSe/pLfpwrmtdhO2sUBEvhdhJm8UzLShP7AbH9lxV+icJOsY7VSrp+R5W526V46ONP6p47b7fOQBbp03BMz01G191N68WYOf6k2arGxU=,iv:nEyTBwJ2EA+OAl8Ulo5cvFX6Ow2FwzTWooF/rdkPiXg=,tag:oYcG16zR+Fb5XzVsHhq2Qw==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,20 +0,0 @@
{
"data": "ENC[AES256_GCM,data:JOOhvl0clDD/b5YO45CXR3wVopBSNe9dYBG+p5iD+nniN2OgOwBgYPNSCVtc+NemqutD12hFUSfCzXidkv0ijhD1JZeLar9Ygxc=,iv:XctQwSYSvKhDRk/XMacC9uMydZ8e9hnhpoWTgyXiFI0=,tag:foAhBlg4DwpQU2G9DzTo5g==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBBVWMvWkp5TnZQcGs5Ykhp\nWC91YkoyZERqdXpxQm5JVmRhaUhueEJETDJVCkM4V0hSYldkV1U2Q0d1TGh3eGNR\nVjJ1VFd6ZEN0SXZjSVEvcnV2WW0vbVUKLS0tIFRCNW9nWHdYaUxLSVVUSXM0OGtN\nVFMzRXExNkYxcFE3QWlxVUM3ay9INm8KV6r8ftpwarly3qXoU9y8KxKrUKLvP9KX\nGsP0pORsaM+qPMsdfEo35CqhAeQu0+6DWd7/67+fUMp6Jr0DthtTmg==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:25:28Z",
"mac": "ENC[AES256_GCM,data:scY9+/fcXhfHEdrsZJLOM6nfjpRaURgTVbCRepUjhUo24B4ByEsAo2B8psVAaGEHEsFRZuoiByqrGzKhyUASmUs+wn+ziOKBTLzu55fOakp8PWYtQ4miiz2TQffp80gCQRJpykcbUgqIKXNSNutt4tosTBL7osXwCEnEQWd+SaA=,iv:1VXNvLP6DUxZYEr1juOLJmZCGbLp33DlwhxHQV9AMD4=,tag:uFM1R8OmkFS74/zkUG0k8A==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,20 +0,0 @@
{
"data": "ENC[AES256_GCM,data:i1YBJdK8XmWnVnZKBpmWggSN8JSOr8pm2Zx+CeE8qqeLZ7xwMO8SYCutM8l94M5vzmmX0CmwzeMZ/JVPbEwFd3ZAImUfh685HOY=,iv:N4rHNaX+WmoPb0EZPqMt+CT1BzaWO9LyoemBxKn+u/s=,tag:PnzSvdGwVnTMK8Do8VzFaQ==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4RXlmcVNGTnlkY2ZqZFlH\nVnh0eHhRNE5hRDNDVkt0TEE0bmRNN2JIVkN3CkxnaGM4Y3M3a0xoK2xMRzBLMHRV\nT1FzKzNRMFZOeWc2K3E5K2FzdUsvWmsKLS0tIENtVlFSWElHN3RtOUY2alhxajhs\naXI1MmR4WC9EVGVFK3dHM1gvVnlZMVUKCyLz0DkdbWfSfccShO1xjWfxhunEIbD0\n6imeIBhZHvVJmZLXnVl7B0pNXo6be7WSBMAUM9gUtCNh4zaChBNwGw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:25:52Z",
"mac": "ENC[AES256_GCM,data:WFGysoXN95e/RxL094CoL4iueqEcSqCSQZLahwz9HMLi+8HWZIXr55a+jyK7piqR8nBS4BquU5fKhlC6BvEbZFt69t4onTA+LxS3D7A8/TO0CWS0RymUjW9omJUseRQWwAHtE7l0qI5hdOUKhQ+o5pU+2bc3PUlaONM0aOCCoFo=,iv:l1f4aVqLl5VAMfjNxDbxQEQp/qY/nxzgv2GTuPVBoBA=,tag:4PPDCmDrviqdn42RLHQYbA==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,24 +0,0 @@
{
"data": "ENC[AES256_GCM,data:w3bU23Pfe8W89lF+tOmEYPU/A4FkY6n7rgQ6yo+eqCJFxTyHydV6Mg4/g4jaL+4wwIqNYRiMR8J8jLhSvw3Bc59u7Ul+RGwdpiKoBBJfsHjO8r6uOz2u9Raa+iUJH1EJWmGvsQXAILpliZ+klS96VWnGN3pYMEI=,iv:7QbUxta6NPQLZrh6AOcNe+0wkrADuTI9VKVp8q+XoZ8=,tag:ZH0t3RylfQk5U23ZHWaw0g==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age10zxkj45fah3qa8uyg3a36jsd06d839xfq64nrez9etrsf4km0gtsp45gsz",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBKaTBoSFJVSTdZeW4wZG9p\nWFR1LzVmYS8xWmRqTlNtWFVkSW9jZXpVejJBCkpqZm12L1dDSmNhekVsK1JBOU9r\nZThScGdDakFlRzNsVXp1eE5yOStFSW8KLS0tIFRrTkZBQlRsR2VNcUJvNEkzS2pw\nNksvM296UkFWTkZDVVp1ZVZMNUs4cWsKWTteB1G9Oo38a81PeqKO09NUQetuqosC\nhrToQ6NMo5O7/StmVG228MHbJS3KLXsvh2AFOEPyZrbpB2Opd2wwoA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB6U2FWRThRNkVQdk9yZ0VE\nM09iSVhmeldMcDZVaFRDNGtjWTdBa0VIT2pJCkdtd04xSXdicDY3OHI1WXl5TndB\nemtQeW1SS2tVVllPUHhLUTRla3haZGMKLS0tIGN0NVNEN3RKeWM0azBBMnBpQU4r\nTFFzQ0lOcGt0ek9UZmZZRjhibTNTc0EKReUwYBVM1NKX0FD/ZeokFAAknwju5Azq\nGzl4UVJBi5Es0GWORdCGElPXMd7jMud1SwgY04AdZj/dzinCSW4CZw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:25:10Z",
"mac": "ENC[AES256_GCM,data:0vl9Gt4QeH+GJcnl8FuWSaqQXC8S6Pe50NmeDg5Nl2NWagz8aLCvOFyTqX/Icp/bTi1XQ5icHHhF3YhM+QAvdUL3aO0WGbh92dPRnFuvlZsdtwCFhT+LyHyYHFf6yP+0h/uFpJv9fE6xY22CezA6ZVQ8ywi1epaC548Gr27uVe4=,iv:G4hZVCLkIpbg9uwB7Y8xtHLdnlmBvFrPjxSoqdyHNvM=,tag:uvKwakhUY2aa7v0tmR/o8A==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,3 +0,0 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAm204bpSFi4jOjZuXDpIZ/rcJBrbG4zAc7OSA4rAVSYE=
-----END PUBLIC KEY-----

View File

@@ -1,24 +0,0 @@
{
"data": "ENC[AES256_GCM,data:kERPY40pyvke0mRBnafa4zOaF46rbueRbhpUCXjYP5ORpC7zoOhbdlVBhOsPqE2vfEP4RWkH+ZPdDYXOKXwotBCmlq2i7TfZeoNXFkzWXc3GyM5mndnjCc8hvYEQF1w6xkkVSUt4n06BAw/gT0ppz+vo5dExIA8=,iv:JmYD2o4DGqds6DV7ucUmUD0BRB61exbRsNAtINOR8cQ=,tag:Z58gVnHD+4s21Z84IRw+Vw==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age1faqrml2ukc6unfm75d3v2vnaf62v92rdxaagg3ty3cfna7vt99gqlzs43l",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB4OFluVThBdUJSTmRVTk94\neFZnLytvcnNSdmQvR3ZkT2UvWFVieFV1SUFNCm9jWHlyZXRwaVdFaG9ocnd4S3FU\ndTZ2dklBbkFVL0hVT0Y2L1o5dnUyNG8KLS0tIGFvYlBJR3l2b3F6OU9uMTFkYjli\nNVFLOWQzOStpU2kzb0xyZUFCMnBmMVUK5Jzssf1XBX25bq0RKlJY8NwtKIytxL/c\nBPPFDZywJiUgw1izsdfGVkRhhSFCQIz+yWIJWzr01NU2jLyFjSfCNw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAzYW92c3Q4SktwSnJ1TkRJ\nZEJyZk96cG8ybkpPQzYzVk0xZGs0eCtISVR3CmhDaWxTem1FMjJKNmZNaTkxN01n\nenUvdFI1UkFmL1lzNlM5N0Ixd0dpc1EKLS0tIHpyS2VHaHRRdUovQVgvRmRHaXh3\naFpSNURjTWkxaW9TOXpKL2IvcUFEbmMKq4Ch7DIL34NetFV+xygTdcpQjjmV8v1n\nlvYcjUO/9c3nVkxNMJYGjuxFLuFc4Gw+AyawCjpsIYXRskYRW4UR1w==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:25:43Z",
"mac": "ENC[AES256_GCM,data:YhL2d6i0VpUd15B4ow2BgRpyEm0KEA8NSb7jZcjI58d7d4lAqBMcDQB+8a9e2NZbPk8p1EYl3q4VXbEnuwsJiPZI2kabRusy/IGoHzUTUMFfVaOuUcC0eyINNVSmzJxnCbLCAA1Aj1yXzgRQ0MWr7r0RHMKw0D1e0HxdEsuAPrA=,iv:yPlMmE6+NEEQ9uOZzD3lUTBcfUwGX/Ar+bCu0XKnjIg=,tag:eR22BCFVAlRHdggg9oCeaA==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,3 +0,0 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEAv5dICFue2fYO0Zi1IyfYjoNfR6713WpISo7+2bSjL18=
-----END PUBLIC KEY-----

View File

@@ -1,24 +0,0 @@
{
"data": "ENC[AES256_GCM,data:U8F7clQ2Tuj8zy5EoEga/Mc9N3LLZrlFf5m7UJKrP5yybFRCJSBs05hOcNe+LQZdEAvvr0Qbkry1pQyE84gCVbxHvwkD+l3GbguBuLMsW96bHcmstb6AvZyhMDBpm73Azf4lXhNaiB8p2pDWdxV77E+PPw1MNYI=,iv:hQhN6Ak8tB6cXSCnTmmQqHEpXWpWck3uIVCk5pUqFqU=,tag:uC4ljcs92WPlUOfwSkrK9Q==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age153mke8v2qksyqjc7vta7wglzdqr5epazt83nch0ur5v7kl87cfdsr07qld",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBvV05lejQrdUQvQjZPOG9v\nZ01naXlYZ1JxWHhDT1M1aUs1RWJDSU1acVFFCmdHY094aGRPYWxpdVVxSFVHRU9v\nNnVaeTlpSEdtSWRDMmVMSjdSOEQ4ZlEKLS0tIFo5NVk2bzBxYjZ5ZWpDWTMrQ2VF\nVThWUk0rVXpTY2svSCtiVDhTQ2kvbFkKEM2DBuFtdEj1G/vS1TsyIfQxSFFvPTDq\nCmO7L/J5lHdyfIXzp/FlhdKpjvmchb8gbfJn7IWpKopc7Zimy/JnGQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSArNzVUaHkzUzVEMlh1Q3Qr\nOEo0aDJIMG91amJiZG50MEhqblRCTWxRRVVRCk4xZlp4SkJuUHc2UnFyU1prczkz\nNGtlQlRlNnBDRFFvUGhReTh6MTBZaXMKLS0tIGxtaXhUMDM0RU4yQytualdzdTFt\nWGRiVG54MnYrR2lqZVZoT0VkbmV5WUUKbzAnOkn8RYOo7z4RISQ0yN875vSEQMDa\nnnttzVrQuK0/iZvzJ0Zq8U9+JJJKvFB1tHqye6CN0zMbv55CLLnA0g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:26:07Z",
"mac": "ENC[AES256_GCM,data:uMss4+BiVupFqX7nHnMo+0yZ8RPuFD8VHYK2EtJSqzgurQrZVT4tJwY50mz2gVmwbrm49QYKk5S+H29DU0cM0HiEOgB5P5ObpXTRJPagWQ48CEFrDpBzLplobxulwnN6jJ1dpL3JF3jfrzrnSDFXMvx+n5x/86/AYXYRsi/UeyY=,iv:mPT1svKrNGmYpbL9hh2Bxxakml69q+U6gQ0ZnEcbEyg=,tag:zcZx1lTw/bEsX/1g+6T04g==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

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

View File

@@ -1,32 +0,0 @@
{
"data": "ENC[AES256_GCM,data:nRlCMF58cnkdUAE2aVHEG1+vAckKtVt48Jr21Bklfbsqe1yTiHPFAMLL1ywgWWWd7FjI/Z8WID9sWzh9J8Vmotw4aJWU/rIQSeF8cJHALvfOxarJIIyb7purAiPoPPs6ggGmSmVFGB1aw8kH1JMcppQN8OItdQM=,iv:qTwaL2mgw6g7heN/H5qcjei3oY+h46PdSe3v2hDlkTs=,tag:jYNULrOPl9mcQTTrx1SDeA==,type:str]",
"sops": {
"kms": null,
"gcp_kms": null,
"azure_kv": null,
"hc_vault": null,
"age": [
{
"recipient": "age153mke8v2qksyqjc7vta7wglzdqr5epazt83nch0ur5v7kl87cfdsr07qld",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBRcG44cGFBWXk2Z0pmNklv\nTnJ5b0svLytzZmNNRkxCVU1zaDVhNUs2cld3CklsenpWd0g2OEdKKzBMQlNEejRn\nTlEvY01HYjdvVExadnN3aXZIRTZ4YlEKLS0tIGRPUXdNSHZCRDBMbno2MjJqRHBl\nSzdiSURDYitQWFpaSElkdmdicDVjMWsKweQiRqyzXmzabmU2fmgwHtOa9uDmhx9O\ns9NfUhC3ifooQUSeYp58b1ZGJQx5O5bn9q/DaEoit5LTOUprt1pUPA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBiTEdlL29sVWFpSDNNaXRJ\ndTJDRkU4VzFPQ0M4MkFha2IxV2FXN2o3ZEFRCjF3UnZ5U1hTc3VvSTIzcWxOZjl0\ncHlLVEFqRk1UbGdxaUxEeDFqbFVYaU0KLS0tIFFyMnJkZnRHdWg4Z1IyRHFkY0I5\nQjdIMGtGLzRGMFM0ektDZ3hzZDdHSmMKvxOQuKgePom0QfPSvn+4vsGHhJ4BoOvW\nc27Vn4/i4hbjfJr4JpULAwyIwt3F0RaTA2M6EkFkY8otEi3vkcpWvA==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age10zxkj45fah3qa8uyg3a36jsd06d839xfq64nrez9etrsf4km0gtsp45gsz",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA5ZzdsaVRnSmsrMGR1Ylg3\nZkpscTdwNUl5NUVXN3kvMU1icE0yZU1WSEJBClB6SlJYZUhDSElRREx5b0VueFUw\nNVFRU3BSU24yWEtpRnJoUC83SDVaUWsKLS0tIGVxNEo3TjlwakpDZlNsSkVCOXlz\nNDgwaE1xNjZkSnJBVlU5YXVHeGxVNFEKsXKyTzq9VsERpXzbFJGv/pbAghFAcXkf\nMmCgQHsfIMBJQUstcO8sAkxv3ced0dAEz8O6NUd0FS2zlhBzt29Rnw==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1faqrml2ukc6unfm75d3v2vnaf62v92rdxaagg3ty3cfna7vt99gqlzs43l",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkK1hDMGxCc1IvYXlJMnBF\nWncxaXBQa1RpTWdwUHc3Yk16My8rVHNJc2dFCkNlK2h0dy9oU3Z5ZGhwRWVLYVUz\ncVBKT2x5VnlhbXNmdHkwbmZzVG5sd0EKLS0tIHJaMzhDanF4Rkl3akN4MEIxOHFC\nYWRUZ08xb1UwOFNRaktkMjIzNXZmNkUK1rlbJ96oUNQZLmCmPNDOKxfDMMa+Bl2E\nJPxcNc7XY3WBHa3xFUbcqiPxWxDyaZjhq/LYQGpepiGonGMEzR5JOQ==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-04-08T13:25:20Z",
"mac": "ENC[AES256_GCM,data:za9ku+9lu1TTRjbPcd5LYDM4tJsAYF/yuWFCGkAhqcYguEducsIfoKBwL42ahAzqLjCZp91YJuINtw16mM+Hmlhi/BVwhnXNHqcfnKoAS/zg9KJvWcvXwKMmjEjaBovqaCWXWoKS7dn/wZ7nfGrlsiUilCDkW4BzTIzkqNkyREU=,iv:2X9apXMatwCPRBIRbPxz6PJQwGrlr7O+z+MrsnFq+sQ=,tag:IYvitoV4MhyJyRO1ySxbLQ==,type:str]",
"pgp": null,
"unencrypted_suffix": "_unencrypted",
"version": "3.9.4"
}
}

View File

@@ -1,3 +0,0 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA/5j+Js7oxwWvZdfjfEO/3UuRqMxLKXsaNc3/5N2WSaw=
-----END PUBLIC KEY-----

View File

@@ -94,7 +94,6 @@ in
service-dummy-test = import ./service-dummy-test nixosTestArgs; service-dummy-test = import ./service-dummy-test 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;
service-data-mesher = import ./data-mesher nixosTestArgs;
}; };
packagesToBuild = lib.removeAttrs self'.packages [ packagesToBuild = lib.removeAttrs self'.packages [

View File

@@ -59,7 +59,7 @@
name = "flash"; name = "flash";
nodes.target = { nodes.target = {
virtualisation.emptyDiskImages = [ 4096 ]; virtualisation.emptyDiskImages = [ 4096 ];
virtualisation.memorySize = 3000; virtualisation.memorySize = 4096;
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";

View File

@@ -196,7 +196,7 @@ in
pkgs.xkcdpass pkgs.xkcdpass
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/borgbackup.ssh ssh-keygen -t ed25519 -N "" -C "" -f "$out"/borgbackup.ssh
xkcdpass -n 4 -d - > "$out"/borgbackup.repokey xkcdpass -n 4 -d - > "$out"/borgbackup.repokey
''; '';
}; };

View File

@@ -1,5 +1,4 @@
{ {
config,
pkgs, pkgs,
... ...
}: }:
@@ -9,9 +8,14 @@
config = { config = {
warnings = [ warnings = [
"The clan.disk-id module is deprecated and will be removed on 2025-07-15. ''
Please migrate to user-maintained configuration or the new equivalent clan services The clan.disk-id module is deprecated and will be removed on 2025-07-15.
(https://docs.clan.lol/reference/clanServices)." 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 = { clan.core.vars.generators.disk-id = {
files.diskId.secret = false; files.diskId.secret = false;

View File

@@ -7,7 +7,7 @@ The importer module allows users to configure importing modules in a flexible an
It exposes the `extraModules` functionality of the inventory, without any added configuration. It exposes the `extraModules` functionality of the inventory, without any added configuration.
## Usage: ## Usage
```nix ```nix
inventory.services = { inventory.services = {

View File

@@ -54,7 +54,7 @@ in
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519 ssh-keygen -t ed25519 -N "" -C "" -f "$out"/ssh.id_ed25519
''; '';
}; };
@@ -74,7 +74,7 @@ in
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t rsa -b 4096 -N "" -f "$out"/ssh.id_rsa ssh-keygen -t rsa -b 4096 -N "" -C "" -f "$out"/ssh.id_rsa
''; '';
}; };

View File

@@ -36,7 +36,7 @@
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519 ssh-keygen -t ed25519 -N "" -C "" -f "$out"/id_ed25519
''; '';
}; };

View File

@@ -9,15 +9,37 @@
interface = interface =
{ lib, ... }: { lib, ... }:
{ {
options.allowedKeys = lib.mkOption {
default = { }; options = {
type = lib.types.attrsOf lib.types.str; allowedKeys = lib.mkOption {
description = "The allowed public keys for ssh access to the admin user"; default = { };
example = { type = lib.types.attrsOf lib.types.str;
"key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD..."; description = "The allowed public keys for ssh access to the admin user";
example = {
"key_1" = "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQD...";
};
};
rsaHostKey.enable = lib.mkEnableOption "Generate RSA host key";
# TODO: allow per-server domains that we than collect in the inventory
#certicficateDomains = lib.mkOption {
# type = lib.types.listOf lib.types.str;
# default = [ ];
# example = [ "git.mydomain.com" ];
# description = "List of domains to include in the certificate. This option will not prepend the machine name in front of each domain.";
#};
certificateSearchDomains = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [ "mydomain.com" ];
description = ''
List of domains to include in the certificate.
This option will prepend the machine name in front of each domain before adding it to the certificate.
'';
}; };
}; };
}; };
perInstance = perInstance =
@@ -27,10 +49,15 @@
{ ... }: { ... }:
{ {
imports = [ imports = [
../../clanModules/sshd # We don't have a good way to specify dependencies between
../../clanModules/root-password # clanServices for now. When it get's implemtende, we should just
# use the ssh and users modules here.
./ssh.nix
./root-password.nix
]; ];
_module.args = { inherit settings; };
users.users.root.openssh.authorizedKeys.keys = builtins.attrValues settings.allowedKeys; users.users.root.openssh.authorizedKeys.keys = builtins.attrValues settings.allowedKeys;
}; };
}; };

View File

@@ -0,0 +1,39 @@
# We don't have a way of specifying dependencies between clanServices for now.
# When it get's added this file should be removed and the users module used instead.
{
config,
pkgs,
...
}:
{
users.mutableUsers = false;
users.users.root.hashedPasswordFile =
config.clan.core.vars.generators.root-password.files.password-hash.path;
clan.core.vars.generators.root-password = {
files.password-hash.neededFor = "users";
files.password.deploy = false;
runtimeInputs = [
pkgs.coreutils
pkgs.mkpasswd
pkgs.xkcdpass
];
prompts.password.type = "hidden";
prompts.password.persist = true;
prompts.password.description = "You can autogenerate a password, if you leave this prompt blank.";
script = ''
prompt_value="$(cat "$prompts"/password)"
if [[ -n "''${prompt_value-}" ]]; then
echo "$prompt_value" | tr -d "\n" > "$out"/password
else
xkcdpass --numwords 5 --delimiter - --count 1 | tr -d "\n" > "$out"/password
fi
mkpasswd -s -m sha-512 < "$out"/password | tr -d "\n" > "$out"/password-hash
'';
};
}

115
clanServices/admin/ssh.nix Normal file
View File

@@ -0,0 +1,115 @@
{
config,
pkgs,
lib,
settings,
...
}:
let
stringSet = list: builtins.attrNames (builtins.groupBy lib.id list);
domains = stringSet settings.certificateSearchDomains;
in
{
services.openssh = {
enable = true;
settings.PasswordAuthentication = false;
settings.HostCertificate = lib.mkIf (
settings.certificateSearchDomains != [ ]
) config.clan.core.vars.generators.openssh-cert.files."ssh.id_ed25519-cert.pub".path;
hostKeys =
[
{
path = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519".path;
type = "ed25519";
}
]
++ lib.optional settings.rsaHostKey.enable {
path = config.clan.core.vars.generators.openssh-rsa.files."ssh.id_rsa".path;
type = "rsa";
};
};
clan.core.vars.generators.openssh = {
files."ssh.id_ed25519" = { };
files."ssh.id_ed25519.pub".secret = false;
migrateFact = "openssh";
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -C "" -f "$out"/ssh.id_ed25519
'';
};
programs.ssh.knownHosts.clan-sshd-self-ed25519 = {
hostNames = [
"localhost"
config.networking.hostName
] ++ (lib.optional (config.networking.domain != null) config.networking.fqdn);
publicKey = config.clan.core.vars.generators.openssh.files."ssh.id_ed25519.pub".value;
};
clan.core.vars.generators.openssh-rsa = lib.mkIf settings.rsaHostKey.enable {
files."ssh.id_rsa" = { };
files."ssh.id_rsa.pub".secret = false;
runtimeInputs = [
pkgs.coreutils
pkgs.openssh
];
script = ''
ssh-keygen -t rsa -b 4096 -N "" -C "" -f "$out"/ssh.id_rsa
'';
};
clan.core.vars.generators.openssh-cert = lib.mkIf (settings.certificateSearchDomains != [ ]) {
files."ssh.id_ed25519-cert.pub".secret = false;
dependencies = [
"openssh"
"openssh-ca"
];
validation = {
name = config.clan.core.settings.machine.name;
domains = lib.genAttrs settings.certificateSearchDomains lib.id;
};
runtimeInputs = [
pkgs.openssh
pkgs.jq
];
script = ''
ssh-keygen \
-s $in/openssh-ca/id_ed25519 \
-I ${config.clan.core.settings.machine.name} \
-h \
-n ${lib.concatMapStringsSep "," (d: "${config.clan.core.settings.machine.name}.${d}") domains} \
$in/openssh/ssh.id_ed25519.pub
mv $in/openssh/ssh.id_ed25519-cert.pub "$out"/ssh.id_ed25519-cert.pub
'';
};
clan.core.vars.generators.openssh-ca = lib.mkIf (settings.certificateSearchDomains != [ ]) {
share = true;
files.id_ed25519.deploy = false;
files."id_ed25519.pub" = {
deploy = false;
secret = false;
};
runtimeInputs = [
pkgs.openssh
];
script = ''
ssh-keygen -t ed25519 -N "" -C "" -f "$out"/id_ed25519
'';
};
programs.ssh.knownHosts.ssh-ca = lib.mkIf (settings.certificateSearchDomains != [ ]) {
certAuthority = true;
extraHostNames = builtins.map (domain: "*.${domain}") settings.certificateSearchDomains;
publicKey = config.clan.core.vars.generators.openssh-ca.files."id_ed25519.pub".value;
};
}

View File

@@ -256,7 +256,7 @@
pkgs.xkcdpass pkgs.xkcdpass
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/borgbackup.ssh ssh-keygen -t ed25519 -N "" -C "" -f "$out"/borgbackup.ssh
xkcdpass -n 4 -d - > "$out"/borgbackup.repokey xkcdpass -n 4 -d - > "$out"/borgbackup.repokey
''; '';
}; };

View File

@@ -41,14 +41,6 @@
clan-core, clan-core,
... ...
}: }:
let
dependencies = [
clan-core
pkgs.stdenv.drvPath
] ++ builtins.map (i: i.outPath) (builtins.attrValues clan-core.inputs);
closureInfo = pkgs.closureInfo { rootPaths = dependencies; };
in
{ {
services.openssh.enable = true; services.openssh.enable = true;
@@ -59,15 +51,6 @@
environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ]; environment.systemPackages = [ clan-core.packages.${pkgs.system}.clan-cli ];
environment.etc.install-closure.source = "${closureInfo}/store-paths";
nix.settings = {
substituters = pkgs.lib.mkForce [ ];
hashed-mirrors = null;
connect-timeout = pkgs.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-backups.folders = [ "/var/test-backups" ];
}; };

View File

@@ -0,0 +1,29 @@
This service will set up data-mesher.
## Usage
```nix
inventory.instances = {
data-mesher = {
module = {
name = "data-mesher";
input = "clan-core";
};
roles.admin.machines.server0 = {
settings = {
bootstrapNodes = {
node1 = "192.168.1.1:7946";
node2 = "192.168.1.2:7946";
};
network = {
hostTTL = "24h";
interface = "tailscale0";
};
};
};
roles.peer.machines.server1 = { };
roles.signer.machines.server2 = { };
};
}
```

View File

@@ -0,0 +1,29 @@
{
lib,
config,
settings,
...
}:
{
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 = settings.network.tld;
hostTTL = settings.network.hostTTL;
# admin and signer host public keys
signingKeys = builtins.map readHostKey (builtins.attrNames settings.bootstrapNodes);
};
}

View File

@@ -0,0 +1,142 @@
{ ... }:
let
sharedInterface =
{ lib, ... }:
{
options = {
bootstrapNodes = lib.mkOption {
type = lib.types.nullOr (lib.types.attrsOf lib.types.str);
# 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
# default = 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 settings.network.port}" ]
# else
# urls
# ) [ ] (dmLib.machines config).bootstrap;
description = ''
A list of bootstrap nodes that act as an initial gateway when joining
the cluster.
'';
example = {
"node1" = "192.168.1.1:7946";
"node2" = "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.
'';
};
};
};
};
in
{
_class = "clan.service";
manifest.name = "data-mesher";
manifest.description = "Set up data-mesher";
manifest.categories = [ "System" ];
manifest.readme = builtins.readFile ./README.md;
roles.admin = {
interface =
{ lib, ... }:
{
imports = [ sharedInterface ];
options = {
network = {
tld = lib.mkOption {
type = lib.types.str;
default = "clan";
description = "Top level domain to use for the network";
};
hostTTL = lib.mkOption {
type = lib.types.str;
default = "${toString (24 * 28)}h";
example = "24h";
description = "The TTL for hosts in the network, in the form of a Go time.Duration";
};
};
};
};
perInstance =
{ settings, roles, ... }:
{
nixosModule = {
imports = [
./admin.nix
./shared.nix
];
_module.args = { inherit settings roles; };
};
};
};
roles.signer = {
interface =
{ ... }:
{
imports = [ sharedInterface ];
};
perInstance =
{ settings, roles, ... }:
{
nixosModule = {
imports = [
./signer.nix
./shared.nix
];
_module.args = { inherit settings roles; };
};
};
};
roles.peer = {
interface =
{ ... }:
{
imports = [ sharedInterface ];
};
perInstance =
{ settings, roles, ... }:
{
nixosModule = {
imports = [
./peer.nix
./shared.nix
];
_module.args = { inherit settings roles; };
};
};
};
}

View File

@@ -0,0 +1,17 @@
{ lib, ... }:
let
module = lib.modules.importApply ./default.nix { };
in
{
clan.modules = {
data-mesher = module;
};
perSystem =
{ ... }:
{
clan.nixosTests.service-data-mesher = {
imports = [ ./tests/vm/default.nix ];
clan.modules."@clan/data-mesher" = module;
};
};
}

View File

@@ -0,0 +1,2 @@
{
}

View File

@@ -0,0 +1,86 @@
{
config,
settings,
...
}:
{
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 = settings.network.port;
join_interval = "30s";
push_pull_interval = "30s";
interface = settings.network.interface;
bootstrap_nodes = (builtins.attrValues settings.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

@@ -0,0 +1,2 @@
{
}

View File

@@ -0,0 +1,90 @@
{
...
}:
{
name = "service-data-mesher";
clan = {
directory = ./.;
test.useContainers = true;
inventory = {
machines.peer = { };
machines.admin = { };
machines.signer = { };
instances = {
data-mesher =
let
bootstrapNodes = {
admin = "[2001:db8:1::1]:7946";
peer = "[2001:db8:1::2]:7946";
# signer = "2001:db8:1::3:7946";
};
in
{
roles.peer.machines.peer.settings = {
network.interface = "eth1";
inherit bootstrapNodes;
};
roles.signer.machines.signer.settings = {
network.interface = "eth1";
inherit bootstrapNodes;
};
roles.admin.machines.admin.settings = {
network.tld = "foo";
network.interface = "eth1";
inherit bootstrapNodes;
};
};
};
};
};
nodes =
let
commonConfig =
{ lib, config, ... }:
{
environment.systemPackages = [
config.services.data-mesher.package
];
# speed up for testing
services.data-mesher.settings = {
cluster.join_interval = lib.mkForce "2s";
cluster.push_pull_interval = lib.mkForce "5s";
};
};
in
{
peer = commonConfig;
admin = commonConfig;
signer = commonConfig;
};
testScript = ''
def resolve(node, success = {}, fail = [], timeout = 60):
for hostname, ips in success.items():
for ip in ips:
node.wait_until_succeeds(f"getent ahosts {hostname} | grep {ip}", timeout)
for hostname in fail:
node.wait_until_fails(f"getent ahosts {hostname}")
start_all()
admin.wait_for_unit("data-mesher")
signer.wait_for_unit("data-mesher")
peer.wait_for_unit("data-mesher")
# check dns resolution
for node in [admin, signer, peer]:
resolve(node, {
"admin.foo": ["2001:db8:1::1", "192.168.1.1"],
"peer.foo": ["2001:db8:1::2", "192.168.1.2"],
"signer.foo": ["2001:db8:1::3", "192.168.1.3"]
})
'';
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:87WFWukgpTGlH67MTkHxzTosABK/6flJObt+u9UrGSOzBr1lx4V5IsMQ9HAM4jvLpveBNH4hlFDCxbD5666n2oYylGoyBph2vAg=,iv:GKLcU7Xqmb0ImvY7M71NddkOlUDSPa/fcXrXny2iZ1o=,tag:589QMSZeXdmTxRFtMFasZg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBFaXlqZEU0eHRZZjBncDE1\nV2hzTGZiVy9rM0NnWjc1NlpHVVZEUFd5S2pJCmo3Nm11bGQyWWt1R2tHS2pOYlpn\nY3lGa0w3UFpDT1RLSDU4cnJ2YVBkSU0KLS0tIEJjZVc1YXJqcHczYSt6WjV3ai93\nakdPd3VHWkVnWkdhNCtZakp4VXhBUG8Kg3xd9w5oW3/q+s59LkDy5N+xmvuvHRmh\njUv6KFLaB81yv3kb7bzj8E3aMzX0x2fMIDZ3EoPVggqA/sCWQu0p5Q==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:02:45Z",
"mac": "ENC[AES256_GCM,data:IWKfE1Y6SNg/SK+OOAmra5SwqAUfhepCNPClWPDWpOyJDwXSpk/OKl7hi3KFfIZOGupaC0xV2tTni0Uj6IBwf8zW2Mb/b1T+fWkGiyafoKlucfNPXPCob/fyf4Ju4iD/u1mD5BYYYqNTNqJWE+MCyQigL0MPE4tXGEPDa7htM6w=,iv:5RKArbEKnYjacopfL+4QhzGB8txqc3gnlwNPfRWQSlM=,tag:mdXf02nYiW7CexIbUUaMyw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:C9evAr01JpYiMBwuy31h+G9phm+uOYoQu+PegPFAMRbjgkjh0R+uolKtweedtHumMhzEkvz7y+BlfrriVh16ceyMozfzDEkVSWM=,iv:jM4Qx4B/j5Mvc3ybOf+10hKU19l1fCc5KcKulKgMP3c=,tag:mz01kIv5kU6u3f2+FeItYA==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSAydzZrdDVidGpyd1NXT0Fu\nUEtZV3I4S0p5Z095QjBGaXpwOExJSkxVclVJCm54Vk12czQ5dm5TUExNNzlEcFNp\nUWorcWc1c1pvL3pkUFlQY3BJUGhUS3MKLS0tIHd2a291M0xkcjJvTXNnelRNZXda\nQi93R3FQVm0xTXBGR3E3SVpIMzgvR3MKmps5ObV1nODBQ0TKgZ++RLkjCEQM6sMn\nzonKtBingYzfeq+0+cASVkHZJpt/t0G5wmTgivKfv0OIP5eNSgIWFw==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:02:57Z",
"mac": "ENC[AES256_GCM,data:Jk5eL2SmNpakrGF4N/31Q/PWShV5KYfA8NmlxEkD82UsIpPiIJ4Nec6NOoo7Y4bl/J53MLjK3u0/S6q7vv0Tih6+ze6hIddMJHTCp2qqclJvpH2xn6Ln+2ZK4okK2ZbWeSDF+LHc6nIpBak8JVjC/d8dQFT2L49Dkufc1nCD46w=,iv:oR0aQzjaEpFNrpWGc1TX6/zpg0WSfQjVG6VjAMwoLTI=,tag:pigUaCkVv91tynuaNoZenA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1,15 @@
{
"data": "ENC[AES256_GCM,data:bIx3chjDwy4epCyFuJoZlO7EglT/vEg6pdf6x+ISxqekGrrGNdiGtw3Z9foXWAPQrzngVztbwIlcEpUusKwoRPpdGIj5YzbGZbU=,iv:Gi1hjn6cL8z+LP5g6o3bUMsuIzoZRr8e3j3EBwG3p+Y=,tag:ttIfOLhDroV/WK57KBFd0w==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBHNVh6OGE4aGJxbFd2Zks1\nL1ZoNkgrQjFSVFFUL2UzOGNqRXFkZURTMkJRCnZMWk00enRndzNXQmFvMG1UekI0\nUjhwZW9sQnFvb0FGbVE0N042UjF2OTAKLS0tIEdickxQdDdaZkVmN3RsemJzSElY\nWThGQVNMcnpxRlJ3bC9wVE56blljQUUK21wWOBiQc0Kyvl047nJ1N6QKR0/5Dd6r\nlqhhdFWninzqfVXJUk2pcMio8RVlvBujDsyjrPuhbRceSi+bUXIn+w==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:03:08Z",
"mac": "ENC[AES256_GCM,data:kA2KCDZkZuR5rD7uU4xn5sIkizcnpGcoa3PYMbl73eux7JJYuSpUojFBRcYo1WCwMeOQUGsqo8LVF/rYhH4BVJ9LERs5zTLBaUsTarY8r/UK0Q5lNYZqIrqcb5LgOf1uCvfdXg5yfaFgPFJrEqjeekb9bx8xvhDZXpsND93rrUI=,iv:B6JqWWcQV/MxP4ucAIe7EnLiq9c4pnAUj3dnEp9IXJU=,tag:1i0Fv2i7Lak5JzIbPa2/cw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:2FgvnmawAdk+/k+RVWNsKQlUFUF+pZrrEBuupdG50uLNyxHd7Gi772gKNgHWyzZ/lpODg5mQi0rL+GmZYQwtZ7h76AGUEeQvuMMTzVUop69txxwhJD2dxZyhUAxZpibwo/St84ai+8+VksLkCSYfTXCulaeOVh4=,iv:YkPNq4zDj35PRNgt2kHEkHhbLcVc9dHP/zrAwdd94sM=,tag:KwW/74C7Z/+3dNoXB3NHwQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBoaS94M0JsR2Q5N21DNnFB\nUHgvelRTK3FKZkNKcTJFbEJ1VGFIM256MVVRCmw5YjdyTVlXMlFpWnczV2dTSzhu\nSm5mMVRPeU1pYVFZNEN5MjJFZHVTejgKLS0tIDB0V2hSRkt5QzFYald0TWVza1lC\ncGNXemhGcklENTJiV1QvTFZxUDNRRlUK2dVEzSbdDNXZy7rQi5/Vq4KyHq5rMtEz\npTI8i1rFKIAy4TC7to03bOIudOIzKSCCzX31xARkM6qON0vEU9aHFg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1r99qtxl0v86wg8ndcem87yk5wag5xcsk98ngaumqzww6t7pyms0q5cyl80",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBEOEMzcExzTTF3MmpaenRN\ncS9RbnM0aStZSjNqbjF4QisrRjhoaDg1T0ZBCmFVOWJYZkFaOXBOUGJTdytYWk52\nVXV1MDdmSWQ1OS9iODAvN2c2Q3VGYXMKLS0tIEQxeWR4bmRoOWJ2Z1FyUk1PUk1n\nM0c5Ri9FdG9FNE9CZ29VSmgvN2xDdjgKjfG38gVOXXN2ftGiCPxMFbnh7lKM1USl\nqf11k+rgvR8M9XsDy2SnirKAaNmpks1dR6Zs5ppQuYJDEYyQCrEO5g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:02:45Z",
"mac": "ENC[AES256_GCM,data:TEH57vUZ/swTsWQPJ1X3J//xa1Q1LYPETZS7fuXCH1LCK51u88XGqVpNzSETREQ8LAOt34qN284b03UQIBGTeTr7I9cqt+/l8ew/0rFTiO3aiaT49q9aBkeFZlA+gy47r4hkhMmzGQJMUenvnzTHwT3Pw2RES5Vjs/2TSitpqlA=,iv:ffIotRGKU8y6j/VDLKbTmA8dZJVP5vafeG4F3wd60tc=,tag:q4xOwzLw5jxDR0pPIy2irA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:LUNuEP/xSmzJ44sheoIYN6F24Qpr3svn6rTVUpr4KZA8uVJ9gPUd4ko4+pDisc9PyXCcxx+cYGRqr1cBp8Q3R+IyFFlR2HzuReQJaScvgjlntGtMJ2hin/aBp4pHS0F4nqPcKKROiZvIN4NHsxQ6XRVDOZbI3kE=,iv:BdRHjQXJL/OGgmqWaEDLit/zHgduNfPe3GUmYDrWLPw=,tag:N0n7CCiu+COgrfrwHUwQBQ==,type:str]",
"sops": {
"age": [
{
"recipient": "age1hgjs2yqxhcxfgtvhydnfe5wzlagxw2dw4hu658e8neduy0lkye0skmjfc7",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBCYlhrU2c1NnIyTzlVRHEx\nQTFxOUY1OWJXcHl1OHpPdWN1ZGpQV0UvZ1NzCnlKbmx0bllWMTd1ZnIxUHY0ZUU0\nVG9Jb3grSEdWeVpwaHoyQUxvNERqT00KLS0tIGtwZm5aMU1DOUhJbVVpVzIxZFow\nNVEvMy91SEg3M094MEFBSkVMRkhKZmMKuUzbEITGkYS39G14JXbKWLjiQFd4SVft\nWH34B97TFhOqusVF3zHsSCMxm/0BMeBvLxO/3RmzlwBtgNiKOqLwtQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSA2SUhJQW5EN0VKVHpQdlZC\nYTczdVJiRFdFNGtURFc2SmxKWFFycjZkQUgwCnRBVkJvUytuUDlhVlhFYno2cnBR\nRUdjL0lab1MwZzhGTklyVWZDVFJmN3cKLS0tIFRjOC9DS3llWGZWMGI2aThVYTRu\nVEFhK2Y2YkRTZHEyMWV0Q05ISHdhVVUKo9bPdV1dUeIkm4gI0r9V/s1dAfJC+H5Z\nEIUdYA7fl3jRZ01cSZ0iYWlvdl2jj0XzKafZsEQU7rL0jg9zbA2s2g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:02:59Z",
"mac": "ENC[AES256_GCM,data:+JtuPacwUMHXtp93DZmkiVne7bQUP8J7VpoS8koM0oJWJqZoQRHd9qH/04lrpp8q/YoOXtqXwhViZvFLieJVRexiXf/AAHfAfMn0EI7ois9oHhscN88Ps9nY6JUxhNd0h0OrUA58KKhrkGoqreAKAPADtVhaVCmWbU7vMUu1StE=,iv:BmJnTsgMSbl4XsBUkhSLfKd0XjhrEQfurEkaRJ6uD/g=,tag:jg21c4y4bQp0RwWTXkxF1A==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,19 @@
{
"data": "ENC[AES256_GCM,data:armAfuTE0mkoy1fxAysCX/UPNM4/mt9P6/zEDwtagTSvQjMTwVzzsM+kRdLOUV4fbZ7HdqMceaZWzurAQJenXvWlBXgn87YFOFBSpf3OnpEwCTUs9H8dsVrdSUk4SrKjCjV33mybTrae/h9tMHdkRhKJzPD1+/8=,iv:x9KVGqT2Ug6B6PNwzL7NVDQqyOmFUptUsHAJEdn30dg=,tag:XSSO6JvXaXq8aezYvpF65Q==,type:str]",
"sops": {
"age": [
{
"recipient": "age1k6h9mespmnr9zhtwwqlhnla80x5jhpd4c2p7hp0nfanr5tspup0s0rld2f",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBIMVUwMEFzVjJhYXg5MXR4\nMzZPZUFrUWdEU2hPWUVDNHpVVENpdEdYSWtnCnN0R2pVdEIxYWZXYWNBb3N5bGNK\naVpWOXp5aWVJWG9vUWtMUnhYSmMyV0UKLS0tIEtMdFAybk1PN0t2M2lkaEYzUTY3\nVzVOdTBFbnlNVTAvRU5kU0dReEZ6MlUKNHIkAUUAqnuMtXbvXqLxQwuFALsnD/i0\naBCiz6J4S18uqt3kFbXAEksbD7jCexI8m5SMp4iuumWJ/Bx1lL4TWg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkbzBFSGt1dXI2bDN5TmFU\nY3N6djNmMTh2ek4vUzdHbTF6Z1hDQ2t5WVNJClEzZDZiaVpBekFrYTYweDNsNmk5\nTlhYZGRNd0llMndyMkZWMyt5N3pwTE0KLS0tIGJJbU9vbnBhSE5vRW1pRG83cEFJ\nR2xDTHk3VkJaVUZSVThRV3Jldkp6cnMK1V37txaSFYfLQM0qqRWjojyTN4fTJkRm\nGO3yHX9uwo/4D2xI7LM48n4vnNhSF05bWpq0X4r13fI4DofCJeEo1g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:03:11Z",
"mac": "ENC[AES256_GCM,data:qD1w+DO8cWFDQMBOrmO9FvxvJRn+mlUbh13exTGgmsdPn3uzTXknIDDHeWfkpF699nSzS6wRmgrB21e55rBU6iHMx1TW16S8wvCoYMFwib8zTrJzND7EJr/gRwQa0N080kBY3xBivKLUFlctgKtFUYZ9GQ6UTQeq18QKPoROjww=,iv:1mt8Er6YHxQ42F5Kb+xNtjbCAzokbeoNlHesC9Uzmhk=,tag:provO4tKDzoL5PHDg5EmhA==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

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

View File

@@ -0,0 +1,27 @@
{
"data": "ENC[AES256_GCM,data:VzcB/JABSPoFdKYhRSn+nKxasn9zO/9fyNMrg3XstBelQNPpbO8mhmcnSamc/7e5GkpoVWgLRSULvosv+o6sz9EHRZ3UpSLBBTkDGAJmoBnkR8DbstPA9EgScpQ9IGOUP5tQ0oEOcJC3FrivdbWIzeXjpWb9BrU=,iv:6BNUrubJ9aNCkgonDRNgdyckCTndkPVDLE4X3J5d2zA=,tag:YqHTiGslEkslzUk24bmPZg==,type:str]",
"sops": {
"age": [
{
"recipient": "age1hgjs2yqxhcxfgtvhydnfe5wzlagxw2dw4hu658e8neduy0lkye0skmjfc7",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBwK2lMUTkrSmM4dHQxU0tI\nRVV6Wm4wWlJMYXBGbGdubExrMi8vRnJjdVd3CjI3aFVpdHRURHp6UEk3ZEZMcDZT\nZWZWaGFWYmY2Mk1iQ1BjalZkUnpUUm8KLS0tIEhFUVhBUjg1dC9LWHg2TytkRTlX\nNnlJZkJQc2ExK1BwaVVFcEw2b3BLZjQK8kqf3ZP9uLtbjCJLSEYpAqgq9zOS2HrY\n5MbPAKQI8iCUfnegti6hU+/MxjvPlaX1vT4V0Kd3gT4Khjl+OPw0Og==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1r99qtxl0v86wg8ndcem87yk5wag5xcsk98ngaumqzww6t7pyms0q5cyl80",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBWeUk3ZW9rdnZBTk9vQlFZ\nTzFZVDAvcXZyQjdkcGNNbnA0T3UyM3lzVERvCjFreE9RdWxnb2xWWmI4amJVdHBv\nNE9JN2tFazRnSGhiM0FId2RCUHNKWVEKLS0tIGlmM3JNSVZtR21ndFliUVpLTzJO\ncHJ2SjI1OExQK2hEN01WdG9wZ3RmVTAKi0BXp9yV2/9a9NeT7aTSK2CfkQ5yColJ\nm0+uv5AJndZ9IsaZGJxNOdAOspYdvsW38hFdfjUtVuUCyIOPc20WUg==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1k6h9mespmnr9zhtwwqlhnla80x5jhpd4c2p7hp0nfanr5tspup0s0rld2f",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSBkSUR1QVMvZ3F0NUxXd00z\nOWJGZFlsUy8vUmMxa1NoakZRVmJrSmd1RzBrCk1ZcDlBMFB0WVdWeFZaT3ZBTTh5\nS2RReWpUOGRBdGV6MDdjcEY5dFYrdjAKLS0tIG9oRWhUaWJZSElRdmlOZmRKSnNq\nUUNDZFdZbmM0c25MOGpvem1JSm9pVWsKxCLPivdHc6IN6Jbf9FujLGJaXP6ieO1S\nKsrs3Fe0RdYcEKI7P9EQNebQD2kKXficM0kKV5lRRVtW5024PftWoQ==\n-----END AGE ENCRYPTED FILE-----\n"
},
{
"recipient": "age1qm0p4vf9jvcnn43s6l4prk8zn6cx0ep9gzvevxecv729xz540v8qa742eg",
"enc": "-----BEGIN AGE ENCRYPTED FILE-----\nYWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IFgyNTUxOSB3amkyWWlxSTJkZEdMZFhL\nU2t5OGFIa25TRmdFM0ZNcUhFRHk0eDJQN2tjCm9UcUs2V0lEZ0hyNU9uaDVrckpj\nZ1JSQlhNeExjOER2aFJTM2NDS25PN2MKLS0tIFhmM21rT0Z4aUI5TUZyNnNBQ3Jy\nSDAxejhhZDZNQTVCNjNUSTBsZncra1kKFFQrFxNMyg0AEMb1wpKBc7LOVtEHyFZW\n/o7L52fTNa0GFJ3SVEdqg0PpnRzTyA8F5L77FBGKtx6auCVVHyZZ9g==\n-----END AGE ENCRYPTED FILE-----\n"
}
],
"lastmodified": "2025-07-09T10:02:48Z",
"mac": "ENC[AES256_GCM,data:HooesDb1S24Cfb7H0lVTA8fAjM2QAN9MaJFvOSHniR6ICJAX8t8X0xfWIFRFuwPjAxi4kpBYSjW0420Yz9lZ2m4Fxswo1TV3lzHDVN2u9hdrsfpKXg5fW+2oZihuvCRStDagT3l2fKv+C+gBnGs1qyCM60BStvrEiQxTxTTHfho=,iv:kL8N0qBj4q+ZJbNJ8Y8RcV1KpUUMvNCpdwKbTPGpG6k=,tag:o2PmRsSkqTP5Idq7veGDOw==,type:str]",
"unencrypted_suffix": "_unencrypted",
"version": "3.10.2"
}
}

View File

@@ -0,0 +1,3 @@
-----BEGIN PUBLIC KEY-----
MCowBQYDK2VwAyEA/MuamRX6ZLcJunm7lZvlai0OZh++YuqMa56GiTwO68A=
-----END PUBLIC KEY-----

View File

@@ -4,6 +4,7 @@
manifest.name = "clan-core/emergency-access"; manifest.name = "clan-core/emergency-access";
manifest.description = "Set recovery password for emergency access to machine"; manifest.description = "Set recovery password for emergency access to machine";
manifest.categories = [ "System" ]; manifest.categories = [ "System" ];
manifest.readme = builtins.readFile ./README.md;
roles.default.perInstance = { roles.default.perInstance = {
nixosModule = nixosModule =

View File

@@ -23,7 +23,13 @@ in
unit-test-module = ( unit-test-module = (
self.clanLib.test.flakeModules.makeEvalChecks { self.clanLib.test.flakeModules.makeEvalChecks {
inherit module; inherit module;
inherit self inputs; inherit inputs;
fileset = lib.fileset.unions [
# The hello-world service being tested
../../clanServices/hello-world
# Required modules
../../nixosModules/clanCore
];
testName = "hello-world"; testName = "hello-world";
tests = ./tests/eval-tests.nix; tests = ./tests/eval-tests.nix;
# Optional arguments passed to the test # Optional arguments passed to the test

View File

@@ -1,7 +1,7 @@
The importer module allows users to configure importing modules in a flexible and structured way. The importer module allows users to configure importing modules in a flexible and structured way.
It exposes the `extraModules` functionality of the inventory, without any added configuration. It exposes the `extraModules` functionality of the inventory, without any added configuration.
## Usage: ## Usage
```nix ```nix
inventory.instances = { inventory.instances = {

View File

@@ -0,0 +1,36 @@
The `sshd` Clan service manages SSH to make it easy to securely access your machines over the internet. The service uses `vars` to store the SSH host keys for each machine to ensure they remain stable across deployments.
`sshd` also generates SSH certificates for both servers and clients allowing for certificate-based authentication for SSH.
The service also disables password-based authentication over SSH, to access your machines you'll need to use public key authentication or certificate-based authentication.
## Usage
```nix
{
inventory.instances = {
# By default this service only generates ed25519 host keys
sshd-basic = {
module = {
name = "sshd";
input = "clan-core";
};
roles.server.tags.all = { };
roles.client.tags.all = { };
};
# Also generate RSA host keys for all servers
sshd-with-rsa = {
module = {
name = "sshd";
input = "clan-core";
};
roles.server.tags.all = { };
roles.server.settings = {
hostKeys.rsa.enable = true;
};
roles.client.tags.all = { };
};
};
}
```

View File

@@ -2,11 +2,12 @@
{ {
_class = "clan.service"; _class = "clan.service";
manifest.name = "clan-core/sshd"; manifest.name = "clan-core/sshd";
manifest.description = "Enables secure remote access to the machine over ssh."; manifest.description = "Enables secure remote access to the machine over SSH";
manifest.categories = [ manifest.categories = [
"System" "System"
"Network" "Network"
]; ];
manifest.readme = builtins.readFile ./README.md;
roles.client = { roles.client = {
interface = interface =
@@ -49,7 +50,7 @@
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519 ssh-keygen -t ed25519 -N "" -C "" -f "$out"/id_ed25519
''; '';
}; };
@@ -109,7 +110,7 @@
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/id_ed25519 ssh-keygen -t ed25519 -N "" -C "" -f "$out"/id_ed25519
''; '';
}; };
@@ -151,7 +152,7 @@
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t rsa -b 4096 -N "" -f "$out"/ssh.id_rsa ssh-keygen -t rsa -b 4096 -N "" -C "" -f "$out"/ssh.id_rsa
''; '';
}; };
@@ -164,7 +165,7 @@
pkgs.openssh pkgs.openssh
]; ];
script = '' script = ''
ssh-keygen -t ed25519 -N "" -f "$out"/ssh.id_ed25519 ssh-keygen -t ed25519 -N "" -C "" -f "$out"/ssh.id_ed25519
''; '';
}; };
}; };

View File

@@ -4,6 +4,7 @@
manifest.name = "clan-core/state-version"; manifest.name = "clan-core/state-version";
manifest.description = "Automatically generate the state version of the nixos installation."; manifest.description = "Automatically generate the state version of the nixos installation.";
manifest.categories = [ "System" ]; manifest.categories = [ "System" ];
manifest.readme = builtins.readFile ./README.md;
roles.default = { roles.default = {
@@ -24,7 +25,7 @@
warnings = [ warnings = [
'' ''
The clan.state-version service is deprecated and will be The clan.state-version service is deprecated and will be
removed on 2025-07-15 in favor of a nix option. removed on 2025-07-15 in favor of a nix option.
Please migrate your configuration to use `clan.core.settings.state-version.enable = true` instead. Please migrate your configuration to use `clan.core.settings.state-version.enable = true` instead.
'' ''

View File

@@ -4,6 +4,7 @@
manifest.name = "clan-core/trusted-nix-caches"; manifest.name = "clan-core/trusted-nix-caches";
manifest.description = "This module sets the `clan.lol` and `nix-community` cache up as a trusted cache."; manifest.description = "This module sets the `clan.lol` and `nix-community` cache up as a trusted cache.";
manifest.categories = [ "System" ]; manifest.categories = [ "System" ];
manifest.readme = builtins.readFile ./README.md;
roles.default = { roles.default = {

View File

@@ -1,30 +1,31 @@
## Usage ## Usage
``` ```nix
inventory.instances = { {
inventory.instances = {
# Deploy user alice on all machines. Don't prompt for password (will be # Deploy user alice on all machines. Don't prompt for password (will be
# auto-generated). # auto-generated).
user-alice = {
user-alice = { module = {
module = { name = "users";
name = "users"; input = "clan";
input = "clan"; };
roles.default.tags.all = { };
roles.default.settings = {
user = "alice";
prompt = false;
};
}; };
roles.default.tags.all = { };
roles.default.settings = { # Deploy user bob only on his laptop. Prompt for a password.
user = "alice"; user-bob = {
prompt = false; module = {
name = "users";
input = "clan";
};
roles.default.machines.bobs-laptop = { };
roles.default.settings.user = "bob";
}; };
}; };
}
# Deploy user bob only on his laptop. Prompt for a password.
user-bob = {
module = {
name = "users";
input = "clan";
};
roles.default.machines.bobs-laptop = { };
roles.default.settings.user = "bob";
};
``` ```

View File

@@ -1,13 +1,17 @@
{ ... }: { ... }:
{ {
_class = "clan.service"; _class = "clan.service";
manifest.name = "clan-core/users"; manifest.name = "clan-core/user";
manifest.description = "Automatically generates and configures a password for the specified user account."; manifest.description = ''
An instance of this module will create a user account on the added machines,
along with a generated password that is constant across machines and user settings.
'';
manifest.categories = [ "System" ]; manifest.categories = [ "System" ];
manifest.readme = builtins.readFile ./README.md;
roles.default = { roles.default = {
interface = interface =
{ lib, ... }: { config, lib, ... }:
{ {
options = { options = {
user = lib.mkOption { user = lib.mkOption {
@@ -19,7 +23,58 @@
type = lib.types.bool; type = lib.types.bool;
default = true; default = true;
example = false; example = false;
description = "Whether the user should be prompted."; description = ''
Whether the user should be prompted for a password.
Effects:
- *enabled* (`true`) - Prompt for a password during the machine installation or update workflow.
- *disabled* (`false`) - Generate a password during the machine installation or update workflow.
The password can be shown in two steps:
- `clan vars list <machine-name>`
- `clan vars get <machine-name> <name-of-password-variable>`
'';
};
regularUser = lib.mkOption {
type = lib.types.bool;
default = config.user != "root";
defaultText = lib.literalExpression "config.user != \"root\"";
example = false;
description = ''
Whether the user should be a regular user or a system user.
Regular users are normal users that can log in and have a home directory.
System users are used for system services and do not have a home directory.
!!! Warning
`root` cannot be a regular user.
You must set this to `false` for `root`
'';
};
groups = lib.mkOption {
type = lib.types.listOf lib.types.str;
default = [ ];
example = [
"wheel"
"networkmanager"
"video"
"input"
];
description = ''
Additional groups the user should be added to.
You can add any group that exists on your system.
Make sure these group exists on all machines where the user is enabled.
Commonly used groups:
- "wheel" - Allows the user to run commands as root using `sudo`.
- "networkmanager" - Allows the user to manage network connections.
- "video" - Allows the user to access video devices.
- "input" - Allows the user to access input devices.
'';
}; };
}; };
}; };
@@ -35,9 +90,13 @@
... ...
}: }:
{ {
users.mutableUsers = false; users.users.${settings.user} = {
users.users.${settings.user}.hashedPasswordFile = isNormalUser = settings.regularUser;
config.clan.core.vars.generators."user-password-${settings.user}".files.user-password-hash.path; extraGroups = settings.groups;
hashedPasswordFile =
config.clan.core.vars.generators."user-password-${settings.user}".files.user-password-hash.path;
};
clan.core.vars.generators."user-password-${settings.user}" = { clan.core.vars.generators."user-password-${settings.user}" = {
@@ -80,4 +139,11 @@
}; };
}; };
}; };
perMachine = {
nixosModule = {
# Immutable users to ensure that this module has exclusive control over the users.
users.mutableUsers = false;
};
};
} }

View File

@@ -31,7 +31,6 @@
server = { server = {
users.users.testuser.group = "testuser"; users.users.testuser.group = "testuser";
users.groups.testuser = { }; users.groups.testuser = { };
users.users.testuser.isNormalUser = true;
}; };
}; };

View File

@@ -15,7 +15,15 @@ in
unit-test-module = ( unit-test-module = (
self.clanLib.test.flakeModules.makeEvalChecks { self.clanLib.test.flakeModules.makeEvalChecks {
inherit module; inherit module;
inherit self inputs; inherit inputs;
fileset = lib.fileset.unions [
# The zerotier service being tested
../../clanServices/zerotier
# Required modules
../../nixosModules/clanCore
# Dependencies like clan-cli
../../pkgs/clan-cli
];
testName = "zerotier"; testName = "zerotier";
tests = ./tests/eval-tests.nix; tests = ./tests/eval-tests.nix;
testArgs = { }; testArgs = { };

1
devFlake/private.narHash Normal file
View File

@@ -0,0 +1 @@
sha256-LdjcFZLL8WNldUO2LbdqFlss/ERiGeXVqMee0IxV2z0=

165
devFlake/private/flake.lock generated Normal file
View File

@@ -0,0 +1,165 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": [
"systems"
]
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"ixx": {
"inputs": {
"flake-utils": [
"nuschtos",
"flake-utils"
],
"nixpkgs": [
"nuschtos",
"nixpkgs"
]
},
"locked": {
"lastModified": 1748294338,
"narHash": "sha256-FVO01jdmUNArzBS7NmaktLdGA5qA3lUMJ4B7a05Iynw=",
"owner": "NuschtOS",
"repo": "ixx",
"rev": "cc5f390f7caf265461d4aab37e98d2292ebbdb85",
"type": "github"
},
"original": {
"owner": "NuschtOS",
"ref": "v0.0.8",
"repo": "ixx",
"type": "github"
}
},
"nixpkgs-dev": {
"locked": {
"lastModified": 1752039390,
"narHash": "sha256-DTHMN6kh1cGoc5hc9O0pYN+VAOnjsyy0wxq4YO5ZRvg=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "6ec4d5f023c3c000cda569255a3486e8710c39bf",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs",
"type": "github"
}
},
"nuschtos": {
"inputs": {
"flake-utils": "flake-utils_2",
"ixx": "ixx",
"nixpkgs": [
"nixpkgs-dev"
]
},
"locked": {
"lastModified": 1749730855,
"narHash": "sha256-L3x2nSlFkXkM6tQPLJP3oCBMIsRifhIDPMQQdHO5xWo=",
"owner": "NuschtOS",
"repo": "search",
"rev": "8dfe5879dd009ff4742b668d9c699bc4b9761742",
"type": "github"
},
"original": {
"owner": "NuschtOS",
"repo": "search",
"type": "github"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs-dev": "nixpkgs-dev",
"nuschtos": "nuschtos",
"systems": "systems_2",
"treefmt-nix": "treefmt-nix"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"treefmt-nix": {
"inputs": {
"nixpkgs": []
},
"locked": {
"lastModified": 1752055615,
"narHash": "sha256-19m7P4O/Aw/6+CzncWMAJu89JaKeMh3aMle1CNQSIwM=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "c9d477b5d5bd7f26adddd3f96cfd6a904768d4f9",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

View File

@@ -0,0 +1,19 @@
{
description = "private dev inputs";
# Dev dependencies
inputs.nixpkgs-dev.url = "github:NixOS/nixpkgs/nixos-unstable-small";
inputs.flake-utils.url = "github:numtide/flake-utils";
inputs.flake-utils.inputs.systems.follows = "systems";
inputs.nuschtos.url = "github:NuschtOS/search";
inputs.nuschtos.inputs.nixpkgs.follows = "nixpkgs-dev";
inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
inputs.treefmt-nix.inputs.nixpkgs.follows = "";
inputs.systems.url = "github:nix-systems/default";
outputs = _: { };
}

12
devFlake/update-private-narhash Executable file
View File

@@ -0,0 +1,12 @@
#!/usr/bin/env bash
# Used to update the private dev flake hash reference.
set -euo pipefail
cd "$(dirname "$0")"
echo "Updating $PWD/private.narHash" >&2
nix --extra-experimental-features 'flakes nix-command' flake lock ./private
nix --extra-experimental-features 'flakes nix-command' hash path ./private >./private.narHash
echo OK

View File

@@ -51,6 +51,7 @@ nav:
- 🚀 Creating Your First Clan: guides/getting-started/index.md - 🚀 Creating Your First Clan: guides/getting-started/index.md
- 📀 Create USB Installer (optional): guides/getting-started/installer.md - 📀 Create USB Installer (optional): guides/getting-started/installer.md
- ⚙️ Add Machines: guides/getting-started/add-machines.md - ⚙️ Add Machines: guides/getting-started/add-machines.md
- ⚙️ Add User: guides/getting-started/add-user.md
- ⚙️ Add Services: guides/getting-started/add-services.md - ⚙️ Add Services: guides/getting-started/add-services.md
- 🔐 Secrets & Facts: guides/getting-started/secrets.md - 🔐 Secrets & Facts: guides/getting-started/secrets.md
- 🚢 Deploy Machine: guides/getting-started/deploy.md - 🚢 Deploy Machine: guides/getting-started/deploy.md
@@ -62,6 +63,7 @@ nav:
- Vars Backend: guides/vars-backend.md - Vars Backend: guides/vars-backend.md
- Facts Backend: guides/secrets.md - Facts Backend: guides/secrets.md
- Adding more machines: guides/more-machines.md - Adding more machines: guides/more-machines.md
- Target Host: guides/target-host.md
- Inventory: - Inventory:
- Inventory: guides/inventory.md - Inventory: guides/inventory.md
- Secure Boot: guides/secure-boot.md - Secure Boot: guides/secure-boot.md
@@ -78,6 +80,7 @@ nav:
- Migrate existing Flakes: guides/migrations/migration-guide.md - Migrate existing Flakes: guides/migrations/migration-guide.md
- Migrate inventory Services: guides/migrations/migrate-inventory-services.md - Migrate inventory Services: guides/migrations/migrate-inventory-services.md
- Facts Vars Migration: guides/migrations/migration-facts-vars.md - Facts Vars Migration: guides/migrations/migration-facts-vars.md
- Disk id: guides/migrations/disk-id.md
- macOS: guides/macos.md - macOS: guides/macos.md
- Reference: - Reference:
- Overview: reference/index.md - Overview: reference/index.md
@@ -85,6 +88,7 @@ nav:
- Overview: reference/clanServices/index.md - Overview: reference/clanServices/index.md
- reference/clanServices/admin.md - reference/clanServices/admin.md
- reference/clanServices/borgbackup.md - reference/clanServices/borgbackup.md
- reference/clanServices/data-mesher.md
- reference/clanServices/emergency-access.md - reference/clanServices/emergency-access.md
- reference/clanServices/garage.md - reference/clanServices/garage.md
- reference/clanServices/hello-world.md - reference/clanServices/hello-world.md
@@ -154,6 +158,7 @@ nav:
- reference/cli/show.md - reference/cli/show.md
- reference/cli/ssh.md - reference/cli/ssh.md
- reference/cli/state.md - reference/cli/state.md
- reference/cli/templates.md
- reference/cli/vars.md - reference/cli/vars.md
- reference/cli/vms.md - reference/cli/vms.md
- NixOS Modules: - NixOS Modules:
@@ -197,7 +202,6 @@ theme:
- navigation.instant - navigation.instant
- navigation.tabs - navigation.tabs
- navigation.tabs.sticky - navigation.tabs.sticky
- navigation.footer
- content.code.annotate - content.code.annotate
- content.code.copy - content.code.copy
- content.tabs.link - content.tabs.link

View File

@@ -1,5 +1,4 @@
{ {
clan-core,
pkgs, pkgs,
module-docs, module-docs,
clan-cli-docs, clan-cli-docs,
@@ -19,7 +18,17 @@ pkgs.stdenv.mkDerivation {
# Points to repository root. # Points to repository root.
# so that we can access directories outside of docs to include code snippets # so that we can access directories outside of docs to include code snippets
src = clan-core; src = pkgs.lib.fileset.toSource {
root = ../..;
fileset = pkgs.lib.fileset.unions [
# Docs directory
../../docs
# Icons needed for the build
../../pkgs/clan-app/ui/icons
# Any other directories that might be referenced for code snippets
# Add them here as needed based on what mkdocs actually uses
];
};
nativeBuildInputs = nativeBuildInputs =
[ [

View File

@@ -29,7 +29,10 @@
# Frontmatter for clanModules # Frontmatter for clanModules
clanModulesFrontmatter = clanModulesFrontmatter =
let let
docs = pkgs.nixosOptionsDoc { options = self.clanLib.modules.frontmatterOptions; }; docs = pkgs.nixosOptionsDoc {
options = self.clanLib.modules.frontmatterOptions;
transformOptions = self.clanLib.docs.stripStorePathsFromDeclarations;
};
in in
docs.optionsJSON; docs.optionsJSON;
@@ -82,10 +85,9 @@
} }
'' ''
export CLAN_CORE_PATH=${ export CLAN_CORE_PATH=${
self.filter { inputs.nixpkgs.lib.fileset.toSource {
include = [ root = ../..;
"clanModules" fileset = ../../clanModules;
];
} }
} }
export CLAN_CORE_DOCS=${jsonDocs.clanCore}/share/doc/nixos/options.json export CLAN_CORE_DOCS=${jsonDocs.clanCore}/share/doc/nixos/options.json
@@ -126,7 +128,6 @@
}); });
packages = { packages = {
docs = pkgs.python3.pkgs.callPackage ./default.nix { docs = pkgs.python3.pkgs.callPackage ./default.nix {
clan-core = self;
inherit (self'.packages) inherit (self'.packages)
clan-cli-docs clan-cli-docs
docs-options docs-options

View File

@@ -7,6 +7,10 @@
pkgs, pkgs,
clan-core, clan-core,
}: }:
let
inherit (clan-core.clanLib.docs) stripStorePathsFromDeclarations;
transformOptions = stripStorePathsFromDeclarations;
in
{ {
# clanModules docs # clanModules docs
clanModulesViaNix = lib.mapAttrs ( clanModulesViaNix = lib.mapAttrs (
@@ -20,6 +24,7 @@
}).options }).options
).clan.${name} or { }; ).clan.${name} or { };
warningsAreErrors = true; warningsAreErrors = true;
inherit transformOptions;
}).optionsJSON }).optionsJSON
else else
{ } { }
@@ -32,6 +37,7 @@
(nixosOptionsDoc { (nixosOptionsDoc {
inherit options; inherit options;
warningsAreErrors = true; warningsAreErrors = true;
inherit transformOptions;
}).optionsJSON }).optionsJSON
) rolesOptions ) rolesOptions
) modulesRolesOptions; ) modulesRolesOptions;
@@ -52,7 +58,15 @@
(nixosOptionsDoc { (nixosOptionsDoc {
transformOptions = transformOptions =
opt: if lib.strings.hasPrefix "_" opt.name then opt // { visible = false; } else opt; opt:
let
# Apply store path stripping first
transformed = transformOptions opt;
in
if lib.strings.hasPrefix "_" transformed.name then
transformed // { visible = false; }
else
transformed;
options = (lib.evalModules { modules = [ role.interface ]; }).options; options = (lib.evalModules { modules = [ role.interface ]; }).options;
warningsAreErrors = true; warningsAreErrors = true;
}).optionsJSON }).optionsJSON
@@ -72,5 +86,6 @@
}).options }).options
).clan.core or { }; ).clan.core or { };
warningsAreErrors = true; warningsAreErrors = true;
inherit transformOptions;
}).optionsJSON; }).optionsJSON;
} }

View File

@@ -1,9 +1,15 @@
{ self, config, ... }: {
self,
config,
inputs,
privateInputs ? { },
...
}:
{ {
perSystem = perSystem =
{ {
inputs',
lib, lib,
pkgs,
... ...
}: }:
let let
@@ -157,11 +163,16 @@
}; };
in in
{ {
packages.docs-options = inputs'.nuschtos.packages.mkMultiSearch { packages = lib.optionalAttrs ((privateInputs ? nuschtos) || (inputs ? nuschtos)) {
inherit baseHref; docs-options =
title = "Clan Options"; (privateInputs.nuschtos or inputs.nuschtos)
# scopes = mapAttrsToList mkScope serviceModules; .packages.${pkgs.stdenv.hostPlatform.system}.mkMultiSearch
scopes = [ (mkScope "Clan Inventory" serviceModules) ]; {
inherit baseHref;
title = "Clan Options";
# scopes = mapAttrsToList mkScope serviceModules;
scopes = [ (mkScope "Clan Inventory" serviceModules) ];
};
}; };
}; };
} }

View File

@@ -29,13 +29,13 @@ from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import Any from typing import Any
from clan_lib.api.modules import ( from clan_lib.errors import ClanError
from clan_lib.services.modules import (
CategoryInfo, CategoryInfo,
Frontmatter, Frontmatter,
extract_frontmatter, extract_frontmatter,
get_roles, get_roles,
) )
from clan_lib.errors import ClanError
# Get environment variables # Get environment variables
CLAN_CORE_PATH = Path(os.environ["CLAN_CORE_PATH"]) CLAN_CORE_PATH = Path(os.environ["CLAN_CORE_PATH"])
@@ -62,14 +62,11 @@ def sanitize(text: str) -> str:
return text.replace(">", "\\>") return text.replace(">", "\\>")
def replace_store_path(text: str) -> tuple[str, str]: def replace_git_url(text: str) -> tuple[str, str]:
res = text res = text
if text.startswith("/nix/store/"): name = Path(res).name
res = "https://git.clan.lol/clan/clan-core/src/branch/main/" + str( if text.startswith("https://git.clan.lol/clan/clan-core/src/branch/main/"):
Path(*Path(text).parts[4:]) name = str(Path(*Path(text).parts[7:]))
)
# name = Path(res).name
name = str(Path(*Path(text).parts[4:]))
return (res, name) return (res, name)
@@ -159,7 +156,7 @@ def render_option(
decls = option.get("declarations", []) decls = option.get("declarations", [])
if decls: if decls:
source_path, name = replace_store_path(decls[0]) source_path, name = replace_git_url(decls[0])
name = name.split(",")[0] name = name.split(",")[0]
source_path = source_path.split(",")[0] source_path = source_path.split(",")[0]
@@ -452,7 +449,6 @@ Each `clanService`:
* Is a module of class **`clan.service`** * Is a module of class **`clan.service`**
* Can define **roles** (e.g., `client`, `server`) * Can define **roles** (e.g., `client`, `server`)
* Uses **`inventory.instances`** to configure where and how it is deployed * Uses **`inventory.instances`** to configure where and how it is deployed
* Replaces the legacy `clanModules` and `inventory.services` system altogether
!!! Note !!! Note
`clanServices` are part of Clan's next-generation service model and are intended to replace `clanModules`. `clanServices` are part of Clan's next-generation service model and are intended to replace `clanModules`.

View File

@@ -28,7 +28,7 @@ Benefits:
* Caching mechanism is very simple. * Caching mechanism is very simple.
### Method 2: Direct access: ### Method 2: Direct access
Directly calling the evaluator / build sandbox via `nix build` and `nix eval`within the Python code Directly calling the evaluator / build sandbox via `nix build` and `nix eval`within the Python code

View File

@@ -52,6 +52,7 @@ clanModules/borgbackup
```nix title="flake.nix" ```nix title="flake.nix"
# ... # ...
# Sometimes this attribute set is defined in clan.nix
clan-core.lib.clan { clan-core.lib.clan {
# 1. Add the module to the available clanModules with inventory support # 1. Add the module to the available clanModules with inventory support
inventory.modules = { inventory.modules = {
@@ -175,6 +176,7 @@ The following shows how to add options to your module.
Configuration can be set as follows. Configuration can be set as follows.
```nix title="flake.nix" ```nix title="flake.nix"
# Sometimes this attribute set is defined in clan.nix
clan-core.lib.clan { clan-core.lib.clan {
inventory.services = { inventory.services = {
custom-module.instance_1 = { custom-module.instance_1 = {

View File

@@ -27,6 +27,7 @@ i.e. `@hsjobeki/customNetworking`
outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({ outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } ({
imports = [ inputs.clan-core.flakeModules.default ]; imports = [ inputs.clan-core.flakeModules.default ];
# ... # ...
# Sometimes this attribute set is defined in clan.nix
clan = { clan = {
# If needed: Exporting the module for other people # If needed: Exporting the module for other people
modules."@hsjobeki/customNetworking" = import ./service-modules/networking.nix; modules."@hsjobeki/customNetworking" = import ./service-modules/networking.nix;
@@ -218,6 +219,7 @@ To import the module use `importApply`
outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}: { outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}: {
imports = [ inputs.clan-core.flakeModules.default ]; imports = [ inputs.clan-core.flakeModules.default ];
# ... # ...
# Sometimes this attribute set is defined in clan.nix
clan = { clan = {
# Register the module # Register the module
modules."@hsjobeki/messaging" = lib.importApply ./service-modules/messaging.nix { inherit self; }; modules."@hsjobeki/messaging" = lib.importApply ./service-modules/messaging.nix { inherit self; };
@@ -244,6 +246,7 @@ Then wrap the module and forward the variable `self` from the outer context into
outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}: { outputs = inputs: flake-parts.lib.mkFlake { inherit inputs; } ({self, lib, ...}: {
imports = [ inputs.clan-core.flakeModules.default ]; imports = [ inputs.clan-core.flakeModules.default ];
# ... # ...
# Sometimes this attribute set is defined in clan.nix
clan = { clan = {
# Register the module # Register the module
modules."@hsjobeki/messaging" = { modules."@hsjobeki/messaging" = {

View File

@@ -55,9 +55,37 @@ If you're using VSCode, it has a handy feature that makes paths to source code f
## Finding Print Messages ## Finding Print Messages
To identify where a specific print message comes from, you can enable a helpful feature. Simply set the environment variable `export TRACE_PRINT=1`. When you run commands with `--debug` mode, each print message will include information about its source location. To trace the origin of print messages in `clan-cli`, you can enable special debugging features using environment variables:
- Set `TRACE_PRINT=1` to include the source location with each print message:
```bash
export TRACE_PRINT=1
```
When running commands with `--debug`, every print will show where it was triggered in the code.
- To see a deeper stack trace for each print, set `TRACE_DEPTH` to the desired number of stack frames (e.g., 3):
```bash
export TRACE_DEPTH=3
```
### Additional Debug Logging
You can enable more detailed logging for specific components by setting these environment variables:
- `CLAN_DEBUG_NIX_SELECTORS=1` — verbose logs for flake.select operations
- `CLAN_DEBUG_NIX_PREFETCH=1` — verbose logs for flake.prefetch operations
- `CLAN_DEBUG_COMMANDS=1` — print the diffed environment of executed commands
Example:
```bash
export CLAN_DEBUG_NIX_SELECTORS=1
export CLAN_DEBUG_NIX_PREFETCH=1
export CLAN_DEBUG_COMMANDS=1
```
These options help you pinpoint the source and context of print messages and debug logs during development.
If you need more details, you can expand the stack trace information that appears with each print by setting the environment variable `export TRACE_DEPTH=3`.
## Analyzing Performance ## Analyzing Performance
@@ -105,7 +133,7 @@ git+file:///home/lhebendanz/Projects/clan-core
│ ├───editor omitted (use '--all-systems' to show) │ ├───editor omitted (use '--all-systems' to show)
└───templates └───templates
├───default: template: Initialize a new clan flake ├───default: template: Initialize a new clan flake
└───new-clan: template: Initialize a new clan flake └───default: template: Initialize a new clan flake
``` ```
You can execute every test separately by following the tree path `nix run .#checks.x86_64-linux.clan-pytest -L` for example. You can execute every test separately by following the tree path `nix run .#checks.x86_64-linux.clan-pytest -L` for example.

View File

@@ -122,8 +122,8 @@ CTRL+D
4. Locally generate ssh host keys. You only need to generate ones for the algorithms you're using in `authorizedKeys`. 4. Locally generate ssh host keys. You only need to generate ones for the algorithms you're using in `authorizedKeys`.
```bash ```bash
ssh-keygen -q -N "" -t ed25519 -f ./initrd_host_ed25519_key ssh-keygen -q -N "" -C "" -t ed25519 -f ./initrd_host_ed25519_key
ssh-keygen -q -N "" -t rsa -b 4096 -f ./initrd_host_rsa_key ssh-keygen -q -N "" -C "" -t rsa -b 4096 -f ./initrd_host_rsa_key
``` ```
5. Securely copy your local initrd ssh host keys to the installer's `/mnt` directory: 5. Securely copy your local initrd ssh host keys to the installer's `/mnt` directory:

View File

@@ -10,64 +10,23 @@ See the complete [list](../../guides/more-machines.md#automatic-registration) of
## Create a machine ## Create a machine
=== "flake.nix (flake-parts)" === "clan.nix (declarative)"
```{.nix hl_lines=12-15} ```{.nix hl_lines="3-4"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; inventory.machines = {
inputs.nixpkgs.follows = "clan-core/nixpkgs"; # Define a machine
inputs.flake-parts.follows = "clan-core/flake-parts"; jon = { };
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.clan-core.flakeModules.default ];
clan = {
inventory.machines = {
# Define a machine
jon = { };
};
};
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
}; };
}
```
=== "flake.nix (classic)" # Additional NixOS configuration can be added here.
# machines/jon/configuration.nix will be automatically imported.
```{.nix hl_lines=11-14} # See: https://docs.clan.lol/guides/more-machines/#automatic-registration
{ machines = {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; # jon = { config, ... }: {
inputs.nixpkgs.follows = "clan-core/nixpkgs"; # environment.systemPackages = [ pkgs.asciinema ];
# };
outputs = };
{ self, clan-core, ... }:
let
clan = clan-core.lib.clan {
inherit self;
inventory.machines = {
# Define a machine
jon = { };
};
};
in
{
inherit (clan.config)
nixosConfigurations
nixosModules
clanInternals
darwinConfigurations
darwinModules
;
};
} }
``` ```
@@ -89,15 +48,15 @@ See the complete [list](../../guides/more-machines.md#automatic-registration) of
The option: `machines.<name>` is used to add extra *nixosConfiguration* to a machine The option: `machines.<name>` is used to add extra *nixosConfiguration* to a machine
```{.nix .annotate title="flake.nix" hl_lines="3-13 18-22"} Add the following to your `clan.nix` file for each machine.
clan = { This example demonstrates what is needed based on a machine called `jon`:
```{.nix .annotate title="clan.nix" hl_lines="3-6 15-19"}
{
inventory.machines = { inventory.machines = {
jon = { jon = {
# Define targetHost here # Define tags here (optional)
# Required before deployment tags = [ ]; # (1)
deploy.targetHost = "root@jon"; # (1)
# Define tags here
tags = [ ];
}; };
sara = { sara = {
deploy.targetHost = "root@sara"; deploy.targetHost = "root@sara";
@@ -116,9 +75,24 @@ clan = {
} }
``` ```
1. It is required to define a *targetHost* for each machine before deploying. Best practice has been, to use the zerotier ip/hostname or the ip from the from overlay network you decided to use. 1. Tags can be used to automatically add this machine to services later on. - You dont need to set this now.
2. Add your *ssh key* here - That will ensure you can always login to your machine via *ssh* in case something goes wrong. 2. Add your *ssh key* here - That will ensure you can always login to your machine via *ssh* in case something goes wrong.
### (Optional) Create a `configuration.nix`
```nix title="./machines/jon/configuration.nix"
{
imports = [
# enables GNOME desktop (optional)
../../modules/gnome.nix
];
# Set nixosOptions here
# Or import your own modules via 'imports'
# ...
}
```
### (Optional) Renaming a Machine ### (Optional) Renaming a Machine
Older templates included static machine folders like `jon` and `sara`. Older templates included static machine folders like `jon` and `sara`.

View File

@@ -17,102 +17,61 @@ To learn more: [Guide about clanService](../clanServices.md)
## Configure a Zerotier Network (recommended) ## Configure a Zerotier Network (recommended)
```{.nix title="flake.nix" hl_lines="20-28"} ```{.nix title="clan.nix" hl_lines="8-16"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; inventory.machines = {
inputs.nixpkgs.follows = "clan-core/nixpkgs"; jon = { };
inputs.flake-parts.follows = "clan-core/flake-parts"; sara = { };
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
outputs =
inputs@{ flake-parts, ... }:
flake-parts.lib.mkFlake { inherit inputs; } {
imports = [ inputs.clan-core.flakeModules.default ];
clan = {
inventory.machines = {
jon = {
targetHost = "root@jon";
};
sara = {
targetHost = "root@jon";
};
};
inventory.instances = {
zerotier = { # (1)
# Defines 'jon' as the controller
roles.controller.machines.jon = {};
# Defines all machines as networking peer.
# The 'all' tag is a clan builtin.
roles.peer.tags.all = {};
};
}
};
systems = [
"x86_64-linux"
"aarch64-linux"
"x86_64-darwin"
"aarch64-darwin"
];
}; };
inventory.instances = {
zerotier = { # (1)
# Replace with the name (string) of your machine that you will use as zerotier-controller
# See: https://docs.zerotier.com/controller/
# Deploy this machine first to create the network secrets
roles.controller.machines."jon" = { }; # (2)
# Peers of the network
# this line means 'all' clan machines will be 'peers'
roles.peer.tags.all = { }; # (3)
};
};
# ...
# elided
} }
``` ```
1. See [reference/clanServices](../../reference/clanServices/index.md) for all available services and how to configure them. 1. See [reference/clanServices](../../reference/clanServices/index.md) for all available services and how to configure them.
Or read [authoring/clanServices](../authoring/clanServices/index.md) if you want to bring your own Or read [authoring/clanServices](../authoring/clanServices/index.md) if you want to bring your own
2. Replace `__YOUR_CONTROLLER_` with the *name* of your machine.
3. This line will add all machines of your clan as `peer` to zerotier
## Adding more recommended defaults ## Adding more recommended defaults
Adding the following services is recommended for most users: Adding the following services is recommended for most users:
```{.nix title="flake.nix" hl_lines="25-35"} ```{.nix title="clan.nix" hl_lines="7-14"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; inventory.machines = {
inputs.nixpkgs.follows = "clan-core/nixpkgs"; jon = { };
inputs.flake-parts.follows = "clan-core/flake-parts"; sara = { };
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs"; };
inventory.instances = {
outputs = admin = { # (1)
inputs@{ flake-parts, ... }: roles.default.tags.all = { };
flake-parts.lib.mkFlake { inherit inputs; } { roles.default.settings = {
imports = [ inputs.clan-core.flakeModules.default ]; allowedKeys = {
clan = { "my-user" = "ssh-ed25519 AAAAC3N..."; # (2)
inventory.machines = {
jon = {
targetHost = "root@jon";
};
sara = {
targetHost = "root@jon";
};
};
inventory.instances = {
zerotier = {
roles.controller.machines.jon = {};
roles.peer.tags.all = {};
};
admin = { # (1)
roles.default.tags.all = { };
roles.default.settings = {
allowedKeys = {
"my-user" = "ssh-ed25519 AAAAC3N..."; # elided
};
};
};
state-version = { # (2)
roles.default.tags.all = { };
};
}; };
}; };
systems = [ };
"x86_64-linux" # ...
"aarch64-linux" # elided
"x86_64-darwin"
"aarch64-darwin"
];
}; };
} }
``` ```
1. The `admin` service will generate a **root-password** and **add your ssh-key** that allows for convienient administration. 1. The `admin` service will generate a **root-password** and **add your ssh-key** that allows for convienient administration.
2. Equivalent to directly setting `authorizedKeys` like in [configuring a machine](./add-machines.md#configuring-a-machine)
2. The `state-version` service will generate a [nixos state version](https://wiki.nixos.org/wiki/FAQ/When_do_I_update_stateVersion) for each system once it is deployed. 3. Adds `user = jon` as a user on all machines. Will create a `home` directory, and prompt for a password before deployment.

View File

@@ -0,0 +1,127 @@
# How to add users
!!! Note "Under construction"
The users concept of clan is not done yet. This guide outlines some solutions from our community.
Defining users can be done in many different ways. We want to highlight two approaches:
- Using clan's [users](../../reference/clanServices/users.md) service.
- Using a custom approach.
## Adding Users using the [users](../../reference/clanServices/users.md) service
To add a first *user* this guide will be leveraging two things:
- [clanServices](../../reference/clanServices/index.md): Allows to bind arbitrary logic to something we call an `ìnstance`.
- [clanServices/users](../../reference/clanServices/users.md): Implements logic for adding a single user perInstance.
The example shows how to add a user called `jon`:
```{.nix title="clan.nix" hl_lines="7-21"}
{
inventory.machines = {
jon = { };
sara = { };
};
inventory.instances = {
jon-user = { # (1)
module.name = "users";
roles.default.tags.all = { }; # (2)
roles.default.settings = {
user = "jon"; # (3)
groups = [
"wheel" # Allow using 'sudo'
"networkmanager" # Allows to manage network connections.
"video" # Allows to access video devices.
"input" # Allows to access input devices.
];
};
};
# ...
# elided
};
}
```
1. Add `user = jon` as a user on all machines. Will create a `home` directory, and prompt for a password before deployment.
2. Add this user to `all` machines
3. Define the `name` of the user to be `jon`
The `users` service creates a `/home/jon` directory, allows `jon` to sign in and will take care of the users password as part of [deployment](./deploy.md).
For more information see [clanService/users](../../reference/clanServices/users.md)
## Using a custom approach
Some people like to define a `users` folder in their repository root.
That allows to bind all user specific logic to a single place (`default.nix`)
Which can be imported into individual machines to make the user avilable on that machine.
```bash
.
├── machines
│   ├── jon
# ......
├── users
│   ├── jon
│ │ └── default.nix # <- a NixOS module; sets some options
# ... ... ...
```
## using [home-manager](https://github.com/nix-community/home-manager)
When using clan's `users` service it is possible to define extraModules.
In fact this is always possible when using clan's services.
We can use this property of clan services to bind a nixosModule to the user, which configures home-manager.
```{.nix title="clan.nix" hl_lines="22"}
{
inventory.machines = {
jon = { };
sara = { };
};
inventory.instances = {
jon-user = {
module.name = "users";
roles.default.tags.all = { };
roles.default.settings = {
user = "jon",
groups = [
"wheel"
"networkmanager"
"video"
"input"
];
};
roles.default.extraModules = [ ./users/jon/home.nix ]; # (1)
};
# ...
# elided
};
}
```
1. Type `path` or `string`: Must point to a seperate file. Inlining a module is not possible
!!! Note "This is inspiration"
Our community might come up with better solutions soon.
We are seeking contributions to improve this pattern if you have a nicer solution in mind.
```nix title="users/jon/home.nix"
# NixOS module to import home-manager and the home-manager configuration of 'jon'
{ self, ...}:
{
imports = [ self.inputs.home-manager.nixosModules.default ];
home-manager.users.jon = {
imports = [
./home-configuration.nix
];
};
}
```

View File

@@ -1,6 +1,6 @@
# Deploy a machine # Deploy a machine
Now that you have created a new machine, we will walk through how to install it. Now that you have created a machines, added some services and setup secrets. This guide will walk through how to deploy it.
## Prerequisites ## Prerequisites
@@ -10,256 +10,212 @@ Now that you have created a new machine, we will walk through how to install it.
- [x] **Machine configuration**: See our basic [adding and configuring machine guide](./add-machines.md) - [x] **Machine configuration**: See our basic [adding and configuring machine guide](./add-machines.md)
- [x] **Initialized secrets**: See [secrets](secrets.md) for how to initialize your secrets. - [x] **Initialized secrets**: See [secrets](secrets.md) for how to initialize your secrets.
=== "**Physical Hardware**" ## Physical Hardware
- [x] **USB Flash Drive**: See [Clan Installer](installer.md) !!! note "skip this if using a cloud VM"
!!! Steps Steps:
1. Create a NixOS installer image and transfer it to a bootable USB drive as described in the [installer](./installer.md). - Create a NixOS installer image and transfer it to a bootable USB drive as described in the [installer](./installer.md).
- Boot the target machine and connect it to a network that makes it reachable from your setup computer.
- Note down a reachable ip adress (*ipv4*, *ipv6* or *tor*)
2. Boot the target machine and connect it to a network that makes it reachable from your setup computer. ---
=== "**Cloud VMs**" The installer will generate a password and local addresses on boot, then run ssh with these preconfigured.
The installer shows it's deployment relevant information in two formats, a text form, as well as a QR code.
- [x] Any cloud machine if it is reachable via SSH and supports `kexec`. Sample boot screen shows:
!!! Warning "NixOS can cause strange issues when booting in certain cloud environments." - Root password
If on Linode: Make sure that the system uses Direct Disk boot kernel (found in the configuration pannel) - IP address
- Optional Tor and mDNS details
```{ .bash .annotate .no-copy .nohighlight}
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ ┌───────────────────────────┐ │
│ │███████████████████████████│ # This is the QR Code (1) │
│ │██ ▄▄▄▄▄ █▀▄█▀█▀▄█ ▄▄▄▄▄ ██│ │
│ │██ █ █ █▀▄▄▄█ ▀█ █ █ ██│ │
│ │██ █▄▄▄█ █▀▄ ▀▄▄▄█ █▄▄▄█ ██│ │
│ │██▄▄▄▄▄▄▄█▄▀ ▀▄▀▄█▄▄▄▄▄▄▄██│ │
│ │███▀▀▀ █▄▄█ ▀▄ ▄▀▄█ ███│ │
│ │██▄██▄▄█▄▄▀▀██▄▀ ▄▄▄ ▄▀█▀██│ │
│ │██ ▄▄▄▄▄ █▄▄▄▄ █ █▄█ █▀ ███│ │
│ │██ █ █ █ █ █ ▄▄▄ ▄▀▀ ██│ │
│ │██ █▄▄▄█ █ ▄ ▄ ▄ ▀█ ▄███│ │
│ │██▄▄▄▄▄▄▄█▄▄▄▄▄▄█▄▄▄▄▄█▄███│ │
│ │███████████████████████████│ │
│ └───────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │Root password: cheesy-capital-unwell # password (2) │ │
│ │Local network addresses: │ │
│ │enp1s0 UP 192.168.178.169/24 metric 1024 fe80::21e:6ff:fe45:3c92/64 │ │
│ │enp2s0 DOWN │ │
│ │wlan0 DOWN # connect to wlan (3) │ │
│ │Onion address: 6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion │ │
│ │Multicast DNS: nixos-installer.local │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ Press 'Ctrl-C' for console access │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
```
1. This is not an actual QR code, because it is displayed rather poorly on text sites.
This would be the actual content of this specific QR code prettified:
```json
{
"pass": "cheesy-capital-unwell",
"tor": "6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion",
"addrs": [
"2001:9e8:347:ca00:21e:6ff:fe45:3c92"
]
}
```
To generate the actual QR code, that would be displayed use:
```shellSession
echo '{"pass":"cheesy-capital-unwell","tor":"6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion","addrs":["2001:9e8:347:ca00:21e:6ff:fe45:3c92"]}' | nix run nixpkgs#qrencode -- -s 2 -m 2 -t utf8
```
2. The root password for the installer medium.
This password is autogenerated and meant to be easily typeable.
3. See [how to connect to wlan](./installer.md#optional-connect-to-wifi-manually).
!!! tip
Use [KDE Connect](https://apps.kde.org/de/kdeconnect/) for easyily sharing QR codes from phone to desktop
## Cloud VMs
!!! note "skip this if using a physical machine"
Clan supports any cloud machine if it is reachable via SSH and supports `kexec`.
Steps:
- Go to the configuration panel and note down how to connect to the machine via ssh.
!!! tip "NixOS can cause strange issues when booting in certain cloud environments."
If on Linode: Make sure that the system uses "Direct Disk boot kernel" (found in the configuration panel)
## Setting `targetHost` ## Setting `targetHost`
=== "flake.nix (flake-parts)" In your nix files set the targetHost (reachable ip) that you retrieved in the previous step.
```{.nix hl_lines="22"} ```{.nix title="clan.nix" hl_lines="9"}
{ {
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz"; # Ensure this is unique among all clans you want to use.
inputs.nixpkgs.follows = "clan-core/nixpkgs"; meta.name = "my-clan";
inputs.flake-parts.follows = "clan-core/flake-parts";
inputs.flake-parts.inputs.nixpkgs-lib.follows = "clan-core/nixpkgs";
outputs = inventory.machines = {
inputs@{ flake-parts, ... }: # Define machines here.
flake-parts.lib.mkFlake { inherit inputs; } { # The machine name will be used as the hostname.
systems = [ jon = {
"x86_64-linux" deploy.targetHost = "root@192.168.192.4"; # (1)
"aarch64-linux" };
"x86_64-darwin" };
"aarch64-darwin" # ...
]; # elided
imports = [ inputs.clan-core.flakeModules.default ]; }
```
clan = { 1. Use the ip address of your targetMachine that you want to deploy. If using the [flash-installer](./installer.md) it should display its local ip-address when booted.
inventory.machines = {
jon = {
# targetHost will get picked up by cli commands
deploy.targetHost = "root@jon";
};
};
};
};
}
```
=== "flake.nix (classic)"
```{.nix hl_lines="14"}
{
inputs.clan-core.url = "https://git.clan.lol/clan/clan-core/archive/main.tar.gz";
inputs.nixpkgs.follows = "clan-core/nixpkgs";
outputs =
{ self, clan-core, ... }:
let
clan = clan-core.lib.clan {
inherit self;
inventory.machines = {
jon = {
# targetHost will get picked up by cli commands
deploy.targetHost = "root@jon";
};
};
};
in
{
inherit (clan.config)
nixosConfigurations
nixosModules
clanInternals
darwinConfigurations
darwinModules
;
};
}
```
!!! warning !!! warning
The use of `root@` in the target address implies SSH access as the `root` user. The use of `root@` in the target address implies SSH access as the `root` user.
Ensure that the root login is secured and only used when necessary. Ensure that the root login is secured and only used when necessary.
## Identify the Target Disk See also [how to set TargetHost](../target-host.md) for other methods.
On the setup computer, SSH into the target: ## Retrieve the hardware report
```bash title="setup computer" By default clan uses [nixos-facter](https://github.com/nix-community/nixos-facter) which captures detailed information about the machine or virtual environment.
ssh root@<IP> lsblk --output NAME,ID-LINK,FSTYPE,SIZE,MOUNTPOINT
To generate the hardware-report (`facter.json`) run:
```bash
clan machines update-hardware-config <machineName>
``` ```
Replace `<IP>` with the machine's IP or hostname if mDNS (i.e. Avahi) is available. Example output:
Which should show something like: ```shell-session
$ clan machines update-hardware-config jon
```{.shellSession hl_lines="6" .no-copy} [jon] $ nixos-facter
NAME ID-LINK FSTYPE SIZE MOUNTPOINT Successfully generated: ./machines/jon/facter.json
sda usb-ST_16GB_AA6271026J1000000509-0:0 14.9G
├─sda1 usb-ST_16GB_AA6271026J1000000509-0:0-part1 1M
├─sda2 usb-ST_16GB_AA6271026J1000000509-0:0-part2 vfat 100M /boot
└─sda3 usb-ST_16GB_AA6271026J1000000509-0:0-part3 ext4 2.9G /
nvme0n1 nvme-eui.e8238fa6bf530001001b448b4aec2929 476.9G
├─nvme0n1p1 nvme-eui.e8238fa6bf530001001b448b4aec2929-part1 vfat 512M
├─nvme0n1p2 nvme-eui.e8238fa6bf530001001b448b4aec2929-part2 ext4 459.6G
└─nvme0n1p3 nvme-eui.e8238fa6bf530001001b448b4aec2929-part3 swap 16.8G
``` ```
Look for the top-level disk device (e.g., nvme0n1 or sda) and copy its `ID-LINK`. Avoid using partition IDs like `nvme0n1p1`. See [update-hardware-config cli reference](../../reference/cli/machines.md#machines-update-hardware-config) for further configuration possibilities if needed.
In this example we would copy `nvme-eui.e8238fa6bf530001001b448b4aec2929` ## Configure your disk schema
By default clan uses [disko](https://github.com/nix-community/disko) which allows for declarative disk partitioning.
To setup a disk schema for a machine run
```bash
clan templates apply disk single-disk jon --set mainDisk ""
```
Which should fail and give the valid options for the specific hardware:
```shellSession
Invalid value for placeholder mainDisk - Valid options:
/dev/disk/by-id/nvme-WD_PC_SN740_SDDQNQD-512G-1201_232557804368
```
Re-run the command with the correct disk:
```bash
clan templates apply disk single-disk jon --set mainDisk "/dev/disk/by-id/nvme-WD_PC_SN740_SDDQNQD-512G-1201_232557804368"
```
Should now be succesfull
```shellSession
Applied disk template 'single-disk' to machine 'jon'
```
A disko.nix file should be created in `machines/jon`
You can have a look and customize it if needed.
!!! tip !!! tip
For advanced partitioning, see [Disko templates](https://github.com/nix-community/disko-templates) or [Disko examples](https://github.com/nix-community/disko/tree/master/example). For advanced partitioning, see [Disko templates](https://github.com/nix-community/disko-templates) or [Disko examples](https://github.com/nix-community/disko/tree/master/example).
## Fill in hardware specific machine configuration !!! Danger
Don't change the `disko.nix` after the machine is installed for the first time.
Edit the following fields inside the `./machines/<machine_name>/configuration.nix` Changing disko configuration requires wiping and reinstalling the machine.
<!-- Note: Use "jon" instead of "<machine>" as "<" is not supported in title tag --> Unless you really know what you are doing.
```nix title="./machines/jon/configuration.nix" hl_lines="12 15 19"
{
imports = [
# contains your disk format and partitioning configuration.
../../modules/disko.nix
# this file is shared among all machines
../../modules/shared.nix
# enables GNOME desktop (optional)
../../modules/gnome.nix
];
# Put your username here for login
users.users.user.name = "__YOUR_USERNAME__";
# Replace this __CHANGE_ME__ with the copied result of the lsblk command
disko.devices.disk.main.device = "/dev/disk/by-id/__CHANGE_ME__";
# IMPORTANT! Add your SSH key here
# e.g. > cat ~/.ssh/id_ed25519.pub
users.users.root.openssh.authorizedKeys.keys = [ "__YOUR_SSH_KEY__" ];
# ...
}
```
!!! Info "Replace `__YOUR_USERNAME__` with the ip of your machine, if you use avahi you can also use your hostname"
!!! Info "Replace `__CHANGE_ME__` with the appropriate `ID-LINK` identifier, such as `nvme-eui.e8238fa6bf530001001b448b4aec2929`"
!!! Info "Replace `__YOUR_SSH_KEY__` with your personal key, like `ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILoMI0NC5eT9pHlQExrvR5ASV3iW9+BXwhfchq0smXUJ jon@jon-desktop`"
## Deploy the machine ## Deploy the machine
**Finally deployment time!** Use the following command to build and deploy the image via SSH onto your machine. **Finally deployment time!** Use one of the following commands to build and deploy the image via SSH onto your machine.
=== "**Image Installer**"
The installer will generate a password and local addresses on boot, then run ssh with these preconfigured.
The installer shows it's deployment relevant information in two formats, a text form, as well as a QR code.
Sample boot screen shows:
- Root password
- IP address
- Optional Tor and mDNS details
```{ .bash .annotate .no-copy .nohighlight}
┌─────────────────────────────────────────────────────────────────────────────────────┐
│ ┌───────────────────────────┐ │
│ │███████████████████████████│ # This is the QR Code (1) │
│ │██ ▄▄▄▄▄ █▀▄█▀█▀▄█ ▄▄▄▄▄ ██│ │
│ │██ █ █ █▀▄▄▄█ ▀█ █ █ ██│ │
│ │██ █▄▄▄█ █▀▄ ▀▄▄▄█ █▄▄▄█ ██│ │
│ │██▄▄▄▄▄▄▄█▄▀ ▀▄▀▄█▄▄▄▄▄▄▄██│ │
│ │███▀▀▀ █▄▄█ ▀▄ ▄▀▄█ ███│ │
│ │██▄██▄▄█▄▄▀▀██▄▀ ▄▄▄ ▄▀█▀██│ │
│ │██ ▄▄▄▄▄ █▄▄▄▄ █ █▄█ █▀ ███│ │
│ │██ █ █ █ █ █ ▄▄▄ ▄▀▀ ██│ │
│ │██ █▄▄▄█ █ ▄ ▄ ▄ ▀█ ▄███│ │
│ │██▄▄▄▄▄▄▄█▄▄▄▄▄▄█▄▄▄▄▄█▄███│ │
│ │███████████████████████████│ │
│ └───────────────────────────┘ │
│ ┌─────────────────────────────────────────────────────────────────────────────────┐ │
│ │Root password: cheesy-capital-unwell # password (2) │ │
│ │Local network addresses: │ │
│ │enp1s0 UP 192.168.178.169/24 metric 1024 fe80::21e:6ff:fe45:3c92/64 │ │
│ │enp2s0 DOWN │ │
│ │wlan0 DOWN # connect to wlan (3) │ │
│ │Onion address: 6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion │ │
│ │Multicast DNS: nixos-installer.local │ │
│ └─────────────────────────────────────────────────────────────────────────────────┘ │
│ Press 'Ctrl-C' for console access │
│ │
└─────────────────────────────────────────────────────────────────────────────────────┘
```
1. This is not an actual QR code, because it is displayed rather poorly on text sites.
This would be the actual content of this specific QR code prettified:
```json
{
"pass": "cheesy-capital-unwell",
"tor": "6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion",
"addrs": [
"2001:9e8:347:ca00:21e:6ff:fe45:3c92"
]
}
```
To generate the actual QR code, that would be displayed use:
```shellSession
echo '{"pass":"cheesy-capital-unwell","tor":"6evxy5yhzytwpnhc2vpscrbti3iktxdhpnf6yim6bbs25p4v6beemzyd.onion","addrs":["2001:9e8:347:ca00:21e:6ff:fe45:3c92"]}' | nix run nixpkgs#qrencode -- -s 2 -m 2 -t utf8
```
2. The root password for the installer medium.
This password is autogenerated and meant to be easily typeable.
3. See [how to connect to wlan](./installer.md#optional-connect-to-wifi-manually).
!!! tip
Use [KDE Connect](https://apps.kde.org/de/kdeconnect/) for easyily sharing QR codes from phone to desktop
=== "**Cloud VM**"
Just run the command **Option B: Cloud VM** below
### Deployment Commands ### Deployment Commands
#### Using password auth #### Using password auth
```bash ```bash
clan machines install [MACHINE] --target-host <IP> --update-hardware-config nixos-facter clan machines install [MACHINE] --target-host <IP>
``` ```
#### Using QR JSON #### Using QR JSON
```bash ```bash
clan machines install [MACHINE] --json "[JSON]" --update-hardware-config nixos-facter clan machines install [MACHINE] --json "[JSON]"
``` ```
#### Using QR image file #### Using QR image file
```bash ```bash
clan machines install [MACHINE] --png [PATH] --update-hardware-config nixos-facter clan machines install [MACHINE] --png [PATH]
``` ```
#### Option B: Cloud VM #### Option B: Cloud VM
```bash ```bash
clan machines install [MACHINE] --target-host <IP> --update-hardware-config nixos-facter clan machines install [MACHINE] --target-host <IP>
``` ```
!!! success !!! success
@@ -318,4 +274,3 @@ clan {
``` ```
This is useful for machines that are not always online or are not part of the regular update cycle. This is useful for machines that are not always online or are not part of the regular update cycle.

View File

@@ -38,31 +38,24 @@ By the end of this guide, you'll have a fresh NixOS configuration ready to push
## Add Clan CLI to Your Shell ## Add Clan CLI to Your Shell
Add the Clan CLI into your environment: Create a new clan
```bash ```bash
nix shell git+https://git.clan.lol/clan/clan-core#clan-cli --refresh nix run git+https://git.clan.lol/clan/clan-core#clan-cli --refresh -- flakes create
``` ```
This should prompt for a *name*:
```terminalSession ```terminalSession
clan --help Enter a name for the new clan: my-clan
``` ```
Should print the avilable commands. Enter a *name*, confirm with *enter*. A directory with that name will be created and initialized.
Also checkout the [cli-reference documentation](../../reference/cli/index.md). !!! Note
This command uses the `default` template
## Initialize Your Project See `clan templates list` and the `--help` reference for how to use other templates.
If you want to migrate an existing project, follow this [guide](../migrations/migration-guide.md).
Set the foundation of your Clan project by initializing it by running:
```bash
clan flakes create my-clan
```
This command creates a `flake.nix` and some other files for your project.
## Explore the Project Structure ## Explore the Project Structure
@@ -83,30 +76,47 @@ For example, you might see something like:
└── README.md └── README.md
``` ```
Dont worry if your output looks different—the template evolves over time. Dont worry if your output looks different — Clan templates evolve over time.
??? info "Recommended way of sourcing the `clan` CLI tool" To interact with your newly created clan the you need to load the `clan` cli-package it into your environment by running:
The default template adds the `clan` CLI tool to the development shell. === "Automatic (direnv, recommended)"
This means that you can access the `clan` CLI tool directly from the folder - prerequisite: [install nix-direnv](https://github.com/nix-community/nix-direnv)
you are in right now.
In the `my-clan` directory, run the following command: ```
direnv allow
```
=== "Manual (nix develop)"
``` ```
nix develop nix develop
``` ```
This will ensure the `clan` CLI tool is available in your shell environment. verify that you can run `clan` commands:
To automatically add the `clan` CLI tool to your environment without having to ```bash
run `nix develop` every time, we recommend setting up [direnv](https://direnv.net/). clan show
```
clan machines list
``` ```
If you see no output yet, thats expected — [add machines](./add-machines.md) to populate it. You should see something like this:
```shellSession
Name: __CHANGE_ME__
Description: None
```
To change the name of your clan edit `meta.name` in the `clan.nix` or `flake.nix` file
```{.nix title="clan.nix" hl_lines="3"}
{
# Ensure this is unique among all clans you want to use.
meta.name = "__CHANGE_ME__";
# ...
# elided
}
```
--- ---
@@ -118,6 +128,7 @@ You can continue with **any** of the following steps at your own pace:
- [x] [Initialize Clan](./index.md#initialize-your-project) - [x] [Initialize Clan](./index.md#initialize-your-project)
- [ ] [Create USB Installer (optional)](./installer.md) - [ ] [Create USB Installer (optional)](./installer.md)
- [ ] [Add Machines](./add-machines.md) - [ ] [Add Machines](./add-machines.md)
- [ ] [Add a User](./add-user.md)
- [ ] [Add Services](./add-services.md) - [ ] [Add Services](./add-services.md)
- [ ] [Configure Secrets](./secrets.md) - [ ] [Configure Secrets](./secrets.md)
- [ ] [Deploy](./deploy.md) - Requires configured secrets - [ ] [Deploy](./deploy.md) - Requires configured secrets

View File

@@ -152,6 +152,7 @@ are loaded when using Clan:
outputs = outputs =
{ self, clan-core, ... }: { self, clan-core, ... }:
let let
# Sometimes this attribute set is defined in clan.nix
clan = clan-core.lib.clan { clan = clan-core.lib.clan {
inherit self; inherit self;

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