nixos/lldap: allow automatic creation of a local database

This commit is contained in:
sweenu
2026-01-08 20:44:49 +01:00
parent ee97808ba7
commit 3ab6ee74cf
+82 -4
View File
@@ -8,6 +8,10 @@
let
cfg = config.services.lldap;
format = pkgs.formats.toml { };
dbName = "lldap";
dbUser = "lldap";
localPostgresql = cfg.database.createLocally && cfg.database.type == "postgresql";
localMysql = cfg.database.createLocally && cfg.database.type == "mariadb";
in
{
options.services.lldap = with lib; {
@@ -36,6 +40,25 @@ in
'';
};
database = {
createLocally = mkOption {
type = types.bool;
default = true;
description = "Create the database and database user locally.";
};
type = mkOption {
type = types.enum [
"mariadb"
"postgresql"
"sqlite"
];
example = "postgresql";
default = "sqlite";
description = "Database engine to use.";
};
};
settings = mkOption {
description = ''
Free-form settings written directly to the `lldap_config.toml` file.
@@ -96,9 +119,20 @@ in
};
database_url = mkOption {
type = types.str;
type = types.nullOr types.str;
default = null;
defaultText = lib.literalExpression ''
if config.services.lldap.database.createLocally
then
if cfg.database.type == "sqlite"
then "sqlite://./users.db?mode=rwc"
else if cfg.database.type == "postgresql"
then "postgresql:///lldap?host=/run/postgresql"
else if cfg.database.type == "mariadb"
then "mysql://lldap@localhost/lldap?socket=/run/mysqld/mysqld.sock"
else null
'';
description = "Database URL.";
default = "sqlite://./users.db?mode=rwc";
example = "postgres://postgres-user:password@postgres-server/my-database";
};
@@ -188,7 +222,7 @@ in
];
warnings =
lib.optionals (cfg.settings.ldap_user_pass or null != null) [
lib.optionals ((cfg.settings.ldap_user_pass or null) != null) [
''
lldap: Unsecure `ldap_user_pass` setting is used. Prefer `ldap_user_pass_file` instead.
''
@@ -205,10 +239,29 @@ in
''
];
services.lldap.settings.database_url = lib.mkIf cfg.database.createLocally (
lib.mkDefault (
if cfg.database.type == "sqlite" then
"sqlite://./users.db?mode=rwc"
else if cfg.database.type == "postgresql" then
"postgresql:///${dbName}?host=/run/postgresql"
else if cfg.database.type == "mariadb" then
"mysql://${dbUser}@localhost/${dbName}?socket=/run/mysqld/mysqld.sock"
else
null
)
);
systemd.services.lldap = {
description = "Lightweight LDAP server (lldap)";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
after = [
"network-online.target"
]
++ lib.optional localPostgresql "postgresql.target"
++ lib.optional localMysql "mysql.service";
requires =
lib.optional localPostgresql "postgresql.target" ++ lib.optional localMysql "mysql.service";
wantedBy = [ "multi-user.target" ];
# lldap defaults to a hardcoded `jwt_secret` value if none is provided, which is bad, because
# an attacker could create a valid admin jwt access token fairly trivially.
@@ -238,5 +291,30 @@ in
};
inherit (cfg) environment;
};
services.postgresql = lib.mkIf localPostgresql {
enable = true;
ensureDatabases = [ dbName ];
ensureUsers = [
{
name = dbUser;
ensureDBOwnership = true;
}
];
};
services.mysql = lib.mkIf localMysql {
enable = true;
package = lib.mkDefault pkgs.mariadb;
ensureDatabases = [ dbName ];
ensureUsers = [
{
name = dbUser;
ensurePermissions = {
"${dbName}.*" = "ALL PRIVILEGES";
};
}
];
};
};
}