Files
nixpkgs/nixos/modules/services/networking/lxmd.md
2026-07-24 17:48:55 +02:00

5.5 KiB

LXMD

LXMF daemon (lxmd).

This module runs lxmd as a systemd service with DynamicUser = true and StateDirectory = "lxmd" directives.

Quickstart

A minimal setup:

{
  services.lxmd.enable = true;
}

With custom LXMD and RNSD settings:

{
  services.lxmd = {
    enable = true;

    identityFile = "<path-to-lxmd-identity-file>";

    settings = {
      propagation-node = {
        autopeer = true;
      };
    };

    rnsd = {
      identityFile = "<path-to-rnsd-identity-file>";

      settings = {
        reticulum = {
          require_shared_instance = true;
          is_shared_instance = true;
          enable_transport = true;
          instance_name = "default";
          shared_instance_type = "unix";
        };
      };
    };
  };
}

At startup, settings provided through services.lxmd.settings, services.lxmd.identityFile, and services.lxmd.rnsd.settings are copied into the service state directory.

Health Check

You can optionally wait for lxmd to become responsive during startup using lxmd --status:

{
  services.lxmd = {
    enable = true;

    healthCheck = {
      enable = true;
      intervalSeconds = 2;
      timeoutSeconds = 120;
    };
  };
}

When enabled, startup fails if lxmd --status does not succeed before services.lxmd.healthCheck.timeoutSeconds.

Communicating With RNSD

Even though both services are hardened (via Systemd's DynamicUser = true and StateDirectory = "lxmd" directives), lxmd can still communicate with rnsd in several ways.

Option 1: Shared Instance Over Unix RPC

Use a shared Reticulum instance exposed through a local Unix RPC socket:

{
  services.rnsd = {
    enable = true;

    identityFile = "<path-to-rnsd-identity-file>";

    settings = {
      reticulum = {
        enable_transport = true;
        share_instance = true;
        instance_name = "default";
        shared_instance_type = "unix";
      };
      interfaces = {
        auto = {
          type = "AutoInterface";
          enabled = true;
        };
      };
    };
  };

  services.lxmd = {
    enable = true;

    identityFile = "<path-to-lxmd-identity-file>";

    settings = {
      # LXMD settings, run `lxmd --exampleconfig` for details
    };

    rnsd = {
      identityFile = "<path-to-rnsd-identity-file>";

      settings = {
        reticulum = {
          require_shared_instance = true;
          is_shared_instance = true;
          enable_transport = true;
          instance_name = "default";
          shared_instance_type = "unix";
        };
      };
    };
  };
}

In this model, lxmd points to an RNS configuration that joins the shared instance. Both RNS transport identity files in rnsd and lxmd must be the same. If you use different transport identity files, then set the same rpc_key in both rnsd configurations to allow them to communicate securely.

It is also possible to use a shared instance over TCP, please refer to the Reticulum documentation for details.

Option 2: Isolated Instances Connected Through BackboneInterface

Reticulum applications (rnsd, lxmd, and others) can be isolated by running:

  • one primary rnsd service instance as a non-privileged service account,
  • one instance per application, each with its own user and configuration,
  • a BackboneInterface between each isolated application instance and the primary instance.

On the primary rnsd instance, the BackboneInterface is configured to accept connections from the isolated instances, as such:

{
  services.rnsd = {
    enable = true;

    identityFile = "<path-to-rnsd-identity-file>";

    settings = {
      reticulum = {
        # RNSD settings, run `rnsd --exampleconfig` for details
      };
      interfaces = {
        root = {
          type = "BackboneInterface";
          enabled = true;
          mode = "gateway";
          discoverable = true;
          listen_ip = "127.0.0.1";
          listen_port = 4242;
        };
      };
    };
  };
}

Then, on each isolated application instance, the BackboneInterface is configured to connect to the primary instance:

{
  services.lxmd = {
    enable = true;

    identityFile = "<path-to-lxmd-identity-file>";

    settings = {
      # LXMD settings, run `lxmd --exampleconfig` for details
    };

    rnsd = {
      identityFile = "<path-to-rnsd-identity-file>";

      settings = {
        reticulum = {
          # RNSD settings, run `rnsd --exampleconfig` for details
        };
        interfaces = {
          local = {
            type = "BackboneInterface";
            enabled = true;
            target_host = "127.0.0.1";
            target_port = 4242;
          };
        };
      };
    };
  };
}

The primary rnsd instance serves system-local BackboneInterface links for applications and external interfaces for the wider network. Each isolated app uses its own RNS configuration directory (for example with --rnsconfig <path>), and that local instance connects to the root instance through BackboneInterface.

Running multiple instances increases memory usage and adds one extra hop, but the performance impact is generally negligible.