Use Nix module as a way of declaring global variables

Hello everyone,

I have recently descovered that Nix Expression Language seems to not have a way to define a global variables. The thing I’m willing to achieve is to have all variables in one place and to only reference their values in actual config this way:

variables.nix

userdata = (
  domain = "mydomain.com";
  username = "user";
  hashedMasterPassword = "3hg1509509824h598g<4879gb2g95";
)

mailserver.nix

{ lib, pkgs, ... }:
{
  services = {
    postfix = {
      user = ${userdata.user};
      domain = ${userdata.domain};
    };
  };
}

As far as Nix Language does not provide any way to define global variables, I would like to know, is it possible to create a module and define its options to use them later in the config?

I’ve created the following module:

module.nix

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

with lib;

let
  cfg = config.services.userdata;
  directionArg = if cfg.direction == ""
    then ""
    else "--direction=${cfg.direction}";
in 
  {
    options.services.userdata = {
      enable = mkOption {
        default = true;
        type = types.nullOr types.bool;
      };
      domain = mkOption {
        description = ''
          Domain used by the server
        '';
	type = types.nullOr types.str;
      };
      username = mkOption {
        description = ''
          Username that was defined at the initial setup process
        '';
	type = types.nullOr types.str;
      };
      hashedMasterPassword = {
        description = ''
          Hash of the password that was defined at the initial setup process
        '';
        type = types.nullOr types.str;
      };
    };
}

My idea was to use values from this module in later configuration:

mailserver.nix

{ lib, pkgs, ... }:
{
  services = {

  userdata = {
    user = "user";
  };
    postfix = {
      user = ${services.userdata.user};
    };
  };
}

But when I build this module, I encounter the following issue:

error: You're trying to declare a value of type `string'
rather than an attribute-set for the option
`services.userdata.hashedMasterPassword.description'!

This usually happens if `services.userdata.hashedMasterPassword.description' has option
definitions inside that are not matched. Please check how to properly define
this option by e.g. referring to `man 5 configuration.nix'!

(use '--show-trace' to show detailed location information)

Could someone please suggest, if it possible to implement global variables in the way I’ve chosen?

Thanks

What you’re doing is standard procedure in NixOS modules. It is my understanding that all configs and options are merged together. In other words, any module should have access to all options and configurations set and defined by other modules.

In your case you might have simply forgotten a mkOption for hashedMasterPassword.

I do something very similar in my own configuration. Here I set my alacritty theme to light and here I refer to that option. This is where the option is defined.

1 Like

You need to change this to hashedMasterPassword = mkOption {.

Beyond that, sometimes, its just easier to define some common values in lib.

As a rule of thumb, I’d use lib if I do only want to read some values from other places, while I use the module, to actually set dependant values from that module.

I rarely have a module that only has options.

1 Like
  user = ${services.userdata.user};

needs to be

  user = ${config.services.userdata.user};

too.

1 Like

@cideM @NobbZ @ryantm Thanks for all of the suggestions. Could I please also ask you to suggest me how to use that values in my configuration? I’ve configured userdata module with the options I would like to make available globally, but when I try to use them as a values when configuring some other service using this service’s module, I get the Unexpected value error. For example:

nextcloud.nix(Using part of my Nextcloud configuration as an example)

{ pkgs, ... }:
{
  services = {
    nextloud = {
      ...
      hostName = ${options.services.userdata.domain};
      ...
    };
  };
}

I get this:

error: syntax error, unexpected DOLLAR_CURLY

Is it possible to use those values in the other files and should I include the file with userdata module configuration in the Nextcloud config?

  1. You need to add config to the argument set
  2. do not use ${} outside of strings or attribute pathes
  3. use config.* to access the values.
2 Likes

Thanks. It works now