aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modules/quassel/default.nix9
-rw-r--r--modules/quassel/quassel.nix295
2 files changed, 158 insertions, 146 deletions
diff --git a/modules/quassel/default.nix b/modules/quassel/default.nix
index efb9661..8961546 100644
--- a/modules/quassel/default.nix
+++ b/modules/quassel/default.nix
@@ -22,12 +22,9 @@ in
settings = {
listen = [ "178.63.224.10" "2a01:4f8:231:56a::10" ];
dataDir = "/var/lib/quassel";
- configFromEnvironment = true;
+ useDeclarativeConfig = true;
db = {
- backend = "PostgreSQL";
- pgsql = {
- database = "quassel";
- };
+ backend = "postgresql";
};
ssl = {
required = true;
@@ -56,7 +53,7 @@ in
};
};
- users.users.quassel.extraGroups = [ "acme" ];
+ # users.users.quassel.extraGroups = [ "acme" ];
security.acme.certs = {
"cocaine.farm" = {
diff --git a/modules/quassel/quassel.nix b/modules/quassel/quassel.nix
index 13f6ba9..e3eeac6 100644
--- a/modules/quassel/quassel.nix
+++ b/modules/quassel/quassel.nix
@@ -6,44 +6,54 @@ let
cfg = config.services.quassel;
opt = options.services.quassel;
quassel = cfg.package;
- user = if cfg.user != null then cfg.user else "quassel";
in
{
+ imports = [
+ (mkRenamedOptionModule [ "services" "quassel" "certificateFile" ] [ "services" "quassel" "settings" "ssl" "certFile" ])
+ (mkRenamedOptionModule [ "services" "quassel" "requireSSL" ] [ "services" "quassel" "settings" "ssl" "required" ])
+ ];
+
options = {
services.quassel = {
- enable = mkEnableOption ("the Quassel IRC client daemon");
-
- package = mkOption {
- type = types.package;
- default = pkgs.quasselDaemon;
- defaultText = literalExpression "pkgs.quasselDaemon";
- description = ''
- The package of the quassel daemon.
- '';
- };
+ enable = mkEnableOption (lib.mdDoc "the Quassel IRC client daemon");
+
+ package = lib.mkPackageOptionMD pkgs "quasselDaemon" { };
user = mkOption {
- default = null;
- type = types.nullOr types.str;
- description = ''
- The existing user the Quassel daemon should run as. If left empty, a default "quassel" user will be created.
+ type = types.str;
+ default = "quassel";
+ description = lib.mdDoc ''
+ The user the Quassel daemon should run as. By default a systemd DynamicUser
+ is used with the name specified here. DynamicUser functionality will be
+ automatically disabled if the specified user already exists.
'';
};
environmentFile = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.path;
default = null;
- description = ''
+ description = lib.mdDoc ''
Path to an environment file loaded for the quassel service.
This can be used to securely store tokens and secrets outside of the world-readable Nix store.
+ For example to inject the `DB_PSQL_PASSWORD` and `AUTH_LDAP_BIND_PASSWORD` variables instead
+ of setting {option}`services.quassel.settings.db.psql.password` and {option}`services.quassel.settings.auth.ldap.bindPassword`.
+
+ Example Content:
+ ```
+ DB_PSQL_PASSWORD=changeme
+ AUTH_LDAP_BIND_PASSWORD=changemetoo
+ ```
+
+ ::: {.note}
Since this file is read by systemd, it may have permission 0400 and be owned by root.
+ :::
'';
};
settings = mkOption {
- description = literalExpression ''
+ description = lib.mdDoc ''
Configuration for quassel daemon.
'';
type = types.submodule {
@@ -51,7 +61,7 @@ in
listen = mkOption {
type = types.listOf types.str;
default = [ "127.0.0.1" "::1" ];
- description = ''
+ description = lib.mdDoc ''
The address(es) quasselcore will listen on.
'';
};
@@ -59,50 +69,49 @@ in
port = mkOption {
default = 4242;
type = types.port;
- description = ''
+ description = lib.mdDoc ''
The port quasselcore will listen at.
'';
};
dataDir = mkOption {
- default = "/home/${user}/.config/quassel-irc.org";
- defaultText = literalExpression ''
- "/home/''${config.${opt.user}}/.config/quassel-irc.org"
- '';
- type = types.str;
- description = ''
+ type = types.path;
+ default = "/var/lib/quassel";
+ description = lib.mdDoc ''
The directory holding configuration files, the SQlite database and the SSL Cert.
+ The default directory will be created by systemd using StateDirectory
+
+ ::: {note}
+ If set to a custom directory you might have to create a user and adjust the
+ user used in {option}`services.quassel.user`.
+ :::
'';
};
- configFromEnvironment = mkOption {
+ useDeclarativeConfig = mkOption {
default = false;
type = types.bool;
- description = ''
- Configure quassels authenticator and database settings using environment variables,
- Instead of imperatively setting it up using the setup wizard during first connection to the quassel core.
+ description = lib.mdDoc ''
+ Configure quassels authenticator and database settings using the
+ {option}`services.quassel.settings.auth` and {option}`services.quassel.settings.db` sections.
+
+ Overrides whatever configuration for the database and authentication you have made using the setup wizard.
'';
};
ident = mkOption {
- description = literalExpression ''
+ description = lib.mdDoc ''
Configuration for quassels internal ident daemon.
'';
default = { };
type = types.submodule {
options = {
- enable = mkOption {
- default = false;
- type = types.bool;
- description = ''
- Enable internal ident daemon.
- '';
- };
+ enable = lib.mkEnableOption (lib.mdDoc "internal ident daemon.");
strict = mkOption {
type = types.bool;
default = false;
- description = ''
+ description = lib.mdDoc ''
Use users quasselcore username as ident reply. Ignores each user's configured ident setting.
'';
};
@@ -110,7 +119,7 @@ in
listen = mkOption {
default = [ "127.0.0.1" "::1" ];
type = types.listOf types.str;
- description = ''
+ description = lib.mdDoc ''
The address(es) quasselcore will listen on for ident requests.
'';
};
@@ -118,7 +127,7 @@ in
port = mkOption {
default = 10113;
type = types.port;
- description = ''
+ description = lib.mdDoc ''
The port quasselcore will listen at for ident requests.
'';
};
@@ -127,24 +136,18 @@ in
};
oidentd = mkOption {
- description = literalExpression ''
+ description = lib.mdDoc ''
Configuration for quassels integration with oidentd.
'';
default = { };
type = types.submodule {
options = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Enable oidentd integration.
- '';
- };
+ enable = lib.mkEnableOption (lib.mdDoc "oidentd integration.");
- confFile = mkOption {
- type = types.nullOr types.str;
+ configFile = mkOption {
+ type = types.nullOr types.path;
default = null;
- description = ''
+ description = lib.mdDoc ''
Set path to oidentd configuration file.
'';
};
@@ -154,29 +157,40 @@ in
ssl = mkOption {
default = { };
+ description = lib.mdDoc ''
+ Configuration for quassel ssl
+ '';
type = types.submodule {
options = {
required = mkOption {
type = types.bool;
default = false;
- description = ''
+ description = lib.mdDoc ''
Require SSL for remote (non-loopback) client connections.
'';
};
certFile = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.path;
default = null;
- description = ''
- Specify the path to the SSL certificate.
+ description = lib.mdDoc ''
+ Specify the path to the SSL certificate. Passed to quassel using systemd's LoadCredential.
+
+ ::: {.note}
+ Since this file is read by systemd, it may have permission 0400 and be owned by root.
+ :::
'';
};
keyFile = mkOption {
- type = types.nullOr types.str;
+ type = types.nullOr types.path;
default = null;
- description = ''
- Specify the path to the SSL key.
+ description = lib.mdDoc ''
+ Specify the path to the SSL key. Passed to quassel using systemd's LoadCredential.
+
+ ::: {.note}
+ Since this file is read by systemd, it may have permission 0400 and be owned by root.
+ :::
'';
};
};
@@ -184,24 +198,18 @@ in
};
metrics = mkOption {
- description = literalExpression ''
+ description = lib.mdDoc ''
Export metrics in prometheus format
'';
default = { };
type = types.submodule {
options = {
- enable = mkOption {
- type = types.bool;
- default = false;
- description = ''
- Enable prometheus metrics API.
- '';
- };
+ enable = lib.mkEnableOption (lib.mdDoc "prometheus metrics API.");
listen = mkOption {
default = [ "127.0.0.1" "::1" ];
type = types.listOf types.str;
- description = ''
+ description = lib.mdDoc ''
The address(es) quasselcore will listen on for metrics requests.
'';
};
@@ -209,7 +217,7 @@ in
port = mkOption {
default = 9558;
type = types.port;
- description = ''
+ description = lib.mdDoc ''
The port quasselcore will listen at for metrics requests.
'';
};
@@ -220,38 +228,49 @@ in
logLevel = mkOption {
type = types.enum [ "Debug" "Info" "Warning" "Error" ];
default = "Info";
- description = ''
- Supports one of Debug|Info|Warning|Error;
+ description = lib.mdDoc ''
+ Log level of the quassel core.
'';
};
db = mkOption {
default = { };
+ description = lib.mdDoc ''
+ Configuration for quassel database
+ '';
type = types.submodule {
options = {
backend = mkOption {
- type = types.enum [ "SQLite" "PostgreSQL" ];
- default = "SQLite";
- description = literalExpression ''
+ type = types.enum [ "sqlite" "postgresql" ];
+ default = "sqlite";
+ apply = value: if value == "sqlite" then "SQLite" else "PostgreSQL";
+ description = lib.mdDoc ''
Specify the database backend.
- In case SQLite is used, the database will be stored in ''${opt.settings.dataDir}/quassel-storage.sqlite
+ In case SQLite is used, the database will be stored in `''${services.quassel.settings.dataDir}/quassel-storage.sqlite`
'';
};
pgsql = mkOption {
- description = ''
- Configuration for PostgreSQL Connection if ''${opt.settings.db.type} is set to "PostgreSQL".
+ description = lib.mdDoc ''
+ Configuration for PostgreSQL Connection if {option}`services.quassel.settings.db.type` is set to "PostgreSQL".
TCP and UNIX Sockets are supported
+
+ ::: {.note}
+ If the postgresql server is on the same machine you can add an `after` to the quassel systemd service:
+ ```
+ systemd.services.quassel.after = [ "postgresql.service" ]
+ ```
+ :::
'';
- default = null;
- type = types.nullOr (types.submodule {
+ default = { };
+ type = types.submodule {
options = {
username = mkOption {
type = types.str;
- default = user;
- description = ''
+ default = "quassel";
+ description = lib.mdDoc ''
Specifies the Postgres connection username.
'';
};
@@ -259,16 +278,19 @@ in
password = mkOption {
type = types.nullOr types.str;
default = null;
- description = ''
- Specifies the Postgres connection user password. Warning: do not set confidential
- information here because it is world-readable in the Nix store.
+ description = lib.mdDoc ''
+ Specifies the Postgres connection user password.
+ Can also be set as `DB_PGSQL_PASSWORD` in the `service.quassel.environmentFile`
+
+ Warning: do not set confidential information here because it
+ is world-readable in the Nix store.
'';
};
hostname = mkOption {
type = types.nullOr types.str;
default = "/var/run/postgresql/";
- description = ''
+ description = lib.mdDoc ''
Specifies the Postgres connection hostname.
Either an IP Address or hostname for a TCP Connection or the path to the directory
@@ -277,9 +299,9 @@ in
};
port = mkOption {
- default = 5432;
type = types.port;
- description = ''
+ default = 5432;
+ description = lib.mdDoc ''
Specifies the Postgres connection port.
'';
};
@@ -287,12 +309,12 @@ in
database = mkOption {
type = types.str;
default = "quassel";
- description = ''
+ description = lib.mdDoc ''
Specifies the Postgres connection database name.
'';
};
};
- });
+ };
};
};
};
@@ -300,24 +322,37 @@ in
auth = mkOption {
default = { };
+ description = lib.mdDoc ''
+ Configuration for quassel authentication backends
+ '';
type = types.submodule {
options = {
authenticator = mkOption {
type = types.enum [ "Database" "LDAP" ];
default = "Database";
- description = ''
+ description = lib.mdDoc ''
Specify the backend used to authenticate users to quassel. Either "Database" to
- use quassel database or "Ldap" to use an external LDAP Server
+ use quassel database or "LDAP" to use an external LDAP Server
'';
};
ldap = mkOption {
- default = null;
- type = types.nullOr (types.submodule {
+ description = lib.mdDoc ''
+ Configuration for quassel LDAP authentication backend
+
+ ::: {.note}
+ If the ldap server is on the same machine you can add an `after` to the quassel systemd service:
+ ```
+ systemd.services.quassel.after = [ "your-ldap-server.service" ]
+ ```
+ :::
+ '';
+ type = types.submodule {
options = {
hostname = mkOption {
type = types.str;
- description = ''
+ example = "ldap://example.com";
+ description = lib.mdDoc ''
Specifies the LDAP authenticator connection hostname.
'';
};
@@ -325,14 +360,14 @@ in
port = mkOption {
default = 389;
type = types.port;
- description = ''
+ description = lib.mdDoc ''
Specifies the LDAP authenticator connection port.
'';
};
bindDN = mkOption {
type = types.str;
- description = ''
+ description = lib.mdDoc ''
Specifies the LDAP authenticator bind DN.
'';
};
@@ -340,22 +375,25 @@ in
bindPassword = mkOption {
type = types.nullOr types.str;
default = null;
- description = ''
- Specifies the LDAP authenticator bind password. Warning: do not set
- confidential information here because it is world-readable in the Nix store.
+ description = lib.mdDoc ''
+ Specifies the LDAP authenticator bind password.
+ Can also be set as `AUTH_LDAP_BIND_PASSWORD` in the `service.quassel.environmentFile`
+
+ Warning: do not set confidential information here because it
+ is world-readable in the Nix store.
'';
};
baseDN = mkOption {
type = types.str;
- description = ''
+ description = lib.mdDoc ''
Specifies the LDAP authenticator base DN.
'';
};
filter = mkOption {
type = types.str;
- description = ''
+ description = lib.mdDoc ''
Specifies the LDAP authenticator filter.
'';
example = "(objectClass=inetOrgPerson)";
@@ -364,13 +402,13 @@ in
uidAttribute = mkOption {
default = "uid";
type = types.str;
- description = ''
+ description = lib.mdDoc ''
Specifies the LDAP authenticator UID attribute.
'';
example = "cn";
};
};
- });
+ };
};
};
};
@@ -389,34 +427,6 @@ in
assertion = cfg.settings.ssl.required -> cfg.settings.ssl.certFile != null;
message = "Quassel needs a certificate file in order to require SSL";
}
- {
- assertion = cfg.settings.db.backend == "PostgreSQL" -> cfg.settings.db.pgsql != null;
- message = "Quassel needs postgresql connection settings if database type is set to PostgreSQL";
- }
- {
- assertion = cfg.settings.auth.authenticator == "Ldap" -> cfg.settings.auth.ldap != null;
- message = "Quassel needs ldap connection settings if authenticator type is set to Ldap";
- }
- ];
-
- users.users = optionalAttrs (cfg.user == null) {
- quassel = {
- name = "quassel";
- description = "Quassel IRC client daemon";
- group = "quassel";
- uid = config.ids.uids.quassel;
- };
- };
-
- users.groups = optionalAttrs (cfg.user == null) {
- quassel = {
- name = "quassel";
- gid = config.ids.gids.quassel;
- };
- };
-
- systemd.tmpfiles.rules = [
- "d '${cfg.settings.dataDir}' - ${user} - - -"
];
systemd.services.quassel =
@@ -424,9 +434,7 @@ in
description = "Quassel IRC client daemon";
wantedBy = [ "multi-user.target" ];
- after = [ "network.target" ]
- ++ optional config.services.postgresql.enable "postgresql.service"
- ++ optional config.services.mysql.enable "mysql.service";
+ after = [ "network.target" ];
serviceConfig =
{
@@ -452,19 +460,27 @@ in
"--metrics-listen=${concatStringsSep "," cfg.settings.metrics.listen}"
"--metrics-port=${toString cfg.settings.metrics.port}"
]
- ++ optional cfg.settings.configFromEnvironment "--config-from-environment"
+ ++ optional cfg.settings.useDeclarativeConfig "--config-from-environment"
# SSL
++ optional cfg.settings.ssl.required "--require-ssl"
- ++ optional (cfg.settings.ssl.certFile != null) "--ssl-cert=${cfg.settings.ssl.certFile}"
- ++ optional (cfg.settings.ssl.keyFile != null) "--ssl-key=${cfg.settings.ssl.keyFile}"
+ ++ optional (cfg.settings.ssl.certFile != null) "--ssl-cert=%d/certfile"
+ ++ optional (cfg.settings.ssl.keyFile != null) "--ssl-key=%d/keyfile"
));
- ExecReload="${pkgs.coreutils}/bin/kill -HUP $MAINPID";
+ LoadCredential =
+ optional (cfg.settings.ssl.certFile != null) "certfile:${cfg.settings.ssl.certFile}"
+ ++ optional (cfg.settings.ssl.keyFile != null) "keyfile:${cfg.settings.ssl.keyFile}";
+
+ DynamicUser = true;
+ User = cfg.user;
+ StateDirectory = "quassel";
+
+ ExecReload = "${pkgs.coreutils}/bin/kill -HUP $MAINPID";
EnvironmentFile = mkIf
(cfg.environmentFile != null) [ cfg.environmentFile ];
- Environment = mkIf cfg.settings.configFromEnvironment ([
+ Environment = mkIf cfg.settings.useDeclarativeConfig ([
"AUTH_AUTHENTICATOR=${cfg.settings.auth.authenticator}"
"DB_BACKEND=${cfg.settings.db.backend}"
] ++ (optional (cfg.settings.db.backend == "PostgreSQL") [
@@ -482,7 +498,6 @@ in
"AUTH_LDAP_UID_ATTRIBUTE=${cfg.settings.auth.ldap.uidAttribute}"
] ++ optional (cfg.settings.auth.ldap.bindPassword != null) "AUTH_LDAP_BIND_PASSWORD=${cfg.settings.auth.ldap.bindPassword}"
));
- User = user;
};
};
};