yep, more dotfiles

server: cleanup and remove gerrit

There is still a lot of oidc issues to fix

wiro.world d0779e27 93b459a2

verified
+140 -119
+9 -13
home-manager/fragments/epita.nix
··· 27 27 { 28 28 options.local.fragment.epita.enable = lib.mkEnableOption '' 29 29 EPITA related 30 - 31 - Depends on: 32 - - `ssh` program: Mount AFS script needs SSH 33 30 ''; 34 31 35 32 config = lib.mkIf cfg.enable { 36 - assertions = [ 37 - { assertion = config.programs.ssh.enable; message = "`epita` fragment depends on `ssh` program"; } 38 - ]; 33 + programs.ssh = { 34 + package = pkgs.openssh_gssapi; 39 35 40 - programs.ssh.package = pkgs.openssh_gssapi; 41 - 42 - # Needed for sshfs 43 - programs.ssh.matchBlocks."ssh.cri.epita.fr" = { 44 - extraOptions = { 45 - GSSAPIAuthentication = "yes"; 46 - GSSAPIDelegateCredentials = "yes"; 36 + # Needed for sshfs 37 + enable = true; 38 + matchBlocks."ssh.cri.epita.fr" = { 39 + extraOptions = { 40 + GSSAPIAuthentication = "yes"; 41 + GSSAPIDelegateCredentials = "yes"; 42 + }; 47 43 }; 48 44 }; 49 45
-13
home-manager/profiles/desktop.nix
··· 128 128 129 129 programs.broot.enable = true; 130 130 131 - # TODO: move out 132 - programs.ssh = { 133 - enable = true; 134 - 135 - matchBlocks."weird-row-server" = { 136 - hostname = "weird-row.portal.wiro.world"; 137 - # TODO: reduce automated load on ssh port by changing to a random port 138 - # port = "" 139 - }; 140 - }; 141 - 142 - stylix.targets.qt.enable = false; 143 - 144 131 programs.go = { 145 132 enable = true; 146 133 goPath = ".local/share/go";
+118 -92
nixos/profiles/server.nix
··· 21 21 pds-port = 3001; 22 22 pds-hostname = "pds.wiro.world"; 23 23 24 + grafana-port = 3002; 25 + grafana-hostname = "console.wiro.world"; 26 + 24 27 tangled-owner = "did:plc:xhgrjm4mcx3p5h3y6eino6ti"; 25 - tangled-knot-port = 3002; 28 + tangled-knot-port = 3003; 26 29 tangled-knot-hostname = "knot.wiro.world"; 27 - tangled-spindle-port = 3003; 30 + tangled-spindle-port = 3004; 28 31 tangled-spindle-hostname = "spindle.wiro.world"; 29 32 30 - thelounge-port = 3004; 33 + thelounge-port = 3005; 31 34 thelounge-hostname = "lounge.wiro.world"; 32 35 33 - headscale-port = 3005; 36 + headscale-port = 3006; 34 37 headscale-hostname = "headscale.wiro.world"; 35 38 36 - lldap-port = 3006; 39 + lldap-port = 3007; 37 40 lldap-hostname = "ldap.wiro.world"; 38 41 39 - authelia-port = 3007; 42 + authelia-port = 3008; 40 43 authelia-hostname = "auth.wiro.world"; 41 44 42 - gerrit-port = 3008; 43 - gerrit-hostname = "gerrit.wiro.world"; 44 - 45 - grafana-port = 9000; 46 - grafana-hostname = "console.wiro.world"; 47 45 prometheus-port = 9001; 48 46 prometheus-node-exporter-port = 9002; 47 + headscale-metrics-port = 9003; 49 48 in 50 49 { 51 50 imports = [ ··· 76 75 defaultGateway = { interface = ext-if; address = external-gw; }; 77 76 defaultGateway6 = { interface = ext-if; address = external-gw6; }; 78 77 79 - # TODO: rely on Hetzner firewall instead? 80 - # firewall.enable = false; 78 + # Reflect firewall configuration on Hetzner 81 79 firewall.allowedTCPPorts = [ 22 80 443 ]; 82 80 }; 83 81 82 + services.qemuGuest.enable = true; 83 + 84 84 services.openssh.enable = true; 85 85 86 - services.qemuGuest.enable = true; 86 + services.tailscale.enable = true; 87 + 88 + security.sudo.wheelNeedsPassword = false; 89 + 90 + local.fragment.nix.enable = true; 91 + 92 + programs.fish.enable = true; 87 93 88 94 services.fail2ban = { 89 95 enable = true; ··· 100 106 }; 101 107 102 108 jails = { }; 103 - }; 104 - 105 - services.tailscale.enable = true; 106 - 107 - age.secrets.pds-env.file = ../../secrets/pds-env.age; 108 - services.pds = { 109 - enable = true; 110 - package = upkgs.bluesky-pds; 111 - 112 - settings = { 113 - PDS_HOSTNAME = "pds.wiro.world"; 114 - PDS_PORT = pds-port; 115 - # is in systemd /tmp subfolder 116 - LOG_DESTINATION = "/tmp/pds.log"; 117 - }; 118 - 119 - environmentFiles = [ 120 - config.age.secrets.pds-env.path 121 - ]; 122 109 }; 123 110 124 111 services.caddy = { 125 112 enable = true; 126 - package = upkgs.caddy.withPlugins { 127 - plugins = [ "github.com/tailscale/caddy-tailscale@v0.0.0-20251016213337-01d084e119cb" ]; 128 - hash = "sha256-gDNYWwlQQ0Hbg1/TCf421NYcY3LnYWW248RzyGR2f28="; 129 - }; 130 113 131 114 globalConfig = '' 132 115 metrics { per_host } ··· 143 126 # reverse_proxy http://localhost:${toString website-port} 144 127 # ''; 145 128 146 - # Grafana has its own auth 147 129 virtualHosts.${grafana-hostname}.extraConfig = '' 148 130 reverse_proxy http://localhost:${toString grafana-port} 149 131 ''; ··· 179 161 virtualHosts.${authelia-hostname}.extraConfig = '' 180 162 reverse_proxy http://localhost:${toString authelia-port} 181 163 ''; 182 - 183 - virtualHosts.${gerrit-hostname}.extraConfig = '' 184 - reverse_proxy http://localhost:${toString gerrit-port} 185 - ''; 186 164 }; 187 165 188 - security.sudo.wheelNeedsPassword = false; 166 + age.secrets.pds-env.file = ../../secrets/pds-env.age; 167 + services.pds = { 168 + enable = true; 169 + package = upkgs.bluesky-pds; 189 170 190 - local.fragment.nix.enable = true; 171 + settings = { 172 + PDS_HOSTNAME = "pds.wiro.world"; 173 + PDS_PORT = pds-port; 174 + # is in systemd /tmp subfolder 175 + LOG_DESTINATION = "/tmp/pds.log"; 176 + }; 191 177 192 - programs.fish.enable = true; 178 + environmentFiles = [ 179 + config.age.secrets.pds-env.path 180 + ]; 181 + }; 193 182 194 183 services.tangled-knot = { 195 184 enable = true; ··· 203 192 }; 204 193 }; 205 194 206 - 207 195 services.tangled-spindle = { 208 196 enable = true; 209 197 ··· 214 202 }; 215 203 }; 216 204 205 + age.secrets.grafana-oidc-secret = { file = ../../secrets/grafana-oidc-secret.age; owner = "grafana"; }; 217 206 services.grafana = { 218 207 enable = true; 219 208 220 - settings.server = { 221 - http_port = grafana-port; 222 - domain = grafana-hostname; 209 + settings = { 210 + server = { 211 + http_port = grafana-port; 212 + domain = grafana-hostname; 213 + }; 214 + 215 + "auth.generic_auth" = { 216 + enable = true; 217 + name = "Authelia"; 218 + icon = "signin"; 219 + 220 + client_id = "grafana"; 221 + client_secret_path = config.age.secrets.grafana-oidc-secret.path; 222 + 223 + scopes = [ "openid" "profile" "email" "groups" ]; 224 + auth_url = "https://auth.wiro.world/api/oidc/authorization"; 225 + token_url = "https://auth.wiro.world/api/oidc/token"; 226 + api_url = "https://auth.wiro.world/api/oidc/userinfo"; 227 + login_attribute_path = "preferred_username"; 228 + groups_attribute_path = "groups"; 229 + name_attribute_path = "name"; 230 + use_pkce = true; 231 + }; 223 232 }; 224 233 }; 225 234 ··· 248 257 enable = true; 249 258 port = thelounge-port; 250 259 public = false; 260 + 251 261 extraConfig = { 252 262 host = "127.0.0.1"; 253 263 reverseProxy = true; 264 + 265 + # TODO: use ldap, find a way to hide password 254 266 }; 255 267 }; 256 268 269 + age.secrets.headscale-oidc-secret = { file = ../../secrets/headscale-oidc-secret.age; owner = config.services.headscale.user; }; 257 270 services.headscale = { 258 271 enable = true; 259 272 260 273 port = headscale-port; 261 274 settings = { 262 - server_url = "https://${headscale-hostname}:443"; 263 - # metrics_listen_addr = "127.0.0.1:${headscale-port-metrics}"; 275 + server_url = "https://${headscale-hostname}"; 276 + metrics_listen_addr = "127.0.0.1:${toString headscale-metrics-port}"; 264 277 265 278 # disable TLS 266 279 tls_cert_path = null; ··· 268 281 269 282 dns = { 270 283 magic_dns = true; 271 - # TODO: headnet? portal? keep short? 272 - base_domain = "p.wiro.world"; 284 + base_domain = "net.wiro.world"; 273 285 }; 274 286 275 - oidc = { }; 287 + oidc = { 288 + issuer = "https://auth.wiro.world"; 289 + client_id = "headscale"; 290 + client_secret_path = config.age.secrets.headscale-oidc-secret.path; 291 + pkce.enable = true; 292 + }; 276 293 }; 277 294 }; 278 295 ··· 288 305 environmentFile = config.age.secrets.lldap-env.path; 289 306 }; 290 307 291 - age.secrets.authelia-jwt-secret.file = ../../secrets/authelia-jwt-secret.age; 292 - age.secrets.authelia-jwt-secret.owner = config.services.authelia.instances.main.user; 293 - age.secrets.authelia-storage-enc-key.file = ../../secrets/authelia-storage-enc-key.age; 294 - age.secrets.authelia-storage-enc-key.owner = config.services.authelia.instances.main.user; 295 - age.secrets.authelia-ldap-password.file = ../../secrets/authelia-ldap-password.age; 296 - age.secrets.authelia-ldap-password.owner = config.services.authelia.instances.main.user; 297 - age.secrets.authelia-smtp-password.file = ../../secrets/authelia-smtp-password.age; 298 - age.secrets.authelia-smtp-password.owner = config.services.authelia.instances.main.user; 308 + age.secrets.authelia-jwt-secret = { file = ../../secrets/authelia-jwt-secret.age; owner = config.services.authelia.instances.main.user; }; 309 + age.secrets.authelia-issuer-private-key = { file = ../../secrets/authelia-issuer-private-key.age; owner = config.services.authelia.instances.main.user; }; 310 + age.secrets.authelia-storage-key = { file = ../../secrets/authelia-storage-key.age; owner = config.services.authelia.instances.main.user; }; 311 + age.secrets.authelia-ldap-password = { file = ../../secrets/authelia-ldap-password.age; owner = config.services.authelia.instances.main.user; }; 312 + age.secrets.authelia-smtp-password = { file = ../../secrets/authelia-smtp-password.age; owner = config.services.authelia.instances.main.user; }; 299 313 services.authelia.instances.main = { 300 314 enable = true; 301 315 302 316 secrets = { 303 317 jwtSecretFile = config.age.secrets.authelia-jwt-secret.path; 304 - # oidcHmacSecretFile = config.age.secrets.authelia-oidc-hmac-secret.path; 305 - # oidcIssuerPrivateKeyFile = config.age.secrets.authelia-oidc-issuer-pkey.path; 306 - # sessionSecretFile = config.age.secrets.authelia-session-secret.path; 307 - storageEncryptionKeyFile = config.age.secrets.authelia-storage-enc-key.path; 318 + oidcIssuerPrivateKeyFile = config.age.secrets.authelia-issuer-private-key.path; 319 + storageEncryptionKeyFile = config.age.secrets.authelia-storage-key.path; 308 320 }; 309 321 environmentVariables = { 310 322 AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.age.secrets.authelia-ldap-password.path; ··· 312 324 }; 313 325 settings = { 314 326 server.address = "localhost:${toString authelia-port}"; 315 - 316 327 storage.local.path = "/var/lib/authelia-main/db.sqlite3"; 317 328 318 329 session = { ··· 323 334 }]; 324 335 }; 325 336 326 - authentication_backend = { 327 - ldap = { 328 - address = "ldap://localhost:3890"; 329 - timeout = "5m"; # replace with systemd dependency 337 + authentication_backend.ldap = { 338 + address = "ldap://localhost:3890"; 339 + timeout = "5m"; # replace with systemd dependency 340 + 341 + user = "uid=authelia,ou=people,dc=wiro,dc=world"; 342 + # Set in `AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE`. 343 + # password = ""; 330 344 331 - base_dn = "dc=wiro,dc=world"; 332 - users_filter = "(&({username_attribute}={input})(objectClass=person))"; 333 - groups_filter = "(&(member={dn})(objectClass=groupOfNames))"; 345 + base_dn = "dc=wiro,dc=world"; 346 + users_filter = "(&({username_attribute}={input})(objectClass=person))"; 347 + groups_filter = "(&(member={dn})(objectClass=groupOfNames))"; 334 348 335 - user = "uid=authelia,ou=people,dc=wiro,dc=world"; 336 - # Set in `AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE`. 337 - # password = ""; 338 - }; 349 + # attributes = { 350 + # # username = "user_id"; 351 + # username = "uid"; 352 + # display_name = "display_name"; 353 + # mail = "mail"; 354 + # group_name = "cn"; 355 + # }; 339 356 }; 357 + 340 358 access_control = { 341 359 default_policy = "deny"; 342 360 rules = [ ··· 347 365 ]; 348 366 }; 349 367 368 + 369 + identity_providers.oidc = { 370 + # enforce_pkce = "always"; 371 + clients = [ 372 + { 373 + client_name = "Headscale"; 374 + client_id = "headscale"; 375 + client_secret = "$pbkdf2-sha256$310000$XY680D9gkSoWhD0UtYHNFg$ptWB3exOYCga6uq1N.oimuV3ILjK3F8lBWBpsBpibos"; 376 + 377 + redirect_uris = [ "https://headscale.wiro.world/oidc/callback" ]; 378 + } 379 + { 380 + client_name = "Grafana Console"; 381 + client_id = "grafana"; 382 + client_secret = "$pbkdf2-sha256$310000$UkwrqxTZodGMs9.Ca2cXAA$HCWFgQbFHGXZpuz.I3HHdkTZLUevRVGlhKEFaOlPmKs"; 383 + 384 + redirect_uris = [ "https://console.wiro.world/login/generic_oauth" ]; 385 + } 386 + ]; 387 + }; 388 + 389 + 350 390 notifier.smtp = { 351 391 address = "smtp://smtp.resend.com:2587"; 352 392 username = "resend"; ··· 354 394 # password = ""; 355 395 sender = "authelia@wiro.world"; 356 396 }; 357 - }; 358 - }; 359 - 360 - services.gerrit = { 361 - enable = true; 362 - 363 - listenAddress = "[::]:${toString gerrit-port}"; 364 - serverId = "d0b2cbe5-2f32-49af-8609-8be73e4bbbab"; 365 - 366 - settings = { 367 - gerrit.canonicalWebUrl = "https://gerrit.wiro.world/"; 368 - httpd.listenUrl = "proxy-https://[::]:${toString gerrit-port}"; 369 - 370 - auth.type = "OpenID"; 371 397 }; 372 398 }; 373 399 };
secrets/authelia-issuer-private-key.age

This is a binary file and will not be displayed.

secrets/authelia-storage-enc-key.age secrets/authelia-storage-key.age
+9
secrets/grafana-oidc-secret.age
··· 1 + age-encryption.org/v1 2 + -> ssh-ed25519 sMF1bg 2+JZ3WMnTgnnNYmJqdqAtOsEIk9pAefHfwLcXZQpqlg 3 + yE0R9b0mSzoT6mvoWUG829UmkgGkm6vg0i7WLORaTis 4 + -> ssh-ed25519 SmMcWg c8goAmCIPQ5rsTwoOej9ndGc0uBpWILSn/wy6XJHK14 5 + ArjlEl4hxi4N6Py1emxgxUFKvSXIwLWsy6HrWNqJUHw 6 + -> ssh-ed25519 Q8rMFA t72V+A0n5Tnb0VqvBrzt3j75CbcfvQltodKMhF64SXY 7 + V+Ynzd4tIUI8JPy9uyoi+frW6wJnQxDavHAqnp/lem8 8 + --- mzRky/dA1MDArnDSSaGyZP9yAQgD2va4MfopbrdM0iU 9 + ��*�٪l����a5�QE£ uަ��"�;��3�l.!` �u� _+)$��d ��ˤ����ff�F��mѳc�a�EV��Nߧ��,�@����
secrets/headscale-oidc-secret.age

This is a binary file and will not be displayed.

+4 -1
secrets/secrets.nix
··· 21 21 "pds-env.age".publicKeys = deploy; 22 22 # Defines `LLDAP_JWT_SECRET`, `LLDAP_KEY_SEED`. 23 23 "lldap-env.age".publicKeys = deploy; 24 + "headscale-oidc-secret.age".publicKeys = deploy; 25 + "grafana-oidc-secret.age".publicKeys = deploy; 24 26 "authelia-jwt-secret.age".publicKeys = deploy; 25 - "authelia-storage-enc-key.age".publicKeys = deploy; 27 + "authelia-issuer-private-key.age".publicKeys = deploy; 28 + "authelia-storage-key.age".publicKeys = deploy; 26 29 "authelia-ldap-password.age".publicKeys = deploy; 27 30 "authelia-smtp-password.age".publicKeys = deploy; 28 31