{ lib, pkgs, config, inputs, ... }: let matrixLocations = { "~ ^/\\.well-known/matrix/client$" = { extraConfig = '' add_header Access-Control-Allow-Origin *; add_header Content-Type application/json; return 200 '{"m.homeserver": { "base_url": "https://matrix.kylekrein.com" }, "org.matrix.msc3575.proxy": { "url": "https://matrix.kylekrein.com"}}'; ''; }; "~ ^/\\.well-known/matrix/server$" = { extraConfig = '' add_header Content-Type application/json; return 200 '{"m.server": "matrix.kylekrein.com:443"}'; ''; }; "/" = { proxyPass = "http://127.0.0.1:6167"; }; }; in { services.nginx = { enable = true; recommendedProxySettings = true; recommendedTlsSettings = true; recommendedGzipSettings = true; virtualHosts = { "kylekrein.com" = { enableACME = true; forceSSL = true; locations = config.services.nginx.virtualHosts."matrix.kylekrein.com".locations; }; "turn.kylekrein.com" = { enableACME = true; forceSSL = true; }; "matrix.kylekrein.com" = { enableACME = true; forceSSL = true; locations = matrixLocations; }; "immich.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://[::1]:${toString config.services.immich.port}"; extraConfig = '' client_max_body_size 10G; ''; }; }; "dns.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://${config.services.adguardhome.host}:${builtins.toString config.services.adguardhome.port}"; }; }; "music.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://${toString config.services.navidrome.settings.Address}:${toString config.services.navidrome.settings.Port}"; proxyWebsockets = true; extraConfig = '' client_max_body_size 100M; ''; }; }; "uptime.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://${toString config.services.uptime-kuma.settings.HOST}:${toString config.services.uptime-kuma.settings.PORT}"; proxyWebsockets = true; }; }; "${config.services.nextcloud.hostName}" = { enableACME = true; forceSSL = true; locations."/whiteboard/" = { proxyPass = "http://localhost:3002/"; proxyWebsockets = true; }; }; "alexanderlebedev.com" = { enableACME = true; forceSSL = true; locations."/" = { root = inputs.website.packages.${pkgs.system}.website; extraConfig = '' if ($request_uri ~ ^/(.*)\\.html(\?|$)) { return 302 /$1$is_args$args; } try_files $uri $uri.html $uri/ =404; ''; }; }; # https://github.com/NixOS/nixpkgs/issues/218878#issuecomment-2471223335 "collabora.kylekrein.com" = { enableACME = true; forceSSL = true; locations = let proxyPass = "http://[::1]:${toString config.services.collabora-online.port}"; in { # static files "^~ /browser".proxyPass = proxyPass; # WOPI discovery URL "^~ /hosting/discovery".proxyPass = proxyPass; # Capabilities "^~ /hosting/capabilities".proxyPass = proxyPass; # main websocket "~ ^/cool/(.*)/ws$" = { proxyPass = proxyPass; proxyWebsockets = true; }; # download, presentation and image upload "~ ^/(c|l)ool" = { proxyPass = proxyPass; priority = 1001; }; # Admin Console websocket "^~ /cool/adminws" = { proxyPass = proxyPass; proxyWebsockets = true; }; }; }; "ntfy.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://[::1]${config.services.ntfy-sh.settings.listen-http}"; proxyWebsockets = true; }; }; "chat.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://${config.services.open-webui.host}:${builtins.toString config.services.open-webui.port}"; proxyWebsockets = true; extraConfig = '' proxy_send_timeout 7200; proxy_read_timeout 7200; ''; }; }; "smart-home.kylekrein.com" = { forceSSL = true; enableACME = true; extraConfig = '' proxy_buffering off; ''; locations = { "/" = { proxyPass = "http://[::1]:8123"; proxyWebsockets = true; }; "/api/prometheus" = { proxyPass = "http://[::1]:8123"; proxyWebsockets = true; extraConfig = '' allow 127.0.0.1; allow ::1; deny all; ''; }; }; }; "grafana.kylekrein.com" = { forceSSL = true; enableACME = true; locations."/" = { proxyPass = "http://${toString config.services.grafana.settings.server.http_addr}:${toString config.services.grafana.settings.server.http_port}"; proxyWebsockets = true; }; }; "guix.kylekrein.com" = { forceSSL = true; enableACME = true; locations."/" = { proxyPass = "http://localhost:${toString config.services.guix.publish.port}"; }; }; "paperless.kylekrein.com" = { enableACME = true; forceSSL = true; locations."/" = let cfg = config.services.paperless; in { proxyPass = "http://${cfg.address}:${builtins.toString cfg.port}"; }; }; "jellyfin.kylekrein.com" = { enableACME = true; forceSSL = true; extraConfig = '' ## The default `client_max_body_size` is 1M, this might not be enough for some posters, etc. client_max_body_size 20M; # Comment next line to allow TLSv1.0 and TLSv1.1 if you have very old clients ssl_protocols TLSv1.3 TLSv1.2; # Security / XSS Mitigation Headers add_header X-Content-Type-Options "nosniff"; # Permissions policy. May cause issues with some clients add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always; # Content Security Policy add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; font-src 'self'"; ''; locations."/" = { proxyPass = "http://127.0.0.1:8096"; extraConfig = '' # Disable buffering when the nginx proxy gets very resource heavy upon streaming proxy_buffering off; ''; }; locations."/socket" = { proxyPass = "http://127.0.0.1:8096"; proxyWebsockets = true; }; }; }; }; security.acme = { acceptTerms = true; defaults.email = "alex.lebedev2003@icloud.com"; }; }