confctl 2.2.3 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (178) hide show
  1. checksums.yaml +4 -4
  2. data/.git-hooks/pre_commit/nixfmt.rb +13 -0
  3. data/.github/workflows/rspec.yml +64 -0
  4. data/.github/workflows/rubocop.yml +27 -0
  5. data/.github/workflows/tests.yml +139 -0
  6. data/.gitignore +12 -7
  7. data/.overcommit.yml +2 -0
  8. data/.rspec +1 -0
  9. data/.rubocop.yml +8 -1
  10. data/AGENTS.md +42 -0
  11. data/CHANGELOG.md +54 -0
  12. data/Gemfile +3 -2
  13. data/Gemfile.lock +198 -0
  14. data/README.md +166 -58
  15. data/Rakefile +5 -0
  16. data/confctl.gemspec +20 -2
  17. data/docs/carrier.md +3 -3
  18. data/docs/flake-inputs.md +159 -0
  19. data/docs/swpins-to-flakes.md +325 -0
  20. data/example/cluster/module-list.nix +2 -1
  21. data/example/cluster/nixos-machine/config.nix +12 -2
  22. data/example/cluster/nixos-machine/hardware.nix +6 -1
  23. data/example/cluster/vpsadminos-container/config.nix +6 -1
  24. data/example/cluster/vpsadminos-container/module.nix +4 -1
  25. data/example/cluster/vpsadminos-machine/config.nix +6 -1
  26. data/example/cluster/vpsadminos-machine/hardware.nix +6 -1
  27. data/example/cluster/vpsadminos-machine/module.nix +5 -2
  28. data/example/cluster/vpsfreecz-vps/config.nix +6 -1
  29. data/example/cluster/vpsfreecz-vps/module.nix +4 -1
  30. data/example/configs/swpins.nix +8 -3
  31. data/example/environments/base.nix +6 -1
  32. data/example/swpins/core.json +35 -0
  33. data/example-flake/.gitignore +2 -0
  34. data/example-flake/README.md +38 -0
  35. data/example-flake/cluster/cluster.nix +5 -0
  36. data/example-flake/cluster/module-list.nix +4 -0
  37. data/example-flake/cluster/nested/nixos-machine/config.nix +25 -0
  38. data/example-flake/cluster/nested/nixos-machine/hardware.nix +9 -0
  39. data/example-flake/cluster/nested/nixos-machine/module.nix +8 -0
  40. data/example-flake/cluster/nixos-machine/config.nix +25 -0
  41. data/example-flake/cluster/nixos-machine/hardware.nix +9 -0
  42. data/example-flake/cluster/nixos-machine/module.nix +8 -0
  43. data/example-flake/cluster/vpsadminos-container/config.nix +28 -0
  44. data/example-flake/cluster/vpsadminos-container/module.nix +8 -0
  45. data/example-flake/cluster/vpsadminos-machine/config.nix +27 -0
  46. data/example-flake/cluster/vpsadminos-machine/hardware.nix +9 -0
  47. data/example-flake/cluster/vpsadminos-machine/module.nix +8 -0
  48. data/example-flake/cluster/vpsfreecz-vps/config.nix +31 -0
  49. data/example-flake/cluster/vpsfreecz-vps/module.nix +8 -0
  50. data/example-flake/configs/confctl.nix +10 -0
  51. data/example-flake/data/default.nix +5 -0
  52. data/example-flake/data/ssh-keys.nix +7 -0
  53. data/example-flake/environments/base.nix +18 -0
  54. data/example-flake/flake.lock +75 -0
  55. data/example-flake/flake.nix +36 -0
  56. data/example-flake/modules/module-list.nix +13 -0
  57. data/example-flake/shell.nix +11 -0
  58. data/flake.lock +159 -0
  59. data/flake.nix +189 -0
  60. data/gemset.nix +1022 -0
  61. data/lib/confctl/cli/app.rb +145 -0
  62. data/lib/confctl/cli/attr_filters.rb +1 -1
  63. data/lib/confctl/cli/cluster.rb +681 -108
  64. data/lib/confctl/cli/command.rb +24 -2
  65. data/lib/confctl/cli/configuration.rb +171 -106
  66. data/lib/confctl/cli/generation.rb +65 -1
  67. data/lib/confctl/cli/inputs/channels.rb +190 -0
  68. data/lib/confctl/cli/inputs/machines.rb +83 -0
  69. data/lib/confctl/cli/inputs/root.rb +101 -0
  70. data/lib/confctl/cli/inputs.rb +5 -0
  71. data/lib/confctl/cli/log_view.rb +21 -10
  72. data/lib/confctl/cli/migrate/swpins_to_flakes.rb +866 -0
  73. data/lib/confctl/cli/migrate.rb +5 -0
  74. data/lib/confctl/cli/output_formatter.rb +5 -5
  75. data/lib/confctl/cli/swpins/base.rb +9 -0
  76. data/lib/confctl/cli/swpins/channel.rb +2 -5
  77. data/lib/confctl/cli/swpins/cluster.rb +2 -5
  78. data/lib/confctl/cli/swpins/core.rb +2 -5
  79. data/lib/confctl/config_type.rb +7 -0
  80. data/lib/confctl/flake_lock.rb +78 -0
  81. data/lib/confctl/flake_lock_diff.rb +36 -0
  82. data/lib/confctl/generation/build.rb +131 -24
  83. data/lib/confctl/generation/build_list.rb +4 -3
  84. data/lib/confctl/generation/unified.rb +14 -1
  85. data/lib/confctl/git_repo_mirror.rb +2 -2
  86. data/lib/confctl/health_checks/run_command.rb +3 -2
  87. data/lib/confctl/health_checks/systemd/properties.rb +1 -1
  88. data/lib/confctl/health_checks/systemd/property_list.rb +2 -2
  89. data/lib/confctl/inputs/commit_message.rb +125 -0
  90. data/lib/confctl/inputs/git_commit.rb +17 -0
  91. data/lib/confctl/inputs/nix_output_guard.rb +37 -0
  92. data/lib/confctl/inputs/setter.rb +179 -0
  93. data/lib/confctl/inputs/updater.rb +76 -0
  94. data/lib/confctl/inputs.rb +5 -0
  95. data/lib/confctl/inputs_info.rb +50 -0
  96. data/lib/confctl/line_buffer.rb +1 -1
  97. data/lib/confctl/machine.rb +18 -3
  98. data/lib/confctl/machine_control.rb +8 -2
  99. data/lib/confctl/machine_list.rb +2 -2
  100. data/lib/confctl/machine_status.rb +63 -20
  101. data/lib/confctl/nix/args.rb +48 -0
  102. data/lib/confctl/nix.rb +30 -437
  103. data/lib/confctl/nix_build_flake.rb +95 -0
  104. data/lib/confctl/nix_copy.rb +14 -2
  105. data/lib/confctl/nix_flake.rb +449 -0
  106. data/lib/confctl/nix_format.rb +3 -3
  107. data/lib/confctl/nix_legacy.rb +467 -0
  108. data/lib/confctl/swpins/change_set.rb +24 -2
  109. data/lib/confctl/swpins/specs/base.rb +2 -2
  110. data/lib/confctl/ui.rb +19 -0
  111. data/lib/confctl/version.rb +1 -1
  112. data/man/index.html +11 -0
  113. data/man/man8/confctl-options.nix.8.html +113 -0
  114. data/man/man8/confctl.8 +152 -21
  115. data/man/man8/confctl.8.html +355 -0
  116. data/man/man8/confctl.8.md +148 -17
  117. data/man/style.css +301 -0
  118. data/nix/evaluator.nix +94 -69
  119. data/nix/flake/mk-confctl-devshell.nix +85 -0
  120. data/nix/flake/mk-confctl-outputs.nix +522 -0
  121. data/nix/flake/mk-config-devshell.nix +168 -0
  122. data/nix/lib/default.nix +118 -65
  123. data/nix/lib/machine/default.nix +65 -45
  124. data/nix/lib/machine/info.nix +16 -5
  125. data/nix/lib/swpins/eval.nix +42 -29
  126. data/nix/lib/swpins/options.nix +6 -2
  127. data/nix/machines.nix +23 -15
  128. data/nix/modules/cluster/default.nix +104 -41
  129. data/nix/modules/confctl/carrier/base.nix +11 -4
  130. data/nix/modules/confctl/carrier/carrier-env.rb +2 -2
  131. data/nix/modules/confctl/carrier/netboot/build-netboot-server.rb +50 -13
  132. data/nix/modules/confctl/carrier/netboot/nixos.nix +56 -24
  133. data/nix/modules/confctl/configuration-info.nix +17 -0
  134. data/nix/modules/confctl/generations.nix +2 -2
  135. data/nix/modules/confctl/host.nix +13 -0
  136. data/nix/modules/confctl/inputs-info.nix +21 -0
  137. data/nix/modules/confctl/kexec-netboot/default.nix +13 -6
  138. data/nix/modules/confctl/kexec-netboot/kexec-netboot.8.adoc +3 -0
  139. data/nix/modules/confctl/kexec-netboot/kexec-netboot.rb +25 -16
  140. data/nix/modules/confctl/nix.nix +31 -1
  141. data/nix/modules/confctl/swpins.nix +13 -6
  142. data/nix/modules/module-list.nix +4 -2
  143. data/nix/modules/system-list.nix +4 -1
  144. data/nix/package.nix +37 -0
  145. data/shell.nix +39 -8
  146. data/skills/confctl-configuration-update/SKILL.md +228 -0
  147. data/skills/confctl-configuration-update/agents/openai.yaml +4 -0
  148. data/skills/confctl-release/SKILL.md +102 -0
  149. data/skills/confctl-release/agents/openai.yaml +4 -0
  150. data/spec/confctl/cli/cluster_health_check_spec.rb +43 -0
  151. data/spec/confctl/cli/cluster_skip_current_deploy_spec.rb +157 -0
  152. data/spec/confctl/cli/cluster_status_flake_spec.rb +83 -0
  153. data/spec/confctl/cli/inputs_set_output_spec.rb +70 -0
  154. data/spec/confctl/configuration_spec.rb +45 -0
  155. data/spec/confctl/inputs_spec.rb +104 -0
  156. data/spec/confctl/machine_control_spec.rb +112 -0
  157. data/spec/confctl/machine_list_spec.rb +47 -0
  158. data/spec/confctl/nix_flake_spec.rb +41 -0
  159. data/spec/confctl/swpins_spec.rb +106 -0
  160. data/spec/generation/build_modes_spec.rb +132 -0
  161. data/spec/inputs/commit_message_spec.rb +205 -0
  162. data/spec/inputs/nix_cached_fallback_spec.rb +50 -0
  163. data/spec/inputs/nix_output_guard_spec.rb +45 -0
  164. data/spec/spec_helper.rb +12 -0
  165. data/spec/support/cli_helper.rb +57 -0
  166. data/test-runner.sh +7 -0
  167. data/tests/all-tests.nix +30 -0
  168. data/tests/make-test.nix +15 -0
  169. data/tests/runner/extensions/confctl_helpers.rb +238 -0
  170. data/tests/runner/extensions/hostfwd_ports.rb +41 -0
  171. data/tests/suite/auto_rollback.nix +344 -0
  172. data/tests/suite/carrier/deploy.nix +751 -0
  173. data/tests/suite/carrier/netboot.nix +849 -0
  174. data/tests/suite/deploy/base.nix +806 -0
  175. data/tests/suite/deploy/flakes.nix +1 -0
  176. data/tests/suite/deploy/swpins.nix +1 -0
  177. metadata +104 -4
  178. data/nix/modules/confctl/overlays.nix +0 -15
data/README.md CHANGED
@@ -21,76 +21,160 @@ machines.
21
21
  * [Nix](https://nixos.org)
22
22
 
23
23
  ## Quick start
24
- 1. Either install confctl as a gem:
24
+ ### Flake-based configuration (recommended)
25
+
26
+ confctl works best with a flake-based configuration repository. The repository
27
+ defines flake inputs (nixpkgs/vpsadminos/etc.), maps them into **channels**, and
28
+ machines select channels via `cluster.<name>.inputs.channels`.
29
+
30
+ Create a new configuration directory and initialize it:
31
+
32
+ ```bash
33
+ mkdir cluster-configuration
34
+ cd cluster-configuration
35
+ confctl init
36
+ ```
37
+
38
+ `confctl init` generates a `flake.nix` like this:
39
+
40
+ ```nix
41
+ {
42
+ description = "confctl configuration (flake)";
43
+
44
+ inputs = {
45
+ confctl.url = "github:vpsfreecz/confctl";
46
+
47
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
48
+
49
+ # vpsadminos.url = "github:vpsfreecz/vpsadminos/staging";
50
+ # vpsadminos.inputs.nixpkgs.follows = "nixpkgs";
51
+ };
52
+
53
+ outputs = inputs@{ self, confctl, ... }:
54
+ let
55
+ channels = {
56
+ nixos-unstable = { nixpkgs = "nixpkgs"; };
57
+
58
+ # vpsadminos = {
59
+ # nixpkgs = "nixpkgs";
60
+ # vpsadminos = "vpsadminos";
61
+ # };
62
+ };
63
+
64
+ confctlOutputs = confctl.lib.mkConfctlOutputs {
65
+ confDir = ./.;
66
+ inherit inputs channels;
67
+ };
68
+ in
69
+ {
70
+ confctl = confctlOutputs;
71
+
72
+ # Shell modes:
73
+ # - minimal: no Gemfile, best default
74
+ # - tools: Gemfile for repo tools such as overcommit or rubocop
75
+ # - bundled-confctl: Gemfile includes confctl and scripts/ can use bundle gems
76
+ devShells.x86_64-linux.default = confctl.lib.mkConfigDevShell {
77
+ system = "x86_64-linux";
78
+ mode = "minimal";
79
+ };
80
+ };
81
+ }
25
82
  ```
26
- gem install confctl
83
+
84
+ The optional `vpsadminos` input is commented out by default because most new
85
+ configurations deploy NixOS only.
86
+
87
+ Then enter the dev shell:
88
+
89
+ ```bash
90
+ nix develop
27
91
  ```
28
92
 
29
- Or clone this repository:
93
+ This makes `confctl` available from the pinned flake input package and exposes
94
+ its man pages on `MANPATH`.
95
+
96
+ For the Bundler modes, commit `Gemfile.lock` whenever possible. `confctl` can
97
+ bootstrap those shells without it, but the lockfile makes CI and local shells
98
+ reproducible.
99
+
100
+ Before the first build or deploy, make sure the per-user gcroot directory
101
+ exists:
30
102
 
103
+ ```bash
104
+ sudo mkdir -p /nix/var/nix/gcroots/per-user/$USER
105
+ sudo chown $USER /nix/var/nix/gcroots/per-user/$USER
31
106
  ```
32
- git clone https://github.com/vpsfreecz/confctl
107
+
108
+ Add a new machine to be deployed:
109
+
110
+ ```bash
111
+ confctl add my-machine
33
112
  ```
34
113
 
35
- This guide assumes you have cloned the repository, because otherwise man will
36
- not find confctl's manual pages. If you install confctl using gem, you can
37
- ignore steps with `shell.nix`.
114
+ You can now edit the machine's configuration in directory `cluster/my-machine`.
38
115
 
39
- 2. Create a new directory, where your confctl-managed configuration will be
40
- stored:
116
+ Build the machine:
41
117
 
118
+ ```bash
119
+ confctl build my-machine
42
120
  ```
43
- mkdir cluster-configuration
121
+
122
+ Deploy the machine:
123
+
124
+ ```bash
125
+ confctl deploy my-machine
44
126
  ```
45
- 3. Create `shell.nix` and import the same file from confctl:
127
+
128
+ To update flake inputs, use the `confctl inputs ...` commands:
129
+
130
+ ```bash
131
+ confctl inputs ls
132
+ confctl inputs update --commit nixpkgs
133
+ confctl inputs channel update --commit nixos-unstable nixpkgs
46
134
  ```
47
- cd cluster-configuration
135
+
136
+ If you are migrating an existing configuration repository that uses `configs/swpins.nix`
137
+ and the `swpins/` directory, confctl includes an interactive helper: `confctl migrate swpins-to-flakes`
138
+ (use `--dry-run` to preview). See [docs/swpins-to-flakes.md](docs/swpins-to-flakes.md).
139
+
140
+ ### Legacy configuration (non-flake)
141
+
142
+ The original non-flake workflow is still supported. Use `confctl init --swpins`
143
+ instead of `confctl init`; the `confctl add`, `confctl build`, and `confctl deploy`
144
+ workflow is otherwise the same as above.
145
+
146
+ Legacy non-flake configuration repositories can continue importing
147
+ [`shell.nix`](shell.nix). If you use this workflow, create `shell.nix` in the
148
+ configuration directory and adjust the import path as needed:
149
+
150
+ ```bash
48
151
  cat > shell.nix <<EOF
49
152
  import ../confctl/shell.nix
50
153
  EOF
51
154
  ```
52
155
 
53
- 4. Enter the `nix-shell`. This will make confctl available and install its
54
- dependencies into `.gems/`:
55
- ```
156
+ Enter the `nix-shell`. This uses the legacy bundled-confctl shell and installs
157
+ confctl's dependencies into `.gems/`:
158
+
159
+ ```bash
56
160
  nix-shell
57
161
  ```
58
162
 
59
163
  From within the shell, you can access the [manual](./man/man8/confctl.8.md)
60
164
  and a list of [configuration options](./man/man8/confctl-options.nix.8.md):
61
165
 
62
- ```
166
+ ```bash
63
167
  man confctl
64
168
  man confctl-options.nix
65
169
  ```
66
170
 
67
- 5. Initialize the configuration directory with confctl:
68
- ```
69
- confctl init
70
- ```
71
-
72
- 6. Add a new machine to be deployed:
73
- ```
74
- confctl add my-machine
75
- ```
76
-
77
- You can now edit the machine's configuration in directory `cluster/my-machine`.
171
+ Update pre-configured software pins to fetch current nixpkgs. In flake-based
172
+ configurations, use `confctl inputs ...` instead:
78
173
 
79
- 7. Update pre-configured software pins to fetch current nixpkgs:
80
- ```
174
+ ```bash
81
175
  confctl swpins update
82
176
  ```
83
177
 
84
- 8. Build the machine
85
- ```
86
- confctl build my-machine
87
- ```
88
-
89
- 9. Deploy the machine
90
- ```
91
- confctl deploy my-machine
92
- ```
93
-
94
178
  ## Example configuration
95
179
  Example configuration, which can be used as a starting point, can be found in
96
180
  directory [example/](example/).
@@ -115,11 +199,14 @@ See also existing configurations:
115
199
  │ └── swpins.nix # User-defined software pin channels
116
200
  ├── data/ # User-defined datasets available in machine configurations as confData
117
201
  ├── environments/ # Environment presets for various types of machines, optional
202
+ ├── flake.nix # Flake entrypoint (recommended)
203
+ ├── Gemfile # Optional Bundler config for tools/bundled-confctl modes
204
+ ├── Gemfile.lock # Recommended for Bundler modes
118
205
  ├── modules/ # User-defined modules
119
206
  │ └── cluster/default.nix # User-defined extensions of `cluster.` options used in `<machine>/module.nix` files
120
207
  ├── scripts/ # User-defined scripts
121
- ├── swpins/ # confctl-generated software pins configuration
122
- └── shell.nix # Nix expression for nix-shell
208
+ ├── shell.nix # Legacy nix-shell entrypoint
209
+ └── swpins/ # confctl-generated software pins configuration
123
210
 
124
211
  ## Software pins
125
212
  Software pins in confctl allow you to use specific revisions of
@@ -133,7 +220,7 @@ or selected machines in the configuration. Or, if needed, custom software pins
133
220
  can be configured on selected machines. See below for usage examples.
134
221
 
135
222
  ## Software pin channels
136
- Software pin channels are defined in file `confctl/swpins.nix`:
223
+ Software pin channels are defined in file `configs/swpins.nix`:
137
224
 
138
225
  ```nix
139
226
  { config, ... }:
@@ -154,7 +241,7 @@ Software pin channels are defined in file `confctl/swpins.nix`:
154
241
  fetchSubmodules = false;
155
242
 
156
243
  # git reference to use for manual/automated update using
157
- # `confctl swpins channel update`
244
+ # `confctl swpins channel update`
158
245
  update.ref = "refs/heads/nixos-unstable";
159
246
 
160
247
  # Whether to enable automated updates triggered by `confctl build | deploy`
@@ -163,7 +250,7 @@ Software pin channels are defined in file `confctl/swpins.nix`:
163
250
  # If update.auto is true, this determines how frequently will confctl
164
251
  # try to update the channel, in seconds
165
252
  update.interval = 60*60;
166
- };
253
+ };
167
254
  };
168
255
  };
169
256
 
@@ -175,7 +262,7 @@ Software pin channels are defined in file `confctl/swpins.nix`:
175
262
  git-rev = {
176
263
  url = "https://github.com/vpsfreecz/vpsadminos";
177
264
  update.ref = "refs/heads/staging";
178
- update.auto = true;
265
+ update.auto = true;
179
266
  };
180
267
  };
181
268
  };
@@ -188,6 +275,12 @@ and how to fetch them. Such configured channels can then be manipulated using
188
275
  `confctl`. `confctl` prefetches selected software pins and saves their hashes
189
276
  in JSON files in the `swpins/` directory.
190
277
 
278
+ In flake-based configurations (using `confctl.lib.mkConfctlOutputs`), channel
279
+ names are provided by the flake `channels` mapping. Machines should select
280
+ channels via `cluster.<name>.inputs.channels` (preferred) and can override the
281
+ role-to-input mapping with `cluster.<name>.inputs.overrides`. Legacy
282
+ `cluster.<name>.swpins.channels` remains supported for non-flake configs.
283
+
191
284
  ```
192
285
  # List channels
193
286
  $ confctl swpins channel ls
@@ -232,8 +325,11 @@ For example, machine named `my-machine` would be described in
232
325
  # This tells confctl whether it is a NixOS or vpsAdminOS machine
233
326
  spin = "nixos";
234
327
 
235
- # Use NixOS unstable channel defined in configs/swpins.nix
236
- swpins.channels = [ "nixos-unstable" ];
328
+ # Flake configs: prefer inputs.channels (channels come from mkConfctlOutputs)
329
+ inputs.channels = [ "nixos-unstable" ];
330
+
331
+ # Legacy configs: use swpins.channels (configs/swpins.nix)
332
+ # swpins.channels = [ "nixos-unstable" ];
237
333
 
238
334
  # If the machine name is not a hostname, configure the address to which
239
335
  # should confctl deploy it
@@ -262,11 +358,11 @@ Per-machine software pins are configured in the machine's `module.nix` file:
262
358
  # Per-machine swpins
263
359
  swpins.pins = {
264
360
  "pin-name" = {
265
- type = "git-rev";
266
- git-rev = {
267
- # ...pin definition...
268
- };
269
- };
361
+ type = "git-rev";
362
+ git-rev = {
363
+ # ...pin definition...
364
+ };
365
+ };
270
366
  };
271
367
  };
272
368
  }
@@ -277,11 +373,12 @@ Instead of `confctl swpins channel` commands, use `confctl swpins cluster`
277
373
  to manage configured pins.
278
374
 
279
375
  ## Nix flakes
280
- confctl's software pins are an alternative to flakes and flakes are not supported
281
- by confctl at this time. Software pins are implemented by manipulating the `$NIX_PATH`
282
- environment variable, which is in conflict with using flakes. confctl is likely
283
- to be migrated to flakes when the interface will be stabilized. Since the transition
284
- is going to require a significant effort, there are no plans for it currently.
376
+ confctl can be used from a configuration flake via `confctl.lib.mkConfctlOutputs`.
377
+ In that mode, channel definitions live in the flake `channels` mapping and machines
378
+ select them via `cluster.<name>.inputs.channels`. Per-machine role-to-input overrides
379
+ are done via `cluster.<name>.inputs.overrides`.
380
+
381
+ `cluster.<name>.swpins.*` and `configs/swpins.nix` are not evaluated in flake mode.
285
382
 
286
383
  ## Extra module arguments
287
384
  Machine configs can use the following extra module arguments:
@@ -293,7 +390,17 @@ Machine configs can use the following extra module arguments:
293
390
  - `confMachine` - attrset with information about the machine that is currently
294
391
  being built, contains key `name` and all options from
295
392
  [machine metadata module](##machine-metadata-and-software-pins)
296
- - `swpins` - attrset of software pins of the machine that is currently being built
393
+ - `flakeInputs` - flake inputs passed to `mkConfctlOutputs` (excluding `self`)
394
+ - `configurationInfo` - exact source revision and dirty state of the
395
+ configuration flake when Git metadata is available, exposed as
396
+ `confctl.configurationInfo` and written to
397
+ `/etc/confctl/configuration-info.json`
398
+ - `inputs` - attrset of flake input store paths selected for the machine build
399
+ - `swpins` - (legacy configs only) attrset of prefetched software pins of the machine that is currently being built
400
+ - `inputsInfo` - metadata about flake inputs selected for the machine (keys are
401
+ roles like `nixpkgs`/`vpsadminos`, values include `input`, `url`, `rev`,
402
+ `shortRev`, `lastModified`), exposed as `confctl.inputsInfo` and written to
403
+ `/etc/confctl/inputs-info.json`
297
404
 
298
405
  For example in `cluster/my-machine/config.nix`:
299
406
 
@@ -515,3 +622,4 @@ See the [man pages](./man/man8) for more information:
515
622
 
516
623
  * [confctl(8)](./man/man8/confctl.8.md)
517
624
  * [confctl-options.nix(8)](./man/man8/confctl-options.nix.8.md)
625
+ * [Migrating from swpins to flakes](docs/swpins-to-flakes.md)
data/Rakefile CHANGED
@@ -3,6 +3,7 @@ require 'confctl'
3
3
  require 'md2man/rakefile'
4
4
  require 'md2man/roff/engine'
5
5
  require 'md2man/html/engine'
6
+ require 'rspec/core/rake_task'
6
7
 
7
8
  # Override markdown engine to add extra parameter
8
9
  [Md2Man::Roff, Md2Man::HTML].each do |mod|
@@ -38,3 +39,7 @@ task 'confctl-options' do
38
39
  end
39
40
  }, 'man/man8/confctl-options.nix.8.md')
40
41
  end
42
+
43
+ desc 'Run RSpec tests'
44
+ RSpec::Core::RakeTask.new(:spec)
45
+ task test: :spec
data/confctl.gemspec CHANGED
@@ -10,12 +10,30 @@ Gem::Specification.new do |s|
10
10
  s.description = 'Nix deployment management tool'
11
11
  s.authors = 'Jakub Skokan'
12
12
  s.email = 'jakub.skokan@vpsfree.cz'
13
- s.files = `git ls-files -z`.split("\x0")
13
+ files =
14
+ if File.directory?(File.join(__dir__, '.git'))
15
+ `git ls-files -z`.split("\x0")
16
+ else
17
+ Dir.chdir(__dir__) do
18
+ Dir.glob('**/*', File::FNM_DOTMATCH).reject do |f|
19
+ f == '.' || f == '..' ||
20
+ f.start_with?('.git/') ||
21
+ f.start_with?('pkg/') ||
22
+ f.start_with?('tmp/') ||
23
+ f.start_with?('log/') ||
24
+ f.start_with?('.bundle/') ||
25
+ f.start_with?('vendor/') ||
26
+ f.end_with?('~')
27
+ end
28
+ end
29
+ end
30
+
31
+ s.files = files
14
32
  s.files += Dir['man/man?/*.?']
15
33
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
34
  s.license = 'GPL-3.0-only'
17
35
 
18
- s.required_ruby_version = '>= 3.1.0'
36
+ s.required_ruby_version = '>= 3.3.0'
19
37
 
20
38
  s.add_dependency 'curses'
21
39
  s.add_dependency 'gli', '~> 2.22.0'
data/docs/carrier.md CHANGED
@@ -47,7 +47,7 @@ Custom build attributes can be created by the user. For example, this is how
47
47
 
48
48
  ```nix
49
49
  # File cluster/nixos/config.nix
50
- { config, pkgs, lib, confMachine, swpinsInfo, ... }:
50
+ { config, pkgs, lib, confMachine, inputsInfo, ... }:
51
51
  let
52
52
  # machine.json contains metadata about the machine that the carrier uses
53
53
  # to assemble the netboot server
@@ -72,11 +72,11 @@ let
72
72
  macs = confMachine.netboot.macs;
73
73
 
74
74
  # Information used by confctl status
75
- swpins-info = swpinsInfo;
75
+ inputs-info = inputsInfo;
76
76
  });
77
77
  in {
78
78
  imports = [
79
- <nixpkgs/nixos/modules/installer/netboot/netboot-minimal.nix>
79
+ "${pkgs.path}/nixos/modules/installer/netboot/netboot-minimal.nix"
80
80
  ];
81
81
 
82
82
  # Define custom build attribute
@@ -0,0 +1,159 @@
1
+ # Flake inputs
2
+
3
+ confctl supports flake-based configuration repositories via `confctl.lib.mkConfctlOutputs`.
4
+
5
+ In flake configs:
6
+
7
+ - inputs are normal flake inputs locked in `flake.lock`
8
+ - machines select “channels” via `inputs.channels`
9
+ - machines can override role→input mapping via `inputs.overrides`
10
+ - updates are performed by `confctl inputs ...` (or `nix flake lock --update-input ...`)
11
+
12
+ This document explains the model and the common workflows.
13
+
14
+ ## Roles, inputs, and channels
15
+
16
+ A **role** is a named dependency such as:
17
+
18
+ - `nixpkgs`
19
+ - `vpsadminos`
20
+ - `vpsadmin`
21
+
22
+ A role is mapped to a **flake input name** via **channels**.
23
+
24
+ A **channel** is just a name like `production` or `staging` that selects a set of role mappings.
25
+
26
+ Example:
27
+
28
+ ```nix
29
+ channels = {
30
+ staging = {
31
+ nixpkgs = "nixpkgsStable";
32
+ vpsadminos = "vpsadminosStaging";
33
+ vpsadmin = "vpsadminStaging";
34
+ };
35
+
36
+ production = {
37
+ nixpkgs = "nixpkgsStable";
38
+ vpsadminos = "vpsadminosProduction";
39
+ vpsadmin = "vpsadminProduction";
40
+ };
41
+ };
42
+ ```
43
+
44
+ ## `mkConfctlOutputs` flake skeleton
45
+
46
+ A minimal pattern:
47
+
48
+ ```nix
49
+ {
50
+ description = "my cluster config (confctl flake)";
51
+
52
+ inputs = {
53
+ confctl.url = "github:vpsfreecz/confctl";
54
+
55
+ nixpkgsStable.url = "github:NixOS/nixpkgs/nixos-25.11";
56
+ vpsadminosStaging.url = "github:vpsfreecz/vpsadminos/staging";
57
+ vpsadminosProduction.url = "github:vpsfreecz/vpsadminos/staging";
58
+
59
+ vpsadminStaging = {
60
+ url = "github:vpsfreecz/vpsadmin/2026-02-19-flakes";
61
+ inputs.vpsadminos.follows = "vpsadminosStaging";
62
+ };
63
+
64
+ vpsadminProduction = {
65
+ url = "github:vpsfreecz/vpsadmin/2026-02-19-flakes";
66
+ inputs.vpsadminos.follows = "vpsadminosProduction";
67
+ };
68
+ };
69
+
70
+ outputs = inputs@{ self, confctl, ... }:
71
+ let
72
+ channels = {
73
+ staging = {
74
+ nixpkgs = "nixpkgsStable";
75
+ vpsadminos = "vpsadminosStaging";
76
+ vpsadmin = "vpsadminStaging";
77
+ };
78
+
79
+ production = {
80
+ nixpkgs = "nixpkgsStable";
81
+ vpsadminos = "vpsadminosProduction";
82
+ vpsadmin = "vpsadminProduction";
83
+ };
84
+ };
85
+ in
86
+ {
87
+ confctl = confctl.lib.mkConfctlOutputs {
88
+ confDir = ./.;
89
+ inherit inputs channels;
90
+ };
91
+
92
+ # Optional: configuration-repo dev shell
93
+ devShells.x86_64-linux.default = confctl.lib.mkConfigDevShell {
94
+ system = "x86_64-linux";
95
+ mode = "minimal";
96
+ };
97
+ };
98
+ }
99
+ ```
100
+
101
+ ## Selecting channels on a machine
102
+
103
+ In machine metadata (typically `cluster/<name>/module.nix`), choose channels:
104
+
105
+ ```nix
106
+ { ... }:
107
+ {
108
+ cluster."my-machine" = {
109
+ spin = "nixos";
110
+ inputs.channels = [ "production" ];
111
+ };
112
+ }
113
+ ```
114
+
115
+ Multiple channels can be combined; later channels can override roles from earlier ones.
116
+
117
+ ## Per-machine overrides
118
+
119
+ To override one role for a single machine:
120
+
121
+ ```nix
122
+ cluster."my-machine".inputs.overrides.nixpkgs = "nixpkgsMunin";
123
+ ```
124
+
125
+ Use this sparingly. The default model is: select channels, update channels.
126
+
127
+ ## Updating inputs
128
+
129
+ Inputs are flake inputs in `flake.lock`.
130
+
131
+ Common commands:
132
+
133
+ ```bash
134
+ confctl inputs ls
135
+ confctl inputs update --commit <input...>
136
+
137
+ confctl inputs channel ls
138
+ confctl inputs channel update --commit '{production,staging}' vpsadminos
139
+
140
+ confctl inputs machine update --commit <machine> nixpkgs
141
+ ```
142
+
143
+ - `--no-changelog` disables including `git log --oneline old..new` in the commit message.
144
+ - `--downgrade` is useful when you intentionally move to an older revision and still want the changelog direction to make sense.
145
+
146
+ ## Nested inputs and `follows`
147
+
148
+ If input **A** depends on input **B** and you want the *top-level flake* to decide the revision of **B**, use `follows`.
149
+
150
+ Example (vpsadmin → vpsadminos):
151
+
152
+ ```nix
153
+ inputs.vpsadminStaging = {
154
+ url = "github:vpsfreecz/vpsadmin/2026-02-19-flakes";
155
+ inputs.vpsadminos.follows = "vpsadminosStaging";
156
+ };
157
+ ```
158
+
159
+ Because `follows` is per-input-name, you typically need separate inputs per environment (staging vs production) to pin independently.