module: add ak script
This was made possible by d85dacb6c2
which allows to directly use `manage.py`. That script is
effectively used whenever the `ak` command is referenced in the docs,
e.g. to set a new password for the superuser or to send a test email.
This needs to run as the same (dynamic) user and with the same env file,
otherwise `manage.py` exits early. To achieve that, I
decided to use `systemd-run(1)` because now the invocation can be
configured the same way as services are.
This commit is contained in:
parent
5ed5c481f2
commit
2da27254c1
1 changed files with 50 additions and 14 deletions
64
module.nix
64
module.nix
|
|
@ -7,6 +7,15 @@ let
|
||||||
inherit (lib)
|
inherit (lib)
|
||||||
types;
|
types;
|
||||||
|
|
||||||
|
inherit (lib.attrsets)
|
||||||
|
attrNames
|
||||||
|
getAttrs
|
||||||
|
mapAttrsToList;
|
||||||
|
|
||||||
|
inherit (lib.lists)
|
||||||
|
flatten
|
||||||
|
toList;
|
||||||
|
|
||||||
inherit (lib.modules)
|
inherit (lib.modules)
|
||||||
mkDefault
|
mkDefault
|
||||||
mkIf
|
mkIf
|
||||||
|
|
@ -17,6 +26,13 @@ let
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkOption;
|
mkOption;
|
||||||
|
|
||||||
|
inherit (lib.strings)
|
||||||
|
concatStringsSep;
|
||||||
|
|
||||||
|
inherit (lib.trivial)
|
||||||
|
boolToString
|
||||||
|
isBool;
|
||||||
|
|
||||||
settingsFormat = pkgs.formats.yaml {};
|
settingsFormat = pkgs.formats.yaml {};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|
@ -125,6 +141,25 @@ in
|
||||||
# authentik server
|
# authentik server
|
||||||
(mkIf config.services.authentik.enable (let
|
(mkIf config.services.authentik.enable (let
|
||||||
cfg = config.services.authentik;
|
cfg = config.services.authentik;
|
||||||
|
|
||||||
|
# Passed to each service and to the `ak` wrapper using `systemd-run(1)`
|
||||||
|
serviceDefaults = {
|
||||||
|
DynamicUser = true;
|
||||||
|
User = "authentik";
|
||||||
|
EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
|
||||||
|
};
|
||||||
|
akOptions = flatten (mapAttrsToList
|
||||||
|
# Map defaults for each authentik service (listed above) to command line parameters for
|
||||||
|
# `systemd-run(1)` in order to spin up an environment with correct (dynamic) user,
|
||||||
|
# state directory and environment to run `ak` inside.
|
||||||
|
(k: vs: map
|
||||||
|
(v: "--property ${k}=${if isBool v then boolToString v else toString v}")
|
||||||
|
(toList vs))
|
||||||
|
# Read serviceDefaults from `authentik.service`. That way, module system primitives (mk*)
|
||||||
|
# can be used inside `serviceDefaults` and it doesn't need to be evaluated here again.
|
||||||
|
(getAttrs (attrNames serviceDefaults) config.systemd.services.authentik.serviceConfig // {
|
||||||
|
StateDirectory = "authentik";
|
||||||
|
}));
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
services = {
|
services = {
|
||||||
|
|
@ -154,6 +189,15 @@ in
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = [
|
||||||
|
(pkgs.writeShellScriptBin "ak" ''
|
||||||
|
exec ${config.systemd.package}/bin/systemd-run --pty --collect \
|
||||||
|
${concatStringsSep " \\\n" akOptions} \
|
||||||
|
--working-directory /var/lib/authentik \
|
||||||
|
-- ${cfg.authentikComponents.manage}/bin/manage.py "$@"
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
|
||||||
# https://goauthentik.io/docs/installation/docker-compose#explanation
|
# https://goauthentik.io/docs/installation/docker-compose#explanation
|
||||||
time.timeZone = "UTC";
|
time.timeZone = "UTC";
|
||||||
|
|
||||||
|
|
@ -166,15 +210,12 @@ in
|
||||||
after = lib.optionals cfg.createDatabase [ "postgresql.service" ];
|
after = lib.optionals cfg.createDatabase [ "postgresql.service" ];
|
||||||
before = [ "authentik.service" ];
|
before = [ "authentik.service" ];
|
||||||
restartTriggers = [ config.environment.etc."authentik/config.yml".source ];
|
restartTriggers = [ config.environment.etc."authentik/config.yml".source ];
|
||||||
serviceConfig = {
|
serviceConfig = mkMerge [ serviceDefaults {
|
||||||
Type = "oneshot";
|
Type = "oneshot";
|
||||||
RemainAfterExit = true;
|
RemainAfterExit = true;
|
||||||
DynamicUser = true;
|
|
||||||
User = "authentik";
|
|
||||||
ExecStart = "${cfg.authentikComponents.migrate}/bin/migrate.py";
|
ExecStart = "${cfg.authentikComponents.migrate}/bin/migrate.py";
|
||||||
EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
|
|
||||||
inherit (config.systemd.services.authentik.serviceConfig) StateDirectory;
|
inherit (config.systemd.services.authentik.serviceConfig) StateDirectory;
|
||||||
};
|
} ];
|
||||||
};
|
};
|
||||||
authentik-worker = {
|
authentik-worker = {
|
||||||
requiredBy = [ "authentik.service" ];
|
requiredBy = [ "authentik.service" ];
|
||||||
|
|
@ -183,19 +224,16 @@ in
|
||||||
preStart = ''
|
preStart = ''
|
||||||
ln -svf ${config.services.authentik.authentikComponents.staticWorkdirDeps}/* /run/authentik/
|
ln -svf ${config.services.authentik.authentikComponents.staticWorkdirDeps}/* /run/authentik/
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = mkMerge [ serviceDefaults {
|
||||||
RuntimeDirectory = "authentik";
|
RuntimeDirectory = "authentik";
|
||||||
WorkingDirectory = "%t/authentik";
|
WorkingDirectory = "%t/authentik";
|
||||||
DynamicUser = true;
|
|
||||||
User = "authentik";
|
|
||||||
# TODO maybe make this configurable
|
# TODO maybe make this configurable
|
||||||
ExecStart = "${cfg.authentikComponents.manage}/bin/manage.py worker";
|
ExecStart = "${cfg.authentikComponents.manage}/bin/manage.py worker";
|
||||||
EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
|
|
||||||
LoadCredential = mkIf (cfg.nginx.enable && cfg.nginx.enableACME) [
|
LoadCredential = mkIf (cfg.nginx.enable && cfg.nginx.enableACME) [
|
||||||
"${cfg.nginx.host}.pem:${config.security.acme.certs.${cfg.nginx.host}.directory}/fullchain.pem"
|
"${cfg.nginx.host}.pem:${config.security.acme.certs.${cfg.nginx.host}.directory}/fullchain.pem"
|
||||||
"${cfg.nginx.host}.key:${config.security.acme.certs.${cfg.nginx.host}.directory}/key.pem"
|
"${cfg.nginx.host}.key:${config.security.acme.certs.${cfg.nginx.host}.directory}/key.pem"
|
||||||
];
|
];
|
||||||
};
|
} ];
|
||||||
};
|
};
|
||||||
authentik = {
|
authentik = {
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
|
@ -209,7 +247,7 @@ in
|
||||||
ln -svf ${cfg.authentikComponents.staticWorkdirDeps}/* /var/lib/authentik/
|
ln -svf ${cfg.authentikComponents.staticWorkdirDeps}/* /var/lib/authentik/
|
||||||
mkdir -p ${cfg.settings.paths.media}
|
mkdir -p ${cfg.settings.paths.media}
|
||||||
'';
|
'';
|
||||||
serviceConfig = {
|
serviceConfig = mkMerge [ serviceDefaults {
|
||||||
Environment = [
|
Environment = [
|
||||||
"AUTHENTIK_ERROR_REPORTING__ENABLED=false"
|
"AUTHENTIK_ERROR_REPORTING__ENABLED=false"
|
||||||
"AUTHENTIK_DISABLE_UPDATE_CHECK=true"
|
"AUTHENTIK_DISABLE_UPDATE_CHECK=true"
|
||||||
|
|
@ -220,10 +258,8 @@ in
|
||||||
UMask = "0027";
|
UMask = "0027";
|
||||||
# TODO /run might be sufficient
|
# TODO /run might be sufficient
|
||||||
WorkingDirectory = "%S/authentik";
|
WorkingDirectory = "%S/authentik";
|
||||||
DynamicUser = true;
|
|
||||||
ExecStart = "${cfg.authentikComponents.gopkgs}/bin/server";
|
ExecStart = "${cfg.authentikComponents.gopkgs}/bin/server";
|
||||||
EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
|
} ];
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue