# NixOS Module Integration with OpenLogi: Declarative Logitech Device Management

> Integrate Logitech devices with NixOS using the OpenLogi module. Declaratively manage your Logitech hardware and its daemon, udev rules, and systemd service for seamless control.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: how-to-guide
- Published: 2026-08-24

---

**OpenLogi ships a native NixOS module that declaratively installs the daemon, udev rules, and user-level systemd service through the `programs.openlogi` option set defined in `packaging/linux/nixos-module.nix`.**

The AprilNEA/OpenLogi repository provides first-class NixOS support through a dedicated module that eliminates manual configuration. This integration allows you to manage Logitech devices declaratively using standard NixOS configuration syntax. Understanding the **NixOS module integration with OpenLogi** enables system administrators to deploy the background agent consistently across machines while leveraging the project's Rust-based toolchain.

## How the OpenLogi NixOS Module Works

### Enabling the Module via `programs.openlogi`

The module exposes its interface through the `programs.openlogi` attribute set, declared at lines 12–22 of `packaging/linux/nixos-module.nix`. This option set provides three key configuration knobs:

- **`enable`**: Toggles the entire integration on or off
- **`package`**: Allows overriding the default OpenLogi derivation
- **`launchAtLogin`**: Controls whether the agent starts automatically with graphical sessions

```nix
options.programs.openlogi = {
  enable = lib.mkEnableOption "OpenLogi, a local-first Logitech device manager";
  package = lib.mkPackageOption pkgs "openlogi" { };
  launchAtLogin = lib.mkOption {
    type = lib.types.bool;
    default = true;
    description = "Whether to start the OpenLogi agent with graphical sessions.";
  };
};

```

*Source: [nixos-module.nix lines 12–22](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/nixos-module.nix#L12-L22)*

### System-Wide Integration

When `programs.openlogi.enable` evaluates to `true`, the module performs two critical system-level modifications at lines 24–27. It appends the OpenLogi package to `environment.systemPackages`, making the `openlogi-agent` binary available in the global `$PATH`. Simultaneously, it registers the package's udev rules through `services.udev.packages`, ensuring the kernel recognizes Logitech hardware connections immediately.

```nix
config = lib.mkIf cfg.enable {
  environment.systemPackages = [ cfg.package ];
  services.udev.packages = [ cfg.package ];

```

*Source: [nixos-module.nix lines 24–27](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/nixos-module.nix#L24-L27)*

### User-Level systemd Service

The module creates a per-user systemd service named `openlogi-agent` at lines 28–39. The service configuration uses `lib.getExe' cfg.package "openlogi-agent"` to locate the binary path dynamically. When `launchAtLogin` is enabled, the service attaches to `graphical-session.target`, ensuring the agent starts only after the user session initializes.

```nix
systemd.user.services.openlogi-agent = {
  description = "OpenLogi background agent";
  wantedBy = lib.optionals cfg.launchAtLogin [ "graphical-session.target" ];
  after = [ "graphical-session.target" ];
  partOf = lib.optionals cfg.launchAtLogin [ "graphical-session.target" ];
  serviceConfig = {
    ExecStart = lib.getExe' cfg.package "openlogi-agent";
    Restart = "on-failure";
    RestartSec = 5;
  };
};

```

*Source: [nixos-module.nix lines 28–39](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/nixos-module.nix#L28-L39)*

### Flake Outputs and Wiring

The `flake.nix` file exposes the module through the `nixosModules.openlogi` output at lines 99–108. This wiring imports `packaging/linux/nixos-module.nix` and passes the default package as an argument. The flake also sets up the build environment at lines 31–38 using `oxalica/rust-overlay` to provide a recent Rust toolchain, ensuring the `openlogi` package compiles correctly against NixOS system libraries.

## Configuring OpenLogi on NixOS

To activate the integration, import the flake's module output into your `configuration.nix` and enable the feature:

```nix
{ pkgs, ... }:

{
  imports = [
    # Reference the OpenLogi module from your flake input

    inputs.openlogi.nixosModules.openlogi
  ];

  programs.openlogi = {
    enable = true;              # Activates the module

    launchAtLogin = true;       # Auto-starts with graphical sessions

    # package = pkgs.openlogi;  # Optional: custom derivation override

  };
}

```

Apply the configuration with:

```bash
sudo nixos-rebuild switch

```

If you disable `launchAtLogin`, start the agent manually using:

```bash
systemctl --user start openlogi-agent.service

```

## Module Architecture and Source Files

| File | Purpose |
|------|---------|
| `flake.nix` | Defines flake outputs including `nixosModules.openlogi`, configures the Rust toolchain via `oxalica/rust-overlay`, and builds the package using `packaging/linux/package.nix`. |
| `packaging/linux/nixos-module.nix` | Implements the `programs.openlogi` interface, manages system package installation, udev rule registration, and the user-level systemd service definition. |
| `packaging/linux/package.nix` | Contains the Nix derivation that compiles OpenLogi from source using the Rust toolchain provided by the flake. |

## Summary

- **OpenLogi provides a native NixOS module** located at `packaging/linux/nixos-module.nix` that integrates the daemon, udev rules, and user services declaratively.
- **The `programs.openlogi` option set** controls enablement, package selection, and autostart behavior through standard NixOS configuration.
- **System integration** automatically adds the binary to `environment.systemPackages` and registers device rules via `services.udev.packages`.
- **User-level service management** creates a systemd unit that conditionally binds to `graphical-session.target` based on the `launchAtLogin` setting.
- **Flake compatibility** ensures reproducible builds by managing the Rust toolchain and exposing the module through `nixosModules.openlogi`.

## Frequently Asked Questions

### How do I import the OpenLogi NixOS module into my configuration?

Add the OpenLogi flake as an input to your system flake, then import `inputs.openlogi.nixosModules.openlogi` into your `configuration.nix` imports list. This exposes the `programs.openlogi` options namespace automatically.

### Can I override the OpenLogi package version in the NixOS module?

Yes. Set `programs.openlogi.package` to a custom derivation. The module uses `lib.mkPackageOption` with a default pointing to the flake-built package, but any package containing the `openlogi-agent` binary and udev rules will function correctly.

### How do I prevent OpenLogi from starting automatically at login?

Set `programs.openlogi.launchAtLogin = false;` in your configuration. This removes the `graphical-session.target` dependency from the systemd service, requiring you to start the agent manually with `systemctl --user start openlogi-agent.service`.

### Where are the udev rules installed when using the OpenLogi module?

The module appends the OpenLogi package to `services.udev.packages`, which merges the rules into the system-wide udev configuration. The rules are extracted from the `out` directory of the specified package derivation during the NixOS build process.