From e9ffd4d839e1b5583ea664cc53093534fea0780a Mon Sep 17 00:00:00 2001 From: Nikolaos Karaolidis Date: Sat, 8 Mar 2025 00:35:15 +0000 Subject: [PATCH] Add authelia base Signed-off-by: Nikolaos Karaolidis --- .../console/podman/authelia/default.nix | 215 ++++++++++++++++++ .../storm/configs/console/podman/default.nix | 1 + .../configs/console/podman/ntfy/default.nix | 2 + lib/runtime/default.nix | 1 + lib/runtime/log/default.nix | 4 + lib/runtime/log/docker/default.nix | 4 + lib/runtime/log/docker/postgres/default.nix | 6 + lib/runtime/log/docker/postgres/wrapper.sh | 17 ++ 8 files changed, 250 insertions(+) create mode 100644 hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix create mode 100644 lib/runtime/log/default.nix create mode 100644 lib/runtime/log/docker/default.nix create mode 100644 lib/runtime/log/docker/postgres/default.nix create mode 100644 lib/runtime/log/docker/postgres/wrapper.sh diff --git a/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix new file mode 100644 index 0000000..147472f --- /dev/null +++ b/hosts/jupiter/users/storm/configs/console/podman/authelia/default.nix @@ -0,0 +1,215 @@ +{ + user ? throw "user argument is required", + home ? throw "home argument is required", +}: +{ + config, + inputs, + pkgs, + system, + lib, + ... +}: +let + selfLib = inputs.self.lib.${system}; + hmConfig = config.home-manager.users.${user}; + inherit (hmConfig.virtualisation.quadlet) volumes containers networks; +in +{ + environment.persistence."/persist"."${home}/.local/share/authelia" = { }; + + home-manager.users.${user} = { + sops = { + secrets = { + "authelia/jwt".sopsFile = ../../../../../../secrets/secrets.yaml; + "authelia/session".sopsFile = ../../../../../../secrets/secrets.yaml; + "authelia/storage".sopsFile = ../../../../../../secrets/secrets.yaml; + "authelia/postgresql".sopsFile = ../../../../../../secrets/secrets.yaml; + "authelia/smtp".sopsFile = ../../../../../../secrets/secrets.yaml; + "authelia/users/karaolidis".sopsFile = ../../../../../../secrets/secrets.yaml; + }; + + templates = { + "authelia-postgresql.env".content = '' + POSTGRES_PASSWORD=${hmConfig.sops.placeholder."authelia/postgresql"} + ''; + + "authelia-users.yaml".content = builtins.readFile ( + (pkgs.formats.yaml { }).generate "users.yaml" { + users.karaolidis = { + displayname = "Nick Karaolidis"; + password = hmConfig.sops.placeholder."authelia/users/karaolidis"; + email = "nick@karaolidis.com"; + groups = [ "admins" ]; + }; + } + ); + }; + }; + + virtualisation.quadlet = { + networks.authelia = { }; + + volumes."authelia-redis" = { }; + + containers = { + "authelia-init" = { + containerConfig = { + autoUpdate = "registry"; + image = "docker.io/mikefarah/yq:latest"; + networks = [ networks.authelia.ref ]; + volumes = [ + "${home}/.local/share/authelia/config:/workdir/config" + "${hmConfig.sops.templates."authelia-users.yaml".path}:/workdir/users.yaml:ro" + ]; + exec = [ + "eval-all" + ". as $item ireduce ({}; . * $item)" + "/workdir/config/users.yaml" + "/workdir/users.yaml" + "-i" + ]; + userns = "keep-id:uid=1000,gid=1000"; + }; + + serviceConfig = { + Type = "oneshot"; + Restart = "on-failure"; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + authelia = { + containerConfig = + let + config = (pkgs.formats.yaml { }).generate "configuration.yaml" { + theme = "auto"; + telemetry.metrics.enabled = true; + + authentication_backend = { + refresh_interval = "always"; + file = { + path = "/config/users.yaml"; + watch = true; + }; + }; + + password_policy.zxcvbn.enabled = true; + access_control.default_policy = "two_factor"; + + session = { + cookies = [ + { + domain = "karaolidis.com"; + authelia_url = "https://id.karaolidis.com"; + } + ]; + + redis = { + host = "authelia-redis"; + port = 6379; + }; + }; + + storage.postgres = { + address = "tcp://authelia-postgresql:5432"; + database = "authelia"; + username = "authelia"; + }; + + notifier.smtp = { + address = "smtp://smtp.protonmail.ch:587"; + username = "jupiter@karaolidis.com"; + sender = "jupiter@karaolidis.com"; + }; + + }; + in + { + autoUpdate = "registry"; + image = "ghcr.io/authelia/authelia"; + environments = { + AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE = "/secrets/JWT_SECRET"; + AUTHELIA_SESSION_SECRET_FILE = "/secrets/SESSION_SECRET"; + AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE = "/secrets/STORAGE_ENCRYPTION_KEY"; + AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = "/secrets/STORAGE_PASSWORD"; + AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE = "/secrets/SMTP_PASSWORD"; + }; + volumes = [ + "${home}/.local/share/authelia/config:/config" + "${config}:/config/conf.d/configuration.yaml:ro" + "${hmConfig.sops.secrets."authelia/jwt".path}:/secrets/JWT_SECRET:ro" + "${hmConfig.sops.secrets."authelia/session".path}:/secrets/SESSION_SECRET:ro" + "${hmConfig.sops.secrets."authelia/storage".path}:/secrets/STORAGE_ENCRYPTION_KEY:ro" + "${hmConfig.sops.secrets."authelia/postgresql".path}:/secrets/STORAGE_PASSWORD:ro" + "${hmConfig.sops.secrets."authelia/smtp".path}:/secrets/SMTP_PASSWORD:ro" + ]; + networks = [ + networks.authelia.ref + networks.traefik.ref + ]; + exec = [ "--config /config/conf.d/" ]; + labels = [ + "traefik.enable=true" + "traefik.http.routers.authelia.rule=Host(`id.karaolidis.com`)" + "traefik.http.routers.authelia.entryPoints=https" + "traefik.http.routers.traefik.tls.certresolver=letsencrypt" + "traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader=true" + "traefik.http.middlewares.authelia.forwardAuth.address=http://authelia:9091/api/authz/forward-auth" + "traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders=Remote-User,Remote-Groups,Remote-Email,Remote-Name" + ]; + }; + + unitConfig.After = [ + "${containers."authelia-init"._serviceName}.service" + "${containers."authelia-postgresql"._serviceName}.service" + "${containers."authelia-redis"._serviceName}.service" + "sops-nix.service" + ]; + }; + + "authelia-postgresql" = { + containerConfig = { + autoUpdate = "registry"; + image = "docker.io/library/postgres:latest"; + networks = [ networks.authelia.ref ]; + volumes = [ + "${selfLib.runtime.log.docker.postgres}:/entrypoint.sh:ro" + "${home}/.local/share/authelia/postgresql:/var/lib/postgresql/data" + ]; + environments = { + POSTGRES_DB = "authelia"; + POSTGRES_USER = "authelia"; + }; + environmentFiles = [ hmConfig.sops.templates."authelia-postgresql.env".path ]; + entrypoint = "/entrypoint.sh"; + exec = [ "postgres" ]; + user = "999"; + group = "999"; + userns = "keep-id:uid=999,gid=999"; + }; + + unitConfig.After = [ "sops-nix.service" ]; + }; + + "authelia-redis".containerConfig = { + autoUpdate = "registry"; + image = "docker.io/library/redis:latest"; + networks = [ networks.authelia.ref ]; + volumes = [ "${volumes."authelia-redis".ref}:/data" ]; + exec = [ "--save 60 1" ]; + user = "999"; + group = "999"; + userns = "keep-id:uid=999,gid=999"; + }; + }; + }; + + systemd.user.tmpfiles.rules = [ + "d ${home}/.local/share/authelia/config 0755 ${user} ${user}" + "f ${home}/.local/share/authelia/config/users.yaml 644 ${user} ${user}" + "d ${home}/.local/share/authelia/postgresql 0700 ${user} ${user}" + ]; + }; +} diff --git a/hosts/jupiter/users/storm/configs/console/podman/default.nix b/hosts/jupiter/users/storm/configs/console/podman/default.nix index cd86598..6362dca 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/default.nix @@ -8,6 +8,7 @@ let in { imports = [ + (import ./authelia { inherit user home; }) (import ./ntfy { inherit user home; }) (import ./traefik { inherit user home; }) (import ./whoami { inherit user home; }) diff --git a/hosts/jupiter/users/storm/configs/console/podman/ntfy/default.nix b/hosts/jupiter/users/storm/configs/console/podman/ntfy/default.nix index e67f1d2..ece739a 100644 --- a/hosts/jupiter/users/storm/configs/console/podman/ntfy/default.nix +++ b/hosts/jupiter/users/storm/configs/console/podman/ntfy/default.nix @@ -29,6 +29,8 @@ in in builtins.readFile ( (pkgs.formats.yaml { }).generate "server.yml" { + log-level = "warn"; + base-url = "https://ntfy.karaolidis.com"; cache-file = "/var/lib/ntfy/cache.db"; diff --git a/lib/runtime/default.nix b/lib/runtime/default.nix index 8c9cbce..c1ec3f4 100644 --- a/lib/runtime/default.nix +++ b/lib/runtime/default.nix @@ -1,4 +1,5 @@ { pkgs, ... }: { + log = import ./log { inherit pkgs; }; merge = import ./merge { inherit pkgs; }; } diff --git a/lib/runtime/log/default.nix b/lib/runtime/log/default.nix new file mode 100644 index 0000000..e2b386f --- /dev/null +++ b/lib/runtime/log/default.nix @@ -0,0 +1,4 @@ +{ pkgs, ... }: +{ + docker = import ./docker { inherit pkgs; }; +} diff --git a/lib/runtime/log/docker/default.nix b/lib/runtime/log/docker/default.nix new file mode 100644 index 0000000..fe3dbc5 --- /dev/null +++ b/lib/runtime/log/docker/default.nix @@ -0,0 +1,4 @@ +{ pkgs, ... }: +{ + postgres = import ./postgres { inherit pkgs; }; +} diff --git a/lib/runtime/log/docker/postgres/default.nix b/lib/runtime/log/docker/postgres/default.nix new file mode 100644 index 0000000..838f63b --- /dev/null +++ b/lib/runtime/log/docker/postgres/default.nix @@ -0,0 +1,6 @@ +{ pkgs, ... }: +pkgs.writeTextFile { + name = "log-wrapper-docker-postgres"; + text = builtins.readFile ./wrapper.sh; + executable = true; +} diff --git a/lib/runtime/log/docker/postgres/wrapper.sh b/lib/runtime/log/docker/postgres/wrapper.sh new file mode 100644 index 0000000..744976a --- /dev/null +++ b/lib/runtime/log/docker/postgres/wrapper.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +set -o errexit +set -o nounset + +LOG_PIPE="$(mktemp -u)" +mkfifo "$LOG_PIPE" + +while IFS= read -r line; do + if echo "$line" | grep -qE "ERROR|FATAL|PANIC"; then + echo "$line" >&2 + else + echo "$line" >&1 + fi +done < "$LOG_PIPE" & + +exec /usr/local/bin/docker-entrypoint.sh "$@" >"$LOG_PIPE" 2>&1