diff --git a/hosts/vps/configuration.nix b/hosts/vps/configuration.nix index 9cc6a14..1690fa0 100644 --- a/hosts/vps/configuration.nix +++ b/hosts/vps/configuration.nix @@ -42,6 +42,7 @@ in { imports = [ ./hardware-configuration.nix + ./nginx-nextcloud.nix ../../config/base.nix ]; my = import ./toggles.nix { inherit config inputs; } // { diff --git a/hosts/vps/nginx-nextcloud.nix b/hosts/vps/nginx-nextcloud.nix new file mode 100644 index 0000000..ea718ea --- /dev/null +++ b/hosts/vps/nginx-nextcloud.nix @@ -0,0 +1,116 @@ +{ config, lib, ... }: +let + cfg = config.my.servers.nextcloud; +in +{ + config = lib.mkIf (cfg.enableProxy && config.my.enableProxy) { + services.nginx.virtualHosts.${cfg.host} = { + forceSSL = true; + enableACME = true; + http2 = true; + default = true; + serverAliases = [ "cloud.rotehaare.art" ]; + extraConfig = '' + index index.php index.html /index.php$request_uri; + add_header X-Content-Type-Options nosniff always; + add_header X-Robots-Tag "noindex, nofollow" always; + add_header X-Permitted-Cross-Domain-Policies none always; + add_header X-Frame-Options SAMEORIGIN always; + add_header Referrer-Policy no-referrer always; + add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; + ''; + locations = { + "= /robots.txt" = { + priority = 100; + extraConfig = '' + allow all; + access_log off; + ''; + }; + "= /" = { + priority = 100; + proxyPass = cfg.local; + proxyWebsockets = true; + extraConfig = '' + if ( $http_user_agent ~ ^DavClnt ) { + return 302 /remote.php/webdav/$is_args$args; + } + ''; + }; + "= /.well-known/carddav" = { + priority = 210; + extraConfig = '' + return 301 /remote.php/dav/; + ''; + }; + "= /.well-known/caldav" = { + priority = 210; + extraConfig = '' + return 301 /remote.php/dav/; + ''; + }; + "~ ^/\\.well-known/(?!acme-challenge|pki-validation)" = { + priority = 210; + extraConfig = '' + return 301 /index.php$request_uri; + ''; + }; + "^~ /.well-known" = { + priority = 210; + extraConfig = '' + try_files $uri $uri/ =404; + ''; + }; + "~ ^/(?:build|tests|config|lib|3rdparty|templates|data)(?:$|/)" = { + priority = 450; + extraConfig = '' + return 404; + ''; + }; + "~ ^/(?:\\.|autotest|occ|issue|indie|db_|console)" = { + priority = 450; + extraConfig = '' + return 404; + ''; + }; + "~ \\.php(?:$|/)" = { + priority = 500; + proxyPass = cfg.local; + proxyWebsockets = true; + extraConfig = '' + rewrite ^/(?!index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+|.+\/richdocumentscode(_arm64)?\/proxy) /index.php$request_uri; + ''; + }; + "~ \\.(?:css|js|mjs|svg|gif|ico|jpg|jpeg|png|webp|wasm|tflite|map|html|ttf|bcmap|mp4|webm|ogg|flac)$" = + { + proxyPass = cfg.local; + extraConfig = '' + expires 6M; + access_log off; + ''; + }; + "~ ^\\/(?:updater|ocs-provider)(?:$|\\/)" = { + proxyPass = cfg.local; + extraConfig = '' + try_files $uri/ =404; + index index.php; + ''; + }; + "/remote" = { + priority = 1500; + extraConfig = '' + return 301 /remote.php$request_uri; + ''; + }; + "/" = { + priority = 1600; + proxyPass = cfg.local; + proxyWebsockets = true; + extraConfig = '' + try_files $uri $uri/ /index.php$request_uri; + ''; + }; + }; + }; + }; +} diff --git a/hosts/vps/toggles.nix b/hosts/vps/toggles.nix index d952875..3ceb110 100644 --- a/hosts/vps/toggles.nix +++ b/hosts/vps/toggles.nix @@ -40,6 +40,7 @@ in servers = enableList mkEnabledProxySocketIp [ "audiobookshelf" + "collabora" "jellyfin" "nextcloud" "plausible" @@ -47,7 +48,6 @@ in ] // enableList mkEnabledProxyIp [ "bazarr" - "collabora" "gitea" "homepage" "isso" diff --git a/modules/servers/nextcloud.nix b/modules/servers/nextcloud.nix index e96c988..d84c575 100644 --- a/modules/servers/nextcloud.nix +++ b/modules/servers/nextcloud.nix @@ -256,78 +256,51 @@ in }; }; }) - (lib.mkIf (cfg.enableProxy && config.my.enableProxy && config.networking.hostName == "vps") { - services.nginx.virtualHosts = { - "${cfg.host}" = { - forceSSL = true; - enableACME = true; - http2 = true; - default = true; - serverAliases = [ "cloud.rotehaare.art" ]; - extraConfig = '' - add_header X-XSS-Protection "1; mode=block" always; - add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always; - add_header X-Content-Type-Options "nosniff" always; - add_header X-Frame-Options "SAMEORIGIN" always; - add_header Referrer-Policy "no-referrer-when-downgrade" always; - add_header X-Permitted-Cross-Domain-Policies "none" always; - proxy_set_header Host $host; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_set_header X-Forwarded-Host $host; - ''; - locations = { - "/" = { - proxyPass = cfg.local; - proxyWebsockets = true; - }; + (lib.mkIf (cfgC.enableProxy && config.my.enableProxy) { + services.nginx.virtualHosts.${cfgC.host} = { + forceSSL = true; + enableACME = true; + http2 = true; + locations = { + # static files + "^~ /browser" = { + proxyPass = cfgC.local; + extraConfig = commonProxyConfig; }; - }; - "${cfgC.host}" = lib.mkIf cfgC.enableProxy { - forceSSL = true; - enableACME = true; - http2 = true; - locations = { - # static files - "^~ /browser" = { - proxyPass = cfgC.local; - extraConfig = commonProxyConfig; - }; - # Legacy static files (for compatibility) - "^~ /loleaflet" = { - proxyPass = cfgC.local; - extraConfig = commonProxyConfig; - }; - # WOPI discovery URL - "^~ /hosting/discovery" = { - proxyPass = cfgC.local; - extraConfig = commonProxyConfig; - }; - # Capabilities - "^~ /hosting/capabilities" = { - proxyPass = cfgC.local; - extraConfig = commonProxyConfig; - }; - # download, presentation, image upload and websocket - "~ ^/cool" = { - proxyPass = cfgC.local; - extraConfig = commonWebsocketConfig; - }; - # Legacy websocket (for compatibility) - "~ ^/lool" = { - proxyPass = cfgC.local; - extraConfig = commonWebsocketConfig; - }; - # Admin Console websocket - "^~ /cool/adminws" = { - proxyPass = cfgC.local; - extraConfig = commonWebsocketConfig; - }; - # Legacy Admin Console websocket (for compatibility) - "^~ /lool/adminws" = { - proxyPass = cfgC.local; - extraConfig = commonWebsocketConfig; - }; + # Legacy static files (for compatibility) + "^~ /loleaflet" = { + proxyPass = cfgC.local; + extraConfig = commonProxyConfig; + }; + # WOPI discovery URL + "^~ /hosting/discovery" = { + proxyPass = cfgC.local; + extraConfig = commonProxyConfig; + }; + # Capabilities + "^~ /hosting/capabilities" = { + proxyPass = cfgC.local; + extraConfig = commonProxyConfig; + }; + # download, presentation, image upload and websocket + "~ ^/cool" = { + proxyPass = cfgC.local; + extraConfig = commonWebsocketConfig; + }; + # Legacy websocket (for compatibility) + "~ ^/lool" = { + proxyPass = cfgC.local; + extraConfig = commonWebsocketConfig; + }; + # Admin Console websocket + "^~ /cool/adminws" = { + proxyPass = cfgC.local; + extraConfig = commonWebsocketConfig; + }; + # Legacy Admin Console websocket (for compatibility) + "^~ /lool/adminws" = { + proxyPass = cfgC.local; + extraConfig = commonWebsocketConfig; }; }; };