Guide on "how to use Qtile's flake in your nixos configuration."

Even though Qtile's documentation already demonstrates how one could use it's flake, it might be too much for someone just starting out with nix flakes.

I'll try to touch important details, while also keeping the main focus on Qtile.

Enabling nix flakes

Nix flakes are still technically experimental, but they have become the industry standard for reproducible configurations. In order to enable flakes you are going to have to add following to your configuration.nix file:

Note: usually in /etc/nixos/configuration.nix

  nix.settings.experimental-features = [ "nix-command" "flakes"];

And then you are going to rebuild your system.

Creating flake that provides qtile-flake

I've drafted a flake template with the logic moved out for clarity.

{
  description = "Basic NixOS Flake - Starter Template";

  inputs = {
    nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";

    qtile-flake = {
      url = "github:qtile/qtile";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  outputs = {
    self,
    nixpkgs,
    qtile-flake,
    ...
  } @ inputs: {
    nixosConfigurations.nixos = nixpkgs.lib.nixosSystem {
      specialArgs = {inherit inputs qtile-flake;};

      modules = [
        ./configuration.nix 
      ];
    };
  };
}

Breakdown of the Flake logic:

  • nixpkgs.url: The primary source of packages. Using nixos-unstable for the latest packages.

  • qtile-flake: We pull this directly from the source to get specific features or PRs. To test a specific PR or fork, you would replace this URL.

  • inputs.nixpkgs.follows: This line ensures Qtile uses the SAME nixpkgs version as the rest of your system. This prevents downloading two different versions of the same dependencies.

  • nixosConfigurations.nixos: The name 'nixos' here is your hostname. You target this with: sudo nixos-rebuild switch --flake /path/to/flake#nixos.

  • specialArgs: passes our inputs (like qtile-flake) into our configuration files. This allows you to use qtile-flake inside your configuration.nix or home.nix.

Note: Replace 'nixos' with whatever your actual hostname is."

Using Qtile package provided by flake

Assuming you already have Qtile enabled, go to a file where you have the module defined. Example:

{
  services.xserver.windowManager.qtile = {
    enable = true;
  };
}

In order to use flake, we are going to modify the file a bit.

Note: Qtile's flake exposes a package that contains upstream Qtile (source version).

{qtile-flake, pkgs, ...}: {
  services.xserver.windowManager.qtile = {
    enable = true;
    package = qtile-flake.packages.${pkgs.stdenv.hostPlatform.system}.default;
  };
}

Breakdown of the package selection:

  • {qtile-flake, pkgs, ...}:: We add this at the top of the file. It gives us access to specified variables (qtile-flake, pkgs) in current module.

  • package option: By setting this, we tell the nixos module to use our specified package instead of default pkgs.python3Packages.qtile.

  • qtile-flake: Local variable that holds the value of the flake.

  • qtile-flake.packages: Flakes have an exposed variable packages that hold all the package derivations.

  • ${pkgs.stdenv.hostPlatform.system}: This package holds the value of the system architecture. By specifying it, we tell nix to use the package defined for "our" system arch. e.g x86_64-linux.

  • default: Holds the default package exposed by the flake.


For Qtile-Extras users!

If you are using Qtile-Extras you might get some conflicts. To avoid that, you might want to use upstream Qtile-Extras as well.

Updating flake.nix inputs:

    qtile-extras-flake = {
      url = "github:elparaguayo/qtile-extras";
      flake = false;
    };
  • flake = false: Even though Qtile-Extras currently doesn't have a flake in its repo, by setting this flag, we tell nix: "This repository doesn't have a flake, but still fetch the source." This lets us use the latest source code from GitHub even if the author hasn't officially packaged it for Nix yet.

Overriding the package in your module:

We add inputs in file imports because we didn't specify qtile-extras-flake in specialArgs and we need some way to access it.

{inputs, qtile-flake, pkgs, ...}: let 
  qtile-extras-flake = pkgs.python3Packages.qtile-extras.overridePythonAttrs {
    src = inputs.qtile-extras-flake.outPath;
    doCheck = false;
    patches = [];
  };
in {
  services.xserver.windowManager.qtile = {
    enable = true;
    package = qtile-flake.packages.${pkgs.stdenv.hostPlatform.system}.default;
    extraPackages = ps: [qtile-extras-flake];
  };
}

Breakdown of the Override:

  • let/in: The let statement defines variables to be used inside the in block. This saves us the trouble and mess of overriding a package inside a list.

  • src: We set the source to the outPath of our fetched input.

  • doCheck = false: Sometimes tests break or take really long while they barely affect your experience. I personally choose to disable the checking phase.

  • patches = ]: As of now, patches specified in upstream nixpkgs break Qtile-Extras if built from src. By overriding patches we are removing all the patches specified in the package derivation.

  • extraPackages: This line tells nix to install Qtile with the specified packages injected.

Note: Some useful resources to learn about overrides/overlays
Nixos & Flakes Book about package overrides
Nixos Wiki about Overlays
Ryantm about Overriding


Rebuild and check

After doing all the steps above, we get to finally rebuild nixos. In order to rebuild using flake we need to specify the flake flag:

sudo nixos-rebuild switch --flake /path/to/flake#HOSTNAME

After rebuilding and restarting Qtile's session, you can run qtile --version just to make sure you did everything correctly. It should look like this:

qtile --version
0.34.1+d005851.flake

Note: +XXXXXXX represents shortRev.

Helpful books/docs

Note: best way to learn nix is to read other people's config files and source codes.

References