Going crazy on Flake with systemd service

Hi,

I’m new to Nix. I’ve finally found the courage to try it out! I love the ideas behind Nix, but I’m having some issues.

I’m building a Flake for a small program I wrote called evcape. I want my flake to add a systemd service when it is installed on a NixOS host, so that it can be enabled by the user and do it’s thing.

evcape/flake.nix

{
  description = "A flake for building evcape";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
    flake-utils.url = "github:numtide/flake-utils";
  };

  # See https://wiki.nixos.org/wiki/Flakes#Output_schema for more information
  outputs = { self, nixpkgs, flake-utils }: {

    nixosModules.default = import ./nixos.nix;

  } // flake-utils.lib.eachDefaultSystem(system:

    let pkgs = nixpkgs.legacyPackages.${system}; in
    {

      packages.evcape = pkgs.stdenv.mkDerivation {
        name = "evcape";
        src = self;
        nativeBuildInputs = with pkgs; [
          meson
          ninja
          pkg-config
        ];
        buildInputs = with pkgs; [
          libevdev
          systemd
        ];
        meta = with pkgs.lib; {
          homepage = "https://github.com/samvv/evcape";
          description = "A small tool for making the Control key act as an Escape-key on Linux/Wayland";
          license = licenses.mit;
          maintainers = [ maintainers.samvv ];
          platforms = platforms.linux;
          mainProgram = "evcape";
        };
      };

      packages.default = self.packages.${system}.evcape;

  });

}

evcape/nixos.nix

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

  let cfg = config.services.float; in {

    options.services.evcape = {
      enable = mkEnableOption "enable the evcape key remapper service";
      log_level = mkOption {
        type = types.int;
        default = 5;
        description = "how much messages to log in the console";
      };
    };

    config = mkIf cfg.enable {
      systemd.services.evcape = {
        description = "evcape key remapper";
        wantedBy = [ "multi-user.tarrget" ];
        after = [ "udev.service" ];
        environment = {
          EVCAPE_LOG_LEVEL = "${cfg.log_level}";
        };
        serviceConfig = {
          Type = "simple";
          ExecStart = "${cfg.package}/bin/evcape";
          Restart = "on-failure";
          ProtectHome = "read-only";
        };
      };
    };

  }

/etc/nixos/flake.nix

{
  inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
  inputs.evcape.url = "path:/home/samvv/Projects/evcape";
  outputs = { self, nixpkgs, evcape }: {
    nixosConfigurations.xana = nixpkgs.lib.nixosSystem {
      modules = [
        ./configuration.nix
        evcape.nixosModules # or evcape.nixosModules.default?
      ];
    };
  };
}

My experience so far:

  1. The caches are working against me. Each time I run sudo nixos-rebuild switch, it reports error: cached failure of attribute 'nixosConfigurations.xana.config or keeps building an old version of the library. (yes, it took me a while to figure that out). Doing a rm -rf /root/.cache/nix for each rebuild feels very awkward. I’m doing something wrong.
  2. I managed to replicate this issue, where hashes inside Nix’s cache are inconsistent. I’ve never been able to fix the issue, besides switching to my GitHub repo as ‘the source of truth’ instead of my project dir.
  3. I’m getting an error message I’m unable to decrypt.
error:
       … while calling the 'seq' builtin

         at /nix/store/1h99qq6970gkx3j0m9w4yrrl9y99y1nk-source/lib/modules.nix:322:18:

          321|         options = checked options;
          322|         config = checked (removeAttrs config [ "_module" ]);
             |                  ^
          323|         _module = checked (config._module);

       … while calling the 'throw' builtin

         at /nix/store/1h99qq6970gkx3j0m9w4yrrl9y99y1nk-source/lib/modules.nix:298:18:

          297|                     ''
          298|             else throw baseMsg
             |                  ^
          299|         else null;

       error: The option `default' does not exist. Definition values:
       - In `/nix/store/1h99qq6970gkx3j0m9w4yrrl9y99y1nk-source/flake.nix': <function, args: {config, lib, pkgs}>

Can someone help me fix these issues? In particular, can someone illustrate how to create a flake with a systemd unit? Also: is this the right way to develop flakes (by installing them)? If not, what is?

Thanks,
Sam

All right, looks like I’ve found some answers:

  1. Use sudo nixos-rebuild switch --impure if you want to avoid the caches.
  2. Use sudo nix flake update inside /etc/nixos if you want to fetch the latest changes from GitHub.
  3. My configuration was close from being complete. I was just having issues with the caches.

--impure might have unwanted side effects as it’s very broad in scope. The flag you’re probably looking for is --option eval-cache false or --no-eval-cache

Use sudo nix flake update inside /etc/nixos if you want to fetch the latest changes from GitHub.

You can also move the configuration to an arbitrary location where a standard user can edit it without sudo and use sudo nixos-rebuild switch --flake <thatArbitraryLocation>

You can also move the configuration to an arbitrary location where a standard user can edit it without sudo and use sudo nixos-rebuild switch --flake

Thanks, I’m doing that right now. Let’s see how it goes …