199 lines
6.3 KiB
Nix
199 lines
6.3 KiB
Nix
flake: { config, pkgs, ... }:
|
|
let
|
|
inherit (flake.packages.${pkgs.stdenv.hostPlatform.system}) idcoop;
|
|
inherit (pkgs.lib) mkOption mkDefault mkIf types literalExpression mdDoc;
|
|
inherit (pkgs.writers) writeTOML;
|
|
inherit (builtins) mapAttrs;
|
|
|
|
defaultUser = "idcoop";
|
|
|
|
cfg = config.services.idcoop;
|
|
format = pkgs.formats.toml { };
|
|
|
|
oidcClientSubmodule = types.submodule {
|
|
# freeformType = format.type; — one day we may want to enable freeform types, but for now just keep it strongly defined
|
|
options = {
|
|
name = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
User-friendly name of the OIDC Client.
|
|
'';
|
|
};
|
|
redirect_uris = mkOption {
|
|
type = types.listOf types.str;
|
|
description = ''
|
|
List of redirect URIs that the client can use to redirect login attempts back to itself.
|
|
Consult the documentation for the other service if you aren't sure.
|
|
'';
|
|
};
|
|
allow_user_classes = mkOption {
|
|
type = types.listOf types.str;
|
|
description = ''
|
|
List of user classes which are authorised (allowed) to use this client (access this service).
|
|
As of idCoop v0.0.1, this setting is unimplemented and has no effect.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
in
|
|
{
|
|
options.services.idcoop = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to enable idCoop, a simple identity provider.
|
|
'';
|
|
};
|
|
|
|
configurePostgres = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to configure a Postgres database for idCoop.
|
|
Enabled by default.
|
|
'';
|
|
};
|
|
|
|
user = mkOption {
|
|
type = types.str;
|
|
default = defaultUser;
|
|
description = ''
|
|
User to run the service as.
|
|
Will be created automatically if it is left at the default.
|
|
'';
|
|
};
|
|
|
|
group = mkOption {
|
|
type = types.str;
|
|
default = defaultUser;
|
|
description = ''
|
|
User to run the service as.
|
|
Will be created automatically if it is left at the default.
|
|
'';
|
|
};
|
|
|
|
secretsPath = mkOption {
|
|
type = types.path;
|
|
default = builtins.toFile "blank.toml" "";
|
|
description = ''
|
|
Path to a file containing secrets. This file should be kept out of the Nix store.
|
|
Consult the idCoop documentation for the format of the secrets file.
|
|
'';
|
|
};
|
|
|
|
settings = mkOption {
|
|
default = {};
|
|
description = "idCoop configuration.";
|
|
|
|
type = types.submodule {
|
|
# freeformType = format.type; — one day we may want to enable freeform types, but for now just keep it strongly defined
|
|
options = {
|
|
listen = {
|
|
bind = mkOption {
|
|
type = types.str;
|
|
default = "127.0.0.1:8072";
|
|
description = ''
|
|
Host and port combination upon which to bind the web interface.
|
|
'';
|
|
};
|
|
public_base_uri = mkOption {
|
|
type = types.str;
|
|
default = "http://${cfg.settings.listen.bind}";
|
|
defaultText = "`http://{listen.bind}`";
|
|
description = ''
|
|
Public-facing HTTP(S) base URL.
|
|
'';
|
|
};
|
|
};
|
|
|
|
oidc = {
|
|
issuer = mkOption {
|
|
type = types.str;
|
|
default = cfg.settings.listen.public_base_uri;
|
|
defaultText = "`listen.public_base_uri`";
|
|
description = ''
|
|
The identity provider's 'issuer' identifier, as used in OpenID Connect.
|
|
This should be configured in clients (relying parties) and should likely not be changed.
|
|
'';
|
|
};
|
|
|
|
rsa_keypair = mkOption {
|
|
type = types.path;
|
|
description = ''
|
|
Path to an RSA keypair used for signing JSON Web Tokens.
|
|
'';
|
|
};
|
|
|
|
|
|
clients = mkOption {
|
|
type = types.attrsOf oidcClientSubmodule;
|
|
default = {};
|
|
description = ''
|
|
OpenID Connect 'clients' (also known as relying parties).
|
|
These entries are for the different services you want users to be able to log in to using idCoop.
|
|
'';
|
|
};
|
|
};
|
|
|
|
postgres = {
|
|
connect = mkOption {
|
|
type = types.str;
|
|
default = "postgres:";
|
|
description = mdDoc ''
|
|
Connection string for the Postgres database. The default of `postgres:` uses the [libpq environment variables] to form a connection;
|
|
usually this by default connects to the local UNIX socket with the current user's name as a username and database name,
|
|
if no environment variables are set.
|
|
|
|
[libpq environment variables]: https://www.postgresql.org/docs/current/libpq-envars.html
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
};
|
|
|
|
config = let
|
|
configPath = writeTOML "idcoop_config.toml" cfg.settings;
|
|
in {
|
|
users.users.idcoop = mkIf (cfg.enable && cfg.user == defaultUser) {
|
|
isSystemUser = true;
|
|
group = cfg.group;
|
|
home = mkDefault "/var/lib/idcoop";
|
|
createHome = true;
|
|
|
|
packages = [
|
|
# Add a wrapper for the idcoop command so the user can use the CLI conveniently
|
|
(pkgs.writeShellScriptBin "idcoop" ''
|
|
IDCOOP_CONFIG=${pkgs.lib.escapeShellArg configPath} IDCOOP_SECRETS=${pkgs.lib.escapeShellArg cfg.secretsPath} exec ${idcoop}/bin/idcoop "$@"
|
|
'')
|
|
];
|
|
};
|
|
users.groups.idcoop = mkIf (cfg.enable && cfg.group == defaultUser) {};
|
|
|
|
systemd.services.idcoop = mkIf cfg.enable {
|
|
description = "idCoop: simple identity provider";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "networking.target" "network-online.target" "postgresql.service" ];
|
|
|
|
serviceConfig =
|
|
{
|
|
ExecStart = "${idcoop}/bin/idcoop --config ${pkgs.lib.escapeShellArg configPath} --secrets ${pkgs.lib.escapeShellArg cfg.secretsPath} serve";
|
|
User = cfg.user;
|
|
Group = cfg.group;
|
|
};
|
|
};
|
|
|
|
services.postgresql = mkIf cfg.configurePostgres {
|
|
ensureUsers = [
|
|
{
|
|
name = "idcoop";
|
|
ensureDBOwnership = true;
|
|
}
|
|
];
|
|
ensureDatabases = ["idcoop"];
|
|
};
|
|
};
|
|
}
|