NixOS & overlays

Posted on May 29, 2023

I re-installed NixOS on a machine recently, and would like to use display-switch for this machine as well. This software isn’t packaged for NixOS yet, but I found a overlay containing it, and these are the steps needed to use it.

  1. I saved the service file to /etc/nixos/display-switch.nix
  2. I saved the package file to /etc/nixos/pkgs/display-switch.nix
  3. I saved the overlay file to /etc/nixos/overlays/pkgs.nix, after removing unused packages
  4. I edited my /etc/nixos/configuration.nix to include the overlay file and the service file

Snippets from my configuration.nix file relevant to this change:

{ config, pkgs, lib, ... }:

{
  imports =
    [
      ./hardware-configuration.nix
      ./display-switch.nix
    ];

  # ...

  nixpkgs.overlays = [ (import ./overlays/pkgs.nix) ];

Files

And for anyone looking to copy paste files instead of links…

/etc/nixos/display-switch.nix

{ config, pkgs, ... }:
{
  boot.kernelModules = [ "i2c_dev" ]; # i2c_dev for DDC support (/dev/i2c-*)

  # DDC support (/dev/i2c-*)
  services.udev.extraRules = ''
    KERNEL=="i2c-[0-9]*", TAG+="uaccess"
  '';

  systemd.services.display-switch =
    let
      display-switch-config = pkgs.runCommand "display-switch-config"
        {
          # The configuration file for display-switch, works like on all other
          # platforms
          config = pkgs.writeText "display-switch.ini" ''
            usb_device = "1a40:0101"
            on_usb_connect = "DisplayPort1"
          '';
        } ''
        mkdir -p "$out/display-switch"
        cp "$config" "$out/display-switch/display-switch.ini"
      '';
    in
    {
      description = "USB-triggered display switch";
      environment = {
        XDG_CONFIG_HOME = display-switch-config;
      };
      serviceConfig = {
        Type = "simple";
        ExecStart = "${pkgs.display-switch}/bin/display_switch";
      };
      wantedBy = [ "default.target" ];
    };
}

/etc/nixos/pkgs/display-switch.nix

I should update to the latest version…

{ lib, stdenv, fetchFromGitHub, rustPlatform, udev, pkgconfig }:

rustPlatform.buildRustPackage rec {
  pname = "display-switch";
  version = "dev";

  src = fetchFromGitHub {
    owner = "haimgel";
    repo = "display-switch";
    rev = "1.1.0";
    sha256 = "sha256-jucXTVuC3H7/fkn9Z/d2ElbpRI135EooYnCfRIVuUy0=";
  };

  cargoSha256 = "sha256-IJRlBto5CKAIuPMzhEjpdj9DKXqJ/Hvn+oxi9bqwbjw=";

  nativeBuildInputs = [ pkgconfig ];
  buildInputs = [ udev ];

  doCheck = false;

  meta = with lib; {
    description = "Turn a $30 USB switch into a full-featured multi-monitor KVM switch";
    homepage = "https://github.com/haimgel/display-switch";
    license = licenses.mit;
    maintainers = with maintainers; [ ];
    platforms = platforms.all; # Linux, Darwin, Windows
  };
}

/etc/nixos/overlays/pkgs.nix

self: super:
{
  display-switch = super.callPackage ../pkgs/display-switch.nix { };
}