How the NixOS Module Configures and Automatically Starts the OpenLogi Agent

The NixOS module defined in packaging/linux/nixos-module.nix exposes the programs.openlogi option set, which installs the package system-wide and registers a user-level systemd service (openlogi-agent.service) that automatically starts with graphical sessions when launchAtLogin is enabled.

The OpenLogi project provides a dedicated NixOS module to streamline installation and daemon management on NixOS systems. By declaring programs.openlogi.enable = true, users can configure the OpenLogi agent to start automatically with graphical sessions without manual systemd unit creation. This guide examines the implementation details found in the AprilNEA/OpenLogi repository, explaining exactly how the module handles package installation, udev rule deployment, and user service activation.

Enabling the OpenLogi NixOS Module

The module is controlled through the programs.openlogi option set defined in packaging/linux/nixos-module.nix.

To activate the software, users set the enable boolean defined at lines 12–14:

programs.openlogi.enable = true;

When enabled, the module immediately performs two actions. First, it adds the selected package to environment.systemPackages (lines 24–27), making the openlogi-agent binary available globally. Second, it registers the udev rules via services.udev.packages to ensure Logitech HID++ devices are accessible to the service.

The package option (lines 15–16) uses mkPackageOption and defaults to the openlogi package from Nixpkgs. Users may override this with custom builds:

programs.openlogi.package = pkgs.callPackage ./my-openlogi.nix {};

Configuring Automatic Startup Behavior

The launchAtLogin boolean (lines 17–20) controls whether the background agent starts automatically when a graphical session begins. The default value is true.

When launchAtLogin is enabled, the module creates systemd.user.services.openlogi-agent (lines 28–38) with the following configuration:

  • Activation trigger: The service defines wantedBy = [ "graphical-session.target" ] and partOf = [ "graphical-session.target" ] (lines 30–33), ensuring systemd starts the agent whenever the graphical session target is reached.
  • Command execution: The ExecStart directive (line 35) calls lib.getExe' cfg.package "openlogi-agent", which resolves to the openlogi-agent binary from the configured package.
  • Resilience: The service includes Restart = "on-failure" and RestartSec = 5 (lines 36–38), guaranteeing that systemd automatically restarts the agent if it crashes, with a five-second backoff between attempts.

Setting programs.openlogi.launchAtLogin = false generates the same service unit but omits the wantedBy linkage, requiring manual startup via systemctl --user start openlogi-agent.

System-Wide Integration and Hardware Support

Beyond the user service, the module ensures proper hardware access. When enabled, it installs the 70-openlogi.rules file (located in packaging/linux/udev/) through services.udev.packages (lines 24–27). This rule allows the kernel to expose Logitech HID++ devices to the agent with appropriate permissions. Combined with the environment.systemPackages injection, this creates a complete runtime environment where the agent binary, udev rules, and systemd service are managed declaratively.

Practical Configuration Examples

A minimal configuration to enable OpenLogi with automatic startup:

{ pkgs, ... }:

{
  programs.openlogi = {
    enable = true;
    launchAtLogin = true;  # Optional; true is the default

  };
}

To install without automatic startup, allowing manual control:

programs.openlogi = {
  enable = true;
  launchAtLogin = false;
};

After running sudo nixos-rebuild switch, the system applies the udev rules, installs the binaries, and registers the systemd user service according to your launchAtLogin preference.

Summary

  • The NixOS module in packaging/linux/nixos-module.nix provides the programs.openlogi option set to declaratively manage OpenLogi.
  • programs.openlogi.enable triggers installation via environment.systemPackages and registers udev rules for hardware access.
  • programs.openlogi.launchAtLogin controls whether systemd.user.services.openlogi-agent is wanted by graphical-session.target.
  • The service uses Restart = "on-failure" with a 5-second delay to ensure the agent remains running.
  • Users may override the default package via programs.openlogi.package.

Frequently Asked Questions

How do I prevent the OpenLogi agent from starting automatically?

Set programs.openlogi.launchAtLogin = false in your configuration.nix. This removes the wantedBy dependency on graphical-session.target, preventing automatic startup while keeping the binary installed and the service available for manual activation.

Can I use a custom OpenLogi package with the NixOS module?

Yes. Override the programs.openlogi.package option with your derivation. The module uses lib.getExe' to locate the openlogi-agent binary within whatever package you specify, ensuring compatibility with custom builds or specific versions.

How does the module handle Logitech device permissions?

The module installs 70-openlogi.rules from packaging/linux/udev/ via services.udev.packages. These rules ensure the kernel exposes Logitech HID++ devices with correct permissions, allowing the unprivileged user service to communicate with the hardware.

What happens if the OpenLogi agent crashes?

The systemd service definition includes Restart = "on-failure" and RestartSec = 5, as defined in lines 36–38 of the module. Systemd will automatically attempt to restart the agent after any failure, waiting five seconds between attempts to avoid rapid restart loops.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →