Conditional Configurations in Partitioned NixOS Flake Setup

Hello everyone,

I’m currently working on a NixOS setup where I’ve partitioned my configuration into multiple files, each tailored to specific environments (e.g., server, desktop, laptop). My setup is working well, but I’m encountering issues when trying to introduce conditional configurations based on variables like ‘systemType’.

Here’s a brief overview of my current setup:

Flake Configuration

In my ‘flake.nix’, I have defined different NixOS configurations:

nixosConfigurations = {
  server = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs outputs; };
    modules = [ ./nixos/server.nix ];
  };
  desktop = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs outputs; };
    modules = [ ./nixos/desktop.nix { systemType = "x11"; } ];
  };
  laptop = nixpkgs.lib.nixosSystem {
    specialArgs = { inherit inputs outputs; };
    modules = [ 
      ./nixos/laptop.nix 
      { systemType = "wayland"; } 
    ];
  };
};

Laptop Configuration

In my ‘laptop.nix’, I attempt to use the ‘systemType’ variable to conditionally import other configuration files:

{ inputs, outputs, config, lib, pkgs, systemType, ... } :

{
  imports = [
    ./hardware/hardware-configuration.laptop.nix
    ./core.nix { inherit systemType; }
    (if systemType == "x11" then ./x11.nix else null)
    (if systemType == "wayland" then ./wayland.nix else null)
  ];
};

Core Configuration

The ‘core.nix’ handles shared configurations and Home Manager:

# home-manager.useUserPackages = true;
home-manager = {
  extraSpecialArgs = { inherit inputs outputs systemType; };
  users = {
    # Import your home-manager configuration
    iamanaws = import ../home-manager/home.nix;
  };
};

Home Manager Configuration

In ‘home.nix’, I want to conditionally configure files based on ‘systemType’:


{
  inputs,
  outputs,
  lib,
  config,
  pkgs,
  systemType,
  ...
}:
...
home.file.qtile_config = if systemType == "x11" then {
    source = ../config/qtile;
    target = ".config/qtile";
    recursive = true;
  } else null;

The Issue

While the structure seems logically sound, I’m running into recursive errors. It appears that the problem stems from trying to pass ‘systemType’ through the configuration files, particularly when I attempt to import ‘core.nix’ into ‘laptop.nix’ while simultaneously passing ‘systemType’ back to ‘core.nix’.

I’ve tried various approaches, including passing ‘systemType’ directly through specialArgs:

laptop = nixpkgs.lib.nixosSystem {
  specialArgs = { inherit inputs outputs; systemType = "wayland"; };
  modules = [ ./nixos/laptop.nix ];
};

However, this often results in errors such as “null is not a valid string variable,” and other issues related to the conditional imports.

What I Need Help With

  1. Understanding the recursive error: Why does the configuration get stuck in a recursive loop when trying to pass variables through multiple files?
  2. Best practices for conditional imports: How can I effectively pass variables like systemType between different NixOS modules without running into these issues?
  3. Simplifying the structure: Are there ways to refactor my configuration to avoid these problems while still maintaining modularity and flexibility?

Any guidance or suggestions would be greatly appreciated! I’m eager to learn how to properly manage conditional configurations in a split NixOS setup using flakes.

Thanks in advance for your help!

Don’t conditionally import, you’re fighting the module system. You don’t want to add null to imports either of course.
Create options like .enable or so on> and conditionally set bits of config with that. Or you can create profiles that you explicitly just import and group some defaults.

6 Likes

Hello,
I have been trying, but not get it at all…

Could you give me and example of how and where to define, and pass the option?

Can it be defined on the flake? how do we pass the option value?

Seems like what you need to learn is the nixpkgs module system.