{ pkgs, flakeInputs, system, ... }: { imports = [ ./nginx.nix ]; services.nginx = { virtualHosts."home.queezle.net" = { listen = [ { addr = "10.0.0.1"; } { addr = "10.0.0.1"; port = 443; ssl = true; } ]; forceSSL = true; useACMEHost = "home.queezle.net"; # for qauth extraConfig = '' error_page 401 = @error401; ''; locations = { "= /" = { extraConfig = "default_type text/plain;"; return = ''307 /qapp/''; }; "/ip" = { extraConfig = "default_type text/plain;"; return = ''200 $remote_addr''; }; "/ip.json" = { extraConfig = "default_type application/json;"; return = ''200 "{\"ip\":\"$remote_addr\"}"''; }; "/qapp" = { return = ''301 /qapp/''; }; "/qapp/" = { alias = "/srv/qapp/"; index = "index.html"; #extraConfig = "auth_request /auth;"; }; "/tmp/" = { alias = "/srv/tmp/"; }; "/mqtt" = { proxyPass = "http://localhost:1884"; proxyWebsockets = true; extraConfig = '' proxy_read_timeout 5m; ''; #extraConfig = '' # auth_request /auth; #''; }; "@error401" = { # "303 See Other" instructs the client to do a temporary redirect but change # the request method to GET #return = "303 /login?go=$scheme://$http_host$request_uri"; return = "303 /login"; }; "= /auth" = { proxyPass = "http://unix:/run/qauth/http:/auth"; extraConfig = '' internal; proxy_pass_request_body off; proxy_set_header Content-Length ""; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Host $http_host; auth_request_set $qauth_user $upstream_http_x_user; ''; }; "/login" = { proxyPass = "http://unix:/run/qauth/http:"; extraConfig = '' proxy_http_version 1.1; proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; ''; }; "/logout" = { proxyPass = "http://unix:/run/qauth/http:/logout?go=/login"; extraConfig = '' proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; ''; }; "/qauth" = { proxyPass = "http://unix:/run/qauth/http:"; # this also sets "proxy_http_version 1.1;", so chunked transfer (used for noscript) works proxyWebsockets = true; extraConfig = '' proxy_set_header X-Original-URI $request_uri; proxy_set_header X-Real-IP $remote_addr; proxy_read_timeout 5m; ''; }; }; }; }; security.acme = { acceptTerms = true; email = "jens@nightmarestudio.de"; certs."home.queezle.net" = { dnsProvider = "hetzner"; # HACK ask hetzner nameservers directly because acme-lego doesn't follow ns records correctly dnsResolver = "helium.ns.hetzner.de"; credentialsFile = "/etc/secrets/dns/dns.hetzner.com_queezle.net"; group = "nginx"; }; }; systemd.services.qauth = { wantedBy = [ "multi-user.target" ]; after = [ "network.target" ]; serviceConfig = { ExecStart = "${flakeInputs.qauth.packages.${system}.qauth}/bin/qauth daemon"; Sockets = "qauth-http.socket qauth-control.socket"; DynamicUser = true; User = "qauth"; Group = "qauth"; ProtectSystem = "full"; ProtectHome = true; PrivateDevices = true; ProtectKernelTunables = true; ProtectControlGroups = true; ProtectKernelLogs = true; }; }; systemd.sockets.qauth-http = { socketConfig = { ListenStream = "/run/qauth/http"; FileDescriptorName = "http"; Service = "qauth.service"; SocketUser = "nginx"; SocketGroup = "wheel"; SocketMode = "0660"; }; }; systemd.sockets.qauth-control = { socketConfig = { ListenStream = "/run/qauth/control"; FileDescriptorName = "control"; Service = "qauth.service"; SocketGroup = "wheel"; SocketMode = "0660"; }; }; environment.systemPackages = [ flakeInputs.qauth.defaultPackage.${system} ]; }