Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 162 additions & 82 deletions .htaccess
Original file line number Diff line number Diff line change
@@ -1,101 +1,179 @@
<IfModule mod_headers.c>
<IfModule mod_setenvif.c>
<IfModule mod_fcgid.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
<IfModule mod_setenvif.c>
<IfModule mod_fcgid.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
</IfModule>
<IfModule mod_proxy_fcgi.c>
SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>
<IfModule mod_lsapi.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION
</IfModule>
</IfModule>
<IfModule mod_proxy_fcgi.c>
SetEnvIfNoCase Authorization "(.+)" HTTP_AUTHORIZATION=$1
</IfModule>
<IfModule mod_lsapi.c>
SetEnvIfNoCase ^Authorization$ "(.+)" XAUTHORIZATION=$1
RequestHeader set XAuthorization %{XAUTHORIZATION}e env=XAUTHORIZATION

<IfModule mod_env.c>
# Add security and privacy related headers
# Avoid doubled headers by unsetting headers in "onsuccess" table,
# then add headers to "always" table: https://github.com/nextcloud/server/pull/19002

<If "%{REQUEST_URI} =~ m#/login$#">
# Only on the login page we need any Origin or Referer header set.
Header onsuccess unset Referrer-Policy
Header always set Referrer-Policy "same-origin"
</If>
<Else>
Header onsuccess unset Referrer-Policy
Header always set Referrer-Policy "no-referrer"
</Else>

Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"

Header onsuccess unset X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"

Header onsuccess unset X-Permitted-Cross-Domain-Policies
Header always set X-Permitted-Cross-Domain-Policies "none"

Header onsuccess unset X-Robots-Tag
Header always set X-Robots-Tag "noindex, nofollow"

SetEnv modHeadersAvailable true
</IfModule>
</IfModule>

<IfModule mod_env.c>
# Add security and privacy related headers
# Avoid doubled headers by unsetting headers in "onsuccess" table,
# then add headers to "always" table: https://github.com/nextcloud/server/pull/19002

<If "%{REQUEST_URI} =~ m#/login$#">
# Only on the login page we need any Origin or Referer header set.
Header onsuccess unset Referrer-Policy
Header always set Referrer-Policy "same-origin"
</If>
<Else>
Header onsuccess unset Referrer-Policy
Header always set Referrer-Policy "no-referrer"
</Else>

Header onsuccess unset X-Content-Type-Options
Header always set X-Content-Type-Options "nosniff"

Header onsuccess unset X-Frame-Options
Header always set X-Frame-Options "SAMEORIGIN"

Header onsuccess unset X-Permitted-Cross-Domain-Policies
Header always set X-Permitted-Cross-Domain-Policies "none"

Header onsuccess unset X-Robots-Tag
Header always set X-Robots-Tag "noindex, nofollow"

SetEnv modHeadersAvailable true
</IfModule>

# Add cache control for static resources
<FilesMatch "\.(css|js|mjs|svg|gif|png|jpg|webp|ico|wasm|tflite)$">
<If "%{QUERY_STRING} =~ /(^|&)v=/">
Header set Cache-Control "max-age=15778463, immutable"
</If>
<Else>
Header set Cache-Control "max-age=15778463"
</Else>
</FilesMatch>

# Let browsers cache OTF and WOFF files for a week
<FilesMatch "\.(otf|woff2?)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>

# Add cache control for static resources
<FilesMatch "\.(css|js|mjs|svg|gif|png|jpg|webp|ico|wasm|tflite)$">
<If "%{QUERY_STRING} =~ /(^|&)v=/">
Header set Cache-Control "max-age=15778463, immutable"
</If>
<Else>
Header set Cache-Control "max-age=15778463"
</Else>
</FilesMatch>

# Let browsers cache OTF and WOFF files for a week
<FilesMatch "\.(otf|woff2?)$">
Header set Cache-Control "max-age=604800"
</FilesMatch>
</IfModule>

<IfModule mod_php.c>
php_value mbstring.func_overload 0
php_value default_charset 'UTF-8'
php_value output_buffering 0
<IfModule mod_env.c>
SetEnv htaccessWorking true
</IfModule>
php_value mbstring.func_overload 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mbstring.func_overload was removed with php8

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#53578 ;-)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merged, please rebase and fix conflicts here

php_value default_charset 'UTF-8'
php_value output_buffering 0
<IfModule mod_env.c>
SetEnv htaccessWorking true
</IfModule>
</IfModule>

<IfModule mod_mime.c>
AddType image/svg+xml svg svgz
AddType application/wasm wasm
AddEncoding gzip svgz
# Serve ESM javascript files (.mjs) with correct mime type
AddType text/javascript js mjs
AddType image/svg+xml svg svgz
AddType application/wasm wasm
AddEncoding gzip svgz
# Serve ESM javascript files (.mjs) with correct mime type
AddType text/javascript js mjs
</IfModule>

<IfModule mod_dir.c>
DirectoryIndex index.php index.html
DirectoryIndex index.php index.html
</IfModule>

<IfModule pagespeed_module>
ModPagespeed Off
ModPagespeed Off
</IfModule>

#############
#### Rewrites
#############

<IfModule mod_rewrite.c>
RewriteEngine on
RewriteCond %{HTTP_USER_AGENT} DavClnt
RewriteRule ^$ /remote.php/webdav/ [L,R=302]
RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]
RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]
RewriteRule ^remote/(.*) remote.php [QSA,L]
RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]
RewriteRule ^\.well-known/(?!acme-challenge|pki-validation) /index.php [QSA,L]
RewriteRule ^ocm-provider/?$ index.php [QSA,L]
RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]
RewriteEngine on

##
## Rule: Workaround for WebDAV with apache+php-cgi
##
## Context:
## - Sets the environment variable `HTTP_AUTHORIZATION` to the value of the `Authorization` request header
## - Always executed before and along with other rules (no `L` used)
## - XXX: *May* be replaced with an equivalent SetEnvIf in theory
## - XXX: SetEnvIf approach is already in use above for mod_proxy_cgi / mod_lsapi / mod_fcgid
##

RewriteRule .* - [env=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

##
## Rule: Workaround for WebDAV with MS DavClnt
##
## Context:
## - DavClnt attempts an OPTIONS request against `/` instead of the specified endpoint
## - Redirects the client to the endpoint rather than the login page (which confuses DavClnt)
##

RewriteCond %{HTTP_USER_AGENT} DavClnt
RewriteRule ^$ /remote.php/webdav/ [L,R=302]

##
## Rule: Map the RFC 8615 / RFC 6764 compliant well-known URI for CardDAV to our Remote DAV endpoint
##

RewriteRule ^\.well-known/carddav /remote.php/dav/ [R=301,L]

##
## Rule: Map the RFC 8615 / RFC 6764 compliant well-known URI for CalDAV to our Remote DAV endpoint
##

RewriteRule ^\.well-known/caldav /remote.php/dav/ [R=301,L]

##
## Rule: Map /remote* --> /remote.php* including the query string
##
## Context:
## - XXX: `QSA` seems unnecessary (no-op) here (query string is passed by default when the replacement URI doesn't contain a query string)
## - XXX: Is this even used anymore? Seems a relic from <NC12
##

RewriteRule ^remote/(.*) remote.php [QSA,L]

##
## Rule: Prevent access to non-public files
##

RewriteRule ^(?:build|tests|config|lib|3rdparty|templates)/.* - [R=404,L]

##
## Rule: Maps most RFC 8615 compliant well-known URIs to our main frontend controller (/index.php) by default
##
## Context:
## - Intentionally excludes URIs used for HTTPS certificate verifications
## - RFC 8555 / ACME HTTP Challenges (acme-challenge)
## - File-based Validations (pki-validation)
## - XXX: `QSA` seems unnecessary (no-op) here (query string is passed by default when the replacement URI doesn't contain a query string)
## - XXX: Sometimes we are using `/index.php` and other times `index.php` as our replacement URI; this may be incorrect
##

RewriteRule ^\.well-known/(?!acme-challenge|pki-validation) /index.php [QSA,L]

##
## Rule: Map the ocm-provider handling to our main frontend controller (/index.php)
##
## Context:
## - XXX: `QSA` seems unnecessary (no-op) here (query string is passed by default when the replacement URI doesn't contain a query string)
## - XXX: Sometimes we are using `/index.php` and other times `index.php` as our replacement URI; this may be incorrect
##

RewriteRule ^ocm-provider/?$ index.php [QSA,L]

##
## Rule: Prevent access to more non-public files
##
## Context:
## - XXX It may make sense to merge some of these with the others (i.e. the ones that don't need to be last)
##

RewriteRule ^(?:\.(?!well-known)|autotest|occ|issue|indie|db_|console).* - [R=404,L]

</IfModule>

# Clients like xDavv5 on Android, or Cyberduck, use chunked requests.
Expand All @@ -106,16 +184,18 @@
# Here are more information about the issue:
# - https://docs.cyberduck.io/mountainduck/issues/fastcgi/
# - https://docs.nextcloud.com/server/latest/admin_manual/issues/general_troubleshooting.html#troubleshooting-webdav

<IfModule mod_setenvif.c>
SetEnvIfNoCase Transfer-Encoding "chunked" proxy-sendcl=1
SetEnvIfNoCase Transfer-Encoding "chunked" proxy-sendcl=1
</IfModule>

# Apache disabled the sending of the server-side content-length header
# in their 2.4.59 patch updated which breaks some use-cases in Nextcloud.
# Setting ap_trust_cgilike_cl allows to bring back the usual behaviour.
# See https://bz.apache.org/bugzilla/show_bug.cgi?id=68973

<IfModule mod_env.c>
SetEnv ap_trust_cgilike_cl
SetEnv ap_trust_cgilike_cl
</IfModule>

AddDefaultCharset utf-8
Expand Down
Loading