Skip to content

Latest commit

 

History

History
139 lines (106 loc) · 2.82 KB

40-module-anatomy.org

File metadata and controls

139 lines (106 loc) · 2.82 KB

Module anatomy

Short recap


  • Nix modules are attribute sets all the way down
  • Module system uses some “magic keys”
  • Modules are parsed, then merged into one big attrset

Putting this all together, let’s write our own module

Basic outline


{ config, pkgs, lib, ... }:
{
  imports = [ ... ];
  options = { ... };
  config = { ... };
}
  • options keys are merged for pre-evaluation
  • config keys are merged for post-evalutation
  • imports are not merged but instead queued for evaluation

# hamster-module.nix
{ config, lib, pkgs, ... }:
{
  options = {
    programs.hamster.enable =
      lib.mkEnableOption "hamster, a time tracking program";
  };
  config = lib.mkIf config.programs.hamster.enable {
    environment.systemPackages = [ pkgs.hamster ];
  };
}

Defining options


  • nixpkgs/lib defines some types and utilities that we can use in the module system
  • lib.mkEnableOption creates a boolean type option
  • lib.mkOption creates an arbitrary typed option
  • Each option can be given a description, default value, example configuration, etc

{
  options.services.cow-server = {
    enable = lib.mkEnableOption "Enable the cow server";
    message = lib.mkOption {
      type = lib.types.str;
      default = "Hello!";
      description = ''
        The kind of message that you will get from the cow-server
      '';
    };
  };

  config = { ... };
}

Using options


  • The config key is evaluated after the options
  • Via the config.services.cow-server key we have access to user-selected options
  • Again, lib contains some utilities to make our life easier
{
  options = { ... };

  config = lib.mkIf config.services.cow-server.enable {
    # ... our configuration from previously ...
  };
}

Module patterns


When creating a module, alias the local option scope in a let...in.

{ config, lib, ... }:

let cfg = config.foo.bar.my-module;
in
with lib;
{
  options.foo.bar.my-module = {
    # ...
  };

  config = mkIf cfg.enable {
    # ...
  }
}

Module patterns


If your configuration block is too complex, consider moving it to a different file.

{ config, lib, ... } @ args:

with lib;
{
  options.foo.bar.my-module = {
    # ...
  };
  
  config = (import ./config.nix args);
}