This avoids restarting the postgresql server, when only ensureDatabases or ensureUsers have been changed. It will also allow to properly wait for recovery to finish later. To wait for "postgresql is ready" in other services, we now provide a postgresql.target. Resolves #400018 Co-authored-by: Marcel <me@m4rc3l.de>
171 lines
5.1 KiB
Nix
171 lines
5.1 KiB
Nix
{
|
|
config,
|
|
lib,
|
|
pkgs,
|
|
...
|
|
}:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.dex;
|
|
fixClient =
|
|
client:
|
|
if client ? secretFile then
|
|
(
|
|
(builtins.removeAttrs client [ "secretFile" ])
|
|
// {
|
|
secret = client.secretFile;
|
|
}
|
|
)
|
|
else
|
|
client;
|
|
filteredSettings = mapAttrs (
|
|
n: v: if n == "staticClients" then (builtins.map fixClient v) else v
|
|
) cfg.settings;
|
|
secretFiles = flatten (
|
|
builtins.map (c: optional (c ? secretFile) c.secretFile) (cfg.settings.staticClients or [ ])
|
|
);
|
|
|
|
settingsFormat = pkgs.formats.yaml { };
|
|
configFile = settingsFormat.generate "config.yaml" filteredSettings;
|
|
|
|
startPreScript = pkgs.writeShellScript "dex-start-pre" (
|
|
concatStringsSep "\n" (
|
|
map (file: ''
|
|
replace-secret '${file}' '${file}' /run/dex/config.yaml
|
|
'') secretFiles
|
|
)
|
|
);
|
|
|
|
restartTriggers =
|
|
[ ]
|
|
++ (optionals (cfg.environmentFile != null) [ cfg.environmentFile ])
|
|
++ (filter (file: builtins.typeOf file == "path") secretFiles);
|
|
in
|
|
{
|
|
options.services.dex = {
|
|
enable = mkEnableOption "the OpenID Connect and OAuth2 identity provider";
|
|
|
|
package = mkPackageOption pkgs "dex-oidc" { };
|
|
|
|
environmentFile = mkOption {
|
|
type = types.nullOr types.path;
|
|
default = null;
|
|
description = ''
|
|
Environment file (see {manpage}`systemd.exec(5)`
|
|
"EnvironmentFile=" section for the syntax) to define variables for dex.
|
|
This option can be used to safely include secret keys into the dex configuration.
|
|
'';
|
|
};
|
|
|
|
settings = mkOption {
|
|
type = settingsFormat.type;
|
|
default = { };
|
|
example = literalExpression ''
|
|
{
|
|
# External url
|
|
issuer = "http://127.0.0.1:5556/dex";
|
|
storage = {
|
|
type = "postgres";
|
|
config.host = "/var/run/postgres";
|
|
};
|
|
web = {
|
|
http = "127.0.0.1:5556";
|
|
};
|
|
enablePasswordDB = true;
|
|
staticClients = [
|
|
{
|
|
id = "oidcclient";
|
|
name = "Client";
|
|
redirectURIs = [ "https://example.com/callback" ];
|
|
secretFile = "/etc/dex/oidcclient"; # The content of `secretFile` will be written into to the config as `secret`.
|
|
}
|
|
];
|
|
}
|
|
'';
|
|
description = ''
|
|
The available options can be found in
|
|
[the example configuration](https://github.com/dexidp/dex/blob/v${cfg.package.version}/config.yaml.dist).
|
|
|
|
It's also possible to refer to environment variables (defined in [services.dex.environmentFile](#opt-services.dex.environmentFile))
|
|
using the syntax `$VARIABLE_NAME`.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
systemd.services.dex = {
|
|
description = "dex identity provider";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [
|
|
"networking.target"
|
|
] ++ (optional (cfg.settings.storage.type == "postgres") "postgresql.target");
|
|
path = with pkgs; [ replace-secret ];
|
|
restartTriggers = restartTriggers;
|
|
serviceConfig =
|
|
{
|
|
ExecStart = "${cfg.package}/bin/dex serve /run/dex/config.yaml";
|
|
ExecStartPre = [
|
|
"${pkgs.coreutils}/bin/install -m 600 ${configFile} /run/dex/config.yaml"
|
|
"+${startPreScript}"
|
|
];
|
|
|
|
RuntimeDirectory = "dex";
|
|
BindReadOnlyPaths = [
|
|
"/nix/store"
|
|
"-/etc/dex"
|
|
"-/etc/hosts"
|
|
"-/etc/localtime"
|
|
"-/etc/nsswitch.conf"
|
|
"-/etc/resolv.conf"
|
|
"${config.security.pki.caBundle}:/etc/ssl/certs/ca-certificates.crt"
|
|
];
|
|
BindPaths = optional (cfg.settings.storage.type == "postgres") "/var/run/postgresql";
|
|
# ProtectClock= adds DeviceAllow=char-rtc r
|
|
DeviceAllow = "";
|
|
DynamicUser = true;
|
|
LockPersonality = true;
|
|
MemoryDenyWriteExecute = true;
|
|
NoNewPrivileges = true;
|
|
PrivateDevices = true;
|
|
PrivateMounts = true;
|
|
# Port needs to be exposed to the host network
|
|
#PrivateNetwork = true;
|
|
PrivateTmp = true;
|
|
PrivateUsers = true;
|
|
ProcSubset = "pid";
|
|
ProtectClock = true;
|
|
ProtectHome = true;
|
|
ProtectHostname = true;
|
|
ProtectSystem = "strict";
|
|
ProtectControlGroups = true;
|
|
ProtectKernelLogs = true;
|
|
ProtectKernelModules = true;
|
|
ProtectKernelTunables = true;
|
|
ProtectProc = "invisible";
|
|
RestrictAddressFamilies = [
|
|
"AF_INET"
|
|
"AF_INET6"
|
|
"AF_UNIX"
|
|
];
|
|
RestrictNamespaces = true;
|
|
RestrictRealtime = true;
|
|
RestrictSUIDSGID = true;
|
|
SystemCallArchitectures = "native";
|
|
SystemCallFilter = [
|
|
"@system-service"
|
|
"~@privileged @setuid @keyring"
|
|
];
|
|
UMask = "0066";
|
|
}
|
|
// optionalAttrs (cfg.environmentFile != null) {
|
|
EnvironmentFile = cfg.environmentFile;
|
|
};
|
|
};
|
|
};
|
|
|
|
# uses attributes of the linked package
|
|
meta.buildDocsInSandbox = false;
|
|
}
|