confctl 1.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 (130) hide show
  1. checksums.yaml +7 -0
  2. data/.editorconfig +11 -0
  3. data/.gitignore +8 -0
  4. data/.overcommit.yml +6 -0
  5. data/.rubocop.yml +67 -0
  6. data/.rubocop_todo.yml +5 -0
  7. data/.ruby-version +1 -0
  8. data/CHANGELOG.md +2 -0
  9. data/Gemfile +2 -0
  10. data/LICENSE.txt +674 -0
  11. data/README.md +522 -0
  12. data/Rakefile +40 -0
  13. data/bin/confctl +4 -0
  14. data/confctl.gemspec +33 -0
  15. data/example/.gitignore +2 -0
  16. data/example/README.md +38 -0
  17. data/example/cluster/cluster.nix +7 -0
  18. data/example/cluster/module-list.nix +3 -0
  19. data/example/cluster/nixos-machine/config.nix +15 -0
  20. data/example/cluster/nixos-machine/hardware.nix +4 -0
  21. data/example/cluster/nixos-machine/module.nix +8 -0
  22. data/example/cluster/vpsadminos-container/config.nix +22 -0
  23. data/example/cluster/vpsadminos-container/module.nix +8 -0
  24. data/example/cluster/vpsadminos-machine/config.nix +22 -0
  25. data/example/cluster/vpsadminos-machine/hardware.nix +4 -0
  26. data/example/cluster/vpsadminos-machine/module.nix +8 -0
  27. data/example/cluster/vpsfreecz-vps/config.nix +25 -0
  28. data/example/cluster/vpsfreecz-vps/module.nix +8 -0
  29. data/example/configs/confctl.nix +10 -0
  30. data/example/configs/swpins.nix +28 -0
  31. data/example/data/default.nix +5 -0
  32. data/example/data/ssh-keys.nix +7 -0
  33. data/example/environments/base.nix +13 -0
  34. data/example/modules/module-list.nix +13 -0
  35. data/example/shell.nix +11 -0
  36. data/example/swpins/channels/nixos-unstable.json +35 -0
  37. data/example/swpins/channels/vpsadminos-staging.json +35 -0
  38. data/lib/confctl/cli/app.rb +551 -0
  39. data/lib/confctl/cli/attr_filters.rb +51 -0
  40. data/lib/confctl/cli/cluster.rb +1248 -0
  41. data/lib/confctl/cli/command.rb +206 -0
  42. data/lib/confctl/cli/configuration.rb +296 -0
  43. data/lib/confctl/cli/gen_data.rb +97 -0
  44. data/lib/confctl/cli/generation.rb +335 -0
  45. data/lib/confctl/cli/log_view.rb +267 -0
  46. data/lib/confctl/cli/output_formatter.rb +288 -0
  47. data/lib/confctl/cli/swpins/base.rb +40 -0
  48. data/lib/confctl/cli/swpins/channel.rb +73 -0
  49. data/lib/confctl/cli/swpins/cluster.rb +80 -0
  50. data/lib/confctl/cli/swpins/core.rb +86 -0
  51. data/lib/confctl/cli/swpins/utils.rb +55 -0
  52. data/lib/confctl/cli/swpins.rb +5 -0
  53. data/lib/confctl/cli/tag_filters.rb +30 -0
  54. data/lib/confctl/cli.rb +5 -0
  55. data/lib/confctl/conf_cache.rb +105 -0
  56. data/lib/confctl/conf_dir.rb +88 -0
  57. data/lib/confctl/erb_template.rb +37 -0
  58. data/lib/confctl/exceptions.rb +3 -0
  59. data/lib/confctl/gcroot.rb +30 -0
  60. data/lib/confctl/generation/build.rb +145 -0
  61. data/lib/confctl/generation/build_list.rb +106 -0
  62. data/lib/confctl/generation/host.rb +35 -0
  63. data/lib/confctl/generation/host_list.rb +81 -0
  64. data/lib/confctl/generation/unified.rb +117 -0
  65. data/lib/confctl/generation/unified_list.rb +63 -0
  66. data/lib/confctl/git_repo_mirror.rb +79 -0
  67. data/lib/confctl/health_checks/base.rb +66 -0
  68. data/lib/confctl/health_checks/run_command.rb +179 -0
  69. data/lib/confctl/health_checks/systemd/properties.rb +84 -0
  70. data/lib/confctl/health_checks/systemd/property_check.rb +31 -0
  71. data/lib/confctl/health_checks/systemd/property_list.rb +20 -0
  72. data/lib/confctl/health_checks.rb +5 -0
  73. data/lib/confctl/hook.rb +35 -0
  74. data/lib/confctl/line_buffer.rb +53 -0
  75. data/lib/confctl/logger.rb +151 -0
  76. data/lib/confctl/machine.rb +107 -0
  77. data/lib/confctl/machine_control.rb +172 -0
  78. data/lib/confctl/machine_list.rb +108 -0
  79. data/lib/confctl/machine_status.rb +135 -0
  80. data/lib/confctl/module_options.rb +95 -0
  81. data/lib/confctl/nix.rb +382 -0
  82. data/lib/confctl/nix_build.rb +108 -0
  83. data/lib/confctl/nix_collect_garbage.rb +64 -0
  84. data/lib/confctl/nix_copy.rb +49 -0
  85. data/lib/confctl/nix_format.rb +124 -0
  86. data/lib/confctl/nix_literal_expression.rb +15 -0
  87. data/lib/confctl/parallel_executor.rb +43 -0
  88. data/lib/confctl/pattern.rb +9 -0
  89. data/lib/confctl/settings.rb +50 -0
  90. data/lib/confctl/std_line_buffer.rb +40 -0
  91. data/lib/confctl/swpins/change_set.rb +151 -0
  92. data/lib/confctl/swpins/channel.rb +62 -0
  93. data/lib/confctl/swpins/channel_list.rb +47 -0
  94. data/lib/confctl/swpins/cluster_name.rb +94 -0
  95. data/lib/confctl/swpins/cluster_name_list.rb +15 -0
  96. data/lib/confctl/swpins/core.rb +137 -0
  97. data/lib/confctl/swpins/deployed_info.rb +23 -0
  98. data/lib/confctl/swpins/spec.rb +20 -0
  99. data/lib/confctl/swpins/specs/base.rb +184 -0
  100. data/lib/confctl/swpins/specs/directory.rb +51 -0
  101. data/lib/confctl/swpins/specs/git.rb +135 -0
  102. data/lib/confctl/swpins/specs/git_rev.rb +24 -0
  103. data/lib/confctl/swpins.rb +17 -0
  104. data/lib/confctl/system_command.rb +10 -0
  105. data/lib/confctl/user_script.rb +13 -0
  106. data/lib/confctl/user_scripts.rb +41 -0
  107. data/lib/confctl/utils/file.rb +21 -0
  108. data/lib/confctl/version.rb +3 -0
  109. data/lib/confctl.rb +43 -0
  110. data/man/man8/confctl-options.nix.8 +1334 -0
  111. data/man/man8/confctl-options.nix.8.md +1340 -0
  112. data/man/man8/confctl.8 +660 -0
  113. data/man/man8/confctl.8.md +654 -0
  114. data/nix/evaluator.nix +160 -0
  115. data/nix/lib/default.nix +83 -0
  116. data/nix/lib/machine/default.nix +74 -0
  117. data/nix/lib/machine/info.nix +5 -0
  118. data/nix/lib/swpins/eval.nix +71 -0
  119. data/nix/lib/swpins/options.nix +94 -0
  120. data/nix/machines.nix +31 -0
  121. data/nix/modules/cluster/default.nix +459 -0
  122. data/nix/modules/confctl/cli.nix +21 -0
  123. data/nix/modules/confctl/generations.nix +84 -0
  124. data/nix/modules/confctl/nix.nix +28 -0
  125. data/nix/modules/confctl/swpins.nix +55 -0
  126. data/nix/modules/module-list.nix +19 -0
  127. data/shell.nix +42 -0
  128. data/template/confctl-options.nix/main.erb +45 -0
  129. data/template/confctl-options.nix/options.erb +15 -0
  130. metadata +353 -0
data/README.md ADDED
@@ -0,0 +1,522 @@
1
+ # confctl
2
+ confctl is a Nix deployment configuration management tool. It can be used to
3
+ build and deploy [NixOS](https://nixos.org) and [vpsAdminOS](https://vpsadminos.org)
4
+ machines.
5
+
6
+ ## Features
7
+
8
+ * Stateless
9
+ * Per-machine nixpkgs (both modules and packages)
10
+ * Build generations for easy rollback
11
+ * Rotation of old generations
12
+ * Support for configuration interconnections (declare and access other machines'
13
+ configurations)
14
+ * Query machine state, view changelogs and diffs
15
+ * Run health checks
16
+
17
+ ## Requirements
18
+
19
+ * [Nix](https://nixos.org)
20
+
21
+ ## Quick start
22
+ 1. Either install confctl as a gem:
23
+ ```
24
+ gem install confctl
25
+ ```
26
+
27
+ Or clone this repository:
28
+
29
+ ```
30
+ git clone https://github.com/vpsfreecz/confctl
31
+ ```
32
+
33
+ This guide assumes you have cloned the repository, because otherwise man will
34
+ not find confctl's manual pages. If you install confctl using gem, you can
35
+ ignore steps with `shell.nix`.
36
+
37
+ 2. Create a new directory, where your confctl-managed configuration will be
38
+ stored:
39
+
40
+ ```
41
+ mkdir cluster-configuration
42
+ ```
43
+ 3. Prepare `shell.nix` in the new directory:
44
+ - Create a `shell.nix` and import the same file from confctl:
45
+ ```
46
+ cd cluster-configuration
47
+ cat > shell.nix <<EOF
48
+ import ../confctl/shell.nix
49
+ EOF
50
+ ```
51
+
52
+ - Alternatively, you can symlink `shell.nix` from the confctl repository:
53
+ ```
54
+ cd cluster-configuration
55
+ ln -s ../confctl/shell.nix shell.nix
56
+ ```
57
+
58
+ 4. Enter the `nix-shell`. This will make confctl available and install its
59
+ dependencies into `.gems/`:
60
+ ```
61
+ nix-shell
62
+ ```
63
+
64
+ From within the shell, you can access the [manual](./man/man8/confctl.8.md)
65
+ and a list of [configuration options](./man/man8/confctl-options.nix.8.md):
66
+
67
+ ```
68
+ man confctl
69
+ man confctl-options.nix
70
+ ```
71
+
72
+ 5. Initialize the configuration directory with confctl:
73
+ ```
74
+ confctl init
75
+ ```
76
+
77
+ 6. Add a new machine to be deployed:
78
+ ```
79
+ confctl add my-machine
80
+ ```
81
+
82
+ You can now edit the machine's configuration in directory `cluster/my-machine`.
83
+
84
+ 7. Update pre-configured software pins to fetch current nixpkgs:
85
+ ```
86
+ confctl swpins update
87
+ ```
88
+
89
+ 8. Build the machine
90
+ ```
91
+ confctl build my-machine
92
+ ```
93
+
94
+ 9. Deploy the machine
95
+ ```
96
+ confctl deploy my-machine
97
+ ```
98
+
99
+ ## Example configuration
100
+ Example configuration, which can be used as a starting point, can be found in
101
+ directory [example/](example/).
102
+
103
+ See also existing configurations:
104
+
105
+ * [vpsfree-cz-configuration](https://github.com/vpsfreecz/vpsfree-cz-configuration)
106
+ * [vpsadminos-org-configuration](https://github.com/vpsfreecz/vpsadminos-org-configuration)
107
+
108
+ ## Configuration directory structure
109
+ `confctl` configurations should adhere to the following structure:
110
+
111
+ cluster-configuration/ # Configuration root
112
+ ├── cluster/ # Machine configurations
113
+ │ ├── <name>/ # Single machine, can be nested directories
114
+ │ │ ├── config.nix # Standard NixOS system configuration
115
+ │ │ └── module.nix # Config with machine metadata used by confctl
116
+ │ ├── cluster.nix # confctl-generated list of machines
117
+ │ └── module-list.nix # List of all machine modules (including those in cluster.nix)
118
+ ├── configs/ # confctl and other user-defined configs
119
+ │ ├── confctl.nix # Configuration for the confctl tool itself
120
+ │ └── swpins.nix # User-defined software pin channels
121
+ ├── data/ # User-defined datasets available in machine configurations as confData
122
+ ├── environments/ # Environment presets for various types of machines, optional
123
+ ├── modules/ # User-defined modules
124
+ │ └── cluster/default.nix # User-defined extensions of `cluster.` options used in `<machine>/module.nix` files
125
+ ├── scripts/ # User-defined scripts
126
+ ├── swpins/ # confctl-generated software pins configuration
127
+ └── shell.nix # Nix expression for nix-shell
128
+
129
+ ## Software pins
130
+ Software pins in confctl allow you to use specific revisions of
131
+ [nixpkgs](https://github.com/NixOS/nixpkgs) or any other software to build
132
+ and deploy target machines. It doesn't matter what nixpkgs version the build
133
+ machine uses, because each machine gets its own nixpkgs as configured by the
134
+ software pin.
135
+
136
+ Software pins can be grouped in channels, which can then be used by all
137
+ or selected machines in the configuration. Or, if needed, custom software pins
138
+ can be configured on selected machines. See below for usage examples.
139
+
140
+ ## Software pin channels
141
+ Software pin channels are defined in file `confctl/swpins.nix`:
142
+
143
+ ```nix
144
+ { config, ... }:
145
+ {
146
+ confctl.swpins.channels = {
147
+ # Channel for NixOS unstable
148
+ nixos-unstable = { # channel name
149
+ nixpkgs = { # swpin name
150
+ # git-rev fetches the contents of a git commit and adds information
151
+ # about the current git revision
152
+ type = "git-rev";
153
+
154
+ git-rev = { # swpin type-specific configuration
155
+ # Repository URL
156
+ url = "https://github.com/NixOS/nixpkgs";
157
+
158
+ # Fetch git submodules or not
159
+ fetchSubmodules = false;
160
+
161
+ # git reference to use for manual/automated update using
162
+ # `confctl swpins channel update`
163
+ update.ref = "refs/heads/nixos-unstable";
164
+
165
+ # Whether to enable automated updates triggered by `confctl build | deploy`
166
+ update.auto = true;
167
+
168
+ # If update.auto is true, this determines how frequently will confctl
169
+ # try to update the channel, in seconds
170
+ update.interval = 60*60;
171
+ };
172
+ };
173
+ };
174
+
175
+ # Channel for vpsAdminOS staging
176
+ vpsadminos-staging = {
177
+ vpsadminos = {
178
+ type = "git-rev";
179
+
180
+ git-rev = {
181
+ url = "https://github.com/vpsfreecz/vpsadminos";
182
+ update.ref = "refs/heads/staging";
183
+ update.auto = true;
184
+ };
185
+ };
186
+ };
187
+ };
188
+ }
189
+ ```
190
+
191
+ This configuration defines what channels exist, what packages they contain
192
+ and how to fetch them. Such configured channels can then be manipulated using
193
+ `confctl`. `confctl` prefetches selected software pins and saves their hashes
194
+ in JSON files in the `swpins/` directory.
195
+
196
+ ```
197
+ # List channels
198
+ $ confctl swpins channel ls
199
+ CHANNEL SW TYPE PIN
200
+ nixos-unstable nixpkgs git-rev 1f77a4c8
201
+ vpsadminos-staging vpsadminos git-rev 9c9a7bcb
202
+
203
+ # Update channels with update.auto = true to reference in update.ref
204
+ $ confctl swpins channel update
205
+
206
+ # You can update only selected channels or swpins
207
+ $ confctl swpins channel update nixos-unstable
208
+ $ confctl swpins channel update nixos-unstable nixpkgs
209
+
210
+ # Set swpin to a custom git reference
211
+ $ confctl swpins channel set nixos-unstable nixpkgs 1f77a4c8
212
+ ```
213
+
214
+ `confctl build` and `confctl deploy` will now use the prefetched software pins.
215
+
216
+ ## Machine metadata and software pins
217
+ Machine configuration directory usually contains at least two files:
218
+ `cluster/<machine name>/config.nix` and `cluster/<machine name>/module.nix`.
219
+
220
+ `config.nix` is evaluated only when that particular machine is being built. It is
221
+ a standard NixOS configuration module, similar to `/etc/nixos/configuration.nix`.
222
+
223
+ `module.nix` is specific to confctl configurations. `module.nix` files from
224
+ all machines are evaluated during every build, whether that particular machine
225
+ is being built or not. `module.nix` contains metadata about machines from which
226
+ confctl knows how to treat them. It is also used to declare which software pins
227
+ or channels the machine uses. Metadata about any machine can be read from
228
+ `config.nix` of any other machine.
229
+
230
+ For example, machine named `my-machine` would be described in
231
+ `cluster/my-machine/module.nix` as:
232
+
233
+ ```nix
234
+ { config, ... }:
235
+ {
236
+ cluster."my-machine" = {
237
+ # This tells confctl whether it is a NixOS or vpsAdminOS machine
238
+ spin = "nixos";
239
+
240
+ # Use NixOS unstable channel defined in configs/swpins.nix
241
+ swpins.channels = [ "nixos-unstable" ];
242
+
243
+ # If the machine name is not a hostname, configure the address to which
244
+ # should confctl deploy it
245
+ host.target = "<ip address>";
246
+ };
247
+ }
248
+ ```
249
+
250
+ See [man/man8/confctl-options.nix.8.md](./man/man8/confctl-options.nix.8.md)
251
+ for a list of all options.
252
+
253
+ ## Per-machine software pins
254
+ It is simpler to use software pins from channels, because they are usually
255
+ used by multiple machines, but it is possible to define per-machine software
256
+ pins, either to override pins from channels or add custom ones.
257
+
258
+ Per-machine software pins are configured in the machine's `module.nix` file:
259
+
260
+ ```nix
261
+ { config, ... }:
262
+ {
263
+ cluster."my-machine" = {
264
+ # List of channels
265
+ swpins.channels = [ "..." ];
266
+
267
+ # Per-machine swpins
268
+ swpins.pins = {
269
+ "pin-name" = {
270
+ type = "git-rev";
271
+ git-rev = {
272
+ # ...pin definition...
273
+ };
274
+ };
275
+ };
276
+ };
277
+ }
278
+ ```
279
+
280
+ The configuration is exactly the same as that of software pins in channels.
281
+ Instead of `confctl swpins channel` commands, use `confctl swpins cluster`
282
+ to manage configured pins.
283
+
284
+ ## Nix flakes
285
+ confctl's software pins are an alternative to flakes and flakes are not supported
286
+ by confctl at this time. Software pins are implemented by manipulating the `$NIX_PATH`
287
+ environment variable, which is in conflict with using flakes. confctl is likely
288
+ to be migrated to flakes when the interface will be stabilized. Since the transition
289
+ is going to require a significant effort, there are no plans for it currently.
290
+
291
+ ## Extra module arguments
292
+ Machine configs can use the following extra module arguments:
293
+
294
+ - `confDir` - path to the cluster configuration directory
295
+ - `confLib` - confctl functions, see [nix/lib/default.nix](nix/lib/default.nix)
296
+ - `confData` - access to user-defined datasets found in `data/default.nix`,
297
+ see [example/data/default.nix](example/data/default.nix)
298
+ - `confMachine` - attrset with information about the machine that is currently
299
+ being built, contains key `name` and all options from
300
+ [machine metadata module](##machine-metadata-and-software-pins)
301
+ - `swpins` - attrset of software pins of the machine that is currently being built
302
+
303
+ For example in `cluster/my-machine/config.nix`:
304
+
305
+ ```nix
306
+ { config, lib, pkgs, confLib, confData, confMachine, ... }:
307
+ {
308
+ # Set the hostname to the machine name from confctl
309
+ networking.hostName = confMachine.name;
310
+
311
+ # When used with the data defined at example/data/default.nix
312
+ users.users.root.openssh.authorizedKeys.keys = with confData.sshKeys; admins;
313
+ }
314
+ ```
315
+
316
+ ## confctl configuration
317
+ The `confctl` utility itself can be configured using `configs/confctl.nix`:
318
+
319
+ ```nix
320
+ { config, ... }:
321
+ {
322
+ confctl = {
323
+ # Columns that are shown by `confctl ls`. Any option from machine metadata
324
+ # can be used.
325
+ listColumns = {
326
+ "name"
327
+ "spin"
328
+ "host.fqdn"
329
+ };
330
+ };
331
+ }
332
+ ```
333
+
334
+ ## Health checks
335
+ Health checks can be used to verify that the deployed systems behave correctly,
336
+ all services are running, etc. Health checks are run automatically after deploy
337
+ and can also be run on demand using `confctl health-check`. Health checks are
338
+ configured in machine metadata module, i.e. in `cluster/<machine>/module.nix`
339
+ files.
340
+
341
+ ```nix
342
+ { config, ... }:
343
+ {
344
+ cluster."my-machine" = {
345
+ # [...]
346
+
347
+ healthChecks = {
348
+ # Check that there are no failed units (this is actually done automatically
349
+ # by confctl, you don't need to do this yourself)
350
+ systemd.systemProperties = [
351
+ { property = "SystemState"; value = "running"; }
352
+ ];
353
+
354
+ # Check that the firewall is active, we can check any property of any service
355
+ systemd.unitProperties."firewall.service" = [
356
+ { property = "ActiveState"; value = "active"; }
357
+ ];
358
+
359
+ # Run arbitrary commands from the builder
360
+ builderCommands = [
361
+ # Ping the deployed machine
362
+ { command = [ "ping" "-c1" "{host.fqdn}" ]; }
363
+ ];
364
+
365
+ # Run commands on the deployed machine
366
+ machineCommands = [
367
+ # Try to access a fictional internal web server
368
+ { command = [ "curl" "-s" "http://localhost:80" ]; }
369
+
370
+ # We can also check command output
371
+ { command = [ "hostname" ]; standardOutput.match = "my-machine\n"; }
372
+ ];
373
+ };
374
+ };
375
+ }
376
+ ```
377
+
378
+ ## Rotate build generations
379
+ confctl can be used to rotate old generations both on the build machine
380
+ and on the deployed machines.
381
+
382
+ Default rotation settings can be set in confctl settings at `configs/confctl.nix`:
383
+
384
+ ```nix
385
+ { config, lib, ... }:
386
+ with lib;
387
+ {
388
+ confctl = {
389
+ # Generations on the build machine
390
+ buildGenerations = {
391
+ # Keep at least 4 generations
392
+ min = mkDefault 4;
393
+
394
+ # Do not keep more than 10 generations
395
+ max = mkDefault 10;
396
+
397
+ # Delete generations older than 90 days
398
+ maxAge = mkDefault (90*24*60*60);
399
+ };
400
+
401
+ # The same settings can be configured for generations on the deployed machines
402
+ hostGenerations = {
403
+ min = mkDefault 40;
404
+ max = mkDefault 100;
405
+ maxAge = mkDefault (180*24*60*60);
406
+
407
+ # On the deployed machines, confctl can also run nix-collect-garbage to
408
+ # delete unreachable store paths
409
+ collectGarbage = mkDefault true;
410
+ };
411
+ };
412
+ }
413
+ ```
414
+
415
+ If these settings are not set, confctl uses its own defaults. Further, rotation
416
+ settings can be configured on per-machine basis in machine metadata module
417
+ at `cluster/<machine>/module.nix`:
418
+
419
+ ```nix
420
+ { config, ... }:
421
+ {
422
+ cluster."my-machine" = {
423
+ # [...]
424
+
425
+ buildGenerations = {
426
+ min = 8;
427
+ max = 16;
428
+ };
429
+
430
+ hostGenerations = {
431
+ min = 80;
432
+ };
433
+ };
434
+ }
435
+ ```
436
+
437
+ Settings from the machine metadata modules override default confctl settings
438
+ from `configs/confctl.nix`.
439
+
440
+ To rotate the generations both on the build and deployed machines, run:
441
+
442
+ ```
443
+ confctl generation rotate --local --remote
444
+ ```
445
+
446
+ Generations can also be deleted manually, e.g. to delete generations older than
447
+ 90 days, run:
448
+
449
+ ```
450
+ confctl generation rm --local --remote '*' 30d
451
+ ```
452
+
453
+ ## Extending machine metadata
454
+ To define your own options to be used within the `cluster.<name>` modules in
455
+ `cluster/<machine>/module.nix` files, create file `modules/cluster/default.nix`,
456
+ e.g.:
457
+
458
+ ```nix
459
+ { config, lib, ... }:
460
+ with lib;
461
+ let
462
+ myMachine =
463
+ { config, ... }:
464
+ {
465
+ options = {
466
+ myParameter = mkOption { ... };
467
+ };
468
+ };
469
+ in {
470
+ options = {
471
+ cluster = mkOption {
472
+ type = types.attrsOf (types.submodule myMachine);
473
+ };
474
+ };
475
+ }
476
+ ```
477
+
478
+ Then you can use it in machine module as:
479
+
480
+ ```nix
481
+ { config, ... }:
482
+ {
483
+ cluster."my-machine" = {
484
+ myParameter = "1234";
485
+ };
486
+ }
487
+ ```
488
+
489
+ Note that these modules are self-contained. They are not evaluated with the full
490
+ set of NixOS modules. You have to import modules that you need.
491
+
492
+ ## User-defined confctl commands
493
+ User-defined Ruby scripts can be placed in directory `scripts`. Each script
494
+ should create a subclass of `ConfCtl::UserScript` and call class-method `register`.
495
+ Scripts can define their own `confctl` subcommands.
496
+
497
+ ### Example user script
498
+
499
+ ```ruby
500
+ class MyScript < ConfCtl::UserScript
501
+ register
502
+
503
+ def setup_cli(app)
504
+ app.desc 'My CLI command'
505
+ app.command 'my-command' do |c|
506
+ c.action &ConfCtl::Cli::Command.run(c, MyCommand, :run)
507
+ end
508
+ end
509
+ end
510
+
511
+ class MyCommand < ConfCtl::Cli::Command
512
+ def run
513
+ puts 'Hello world'
514
+ end
515
+ end
516
+ ```
517
+
518
+ ## More information
519
+ See the [man pages](./man/man8) for more information:
520
+
521
+ * [confctl(8)](./man/man8/confctl.8.md)
522
+ * [confctl-options.nix(8)](./man/man8/confctl-options.nix.8.md)
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'confctl'
3
+ require 'md2man/rakefile'
4
+ require 'md2man/roff/engine'
5
+ require 'md2man/html/engine'
6
+
7
+ # Override markdown engine to add extra parameter
8
+ [Md2Man::Roff, Md2Man::HTML].each do |mod|
9
+ mod.send(:remove_const, :ENGINE)
10
+ mod.send(:const_set, :ENGINE, Redcarpet::Markdown.new(mod.const_get(:Engine),
11
+ tables: true,
12
+ autolink: true,
13
+ superscript: true,
14
+ strikethrough: true,
15
+ no_intra_emphasis: false,
16
+ fenced_code_blocks: true,
17
+
18
+ # This option is needed for command options to be rendered property
19
+ disable_indented_code_blocks: true))
20
+ end
21
+
22
+ desc 'Generate man/man8/confctl-options.nix.8.md'
23
+ task 'confctl-options' do
24
+ ConfCtl::Logger.open('rake', output: $stdout)
25
+
26
+ opts = ConfCtl::ModuleOptions.new(nix: ConfCtl::Nix.stateless)
27
+ opts.read
28
+
29
+ ConfCtl::ErbTemplate.render_to('confctl-options.nix/main', {
30
+ date: Time.now,
31
+ version: 'master',
32
+ opts:,
33
+ print_options: proc do |opt_list|
34
+ ConfCtl::ErbTemplate.render('confctl-options.nix/options', {
35
+ opts: opt_list,
36
+ indent: proc { |s, n| s.split("\n").join("\n#{' ' * n}") }
37
+ })
38
+ end
39
+ }, 'man/man8/confctl-options.nix.8.md')
40
+ end
data/bin/confctl ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'confctl'
3
+ require 'confctl/cli'
4
+ ConfCtl::Cli::App.run
data/confctl.gemspec ADDED
@@ -0,0 +1,33 @@
1
+ lib = File.expand_path('lib', __dir__)
2
+ $:.unshift(lib) unless $:.include?(lib)
3
+ require 'confctl/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'confctl'
7
+
8
+ s.version = ConfCtl::VERSION
9
+ s.summary =
10
+ s.description = 'Nix deployment management tool'
11
+ s.authors = 'Jakub Skokan'
12
+ s.email = 'jakub.skokan@vpsfree.cz'
13
+ s.files = `git ls-files -z`.split("\x0")
14
+ s.files += Dir['man/man?/*.?']
15
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ s.license = 'GPL-3.0-only'
17
+
18
+ s.required_ruby_version = ">= #{File.read('.ruby-version').strip}"
19
+
20
+ s.add_runtime_dependency 'curses'
21
+ s.add_runtime_dependency 'gli', '~> 2.21.0'
22
+ s.add_runtime_dependency 'json'
23
+ s.add_runtime_dependency 'md2man'
24
+ s.add_runtime_dependency 'rainbow', '~> 3.1.1'
25
+ s.add_runtime_dependency 'rake'
26
+ s.add_runtime_dependency 'require_all', '~> 2.0.0'
27
+ s.add_runtime_dependency 'tty-command', '~> 0.10.1'
28
+ s.add_runtime_dependency 'tty-cursor', '~> 0.7.1'
29
+ s.add_runtime_dependency 'tty-pager', '~> 0.14.0'
30
+ s.add_runtime_dependency 'tty-progressbar', '~> 0.18.2'
31
+ s.add_runtime_dependency 'tty-spinner', '~> 0.9.3'
32
+ s.add_runtime_dependency 'vpsfree-client', '~> 0.18.0'
33
+ end
@@ -0,0 +1,2 @@
1
+ .confctl
2
+ .gems
data/example/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # confctl example configuration
2
+ There are four skeleton deployments:
3
+
4
+ * `nixos-machine` to deploy a standard NixOS machine
5
+ * `vpsadminos-machine` to deploy vpsAdminOS machine
6
+ * `vpsadminos-container` to deploy to a container running on vpsAdminOS
7
+ * `vpsfreecz-container` to deploy to a VPS at [vpsFree.cz](https://vpsfree.org),
8
+ which is the same as `vpsadminos-container`
9
+
10
+ ## Usage
11
+ 1. Enter `nix-shell`:
12
+ ```
13
+ nix-shell
14
+ ```
15
+
16
+ 2. Update software pins:
17
+ ```
18
+ confctl swpins update
19
+ ```
20
+
21
+ 3. Edit configurations in `cluster/` to your liking.
22
+
23
+ Note that to deploy physical machines, you have to supply `hardware.nix` file,
24
+ which is generated by `nixos-generate-config` when installing NixOS, you'll find
25
+ it at `/etc/nixos/hardware-configuration.nix`. confctl cannot actually install
26
+ or provision a machine, it has to already be installed and running. confctl will
27
+ deploy the new system over SSH and activate it.
28
+
29
+ Target IP addresses to which the systems will be deployed to can be set
30
+ in `cluster/*/module.nix`, option `target.host`.
31
+
32
+ Configure SSH keys in `data/ssh-keys.nix`.
33
+
34
+ 4. Build and deploy
35
+ ```
36
+ confctl build vpsfreecz-vps
37
+ confctl deploy vpsfreecz-vps
38
+ ```
@@ -0,0 +1,7 @@
1
+ # This file is generated by confctl, changes will be lost
2
+ [
3
+ ./nixos-machine/module.nix
4
+ ./vpsadminos-container/module.nix
5
+ ./vpsadminos-machine/module.nix
6
+ ./vpsfreecz-vps/module.nix
7
+ ]
@@ -0,0 +1,3 @@
1
+ (import ./cluster.nix) ++ [
2
+ # Place for custom modules
3
+ ]
@@ -0,0 +1,15 @@
1
+ { config, pkgs, lib, ... }:
2
+ {
3
+ imports = [
4
+ ../../environments/base.nix
5
+ ./hardware.nix
6
+ ];
7
+
8
+ networking.hostName = "nixos-machine";
9
+
10
+ boot.loader.grub.enable = true;
11
+ boot.loader.grub.version = 2;
12
+ # boot.loader.grub.device = "";
13
+
14
+ system.stateVersion = "20.09";
15
+ }
@@ -0,0 +1,4 @@
1
+ { config, pkgs, lib, ... }:
2
+ {
3
+ # Your hardware-configuration.nix
4
+ }
@@ -0,0 +1,8 @@
1
+ { config, ... }:
2
+ {
3
+ cluster."nixos-machine" = {
4
+ spin = "nixos";
5
+ swpins.channels = [ "nixos-unstable" ];
6
+ host.target = "<ip address>";
7
+ };
8
+ }