# How the OpenLogi NixOS Module Installs the Agent, Udev Rules, and Graphical Session Integration

> Learn how the OpenLogi NixOS module declaratively installs the agent, udev rules, and integrates graphical session startup. Simplify your OpenLogi setup with Nix.

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

---

**The OpenLogi NixOS module declaratively wires the background agent and udev rules by exposing the package through `programs.openlogi.package`, merging hardware permissions into `services.udev.packages`, and attaching a systemd user service to `graphical-session.target` for automatic startup.**

OpenLogi is an open-source input remapping daemon that requires low-level access to HID devices and a persistent user-space process. The AprilNEA/OpenLogi repository provides a dedicated NixOS module at `packaging/linux/nixos-module.nix` that automates the entire installation lifecycle—from kernel-level udev rules to graphical session integration—through a single `programs.openlogi` configuration namespace.

## Module Architecture and Package Exposure

The module expects a package definition via `config.programs.openlogi.package`. By default, this resolves to the Nix derivation built from `packaging/linux/package.nix`, which bundles the **OpenLogi binaries** alongside the **udev rules** file located at `packaging/linux/udev/70-openlogi.rules` [[source]](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/package.nix#L95-L96).

During the package build’s `installPhase`, the derivation copies the udev rules into the Nix store path at `$out/lib/udev/rules.d/70-openlogi.rules`. It also installs a systemd user unit template and desktop entry, ensuring all runtime artifacts reside within the same immutable closure.

## Installing Udev Rules for Hardware Access

Hardware access relies on declarative udev rule installation rather than manual file manipulation. The module appends the OpenLogi package to the system-wide udev configuration:

```nix
services.udev.packages = [ cfg.package ];

```

This line in `packaging/linux/nixos-module.nix` [[source]](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/nixos-module.nix#L24-L27) instructs NixOS to merge `70-openlogi.rules` from the package’s store path into `/etc/udev/rules.d/`. The rules grant the active user permissions for `/dev/hidraw*` and `/dev/uinput` devices without requiring **sudo** privileges.

## Graphical Session Integration via Systemd User Service

The module defines a systemd **user** service named `openlogi-agent` that executes the binary from the configured package (`cfg.package`). The service unit is conditionally bound to the graphical session lifecycle:

- `wantedBy = lib.optionals cfg.launchAtLogin [ "graphical-session.target" ]`
- `after = [ "graphical-session.target" ]` [[source]](https://github.com/AprilNEA/OpenLogi/blob/master/packaging/linux/nixos-module.nix#L30-L32)

The boolean option `programs.openlogi.launchAtLogin` (defaulting to `true`) controls this behavior. When enabled, the agent starts automatically each time the user logs into a graphical session; when disabled, the service remains available for manual activation via `systemctl --user start openlogi-agent`.

## Configuration Reference

Enable the module and control startup behavior through your `configuration.nix`:

```nix
{
  programs.openlogi = {
    enable = true;           # Installs package and udev rules

    launchAtLogin = true;    # Starts agent with graphical session

    # Optional: override with a custom derivation

    # package = pkgs.callPackage ./custom-openlogi.nix { };

  };
}

```

## Verifying the Installation

After running `nixos-rebuild switch`, confirm that the udev rule is active and the agent is running:

```bash

# Verify udev rules are applied to HID devices

udevadm info -a -p $(udevadm info -q path -n /dev/hidraw0) | grep OPENLOGI

# Expected output references /etc/udev/rules.d/70-openlogi.rules

# Check systemd user service status

systemctl --user status openlogi-agent

```

The status output should show the service loaded from the Nix store path and **active (running)** if `launchAtLogin` is enabled.

## Summary

- The **OpenLogi NixOS module** (`packaging/linux/nixos-module.nix`) consolidates package installation, udev rule deployment, and systemd user service management.
- **Udev rules** are installed declaratively via `services.udev.packages`, granting hardware access without manual configuration.
- A **systemd user service** binds to `graphical-session.target`, ensuring the agent starts only when a graphical session is available.
- The `programs.openlogi.launchAtLogin` option provides toggleable autostart behavior while maintaining the service definition for manual control.

## Frequently Asked Questions

### How does the NixOS module grant permissions to HID devices without manual udev configuration?

The module adds the OpenLogi package to `services.udev.packages`, which causes NixOS to automatically symlink `70-openlogi.rules` from the Nix store into `/etc/udev/rules.d/`. This grants the active user read/write access to `/dev/hidraw*` and `/dev/uinput` without modifying system files manually or running the agent with elevated privileges.

### Can I prevent the agent from starting automatically while keeping the udev rules installed?

Yes. Set `programs.openlogi.launchAtLogin = false` in your configuration. This removes the `graphical-session.target` dependency from the systemd user service, preventing automatic startup while preserving the udev rules and the service definition for manual activation.

### Where is the systemd user service file defined?

The service template resides at `packaging/linux/systemd/openlogi-agent.service` in the source repository. The NixOS module installs this file into the package output at `$out/share/systemd/user/`, then enables it via the `programs.openlogi` option namespace.

### What happens if I override the default package with a custom derivation?

The module respects `programs.openlogi.package` for all operations. The custom derivation must provide the OpenLogi binary and install udev rules to `$out/lib/udev/rules.d/` for the `services.udev.packages` integration to function correctly. The systemd service’s `ExecStart` will automatically reference your custom package’s binary path.