Files
sydnix/modules/nixos/deertopia/authelia.nix
2025-03-09 11:06:11 -06:00

153 lines
5.4 KiB
Nix

{ config, lib, pkgs, ... }:
let cfg = config.sydnix.deertopia.authelia;
in {
options.sydnix.deertopia.authelia = {
enable = lib.mkEnableOption ''Deertopia's Authelia'';
httpPort = lib.mkOption {
description = ''
The port on which Authelia's web UI will be served.
'';
type = lib.types.port;
default = 9091;
};
bindUserName = lib.mkOption {
description = ''
The name of the LDAP user Authelia will bind as.
'';
type = lib.types.str;
default = "authelia";
};
};
config = lib.mkIf cfg.enable
(let authelia-state-dir = "/var/lib/authelia-deertopia";
in {
sydnix.sops.secrets =
let e = {
mode = "0600";
owner = config.services.authelia.instances."deertopia".user;
group = config.services.authelia.instances."deertopia".group;
};
in {
authelia-jwt-secret = e;
authelia-session-secret = e;
authelia-storage-encryption-key = e;
authelia-authentication-backend-ldap-password = e;
};
sydnix.impermanence.directories = [
authelia-state-dir
];
# See:
# - https://github.com/authelia/authelia/blob/v4.38.19/config.template.yml
# - https://matwick.ca/authelia-nginx-sso/
# - https://www.gandalfk7.it/posts/20220713_01_sso-with-lldap-authelia-and-nginx/
services.authelia.instances."deertopia" = {
enable = true;
# "Automatic" secrets are seemingly broken and offer little more than
# some assertions from the Nix module.
secrets.manual = true;
environmentVariables = {
AUTHELIA_JWT_SECRET_FILE =
"/run/secrets/authelia-jwt-secret";
AUTHELIA_SESSION_SECRET_FILE =
"/run/secrets/authelia-session-secret";
AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE =
"/run/secrets/authelia-storage-encryption-key";
AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE =
"/run/secrets/authelia-authentication-backend-ldap-password";
};
settings = {
default_2fa_method = "totp";
theme = "auto";
server = {
address = "tcp://:${builtins.toString cfg.httpPort}";
asset_path = "${authelia-state-dir}/assets";
# Necessary for Nginx integration. No, I do not understand what it
# does.
endpoints.authz.auth-request.implementation = "AuthRequest";
};
authentication_backend =
let base-dn = config.services.lldap.settings.ldap_base_dn;
ldap-port =
builtins.toString config.services.lldap.settings.ldap_port;
in {
password_reset.disable = false;
refresh_interval = "1 minutes";
ldap = {
implementation = "custom";
address = "ldap://127.0.0.1:${ldap-port}";
timeout = "5s";
start_tls = "false";
base_dn = base-dn;
additional_users_dn = "ou=people";
additional_groups_dn = "ou=groups";
groups_filter = "(member={dn})";
users_filter = "(&({username_attribute}={input})(objectClass=person))";
attributes = {
username = "uid";
group_name = "cn";
mail = "mail";
display_name = "displayName";
};
user = "uid=${cfg.bindUserName},ou=people,${base-dn}";
};
};
access_control = {
default_policy = "deny";
rules = [
{
domain = "*.deertopia.net";
policy = "one_factor";
}
];
};
session = {
name = "authelia_session";
same_site = "lax";
inactivity = "5 minutes";
expiration = "1 hour";
remember_me = "1 month";
cookies = [
{
domain = "deertopia.net";
authelia_url = "https://auth.deertopia.net";
default_redirection_url = "https://deertopia.net";
}
];
};
storage.local.path = "${authelia-state-dir}/db.sqlite";
notifier = {
disable_startup_check = false;
filesystem.filename = "${authelia-state-dir}/notifications";
};
# Default is false, which prevents anything from showing up when you run
# `systemctl status authelia-deertopia`, which is really, really confusing.
log = {
keep_stdout = true;
file_path = "${authelia-state-dir}/authelia.log";
};
};
};
sydnix.deertopia.nginx.vhosts."auth" = {
directory = null;
vhost = {
forceSSL = true;
enableACME = true;
extraConfig = ''
set $upstream http://127.0.0.1:${builtins.toString cfg.httpPort};
'';
locations."/".extraConfig = ''
include ${./authelia/proxy.conf};
proxy_pass $upstream;
'';
locations."/api/verify".proxyPass = "$upstream";
locations."/api/authz".proxyPass = "$upstream";
};
};
});
}