All options

Every option dinix declares, rendered from options.nix itself. The guide introduces the ones a configuration usually sets.

package

The dinit package to configure, wrap and verify against.

trimShutdownTools acts on this. What the wrappers actually use is internal.dinitPackage.

Type: package

Default:

<derivation dinit-0.22.1>

Declared by:

  • options.nix

assertions.*.assertion

This option has no description.

Type: boolean

Declared by:

  • options.nix

assertions.*.message

This option has no description.

Type: string

Declared by:

  • options.nix

caCertificates.enable

Whether to enable a CA bundle, named to every service by environment.

Type: boolean

Default:

false

Example:

true

Declared by:

  • cacert.nix

caCertificates.package

The package holding the bundle. Nothing reaches the closure until this is enabled.

Type: package

Default:

<derivation nss-cacert-3.126>

Declared by:

  • cacert.nix

caCertificates.file

The bundle itself.

Mount this at the path a program insists on when it has no way to be told. Go, curl, git and anything using OpenSSL read the environment first, so they need no mount.

Type: string (read only)

Default:

"/nix/store/15x4d7i4p60sjqvls7riw7sd42551s19-nss-cacert-3.126/etc/ssl/certs/ca-bundle.crt"

Declared by:

  • cacert.nix

caCertificates.variables

Which environment variables name the bundle. Each gets caCertificates.file.

SSL_CERT_FILE is the one OpenSSL itself reads, and covers most programs. NIX_SSL_CERT_FILE is what the OpenSSL in nixpkgs and Nix itself read. The other two are for programs that ignore both.

Add REQUESTS_CA_BUNDLE for Python, or any other name a program of yours reads. Nothing here checks the names.

Type: list of string

Default:

[
  "SSL_CERT_FILE"
  "NIX_SSL_CERT_FILE"
  "CURL_CA_BUNDLE"
  "GIT_SSL_CAINFO"
]

Declared by:

  • cacert.nix

configDir

Every file dinix generates, in one store path.

services/<name>   service descriptions
env/<name>        per-service environment files
env-file          the environment file dinit itself reads
init.spec         the directories and checks for dinix-init
etc/              passwd, group, shadow, nsswitch.conf, sshd_config

One path rather than several because a container image built from a Nix closure usually gets a layer per store path. Splitting the same bytes over six paths spends six layers on them, and image formats have a layer ceiling worth saving for things that change independently. These do not: every file here is rewritten whenever any service changes.

A service description refers to its environment file as ../env/<name>, which dinit resolves against the directory holding the description. That keeps the reference inside this path instead of pointing at another one.

Type: package (read only)

Declared by:

  • options.nix

consoleLevel

How much of dinit’s own logging reaches the console.

quiet alone also silences this. The default puts it back at warn, which keeps the “Service <name> process terminated with exit code N” line. That line names the service that brought the container down, and nothing else reports it.

Type: null or one of “none”, “error”, “warn”, “info”, “debug”

Default:

"warn"

Declared by:

  • options.nix

consolidateConfig

Whether to put everything dinix generates in one store path (configDir) rather than one path per piece.

On, because a container image built from a Nix closure usually gets a layer per store path, and the six or so paths dinix would otherwise add are six layers holding bytes that all change together. Image formats have a layer ceiling, and these are not worth spending it on.

Off is the right setting where store paths are not layers, such as a runtime that mounts the closure directly. Then each piece is its own path, and a change to one service does not rebuild the rest.

Type: boolean

Default:

true

Declared by:

  • options.nix

containerWrapper

dinit as PID 1 of a container, reading its services straight from the store.

A plain binary wrapper, so the image needs no shell, no coreutils and no writable root filesystem. Setting users.installAtRuntime makes it a shell script instead, and puts a shell in the closure.

meta.mainProgram is dinit, so lib.getExe resolves it and the whole thing symlinks into a larger environment.

Type: package

Declared by:

  • options.nix

dirs

Directories to make before any service starts, keyed by path.

A Nix build cannot chown, so a directory that needs an owner or a mode has to be made at startup. initPackage does that and nothing else: it has no way to run a program, which is why the image needs no shell.

Setting this adds a dinix-init service that the boot service depends on, so a directory that cannot be made stops the container rather than letting a service start without it.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • options.nix

dirs.<name>.gid

Numeric group, or null to leave it alone. See uid.

Type: null or signed integer

Default:

null

Declared by:

  • options.nix

dirs.<name>.mode

Octal permissions for the directory itself.

Type: string

Default:

"0755"

Declared by:

  • options.nix

dirs.<name>.path

The directory to make. Defaults to the attribute name.

Type: string

Default:

"‹name›"

Declared by:

  • options.nix

dirs.<name>.uid

Numeric owner, or null to leave it alone.

Numeric rather than a name on purpose: this runs before the services do, so the user database may not be in place yet and a name would be a lookup that cannot be relied on. Setting an owner at all needs root.

Type: null or signed integer

Default:

null

Declared by:

  • options.nix

env-file

Environment file dinit itself reads, applied to every service. Either a path, or an attribute set rendered into one. See dinit(8).

Type: null or absolute path or (submodule)

Default:

null

Declared by:

  • options.nix

initPackage

The helper that makes dirs. Statically linked and about 500 KiB in a single store path with no dependencies.

Type: package

Default:

<derivation dinix-init-0.1.0>

Declared by:

  • options.nix

internal.checkArgs

Flags dinit-check accepts: the services directory and the env-file.

Type: string

Declared by:

  • options.nix

internal.configDataFiles

Files copied into configDir, as relative path to the store path holding the content. A modular service’s configData arrives this way: the portable layer renders it to a file and hands over a source, so there is text to read only by building it, which would be import-from-derivation.

Type: attribute set of absolute path

Default:

{ }

Declared by:

  • options.nix

internal.containerArgs

Flags the container wrapper adds on top of dinitArgs.

Type: string

Declared by:

  • options.nix

internal.dinitArgs

Flags every wrapped dinit gets, whatever the mode.

Type: string

Declared by:

  • options.nix

internal.dinitPackage

package, with the shutdown tools removed if asked for.

Type: package

Declared by:

  • options.nix

internal.envFilePath

Where dinit’s own env-file ends up, or null when there is none.

Type: null or string

Default:

null

Declared by:

  • options.nix

internal.envFileText

The top-level env-file text, when it is a set rather than a path.

Type: null or string

Default:

null

Declared by:

  • options.nix

internal.envfileArg

The --env-file argument, or the empty string.

Type: string

Declared by:

  • options.nix

internal.etcFiles

Files under etc/ that dinix renders, as relative path to content: the user database, and any configuration a built-in service writes for the program it runs.

Type: attribute set of string

Default:

{ }

Declared by:

  • options.nix

internal.initSpecPath

Where that spec ends up.

Type: string

Declared by:

  • options.nix

internal.initSpecText

The checks and dirs, rendered for dinix-init.

Type: string

Declared by:

  • options.nix

internal.servicesDir

The directory holding one file per service.

Type: string

Declared by:

  • options.nix

internal.usersInstallScript

Script that installs the user database into the rootfs.

Type: null or package

Default:

null

Declared by:

  • options.nix

logBufferSize

Bytes of output kept for a service with dinix.log = "buffer".

dinit’s own default is 4096, and it discards everything past the limit, so a service of any volume keeps only its last few lines. 256 KiB holds enough to explain a crash.

Type: signed integer

Default:

262144

Declared by:

  • options.nix

logDirs

Every directory a service declared through dinix.logDir, keyed by service name.

Read this when building the container, so the volumes and their limits come from the service definitions rather than from a second list kept in step by hand.

Type: attribute set of (submodule) (read only)

Declared by:

  • options.nix

logDirs.<name>.path

The directory the service writes into.

Type: string

Declared by:

  • options.nix

logDirs.<name>.size

How large it may get, in the consumer’s own syntax.

Type: null or string

Default:

null

Declared by:

  • options.nix

mustExist

Paths that must already exist before any service starts, keyed by path. Nothing is created; this only checks, and stops the container when the check fails.

This is for what a volume is supposed to provide. An unmounted volume otherwise shows up as whichever service happens to touch the path first, failing in its own vocabulary. Checking here names the path and says nothing created it, before anything else runs.

Checked before dirs is made.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • options.nix

mustExist.<name>.kind

What it has to be.

Type: one of “any”, “dir”, “file”

Default:

"dir"

Declared by:

  • options.nix

mustExist.<name>.path

The path that has to be there already.

Type: string

Default:

"‹name›"

Declared by:

  • options.nix

name

Derivation name for the generated wrappers.

Type: string

Default:

"dinixLauncher"

Declared by:

  • options.nix

privileged

Whether dinit will run as root, and so whether a service may drop privilege with run-as.

This is the only thing about an environment that a configuration has to decide in advance. Everything else is answered at runtime: the state directory expands from DINIX_STATE_DIR, and dinix-init skips an owner or a mode that already holds. run-as cannot be, because dinit does not substitute it and a service description has no way to ask at startup whether it is root.

An earlier version called this mode and offered rootContainer, nobodyContainer and noContainer. That conflated two independent questions — containerised or not, privileged or not — and answered only the first for uncontained runs. So a postgres under systemd as root got no run-as, ran as root, and refused to start, which is what found it. Whether there is a container decides which wrapper you run (containerWrapper or userWrapper) and nothing in the service descriptions, so it needs no option here.

dinix reads this nowhere itself. A service module reads it to decide run-as, which is a deployment question and so the consumer’s.

Type: boolean

Default:

true

Declared by:

  • options.nix

quiet

Whether to stop dinit writing its own service status lines, the [  OK  ] and [STOPPD] chatter, to standard output.

Service output is not affected. Where a log collector reads only the output of PID 1, these lines land in the same stream as the services and break a reader that expects one format per stream.

Type: boolean

Default:

true

Declared by:

  • options.nix

services

dinit services, one attribute per service. See dinit-service(5).

Type: attribute set of (open submodule of attribute set of (null or (list of Something stringlike + numbers) or Something stringlike + numbers))

Default:

{ }

Declared by:

  • options.nix

services.<name>.after

See DINIT-SERVICE(5)

Type: null or (list of Something stringlike + numbers)

Default:

null

Declared by:

  • options.nix

services.<name>.command

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.depends-on

See DINIT-SERVICE(5)

Type: null or (list of Something stringlike + numbers)

Default:

null

Declared by:

  • options.nix

services.<name>.dinix

Settings dinix acts on itself. These never reach the service file.

Type: submodule

Default:

{ }

Declared by:

  • options.nix

services.<name>.dinix.critical

Whether dinit must exit when this service stops, so that a container runtime restarts the whole container.

true makes the boot service depend on this one, and turns off boot’s own restart. When the service stops for any reason, boot stops, every service stops, and dinit exits.

false makes boot wait for this one instead. The service can die and restart forever without dinit noticing.

null, the default, wires nothing. Write the dependencies of the boot service yourself.

Setting smooth-recovery on a critical service cancels this. Smooth recovery restarts the process in place without stopping dependents, so boot never stops and dinit never exits. Measured against dinit 0.22.1.

Type: null or boolean

Default:

null

Declared by:

  • options.nix

services.<name>.dinix.log

Where this service’s output goes.

console gives it shares-console, so the output joins the stream dinit itself writes to. That is the only stream a container runtime collects. Output passes through unchanged; dinit adds no prefix, so JSON log lines stay parseable. The default for process, bgprocess and scripted services.

buffer keeps the output in memory, readable with dinitctl catlog. A ring buffer cannot grow without bound, which makes this the one destination that needs no rotation. Use it for a service too chatty for the collected stream. See logBufferSize.

file writes to logfile. dinit does not rotate, and the file grows without bound, so whatever owns the volume has to own the rotation. The default when logfile is set.

none discards the output, which is dinit’s own default.

console and file are exclusive: dinit-service(5) says logfile has no effect on a service that shares the console. dinix picks file for you when you set logfile, rather than letting the console default silently win.

Set this rather than log-type. log-type follows from it, so setting log-type by hand leaves a process service sharing the console, and dinit then ignores the log type.

Type: one of “console”, “buffer”, “file”, “none”

Declared by:

  • options.nix

services.<name>.dinix.logDir

A directory this service writes log files into by itself.

This declares a fact rather than changing dinit’s behaviour. Some applications keep their own log files and cannot be pointed at standard error: Phorge’s phd writes one file per daemon, rotates them itself, and reads them back.

Naming the directory here puts it in the top-level logDirs, so whatever builds the container derives the volume and its size from the service definition instead of matching two independent facts by hand.

This does not make the directory. Such a directory is usually a mounted volume, and the mount makes it. Add it to dirs as well if it needs making and owning.

Type: null or string

Default:

null

Declared by:

  • options.nix

services.<name>.dinix.logDirSize

How large dinix.logDir is allowed to get, as the consumer’s own size syntax, for example 64Mi for a Kubernetes emptyDir. Carried through to logDirs untouched.

Type: null or string

Default:

null

Declared by:

  • options.nix

services.<name>.env-file

See DINIT-SERVICE(5)

Type: null or absolute path or (submodule)

Default:

null

Declared by:

  • options.nix

services.<name>.log-buffer-size

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.log-type

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.logfile

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.options

See DINIT-SERVICE(5)

Type: null or (list of Something stringlike + numbers)

Default:

null

Declared by:

  • options.nix

services.<name>.restart

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.restart-delay

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.restart-limit-count

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.stop-command

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

null

Declared by:

  • options.nix

services.<name>.type

See DINIT-SERVICE(5)

Type: Something stringlike + numbers

Default:

"process"

Declared by:

  • options.nix

services.<name>.waits-for

See DINIT-SERVICE(5)

Type: null or (list of Something stringlike + numbers)

Default:

null

Declared by:

  • options.nix

socketPath

Where dinit puts its control socket, and where the wrapped dinitctl and dinit-monitor look for it.

This is dinit’s own compiled-in default. dinit exits 1 at startup when it cannot create this socket, so on a read-only root filesystem this must name a writable volume. Under Kubernetes that means the path an emptyDir is mounted at, and /dev does not serve: the kubelet creates it mode 755 owned by root, so a container running as a normal user cannot write there either.

Type: string

Default:

"/run/dinitctl"

Declared by:

  • options.nix

system.services

Modular services, run by dinit.

Named system.services because that is what NixOS calls it, so a configuration moves between the two unchanged:

system.services.my-tunnel = {
  imports = [ pkgs.ghostunnel.services.default ];
  ghostunnel.listen = "127.0.0.1:8443";
};

Each becomes a dinit service of the same name, and a sub-service becomes <parent>-<child>. Nothing here attaches them to boot: set services.<name>.dinix.critical, as for any other service.

The portable layer declares no state, no user and no ownership, so dinix adds a dinit tree to every service for them: dinit.dirs, dinit.users, dinit.groups and dinit.service.run-as. A module reaches them through options ? dinit and still evaluates elsewhere. See issue #15.

process.reloadCommand and process.reloadSignal are ignored: dinit has no reload. dinitctl signal sends one by hand.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • modular.nix

system.services.<name>.configData

Configuration data files for the service

These files are made available to the service and can be updated without restarting the service process, enabling configuration reloading. The service manager implementation determines how these files are exposed to the service (e.g., via a specific directory path). This path is available in the path sub-option for each configData.<name> entry.

This is particularly useful for services that support configuration reloading via signals (e.g., SIGHUP) or which pick up changes automatically, so that no downtime is required in order to reload the service.

Type: lazy attribute set of (submodule)

Default:

{ }

Example:

{
  "server.conf" = {
    text = ''
      port = 8080
      workers = 4
    '';
  };
  "ssl/cert.pem" = {
    source = ./cert.pem;
  };
}

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data.nix

  • modular.nix

system.services.<name>.configData.<name>.enable

Whether this configuration file should be generated. This option allows specific configuration files to be disabled.

Type: boolean

Default:

true

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data-item.nix

system.services.<name>.configData.<name>.name

Name of the configuration file (relative to the service’s configuration directory). Defaults to the attribute name.

Type: string

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data-item.nix

system.services.<name>.configData.<name>.path

The actual path where this configuration file will be available. This is determined by the service manager implementation.

On NixOS it is an absolute path. Other service managers may provide a relative path, in order to be unprivileged and/or relocatable.

Type: string (read only)

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data-item.nix

system.services.<name>.configData.<name>.source

Path of the source file.

Type: absolute path

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data-item.nix

system.services.<name>.configData.<name>.text

Text content of the configuration file.

Type: null or strings concatenated with “\n”

Default:

null

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/config-data-item.nix

system.services.<name>.dinit.dirs

Directories to make before anything starts, as dirs takes them. The portable layer has no answer for this, and under systemd the same module would say StateDirectory instead.

Type: attribute set of anything

Default:

{ }

Declared by:

  • modular.nix

system.services.<name>.dinit.groups

Groups this service needs, as users.groups takes them. See dinit.users.

Type: attribute set of anything

Default:

{ }

Declared by:

  • modular.nix

system.services.<name>.dinit.mustExist

Paths a volume has to provide already, as mustExist takes them.

Type: attribute set of anything

Default:

{ }

Declared by:

  • modular.nix

system.services.<name>.dinit.service

Settings written straight into this service’s dinit description, as services.<name> takes them. See DINIT-SERVICE(5).

This is the option tree a portable service module targets:

lib.optionalAttrs (options ? dinit) {
  dinit.service.term-signal = "INT";
}

A module that does so still works where dinit is absent, because the attribute set is only added when this option exists.

Type: attribute set of anything

Default:

{ }

Example:

{ restart = true; term-signal = "INT"; }

Declared by:

  • modular.nix

system.services.<name>.dinit.stateDir

Where this service should keep what it writes.

Read by a service module for its own data directory default. The value is not a path but a template dinit expands when it loads the service, so one store path serves a container, an uncontained run and a systemd unit alike. See dirs.

The portable layer declares nothing like this — the manual lists per-service state as still to be decided — so a module that uses it is dinix-specific to that extent, and says so by reaching it through options ? dinit.

Type: string (read only)

Default:

"\${DINIX_STATE_DIR:-/var/lib}/‹name›"

Declared by:

  • modular.nix

system.services.<name>.dinit.users

Accounts this service needs in the user database, as users.users takes them. Declaring one turns the database on.

A service that refuses to start without an account of its own — sshd without its privilege separation user, for one — has no portable way to say so: the manual lists per-service users as still to be decided. Under systemd the same module would say DynamicUser or leave it to a sysusers file.

Type: attribute set of anything

Default:

{ }

Declared by:

  • modular.nix

system.services.<name>.meta.maintainers

List of maintainers of each module. This option should be defined at most once per module.

The option value is not a list of maintainers, but an attribute set that maps module file names to lists of maintainers.

Type: list of lib.maintainers

Default:

[ ]

Example:

[ lib.maintainers.alice lib.maintainers.bob ]

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/modules/generic/meta-maintainers.nix

system.services.<name>.meta.teams

List of team maintainers of each module. This option should be defined at most once per module.

Type: list of lib.teams

Default:

[ ]

Example:

[ lib.teams.acme lib.teams.haskell ]

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/modules/generic/meta-maintainers.nix

system.services.<name>.notificationProtocol

Notification protocol that this service supports with the underlying service manager.

Type: submodule

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.notificationProtocol.s6

Whether to enable Whether the service supports s6-notify…

Type: boolean

Default:

false

Example:

true

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.notificationProtocol.systemd

Whether to enable Whether the service supports systemd-notify…

Type: boolean

Default:

false

Example:

true

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.process.argv

Command filename and arguments for starting this service. This is a raw command-line that should not contain any shell escaping. If expansion of environmental variables is required then use a shell script or importas from pkgs.execline.

When flags are set, the arguments rendered from them are merged into argv. See flags for how the two are ordered against each other.

Type: list of (string or absolute path convertible to it)

Default:

[ ]

Example:

[ (lib.getExe config.package) "--nobackground" ]

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.process.flagFormat

Function mapping flag names to option format specs for lib.cli.toCommandLine.

Receives the flag name and returns { option, sep, explicitBool, formatArg? }.

Type: function that evaluates to a(n) attribute set of anything

Default:

<function>

Example:

name: {
  option = name;
  sep = "=";
  explicitBool = false;
}

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.process.flags

Flags to pass to the service process. The key is the flag name (e.g. "--port"), the value is the flag value.

Each name = value pair is rendered via lib.cli.toCommandLine using flagFormat.

  • null: the flag is omitted (regardless of flagFormat)

  • bool: rendered per flagFormat.explicitBool

    • explicitBool = false (default): true emits the bare flag, false is omitted

    • explicitBool = true: both true and false are rendered as explicit arguments via flagFormat.formatArg

  • string / path / int: rendered as the option’s argument, joined to the option name per flagFormat.sep and stringified by flagFormat.formatArg

To pass the same flag multiple times, use the list form with repeated keys, e.g. [ { "--host" = "a"; } { "--host" = "b"; } ].

The rendered arguments are merged into argv, so argv and flags share a single lib.mkOrder space:

  • A flag with no ordering property of its own is placed at priority 1250, between lib.modules.defaultOrderPriority (1000, which is what an unadorned argv definition gets) and lib.mkAfter (1500). Plain flags therefore follow the command name and any other plain argv arguments.

  • lib.mkAfter on argv still lands after the flags, which is how trailing positional arguments are expressed.

  • lib.mkOrder on a flag is honoured verbatim against argv, so a sub-command can be placed between two groups of flags.

Because 1250 is substituted for flags that carry no ordering property, lib.mkOrder 1000 on a flag is indistinguishable from leaving that flag unadorned. To order a flag around plain argv entries, pick a priority next to 1000, such as 999 or 1001.

Type: attribute list of (null or boolean or signed integer or (string or absolute path convertible to it))

Default:

{ }

Example:

{
  "--port" = "8080";
  "--verbose" = true;
  # ordered ahead of the unadorned flags above
  "--config" = lib.mkOrder 1100 "/etc/foo.conf";
}
# or, for repeated flags:
[
  { "--host" = "localhost"; }
  { "--host" = "0.0.0.0"; }
]

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.process.reloadCommand

Command used for reloading in the underlying service manager to reload.

Type: null or string

Default:

null

Example:

"${pkgs.coreutils}/bin/kill -HUP $MAINPID"

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.process.reloadSignal

Configures the reload signal to send to the service manager.

Type: null or string

Default:

null

Example:

"HUP"

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

system.services.<name>.services

A collection of modular services that are configured in one go.

You could consider the sub-service relationship to be an ownership relation. It does not automatically create any other relationship between services (e.g. systemd slices), unless perhaps such a behavior is explicitly defined and enabled in another option.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • /nix/store/pzwzs371qflfnkdg37gisaz1pl7qa2jg-source/lib/services/service.nix

  • modular.nix

trimShutdownTools

Whether to drop shutdown, halt, poweroff, reboot and soft-reboot from package.

Those five call /bin/umount and /sbin/swapoff, which nixpkgs rewrites to point at util-linux. That puts five util-linux outputs in the closure of every container, mount and login among them. dinit reaches none of it in container mode: --container makes it exit instead of running a shutdown program.

Measured on a configuration with one service: 57.9 MiB over 17 store paths with the tools, 46.6 MiB over 9 without.

Type: boolean

Default:

true

Declared by:

  • options.nix

tuiWrapper

dinit for a TUI-driven developer runtime.

Unlike userWrapper, it reads its runtime directory from the environment, so one store path serves every checkout. It searches, in order, a writable <DINIX_RUNTIME_DIR>/services and a <DINIX_RUNTIME_DIR>/current symbolic link before the store’s services. A description written into either shadows the built one. The link is what the TUI repoints at a fresh build’s services directory when it reloads, so a running dinit adopts the new configuration without a restart. It puts its control socket at <DINIX_RUNTIME_DIR>/control. DINIX_RUNTIME_DIR defaults to .dinix in the working directory the wrapper is run from, which lets a TUI keep everything under the repository it manages.

Its dinitctl and dinit-monitor use the same socket.

It is a shell script on purpose. containerWrapper must stay free of a shell and userWrapper is left as it is; a developer runtime can afford one.

Type: package

Declared by:

  • options.nix

unlessPackage

dinix-unless <marker> <program> [argument ...], which execs the program only when the marker path is absent. About 320 KiB, no dependencies, and nothing references it until a service does — so it reaches no image that has not asked for it.

This is for a service that initialises its own data directory once. initdb exits 1 on a directory that is not empty, and MySQL and MongoDB behave the same way, so “do it if it has not been done” is a conditional. A shell is the usual answer and costs an interpreter and a few hundred commands in an image that otherwise has neither.

It is a separate binary from initPackage on purpose: dinix-init is in every image and must never be able to run a program. This one can, and so is kept out of the images that do not need it. It is still not a small shell — no PATH search, no expansion, no interpretation: the program is the second argument and the rest are passed through. dinit has already substituted the command line before it runs.

Type: package

Default:

<derivation dinix-unless-0.1.0>

Declared by:

  • options.nix

userWrapper

dinit and its tools, wrapped to read this configuration straight from the store. For running a dinix configuration as an unprivileged user: dinit --user.

Type: package

Declared by:

  • options.nix

users.enable

Whether to enable a user database for this configuration.

Type: boolean

Default:

false

Example:

true

Declared by:

  • users.nix

users.files

The store path holding the user database, as etc/passwd, etc/group, etc/shadow and etc/nsswitch.conf.

This is configDir, which carries the rest of the generated configuration as well. Mount the one file you want out of it, a file at a time: a whole-directory mount over /etc hides what the runtime puts there.

A process that calls getpwuid on its own uid fails outright when the uid is absent from passwd, so the content matters even where nothing reads the file directly.

Every account in etc/shadow is locked, and the file is world-readable because everything in the Nix store is. That is safe only because it holds no hashes. Do not replace it with one that does; mount the real file instead.

Type: package (read only)

Declared by:

  • users.nix

users.groups

Groups to put in group, one attribute per group.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • users.nix

users.groups.<name>.gid

This option has no description.

Type: signed integer

Declared by:

  • users.nix

users.groups.<name>.name

This option has no description.

Type: string

Default:

"‹name›"

Declared by:

  • users.nix

users.groups.<name>.text

This option has no description.

Type: string

Declared by:

  • users.nix

users.groups.<name>.users

This option has no description.

Type: list of string

Default:

[ ]

Declared by:

  • users.nix

users.installAtRuntime

How the user database reaches the container: by copying it into the root filesystem at startup, rather than by mounting it.

Those are the two deliveries, and this picks between them. It is off by default because a container root filesystem is usually read-only, and because a volume mounted over /etc hides the /etc/hosts and /etc/resolv.conf the runtime puts there, which takes out name resolution. The other delivery is to mount the files in users.files one at a time, which is what a read-only or non-root container has to do.

Setting this without users.enable is an error rather than a silent no-op.

Turning this on puts a shell, rsync and coreutils in the closure of containerWrapper, which is otherwise a plain binary wrapper.

Type: boolean

Default:

false

Declared by:

  • users.nix

users.users

Accounts to put in passwd, one attribute per account.

Type: attribute set of (submodule)

Default:

{ }

Declared by:

  • users.nix

users.users.<name>.comment

This option has no description.

Type: string

Default:

""

Declared by:

  • users.nix

users.users.<name>.gid

This option has no description.

Type: signed integer

Declared by:

  • users.nix

users.users.<name>.homeDir

This option has no description.

Type: absolute path

Default:

"/home/‹name›"

Declared by:

  • users.nix

users.users.<name>.name

This option has no description.

Type: string

Default:

"‹name›"

Declared by:

  • users.nix

users.users.<name>.password

This option has no description.

Type: string

Default:

"x"

Declared by:

  • users.nix

users.users.<name>.shadowText

The shadow line for this account. No password can ever match it.

There is deliberately no option to set a password hash. Everything dinix renders goes into the Nix store, and the store is readable by every user and every process on the host. A hash there is a hash published. Mount a real shadow file over this one if an account has to log in with a password.

The field is * rather than !, which is what passwd -l writes. Both refuse every password, but OpenSSH on Linux reads a leading ! as a locked account and then refuses the account outright, key login included, whenever PAM is off. Measured against OpenSSH 10.5p1.

Type: string

Declared by:

  • users.nix

users.users.<name>.shell

This option has no description.

Type: absolute path or package

Default:

"/bin/sh"

Declared by:

  • users.nix

users.users.<name>.text

The passwd line for this account.

Type: string

Declared by:

  • users.nix

users.users.<name>.uid

This option has no description.

Type: signed integer

Declared by:

  • users.nix

verifyConfig

Whether to run dinit-check over the rendered services at build time.

Type: boolean

Default:

true

Declared by:

  • options.nix