From 32ea4fdd8d6a546c417b5d88cb43a15ce88bd0c8 Mon Sep 17 00:00:00 2001 From: chayleaf Date: Mon, 28 Aug 2023 00:46:51 +0700 Subject: [PATCH] server: add keycloak --- system/hosts/nixserver/default.nix | 1 + system/hosts/nixserver/home.nix | 5 ++ system/hosts/nixserver/keycloak.nix | 105 ++++++++++++++++++++++++++++ system/hosts/nixserver/matrix.nix | 2 +- system/hosts/nixserver/options.nix | 5 ++ system/modules/impermanence.nix | 2 + 6 files changed, 119 insertions(+), 1 deletion(-) create mode 100644 system/hosts/nixserver/keycloak.nix diff --git a/system/hosts/nixserver/default.nix b/system/hosts/nixserver/default.nix index 9ab233d..9cfcabf 100644 --- a/system/hosts/nixserver/default.nix +++ b/system/hosts/nixserver/default.nix @@ -20,6 +20,7 @@ in { ./mumble.nix ./mailserver.nix ./home.nix + ./keycloak.nix ]; system.stateVersion = "22.11"; diff --git a/system/hosts/nixserver/home.nix b/system/hosts/nixserver/home.nix index b430e6c..bfd8813 100644 --- a/system/hosts/nixserver/home.nix +++ b/system/hosts/nixserver/home.nix @@ -14,6 +14,7 @@ let (lib.filterAttrs (k: v: builtins.elem k names && v.enable) config.services.prometheus.exporters)); in { # a bunch of services for personal use not intended for the public + # TODO: keycloakify this services.grafana = { enable = true; settings = { @@ -34,6 +35,10 @@ in { }; services.nginx.upstreams.grafana.servers."unix:/${config.services.grafana.settings.server.socket}" = {}; + # TODO: + # services.keycloak.plugins = [ pkgs.keycloak.plugins.keycloak-metrics-spi ]; + services.keycloak.settings.metrics-enabled = true; + services.nginx.virtualHosts."home.${cfg.domainName}" = { quic = true; enableACME = true; diff --git a/system/hosts/nixserver/keycloak.nix b/system/hosts/nixserver/keycloak.nix new file mode 100644 index 0000000..43d12f5 --- /dev/null +++ b/system/hosts/nixserver/keycloak.nix @@ -0,0 +1,105 @@ +{ config +, lib +, pkgs +, ... }: + +let + cfg = config.server; +in { + services.keycloak = { + enable = true; + database.passwordFile = "/secrets/keycloak_db_pass"; + settings = { + hostname = "keycloak.${cfg.domainName}"; + http-enabled = true; + http-host = "127.0.0.1"; + http-port = 5739; + https-port = 5740; + proxy = "edge"; + }; + }; + services.nginx.virtualHosts."keycloak.${cfg.domainName}" = { + quic = true; + enableACME = true; + forceSSL = true; + locations."/".proxyPass = "http://${lib.quoteListenAddr config.services.keycloak.settings.http-host}:${toString config.services.keycloak.settings.http-port}/"; + }; + + services.gitea.settings.openid = { + ENABLE_OPENID_SIGNIN = true; + ENABLE_OPENID_SIGNUP = true; + }; + + services.nextcloud.extraOptions.allow_local_remote_servers = true; + + # a crude way to make some python packages available for synapse + services.matrix-synapse.plugins = with pkgs.python3.pkgs; [ authlib ]; + services.matrix-synapse.settings.password_config.enabled = false; + + # See also https://meta.akkoma.dev/t/390 + # https:///oauth/keycloak?scope=openid+profile + # ...but this doesnt even work, the callback simply gets ignored + # oh well + services.akkoma.config = { + ":ueberauth" = let + url = "https://keycloak.${cfg.domainName}"; + realm = cfg.keycloakRealm; + format = pkgs.formats.elixirConf { }; + in { + "Ueberauth.Strategy.Keycloak.OAuth" = { + client_id = "akkoma"; + client_secret = format.lib.mkRaw ''System.get_env("KEYCLOAK_CLIENT_SECRET")''; + site = url; + authorize_url = "${url}/realms/${realm}/protocol/openid-connect/auth"; + token_url = "${url}/realms/${realm}/protocol/openid-connect/token"; + userinfo_url = "${url}/realms/${realm}/protocol/openid-connect/userinfo"; + token_method = format.lib.mkRaw ":post"; + }; + Ueberauth.providers = { + keycloak = format.lib.mkTuple [ (format.lib.mkRaw "Ueberauth.Strategy.Keycloak") { + default_scope = "openid profile"; + uid_field = format.lib.mkRaw ":preferred_username"; + } ]; + }; + }; + }; + services.akkoma.package = pkgs.akkoma.overrideAttrs (old: { + buildInputs = let + inherit (pkgs.beamPackages) fetchHex buildMix; + oldDeps = old.buildInputs or []; + tesla = builtins.head (builtins.filter (x: x.packageName == "tesla") oldDeps); + ueberauth = builtins.head (builtins.filter (x: x.packageName == "ueberauth") oldDeps); + in oldDeps ++ builtins.attrValues rec { + # TODO: nothing, this is just a reminder to relock these every once in a while + oauth2 = buildMix rec { + name = "oauth2"; + version = "2.1.0"; + + src = fetchHex { + pkg = "${name}"; + version = "${version}"; + sha256 = "0h9bps7gq7bac5gc3q0cgpsj46qnchpqbv5hzsnd2z9hnf2pzh4a"; + }; + + beamDeps = [ tesla ]; + }; + ueberauth_keycloak_strategy = buildMix rec { + name = "ueberauth_keycloak_strategy"; + version = "0.4.0"; + + src = fetchHex { + pkg = "${name}"; + version = "${version}"; + sha256 = "06r10w0azlpypjgggar1lf7h2yazn2dpyicy97zxkjyxgf9jfc60"; + }; + + beamDeps = [ oauth2 ueberauth ]; + }; + }; + OAUTH_CONSUMER_STRATEGIES = "keycloak:ueberauth_keycloak_strategy"; + }); + systemd.services.akkoma = { + environment.OAUTH_CONSUMER_STRATEGIES = "keycloak:ueberauth_keycloak_strategy"; + serviceConfig.EnvironmentFile = "/secrets/akkoma/envrc"; + }; +} diff --git a/system/hosts/nixserver/matrix.nix b/system/hosts/nixserver/matrix.nix index 3ebc060..fc18c45 100644 --- a/system/hosts/nixserver/matrix.nix +++ b/system/hosts/nixserver/matrix.nix @@ -66,7 +66,7 @@ in { server_name = "matrix.${cfg.domainName}"; max_upload_size = "100M"; email = { - smtp_host = "mail.pavluk.org"; + smtp_host = "mail.${cfg.domainName}"; smtp_port = 587; smtp_user = "noreply"; smtp_password = cfg.unhashedNoreplyPassword; diff --git a/system/hosts/nixserver/options.nix b/system/hosts/nixserver/options.nix index d7fc0e3..5f3d591 100644 --- a/system/hosts/nixserver/options.nix +++ b/system/hosts/nixserver/options.nix @@ -9,6 +9,11 @@ default = "pavluk.org"; description = "domain name"; }; + keycloakRealm = mkOption { + type = types.str; + default = "master"; + description = "keycloak realm"; + }; lanCidrV4 = mkOption { type = types.str; description = "LAN mask (IPv4)"; diff --git a/system/modules/impermanence.nix b/system/modules/impermanence.nix index 4be2403..120b2bc 100644 --- a/system/modules/impermanence.nix +++ b/system/modules/impermanence.nix @@ -123,6 +123,8 @@ in { { directory = /var/lib/dovecot; user = "root"; group = "root"; mode = "0755"; } ] ++ lib.optionals config.security.sudo.enable [ { directory = /var/db/sudo/lectured; user = "root"; group = "root"; mode = "0700"; } + ] ++ lib.optionals config.services.openldap.enable [ + { directory = /var/lib/openldap; inherit (config.services.openldap) user group; mode = "0755"; } ] ++ cfg.directories); files = map (x: if builtins.isPath x then toString x