diff --git a/config/hosts/keycloak/configuration.nix b/config/hosts/keycloak/configuration.nix new file mode 100644 index 0000000..2a80a98 --- /dev/null +++ b/config/hosts/keycloak/configuration.nix @@ -0,0 +1,16 @@ +{ ... }: +{ + boot.loader.grub = { + enable = true; + device = "/dev/vda"; + }; + + networking = { + hostName = "keycloak"; + firewall = { + allowedTCPPorts = [ 80 443 8443 ]; + }; + }; + + system.stateVersion = "23.11"; +} diff --git a/config/hosts/keycloak/default.nix b/config/hosts/keycloak/default.nix new file mode 100644 index 0000000..6289ce6 --- /dev/null +++ b/config/hosts/keycloak/default.nix @@ -0,0 +1,8 @@ +{ ... }: +{ + imports = [ + ./configuration.nix + ./keycloak.nix + ./nginx.nix + ]; +} diff --git a/config/hosts/keycloak/keycloak.nix b/config/hosts/keycloak/keycloak.nix new file mode 100644 index 0000000..79e9a96 --- /dev/null +++ b/config/hosts/keycloak/keycloak.nix @@ -0,0 +1,15 @@ +{ ... }: +{ + services.keycloak = { + enable = true; + settings = { + hostname = "id.nekover.se"; + hostname-admin = "keycloak-admin.nekover.se"; + hostname-strict-backchannel = true; + proxy = "edge"; + http-host = "127.0.0.1"; + http-port = 8080; + }; + database.passwordFile = "/secrets/keycloak-database-password.secret"; + }; +} diff --git a/config/hosts/keycloak/nginx.nix b/config/hosts/keycloak/nginx.nix new file mode 100644 index 0000000..0c83ea0 --- /dev/null +++ b/config/hosts/keycloak/nginx.nix @@ -0,0 +1,109 @@ +{ ... }: +{ + services.nginx = { + enable = true; + virtualHosts = { + "id.nekover.se" = { + forceSSL = true; + enableACME = true; + locations = { + # Redirect a user opening any not set location on id.nekover.se to the account management page. + "^~ /" = { + return = "307 https://id.nekover.se/realms/nekoverse/account/"; + }; + "/js/" = { + proxyPass = "http://127.0.0.1:8080/js/"; + }; + "/realms/" = { + proxyPass = "http://127.0.0.1:8080/realms/"; + }; + "/resources/" = { + proxyPass = "http://127.0.0.1:8080/resources/"; + }; + "/robots.txt" = { + proxyPass = "http://127.0.0.1:8080/robots.txt"; + }; + }; + extraConfig = '' + listen 0.0.0.0:8443 http2 ssl proxy_protocol; + + set_real_ip_from 10.202.41.100; + real_ip_header proxy_protocol; + + add_header Strict-Transport-Security "max-age=63072000" always; + + # To not have 502s sometimes when logging through PVE use bigger buffer_sizes. + # The error seemed to occur after logging in and out and in. Maybe related + # to Keycloak logout settings, but probably not. + # See: + # https://stackoverflow.com/questions/56126864/why-do-i-get-502-when-trying-to-authenticate + # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size + proxy_buffer_size 128k; + proxy_buffers 8 128k; + + # Hide the X-Forwarded header. + proxy_hide_header X-Forwarded; + # Assume we are the only Reverse Proxy (well using Proxy Protocol, but that + # is transparent). + # Also provide "_hidden" for by, since it's not relevant. + proxy_set_header Forwarded "for=$remote_addr;proto=https;host=$host;by=_hidden"; + ''; + }; + "keycloak-admin.nekover.se" = { + forceSSL = true; + enableACME = true; + listen = [ + { + addr = "0.0.0.0"; + port = 80; + } + { + addr = "0.0.0.0"; + port = 443; + ssl = true; + } + ]; + locations = { + # Redirect a user opening any not set location on id.nekover.se to the account management page. + "^~ /" = { + return = "307 https://keycloak-admin.nekover.se/admin/master/console/"; + }; + "/js/" = { + proxyPass = "http://127.0.0.1:8080/js/"; + }; + "/realms/" = { + proxyPass = "http://127.0.0.1:8080/realms/"; + }; + "/resources/" = { + proxyPass = "http://127.0.0.1:8080/resources/"; + }; + "/robots.txt" = { + proxyPass = "http://127.0.0.1:8080/robots.txt"; + }; + "/admin/" = { + proxyPass = "http://127.0.0.1:8080/admin/"; + }; + }; + extraConfig = '' + add_header Strict-Transport-Security "max-age=63072000" always; + + # To not have 502s sometimes when logging through PVE use bigger buffer_sizes. + # The error seemed to occur after logging in and out and in. Maybe related + # to Keycloak logout settings, but probably not. + # See: + # https://stackoverflow.com/questions/56126864/why-do-i-get-502-when-trying-to-authenticate + # https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size + proxy_buffer_size 128k; + proxy_buffers 8 128k; + + # Hide the X-Forwarded header. + proxy_hide_header X-Forwarded; + # Assume we are the only Reverse Proxy (well using Proxy Protocol, but that + # is transparent). + # Also provide "_hidden" for by, since it's not relevant. + proxy_set_header Forwarded "for=$remote_addr;proto=https;host=$host;by=_hidden"; + ''; + }; + }; + }; +} diff --git a/config/hosts/keycloak/secrets.nix b/config/hosts/keycloak/secrets.nix new file mode 100644 index 0000000..984e9ad --- /dev/null +++ b/config/hosts/keycloak/secrets.nix @@ -0,0 +1,13 @@ +{ keyCommandEnv, ... }: +{ + deployment.keys = { + "keycloak-database-password.secret" = { + keyCommand = keyCommandEnv ++ [ "pass" "keycloak/database-password" ]; + destDir = "/secrets"; + user = "root"; + group = "systemd-network"; + permissions = "0640"; + uploadAt = "pre-activation"; + }; + }; +} diff --git a/config/hosts/mail-1/secrets.nix b/config/hosts/mail-1/secrets.nix index 3352cee..abf9863 100644 --- a/config/hosts/mail-1/secrets.nix +++ b/config/hosts/mail-1/secrets.nix @@ -81,5 +81,13 @@ permissions = "0640"; uploadAt = "pre-activation"; }; + "mail-id-nekover-se.secret" = { + keyCommand = keyCommandEnv ++ [ "pass" "mail/id-nekover-se" ]; + destDir = "/secrets"; + user = "root"; + group = "root"; + permissions = "0640"; + uploadAt = "pre-activation"; + }; }; } diff --git a/config/hosts/mail-1/simple-nixos-mailserver.nix b/config/hosts/mail-1/simple-nixos-mailserver.nix index 81fa130..61066e9 100644 --- a/config/hosts/mail-1/simple-nixos-mailserver.nix +++ b/config/hosts/mail-1/simple-nixos-mailserver.nix @@ -51,6 +51,11 @@ sendOnly = true; aliases = [ "nyareply@nekover.se" ]; }; + "id@nekover.se" = { + hashedPasswordFile = "/secrets/mail-id-nekover-se.secret"; + sendOnly = true; + aliases = [ "nyareply@nekover.se" ]; + }; }; certificateScheme = "acme-nginx"; }; diff --git a/config/hosts/web-public-2/nginx.nix b/config/hosts/web-public-2/nginx.nix index 907cdb8..dead4b7 100644 --- a/config/hosts/web-public-2/nginx.nix +++ b/config/hosts/web-public-2/nginx.nix @@ -23,6 +23,7 @@ gameserver.grzb.de 127.0.0.1:8443; git.grzb.de 127.0.0.1:8443; hydra.nekover.se 10.202.41.121:8443; + id.nekover.se 10.202.41.124:8443; matrix.nekover.se 10.202.41.112:8443; mewtube.nekover.se 127.0.0.1:8443; nekover.se 127.0.0.1:8443; diff --git a/config/hosts/web-public-2/virtualHosts/acme-challenge.nix b/config/hosts/web-public-2/virtualHosts/acme-challenge.nix index 9350a30..d910998 100644 --- a/config/hosts/web-public-2/virtualHosts/acme-challenge.nix +++ b/config/hosts/web-public-2/virtualHosts/acme-challenge.nix @@ -8,6 +8,7 @@ let "grafana.grzb.de" = "metrics.vs.grzb.de"; "jackett.grzb.de" = "torrent.vs.grzb.de"; "jellyseerr.grzb.de" = "jellyseerr.vs.grzb.de"; + "keycloak-admin.nekover.se" = "keycloak.vs.grzb.de"; "radarr.grzb.de" = "torrent.vs.grzb.de"; "searx.nekover.se" = "searx.vs.grzb.de"; "social.nekover.se" = "mastodon.vs.grzb.de"; diff --git a/hosts.nix b/hosts.nix index 72e0f2b..4dde06c 100644 --- a/hosts.nix +++ b/hosts.nix @@ -45,6 +45,10 @@ in site = "vs"; environment = "proxmox"; }; + keycloak = { + site = "vs"; + environment = "proxmox"; + }; lifeline = { site = "io"; };