LLDAP Block

Table of Contents

Global Setup
SSL
Restrict Access By IP
Manage User and Group
Troubleshooting
Tests
Options Reference

Defined in /modules/blocks/lldap.nix.

This block sets up an LLDAP service for user and group management across services.

Global Setup

shb.lldap = {
  enable = true;
  subdomain = "ldap";
  domain = "example.com";
  dcdomain = "dc=example,dc=com";

  ldapPort = 3890;
  webUIListenPort = 17170;

  jwtSecret.result = config.shb.sops.secret."lldap/jwt_secret".result;
  ldapUserPassword.result = config.shb.sops.secret."lldap/user_password".result;
};
shb.sops.secret."lldap/jwt_secret".request = config.shb.ldap.jwtSecret.request;
shb.sops.secret."lldap/user_password".request = config.shb.ldap.ldapUserPassword.request;

This assumes secrets are setup with SOPS as mentioned in the secrets setup section of the manual.

SSL

Using SSL is an important security practice, like always. Using the SSL block, the configuration to add to the one above is:

shb.certs.certs.letsencrypt.${domain}.extraDomains = [
  "${config.shb.lldap.subdomain}.${config.shb.lldap.domain}"
];

shb.ldap.ssl = config.shb.certs.certs.letsencrypt.${config.shb.lldap.domain};

Restrict Access By IP

For added security, you can restrict access to the LLDAP UI by adding the following line:

shb.lldap.restrictAccessIPRange = "192.168.50.0/24";

Manage User and Group

Currently, managing users and groups must be done manually. Work is in progress to make this declarative.

Troubleshooting

To increase logging verbosity, add:

shb.lldap.debug = true;

Note that verbosity is truly verbose here so you will want to revert this at some point.

Tests

Specific integration tests are defined in /test/blocks/lldap.nix.

Options Reference

shb.lldap.enable

Whether to enable the LDAP service.

Type: boolean

Default: false

Example: true

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup

Backup configuration.

Type: submodule

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request

Request part of the backup contract.

Options set by the requester module enforcing how to backup files.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.excludePatterns

File patterns to exclude.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.hooks

Hooks to run around the backup.

Type: submodule

Default: { }

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.hooks.afterBackup

Hooks to run after backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.hooks.beforeBackup

Hooks to run before backup.

Type: list of string

Default: [ ]

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.sourceDirectories

Directories to backup.

Type: non-empty (list of string)

Default:

[
  "/var/lib/private/lldap"
]

Example: "/var/lib/vaultwarden"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.request.user

Unix user doing the backups.

Type: string

Default: "root"

Example: "vaultwarden"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.result

Result part of the backup contract.

Options set by the provider module that indicates the name of the backup and restor scripts.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.result.backupService

Name of service backing up the database.

This script can be ran manually to backup the database:

$ systemctl start backup.service

Type: string

Default: "backup.service"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.backup.result.restoreScript

Name of script that can restore the database. One can then list snapshots with:

$ restore snapshots

And restore the database with:

$ restore restore latest

Type: string

Default: "restore"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.dcdomain

dc domain to serve.

Type: string

Example: "dc=mydomain,dc=com"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.debug

Enable debug logging.

Type: boolean

Default: false

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.domain

Domain under which the LDAP service will be served.

Type: string

Example: "mydomain.com"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret

JWT secret.

Type: submodule

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.request.group

Linux group owning the secret file.

Type: string

Default: "lldap"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.request.owner

Linux user owning the secret file.

Type: string

Default: "lldap"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "lldap.service"
]

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.jwtSecret.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapPort

Port on which the server listens for the LDAP protocol.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default: 3890

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword

LDAP admin user secret.

Type: submodule

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.request

Request part of the secret contract.

Options set by the requester module enforcing some properties the secret should have.

Type: submodule

Default: ""

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.request.group

Linux group owning the secret file.

Type: string

Default: "lldap"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.request.mode

Mode of the secret file.

Type: string

Default: "0440"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.request.owner

Linux user owning the secret file.

Type: string

Default: "lldap"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.request.restartUnits

Systemd units to restart after the secret is updated.

Type: list of string

Default:

[
  "lldap.service"
]

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.result

Result part of the secret contract.

Options set by the provider module that indicates where the secret can be found.

Type: submodule

Default:

{
  path = "/run/secrets/secret";
}

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ldapUserPassword.result.path

Path to the file containing the secret generated out of band.

This path will exist after deploying to a target host, it is not available through the nix store.

Type: absolute path

Default: "/run/secrets/secret"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.mount

Mount configuration. This is an output option.

Use it to initialize a block implementing the “mount” contract. For example, with a zfs dataset:

shb.zfs.datasets."ldap" = {
  poolName = "root";
} // config.shb.lldap.mount;

Type: anything (read only)

Default:

{
  path = "/var/lib/lldap";
}

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.mount.path

Path to be mounted.

Type: string

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.restrictAccessIPRange

Set a local network range to restrict access to the UI to only those IPs.

Type: null or string

Default: null

Example: "192.168.1.1/24"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ssl

Path to SSL files

Type: null or (anything)

Default: null

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ssl.paths

Paths where the files for the certificate will be located.

This option is the contract output of the shb.certs.certs SSL block.

Type: anything

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ssl.paths.cert

Path to the cert file.

Type: absolute path

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ssl.paths.key

Path to the key file.

Type: absolute path

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.ssl.systemdService

Systemd oneshot service used to generate the certificate. Ends with the .service suffix.

Use this if downstream services must wait for the certificates to be generated before starting.

Type: string

Example: "cert-generator.service"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.subdomain

Subdomain under which the LDAP service will be served.

Type: string

Example: "grafana"

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>
shb.lldap.webUIListenPort

Port on which the web UI is exposed.

Type: 16 bit unsigned integer; between 0 and 65535 (both inclusive)

Default: 17170

Declared by:

<selfhostblocks/modules/blocks/lldap.nix>