blob: 88f8e9ae9bffd71c7aad4b04c4c573457decbb26 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
|
{ lib, pkgs, ... }:
{
services.dex = {
enable = true;
settings = {
issuer = "https://op.mou.fo/dex";
storage = {
# TODO persistence?
type = "memory";
};
web = {
# TODO port
http = "0.0.0.0:5556";
};
enablePasswordDB = true;
staticPasswords = [
{
email = "joe";
username = "joe";
hash = "$2y$10$Vp2MTFeHs6AYpNofOpY5YehFPhE/44VY7Z3TtdsHnBre/N64kM4Ii";
# userID = "b0c5bafa-fa25-4b20-a9aa-ab79f4d57d18";
userID = "joe";
}
];
staticClients = [
{
id = "288565372746006652@mou.fo";
name = "oauth2-proxy";
redirectURIs = [ "https://op.mou.fo/oauth2/callback" ];
# TODO consolidate w/ oauth2-proxy.env?
secretFile = "/var/secrets/oauth2-proxy.secret";
}
];
};
};
services.postgresql = {
ensureDatabases = [ "zitadel" ];
ensureUsers = [{
name = "zitadel";
ensureDBOwnership = true;
}];
};
# CVE-2024-41952 as of 24.05. Leaks existence of usernames.
nixpkgs.config.permittedInsecurePackages = [
"zitadel"
];
services.zitadel = {
enable = true;
settings = {
# We seem to be unable to bind Zitadel to only the loopback interface.
Port = 9068;
ExternalPort = 443;
ExternalDomain = "zd.mou.fo";
Database.postgres = {
Host = "127.0.0.1";
Port = 5432;
Database = "zitadel";
User.Username = "zitadel";
User.SSL.Mode = "disable";
};
};
masterKeyFile = "/run/credentials/zitadel.service/master.key";
# Zitadel only connects to Postgres over the network, so we need to
# configure passwords here and manually for the zitadel Postgres user.
extraSettingsPaths = [ "/run/credentials/zitadel.service/secrets.yaml" ];
};
systemd.services.zitadel = {
# Shim into PATH to avoid start-from-init which requires Postgres admin
# credentials. See https://github.com/zitadel/zitadel/issues/4304
path = let
wrapper = pkgs.writeShellScriptBin "zitadel"
''
shift
exec ${pkgs.zitadel}/bin/zitadel start-from-setup "$@"
'';
in lib.mkBefore [ wrapper ];
# Allow unprivileged zitadel user selective access to secrets.
serviceConfig.LoadCredential = [
"master.key:/var/secrets/zitadel.key"
"secrets.yaml:/var/secrets/zitadel.yaml"
];
};
services.nginx.virtualHosts."zd.mou.fo" = {
enableACME = true;
forceSSL = true;
locations."/".proxyPass = "http://127.0.0.1:9068";
};
# The oauth2-proxy module has a magic nginx.virtualHosts option that rewrites
# nginx configs. It can be heavy handed, but we use it for brevity. In
# particular, it configures Traefik-like ForwardAuth authentication with
# auth_request. Note if this resource is missing for whatever reason, the
# module magic will fail open (auth_request unset).
services.oauth2-proxy = {
enable = true;
cookie.domain = "mou.fo";
nginx.domain = "op.mou.fo";
setXauthrequest = true; # let oauth2-proxy nginx module pass X-User/X-Email
reverseProxy = true;
provider = "oidc";
clientID = "288565372746006652@mou.fo";
oidcIssuerUrl = "https://op.mou.fo/dex";
# Sets OAUTH2_PROXY_COOKIE_SECRET and OAUTH2_PROXY_CLIENT_SECRET.
keyFile = "/var/secrets/oauth2-proxy.env";
# Ignore e-mail address.
email.domains = [ "*" ];
extraConfig = {
code-challenge-method = "S256";
whitelist-domain = ".mou.fo"; # allowed redirects after authentication
};
};
# Kludge to bring up after Kanidm (otherwise OIDC discovery fails). A simple
# ordering dependency isn't enough because kandim.service is active before
# Kanidm responds to requests. Kanidm starts up quickly enough that boot up
# may work without this.
systemd.services.oauth2-proxy.serviceConfig.RestartSec = 5;
# It's somewhat overkill to assign oauth2-proxy its own domain. We can't use
# Kanidm's though, because it uses the /oauth2 path which the oauth2-proxy
# nginx module is hardcoded for (proxyPrefix is ignored); this module magic is
# also why we do not need to explicitly specify proxyPass.
services.nginx.virtualHosts."op.mou.fo" = {
enableACME = true;
forceSSL = true;
locations."/dex".proxyPass = "http://127.0.0.1:5556";
};
}
|