From d64087e1605a7e20b9e42d058d30fd432ee921a6 Mon Sep 17 00:00:00 2001 From: kat witch Date: Sat, 4 Sep 2021 22:57:01 +0100 Subject: [PATCH] services/{keycloak,glauth}: init --- config/hosts/daiyousei/nixos.nix | 3 + config/hosts/rinnosuke/nixos.nix | 2 + config/modules/nixos/glauth.nix | 176 ++++++++++++++++++++++++++ config/services/glauth/default.nix | 56 ++++++++ config/services/keycloak/default.nix | 42 ++++++ config/services/mail/default.nix | 50 ++++---- config/users/kat/personal/weechat.nix | 3 +- nix/sources.json | 6 +- overlays/exprs | 2 +- 9 files changed, 311 insertions(+), 29 deletions(-) create mode 100644 config/modules/nixos/glauth.nix create mode 100644 config/services/glauth/default.nix create mode 100644 config/services/keycloak/default.nix diff --git a/config/hosts/daiyousei/nixos.nix b/config/hosts/daiyousei/nixos.nix index d67dc79b..a61bbd9e 100644 --- a/config/hosts/daiyousei/nixos.nix +++ b/config/hosts/daiyousei/nixos.nix @@ -3,6 +3,7 @@ profiles.hardware.aarch64 profiles.hardware.oracle.ubuntu services.nginx + services.keycloak ]; kw.oci = { @@ -27,4 +28,6 @@ networkFilter = [ "public" ]; block.locations."/" = { root = splashy; }; }; + + system.stateVersion = "21.11"; } diff --git a/config/hosts/rinnosuke/nixos.nix b/config/hosts/rinnosuke/nixos.nix index 5edd66cc..4e43eff0 100644 --- a/config/hosts/rinnosuke/nixos.nix +++ b/config/hosts/rinnosuke/nixos.nix @@ -27,4 +27,6 @@ networkFilter = [ "public" ]; block.locations."/" = { root = splashy; }; }; + + system.stateVersion = "21.11"; } diff --git a/config/modules/nixos/glauth.nix b/config/modules/nixos/glauth.nix new file mode 100644 index 00000000..ac5a9f5e --- /dev/null +++ b/config/modules/nixos/glauth.nix @@ -0,0 +1,176 @@ +{ config, pkgs, lib, ... }: with lib; let + cfg = options.services.glauth; + dbcfg = options.services.glauth.database; +in +{ + options.services.glauth = { + enable = mkEnableOption "GLAuth"; + package = mkOption { + type = types.package; + default = pkgs.glauth; + }; + outTOML = { + description = "The TOML produced from cfg.settings"; + type = type.str; + default = toTOML cfg.settings; + }; + configFile = { + description = "The config path that GLAuth uses"; + type = types.path; + default = pkgs.writeText "glauth-config" outTOML; + }; + database = { + enable = mkEnableOption "use a database"; + local = mkEnableOption "local database creation"; + type = mkOption { + type = types.enum [ + "postgres" + "mysql" + "sqlite" + ]; + default = "postgres"; + }; + host = mkOption { + type = types.str; + default = "localhost"; + }; + port = mkOption { + type = types.port; + default = 5432; + }; + username = mkOption { + type = types.str; + default = "glauth"; + }; + passwordFile = mkOption { + type = types.nullOr types.path; + default = null; + }; + ssl = mkEnableOption "use ssl for the database connection"; + }; + settings = mkOption { + type = json.types.attrs; + default = mkIf cfg.database.enable { + backend = + let + pluginHandlers = { + "mysql" = "NewMySQLHandler"; + "postgres" = "NewPostgresHandler"; + "sqlite" = "NewSQLiteHandler"; + }; + in + { + datastore = "plugin"; + plugin = "bin/${cfg.database.type}.so"; + pluginhandler = pluginHandlers.${dbcfg.type}; + database = builtins.replaceStrings (singleton "\n") (singleton " ") '' + host=${dbcfg.host} + port=${dbcfg.port} + dbname=glauth + username=${dbcfg.username} + password=@db-password@ + sslmode=${if dbcfg.ssl then "enable" else "disable"} + ''; + }; + }; + }; + }; + config = + let + localCheck = dbcfg.local && dbcfg.host != "localhost"; + postgresCheck = localCheck && dbcfg.type == "postgres"; + mysqlCheck = localCheck && dbcfg.type == "mysql"; + in + mkIf cfg.enable { + systemd.services.glauthPostgreSQLInit = lib.mkIf postgresCheck { + after = [ "postgresql.service" ]; + before = [ "glauth.service" ]; + bindsTo = [ "postgresql.service" ]; + path = [ config.services.postgresql.package ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = "postgres"; + Group = "postgres"; + }; + script = '' + set -o errexit -o pipefail -o nounset -o errtrace + shopt -s inherit_errexit + create_role="$(mktemp)" + trap 'rm -f "$create_role"' ERR EXIT + echo "CREATE ROLE glauth WITH LOGIN PASSWORD '$(<'${dbcfg.passwordFile}')' CREATEDB" > "$create_role" + psql -tAc "SELECT 1 FROM pg_roles WHERE rolname='glauth'" | grep -q 1 || psql -tA --file="$create_role" + psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'glauth'" | grep -q 1 || psql -tAc 'CREATE DATABASE "glauth" OWNER "glauth"' + ''; + }; + + systemd.services.glauthMySQLInit = lib.mkIf mysqlCheck { + after = [ "mysql.service" ]; + before = [ "glauth.service" ]; + bindsTo = [ "mysql.service" ]; + path = [ config.services.mysql.package ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + User = config.services.mysql.user; + Group = config.services.mysql.group; + }; + script = '' + set -o errexit -o pipefail -o nounset -o errtrace + shopt -s inherit_errexit + db_password="$(<'${dbcfg.passwordFile}')" + ( echo "CREATE USER IF NOT EXISTS 'glauth'@'localhost' IDENTIFIED BY '$db_password';" + echo "CREATE DATABASE glauth CHARACTER SET utf8 COLLATE utf8_unicode_ci;" + echo "GRANT ALL PRIVILEGES ON glauth.* TO 'glauth'@'localhost';" + ) | mysql -N + ''; + }; + + users.groups.glauth = { }; + users.users.glauth = { + isSystemUser = true; + extraGroups = singleton "glauth"; + }; + + systemd.services.glauth = + let + databaseServices = attrByPath [ dbcfg.type ] [ ] { + "mysql" = [ "glauthMySQLInit.service" "mysql.service" ]; + "postgres" = [ "glauthPostgreSQLInit.service" "postgresql.service" ]; + }; + in { + after = databaseServices; + bindsTo = databaseServices; + wantedBy = singleton "multi-user.target"; + path = [ + cfg.package + replace-secret + ]; + serviceConfig = { + ExecStartPre = + let + startPreFullPrivileges = '' + set -o errexit -o pipefail -o nounset -o errtrace + shopt -s inherit_errexit + umask u=rwx,g=,o= + install -T -m 0400 -o glauth -g glauth '${dbcfg.passwordFile}' /run/glauth/secrets/db_password + ''; + startPre = '' + install -T -m 0600 ${cfg.configFile} /run/glauth/config.cfg + replace-secret '@db-password@' /run/glauth/config.cfg + ''; + in + [ + "+${pkgs.writeShellScript "glauth-start-pre-full-privileges" startPreFullPrivileges}" + "${pkgs.writeShellScript "glauth-start-pre" startPre}" + ]; + ExecStart = "${cfg.package}/bin/glauth -c /run/glauth/config.cfg"; + User = "glauth"; + Group = "glauth"; + RuntimeDirectory = "glauth"; + LogsDirectory = "glauth"; + AmbientCapabilities = "CAP_NET_BIND_SERVICE"; + }; + }; + }; +} diff --git a/config/services/glauth/default.nix b/config/services/glauth/default.nix new file mode 100644 index 00000000..bb0cc571 --- /dev/null +++ b/config/services/glauth/default.nix @@ -0,0 +1,56 @@ +{ config, tf, lib, ... }: with lib; { + services.glauth = { + enable = true; + configFile = config.secrets.files.glauth-config-file.path; + database = { + enable = true; + type = "postgres"; + passwordFile = config.secrets.files.glauth-password-file.path; + }; + settings = { + syslog = true; + ldap = { + enable = false; + listen = "0.0.0.0:3893"; + }; + ldaps = { + enabled = true; + listen = "0.0.0.0:3894"; + cert = "/var/lib/acme/auth.kittywit.ch/fullchain.pem"; + key = "/var/lib/acme/auth.kittywit.ch/key.pem"; + }; + backend = { + baseDN = "dc=kittywitch,dc=com"; + }; + users = [{ + name = "kat"; + passsha256 = tf.variables.glauth-password.ref; + uidnumber = 1000; + primarygroup = 1500; + }]; + groups = [{ + name = "admins"; + gidnumber = 1500; + }]; + }; + }; + + kw.secrets.variables = mapListToAttrs (field: + nameValuePair = "glauth-${field}" { + path = "services/glauth"; + inherit field; + }) ["password-hash" "postgres"]; + + secrets.files = { + glauth-postgres-file = { + text = "${tf.variables.glauth-postgres.ref}"; + owner = "glauth"; + group = "glauth"; + }; + glauth-config-file = { + text = services.glauth.outTOML; + owner = "glauth"; + group = "glauth"; + }; + }; +}; diff --git a/config/services/keycloak/default.nix b/config/services/keycloak/default.nix new file mode 100644 index 00000000..d1e59f3b --- /dev/null +++ b/config/services/keycloak/default.nix @@ -0,0 +1,42 @@ +{ config, lib, tf, ... }: with lib; { + services.keycloak = { + enable = true; + bindAddress = "127.0.0.1"; + httpPort = "8089"; + httpsPort = "8445"; + initialAdminPassword = "mewpymewlymewlies"; + forceBackendUrlToFrontendUrl = true; + frontendUrl = "https://auth.${config.network.dns.domain}/auth"; + database.passwordFile = config.secrets.files.keycloak-postgres-file.path; + }; + + users.groups.keycloak = { }; + users.users.postgres.extraGroups = singleton "keycloak"; + users.users.keycloak = { + isSystemUser = true; + extraGroups = singleton "keycloak"; + }; + + kw.secrets.variables.keycloak-postgres = { + path = "services/keycloak"; + field = "postgres"; + }; + + secrets.files.keycloak-postgres-file = { + text = "${tf.variables.keycloak-postgres.ref}"; + owner = "postgres"; + group = "keycloak"; + }; + + services.nginx.virtualHosts."auth.${config.network.dns.domain}" = { + enableACME = true; + forceSSL = true; + locations = { "/".proxyPass = "http://127.0.0.1:8089"; }; + }; + + deploy.tf.dns.records.services_keycloak = { + inherit (config.network.dns) zone; + domain = "auth"; + cname = { inherit (config.network.addresses.public) target; }; + }; +} diff --git a/config/services/mail/default.nix b/config/services/mail/default.nix index c9db6192..51c86a8a 100644 --- a/config/services/mail/default.nix +++ b/config/services/mail/default.nix @@ -4,6 +4,7 @@ with lib; let domains = [ "kittywitch" "dork" ]; + users = [ "gitea" "kat" "keycloak" ]; in { imports = [ sources.nixos-mailserver.outPath ]; @@ -13,7 +14,8 @@ in nameValuePair "mail-${field}-hash" { path = "secrets/mail-kittywitch"; field = "${field}-hash"; - }) [ "gitea" "kat" ] + }) + users ++ map (domain: nameValuePair "mail-domainkey-${domain}" { @@ -22,7 +24,7 @@ in }) domains); - deploy.tf.dns.records = lib.mkMerge (map + deploy.tf.dns.records = mkMerge (map (domain: let zoneGet = domain: if domain == "dork" then "dork.dev." else config.network.dns.zone; @@ -55,18 +57,14 @@ in }) domains); - secrets.files = { - mail-kat-hash = { - text = '' - ${tf.variables.mail-kat-hash.ref} - ''; - }; - mail-gitea-hash = { - text = '' - ${tf.variables.mail-gitea-hash.ref} - ''; - }; - }; + secrets.files = listToAttrs (map + (user: + nameValuePair "mail-${user}-hash" { + text = '' + ${tf.variables.mail-kat-hash.ref} + ''; + }) + users); mailserver = { enable = true; @@ -85,15 +83,19 @@ in virusScanning = false; # nix run nixpkgs.apacheHttpd -c htpasswd -nbB "" "super secret password" | cut -d: -f2 - loginAccounts = { - "kat@kittywit.ch" = { - hashedPasswordFile = config.secrets.files.mail-kat-hash.path; - aliases = [ "postmaster@kittywit.ch" ]; - catchAll = [ "kittywit.ch" "dork.dev" ]; - }; - "gitea@kittywit.ch" = { - hashedPasswordFile = config.secrets.files.mail-gitea-hash.path; - }; - }; + loginAccounts = mkMerge [ + (listToAttrs (map + (user: + nameValuePair "${user}@kittywit.ch" { + hashedPasswordFile = config.secrets.files."mail-${user}-hash".path; + }) + users)) + { + "kat@kittywit.ch" = { + aliases = [ "postmaster@kittywit.ch" ]; + catchAll = [ "kittywit.ch" "dork.dev" ]; + }; + } + ]; }; } diff --git a/config/users/kat/personal/weechat.nix b/config/users/kat/personal/weechat.nix index 9128cf6a..0cd63f80 100644 --- a/config/users/kat/personal/weechat.nix +++ b/config/users/kat/personal/weechat.nix @@ -3,7 +3,8 @@ home.file = lib.mkIf config.deploy.profile.trusted ( let bitw = pkgs.writeShellScriptBin "bitw" ''${pkgs.rbw-bitw}/bin/bitw -p gpg://${config.kw.secrets.repo.bitw.source} "$@"''; - in { + in + { ".local/share/weechat/sec.conf".text = '' # # weechat -- sec.conf diff --git a/nix/sources.json b/nix/sources.json index 26d585ab..978c262d 100644 --- a/nix/sources.json +++ b/nix/sources.json @@ -89,10 +89,10 @@ "homepage": null, "owner": "kittywitch", "repo": "nixexprs", - "rev": "05050726c147903a257c03bc454250cf0cb6b997", - "sha256": "0fk4fyxvc4kivd5g6nnxrrwll51innx1dlx7wq7mvaarlm9vj5h0", + "rev": "ee427185906d11bb33b10fa9215d65f9cc8cfc37", + "sha256": "13b910rhv8fhf0ls1ajnvz2nc9dvkphxf1hyqbf13c448rvn8ds3", "type": "tarball", - "url": "https://github.com/kittywitch/nixexprs/archive/05050726c147903a257c03bc454250cf0cb6b997.tar.gz", + "url": "https://github.com/kittywitch/nixexprs/archive/ee427185906d11bb33b10fa9215d65f9cc8cfc37.tar.gz", "url_template": "https://github.com///archive/.tar.gz" }, "niv": { diff --git a/overlays/exprs b/overlays/exprs index 35f5ebb5..ee427185 160000 --- a/overlays/exprs +++ b/overlays/exprs @@ -1 +1 @@ -Subproject commit 35f5ebb5b8aa58c12d9b6d55a3c45730e15192a9 +Subproject commit ee427185906d11bb33b10fa9215d65f9cc8cfc37