dynix/README.md

126 lines
5.6 KiB
Markdown
Raw Permalink Normal View History

<!--
SPDX-FileCopyrightText: 2026 Qyriad <qyriad@qyriad.me>
SPDX-License-Identifier: EUPL-1.1
-->
2026-02-18 14:01:39 +01:00
# Dynix — WIP modular dynamicism for NixOS systems
2026-02-18 16:35:00 +01:00
Dynix is a prototype for modifying an append-only NixOS configuration, and dynamically applying that configuration.
2026-02-18 14:01:39 +01:00
## Running the tests
There are currently 3 implemented dynamicism modules: `gotosocial`, `harmonia`, and `distccd`.
Each test uses the [NixOS test infrastructure](https://nixos.org/manual/nixos/unstable/#sec-nixos-tests) to:
1. Setup a virtual machine running NixOS
2. Configure the VM's NixOS to run a given service, with certain settings
3. Verify that the running service is using those settings
4. Use Dynix to change a setting for that service
5. Verify that the running service is now using the new setting
The tests themselves can be run with Nix.
To run the test for, e.g., Gotosocial, you can run:
```bash
$ nix --experimental-features "nix-command flakes pipe-operator pipe-operators" build .#default.tests.gotosocial
```
The experimental [piping operator](https://github.com/NixOS/rfcs/pull/148) is currently used in Dynix, so you must enable the experimental feature `pipe-operator` for Lix or `pipe-operators` for CppNix (you can add both to cover both Nix implementations); flakes are used for locked inputs.
To run a test with fewer experimental features, and without locked inputs, you can use the old CLI:
```bash
$ nix-build --experimental-features "pipe-operator pipe-operators" -A tests.gotosocial
```
All the tests at once can be run with:
```bash
$ nix build --experimental-features "nix-command flakes pipe-operator pipe-operators" .#default.allTests
```
## Gotosocial
This example, implemented in [`./modules/dynamicism/gotosocial.nix`](./modules/dynamicism/gotosocial.nix), is tested in [`./tests/gotosocial`](./tests/gotosocial).
2026-02-18 14:01:39 +01:00
The test sets up a VM using NixOS's `services.gotosocial` module with the following *static* [configuration](./tests/gotosocial/configuration.nix):
```nix
{
services.gotosocial = {
enable = true;
setupPostgresqlDB = true;
settings = {
application-name = "gotosocial-for-machine";
host = "gotosocial-machine.local";
};
};
}
```
The automated [test script](./tests/gotosocial/test-script.py):
1. Asserts that that the above *static* configuration is in effect (by extracting the configuration from the running Gotosocial process)
2. Runs `dynix append "services.gotosocial.settings.application-name" "yay!"`, which modifies the append-only configuration file `/etc/nixos/dynamic.nix` in the VM filesystem
3. Runs the dynamic activation script built by `(import <nixpkgs/nixos>).config.dynamicism.applyDynamicConfiguration { }`, which *applies* the dynamic configuration
4. Asserts that the dynamically configured `application-name` is in effect
5. Runs `nixos-rebuild switch` to re-apply the *static* configuration
6. Asserts that the dynamic configuration is *no longer* in effect, and we are back to the static configuration
## Harmonia
This example, implemented in [`./modules/dynamicism/harmonia.nix`](./modules/dynamicism/harmonia.nix), is tested in [`./tests/harmonia`](./tests/harmonia).
2026-02-18 14:01:39 +01:00
The test sets up a VM using NixOS's `services.harmonia` module with the following *static* [configuration](./tests/harmonia/configuration.nix)
```nix
{
services.harmonia = {
enable = true;
settings = {
workers = 4;
max_connection_rate = 256;
};
};
}
```
The VM [test script](./tests/harmonia/test-script.py):
1. Asserts that the above *static* configuration is in effect (by extracting the configuration from the running Harmonia process)
2. Runs `dynix append "services.harmonia.settings.workers" 20`, to modify the append-only configuration file `/etc/nixos/dynamic.nix` in the VM filesystem
3. Runs the dynamic activation script built by `(import <nixpkgs/nixos>).config.dynamicism.applyDynamicConfiguration { }`, to *apply* the dynamic configuration
4. Asserts that the dynamically configured `workers` is in effect
5. Runs `dynix append "services.harmonia.settings.max_connection_rate" 100`
6. Runs the dynamic activation script
7. Asserts that *both* `max_connection_rate` and `workers` dynamic values are in effect
8. Runs `nixos-rebuild switch` to re-apply the *static* configuration
9. Asserts that the dynamic configuration is *no longer* in effect, and we are back to the static configuration
## Distccd
This example, implemented in [`./modules/dynamicism/distccd.nix`](./modules/dynamicism/distccd.nix), is tested in [`./tests/distccd`](./tests/distccd).
2026-02-18 14:01:39 +01:00
The test sets up a VM using NixOS's `services.distccd` module with the following *static* [configuration](./tests/distccd/configuration.nix):
```nix
{
services.distccd = {
jobTimeout = 900;
maxJobs = 12;
logLevel = "warning";
};
}
```
The VM [test script](./tests/distccd/test-script.py):
1. Asserts that the above *static* configuration is in effect (by extracting the configuration from the running Distccd process)
2. Runs `dynix append "services.distccd.maxJobs" 4`, to modify the append-only configuration file `/etc/nixos/dynamic.nix` in the VM filesystem
3. Runs the dynamic activation script built by `(import <nixpkgs/nixos>).config.dynamicism.applyDynamicConfiguration { }`, to *apply* the dynamic configuration
4. Asserts that the dynamically configured `maxJobs` is in effect
5. Runs `dynix append "services.distccd.logLevel" "error"`
6. Runs the dynamic activation script
7. Asserts that *both* `maxJobs` and `logLevel` dynamic values are in effect
8. Runs `nixos-rebuild switch` to re-apply the *static* configuration
9. Asserts that the dynamic configuration is *no longer* in effect, and we are back to the static configuration.