server: add keycloak

This commit is contained in:
chayleaf 2023-08-28 00:46:51 +07:00
parent 9e70d53ee5
commit 32ea4fdd8d
6 changed files with 119 additions and 1 deletions

View file

@ -20,6 +20,7 @@ in {
./mumble.nix ./mumble.nix
./mailserver.nix ./mailserver.nix
./home.nix ./home.nix
./keycloak.nix
]; ];
system.stateVersion = "22.11"; system.stateVersion = "22.11";

View file

@ -14,6 +14,7 @@ let
(lib.filterAttrs (k: v: builtins.elem k names && v.enable) config.services.prometheus.exporters)); (lib.filterAttrs (k: v: builtins.elem k names && v.enable) config.services.prometheus.exporters));
in { in {
# a bunch of services for personal use not intended for the public # a bunch of services for personal use not intended for the public
# TODO: keycloakify this
services.grafana = { services.grafana = {
enable = true; enable = true;
settings = { settings = {
@ -34,6 +35,10 @@ in {
}; };
services.nginx.upstreams.grafana.servers."unix:/${config.services.grafana.settings.server.socket}" = {}; 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}" = { services.nginx.virtualHosts."home.${cfg.domainName}" = {
quic = true; quic = true;
enableACME = true; enableACME = true;

View file

@ -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://<pleroma>/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";
};
}

View file

@ -66,7 +66,7 @@ in {
server_name = "matrix.${cfg.domainName}"; server_name = "matrix.${cfg.domainName}";
max_upload_size = "100M"; max_upload_size = "100M";
email = { email = {
smtp_host = "mail.pavluk.org"; smtp_host = "mail.${cfg.domainName}";
smtp_port = 587; smtp_port = 587;
smtp_user = "noreply"; smtp_user = "noreply";
smtp_password = cfg.unhashedNoreplyPassword; smtp_password = cfg.unhashedNoreplyPassword;

View file

@ -9,6 +9,11 @@
default = "pavluk.org"; default = "pavluk.org";
description = "domain name"; description = "domain name";
}; };
keycloakRealm = mkOption {
type = types.str;
default = "master";
description = "keycloak realm";
};
lanCidrV4 = mkOption { lanCidrV4 = mkOption {
type = types.str; type = types.str;
description = "LAN mask (IPv4)"; description = "LAN mask (IPv4)";

View file

@ -123,6 +123,8 @@ in {
{ directory = /var/lib/dovecot; user = "root"; group = "root"; mode = "0755"; } { directory = /var/lib/dovecot; user = "root"; group = "root"; mode = "0755"; }
] ++ lib.optionals config.security.sudo.enable [ ] ++ lib.optionals config.security.sudo.enable [
{ directory = /var/db/sudo/lectured; user = "root"; group = "root"; mode = "0700"; } { 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); ] ++ cfg.directories);
files = map (x: files = map (x:
if builtins.isPath x then toString x if builtins.isPath x then toString x