Experiments in modular dynamicism for NixOS systems
  • Nix 46.7%
  • Rust 32.2%
  • Python 21.1%
Find a file
2026-02-18 16:35:00 +01:00
modules/dynamicism remove unused code 2026-02-18 15:02:26 +01:00
src IT WORKS 2026-02-17 19:48:53 +01:00
tests cleanup in tests 2026-02-18 16:17:06 +01:00
.editorconfig normalize whitespace 2026-02-18 13:03:26 +01:00
.gitignore skeleton 2026-01-27 16:30:14 +01:00
Cargo.lock IT WORKS 2026-02-17 19:48:53 +01:00
Cargo.toml IT WORKS 2026-02-17 19:48:53 +01:00
default.nix remove unused code 2026-02-18 15:02:26 +01:00
flake.lock packaging: use fenix for dev shell 2026-02-17 16:10:10 +01:00
flake.nix normalize whitespace 2026-02-18 13:03:26 +01:00
package.nix normalize whitespace 2026-02-18 13:03:26 +01:00
README.md README: oops, finish lead sentence 2026-02-18 16:35:00 +01:00
shell.nix normalize whitespace 2026-02-18 13:03:26 +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.