Experiments in modular dynamicism for NixOS systems
Find a file
2026-03-25 19:21:37 +01:00
.cargo customize Cargo a bit, for now 2026-03-22 16:41:01 +01:00
LICENSES license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
modules/dynamicism license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
src daemon tests for gotosocial 2026-03-25 19:21:37 +01:00
tests daemon tests for gotosocial 2026-03-25 19:21:37 +01:00
.editorconfig license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
.gitignore license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
Cargo.lock daemon w/ tests PoC 2026-03-24 15:07:52 +01:00
Cargo.lock.license license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
Cargo.toml daemon w/ tests PoC 2026-03-24 15:07:52 +01:00
default.nix daemon w/ tests PoC 2026-03-24 15:07:52 +01:00
flake.lock flake.lock: Update 2026-03-22 15:00:06 +01:00
flake.lock.license license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
flake.nix packaging: checkMeta 2026-03-05 17:19:49 +01:00
LICENSE license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
package.nix daemon tests for gotosocial 2026-03-25 19:21:37 +01:00
README.md license under the European Union Public License 1.2 2026-03-05 17:19:49 +01:00
rustfmt.toml daemon w/ tests PoC 2026-03-24 15:07:52 +01:00
shell.nix daemon w/ tests PoC 2026-03-24 15:07:52 +01:00

Dynix — WIP modular dynamicism for NixOS systems

Dynix is a prototype for modifying an append-only NixOS configuration, and dynamically applying that configuration.

Running the tests

There are currently 3 implemented dynamicism modules: gotosocial, harmonia, and distccd. Each test uses the NixOS test infrastructure 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:

$ nix --experimental-features "nix-command flakes pipe-operator pipe-operators" build .#default.tests.gotosocial

The experimental piping operator 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:

$ nix-build --experimental-features "pipe-operator pipe-operators" -A tests.gotosocial

All the tests at once can be run with:

$ nix build --experimental-features "nix-command flakes pipe-operator pipe-operators" .#default.allTests

Gotosocial

This example, implemented in ./modules/dynamicism/gotosocial.nix, is tested in ./tests/gotosocial. The test sets up a VM using NixOS's services.gotosocial module with the following static configuration:

{
  services.gotosocial = {
    enable = true;
    setupPostgresqlDB = true;
    settings = {
      application-name = "gotosocial-for-machine";
      host = "gotosocial-machine.local";
    };
  };
}

The automated test script:

  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, is tested in ./tests/harmonia. The test sets up a VM using NixOS's services.harmonia module with the following static configuration

{
  services.harmonia = {
    enable = true;
    settings = {
      workers = 4;
      max_connection_rate = 256;
    };
  };
}

The VM test script:

  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, is tested in ./tests/distccd. The test sets up a VM using NixOS's services.distccd module with the following static configuration:

{
  services.distccd = {
    jobTimeout = 900;
    maxJobs = 12;
    logLevel = "warning";
  };
}

The VM test script:

  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.