Format comments in Apache configuration

This commit is contained in:
Alex Cabal 2025-07-02 16:48:54 -05:00
parent c32dcb1b42
commit 41c3dc8449
4 changed files with 82 additions and 90 deletions

View file

@ -1,7 +1,7 @@
# Redirect old feed URLs # Redirect old feed URLs.
RewriteRule ^/(opds|rss|atom)(.*)$ /feeds/$1$2 [R=301,L] RewriteRule ^/(opds|rss|atom)(.*)$ /feeds/$1$2 [R=301,L]
# If we ask for /opds/all?query=xyz, rewrite that to the search page. # If we ask for `/opds/all?query=xyz`, rewrite that to the search page.
RewriteCond %{QUERY_STRING} \bquery= RewriteCond %{QUERY_STRING} \bquery=
RewriteRule ^/feeds/(opds|atom|rss)/all.xml$ /feeds/$1/search.php [QSA] RewriteRule ^/feeds/(opds|atom|rss)/all.xml$ /feeds/$1/search.php [QSA]

View file

@ -1,12 +1,12 @@
# Favicon rewrites # Favicon rewrites.
RewriteRule ^/(apple-touch|android-chrome|favicon|mstile|safari-pinned|browserconfig|manifest)([^/]+)$ /images/favicons/$1$2 [L] RewriteRule ^/(apple-touch|android-chrome|favicon|mstile|safari-pinned|browserconfig|manifest)([^/]+)$ /images/favicons/$1$2 [L]
# Redirect tools # Redirect the toolset to GitHub.
RewriteRule ^/tools$ https://github.com/standardebooks/tools [R=302,L] RewriteRule ^/tools$ https://github.com/standardebooks/tools [R=302,L]
# Redirect latest version of the manual # Redirect latest version of the manual.
RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L] RewriteRule ^/manual/latest(.*) /manual/index.php?url=$1 [L]
# Rewrite rules for bulk downloads # Rewrite rules for bulk downloads.
RewriteRule ^/bulk-downloads/(.+\.zip)$ /bulk-downloads/download.php?path=$1 RewriteRule ^/bulk-downloads/(.+\.zip)$ /bulk-downloads/download.php?path=$1
RewriteRule ^/bulk-downloads/([^/\.]+)$ /bulk-downloads/collection.php?class=$1 RewriteRule ^/bulk-downloads/([^/\.]+)$ /bulk-downloads/collection.php?class=$1

View file

@ -1,4 +1,4 @@
# Global configuration; see https://securityheaders.com # Global configuration; see <https://securityheaders.com>.
Header set X-Frame-Options "sameorigin" Header set X-Frame-Options "sameorigin"
Header set X-Content-Type-Options "nosniff" Header set X-Content-Type-Options "nosniff"
Header set X-Xss-Protection "1; mode=block" Header set X-Xss-Protection "1; mode=block"
@ -16,7 +16,7 @@ AddOutputFilterByType deflate image/vnd.microsoft.icon image/x-icon
TraceEnable off TraceEnable off
Protocols h2 h2c http/1.1 Protocols h2 h2c http/1.1
# Set up caching directives for infrequently changed files # Set up caching directives for infrequently changed files.
ExpiresActive on ExpiresActive on
ExpiresByType application/javascript "access plus 6 months" ExpiresByType application/javascript "access plus 6 months"
ExpiresByType text/javascript "access plus 6 months" ExpiresByType text/javascript "access plus 6 months"
@ -30,21 +30,20 @@ ExpiresByType image/vnd.microsoft.icon "access plus 6 months"
ExpiresByType image/x-icon "access plus 6 months" ExpiresByType image/x-icon "access plus 6 months"
ExpiresByType text/css "access plus 6 months" ExpiresByType text/css "access plus 6 months"
# These lines are a workaround for an Apache bug that prevents mod_deflate, etags, and ExpiresByType working at the same time. # These lines are a workaround for an Apache bug that prevents `mod_deflate`, etags, and `ExpiresByType` working at the same time.
# This is probably still broken in 18.04. See https://stackoverflow.com/questions/896974/apache-is-not-sending-304-response-if-mod-deflate-and-addoutputfilterbytype-is # This can only be fixed in Ubuntu 24.04 and later using <https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag>.
# Can possibly be fixed in Ubuntu 22.04 using https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag
FileETag All FileETag All
RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\"" RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\"" Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
# SSL hardening; see https://mozilla.github.io/server-side-tls/ssl-config-generator/ # SSL hardening; see <https://mozilla.github.io/server-side-tls/ssl-config-generator/>.
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256 SSLCipherSuite ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256
SSLHonorCipherOrder on SSLHonorCipherOrder on
SSLCompression off SSLCompression off
SSLSessionTickets off SSLSessionTickets off
SSLStaplingCache shmcb:/var/run/ocsp(128000) SSLStaplingCache shmcb:/var/run/ocsp(128000)
# SSL Stapling should be off for testing to prevent errors in log files, and on for live # SSL Stapling should be off for testing to prevent errors in log files, and on for live.
SSLUseStapling on SSLUseStapling on
SSLStaplingResponderTimeout 5 SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off SSLStaplingReturnResponderErrors off
@ -94,50 +93,49 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline';" Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline';"
<Directory "${web_root}/www/"> <Directory "${web_root}/www/">
# Disable .htaccess files # Disable `.htaccess` files.
AllowOverride none AllowOverride none
# Disable unneeded options # Disable unneeded options.
Options none Options none
# Allow access to www/ # Allow access to `www/`.
Require all granted Require all granted
# Pass HTTP Authorization headers to PHP-FPM # Pass HTTP Authorization headers to PHP-FPM.
CGIPassAuth on CGIPassAuth on
</Directory> </Directory>
AddType application/x-mobi8-ebook .azw3 AddType application/x-mobi8-ebook .azw3
# We explicitly set the content-type for items in the /vocab/ directory, because Apache doesn't set it for us, # We explicitly set the content-type for items in the `/vocab/` directory, because Apache doesn't set it for us, and we need a `Content-Type` header when using the `Nosniff` header. See <https://bugzilla.mozilla.org/show_bug.cgi?id=1547076>.
# and we need a content-type header when using the "nosniff" header. See https://bugzilla.mozilla.org/show_bug.cgi?id=1547076
<LocationMatch "^/vocab/.+$"> <LocationMatch "^/vocab/.+$">
Header set Content-Type "text/plain" Header set Content-Type "text/plain"
</LocationMatch> </LocationMatch>
# Enable HTTP CORS so that browser-based readers like Readium can access opds and ebooks # Enable HTTP CORS so that browser-based readers like Readium can access OPDS and ebooks.
# Allow fonts for newsletter emails # Allow fonts for newsletter emails.
# See https://github.com/standardebooks/tools/issues/2 # See <https://github.com/standardebooks/tools/issues/2>.
<LocationMatch "/(ebooks|feeds/opds|fonts)"> <LocationMatch "/(ebooks|feeds/opds|fonts)">
Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Origin "*"
</LocationMatch> </LocationMatch>
# We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS # We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS.
<LocationMatch "/text/single-page$"> <LocationMatch "/text/single-page$">
Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';"
</LocationMatch> </LocationMatch>
# Remove www from requests # Remove `www.` from requests.
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC] RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L] RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# PHP-FPM configuration # PHP-FPM configuration
# See https://serverfault.com/questions/450628/apache-2-4-php-fpm-proxypassmatch/510784 # See <https://serverfault.com/questions/450628/apache-2-4-php-fpm-proxypassmatch/510784>.
# Required for FPM to receive POST data sent with Transfer-Encoding: chunked # Required for FPM to receive POST data sent with `Transfer-Encoding: chunked`.
SetEnv proxy-sendcl 1 SetEnv proxy-sendcl 1
# Forward all PHP requests to the php-fpm pool for this domain. # Forward all PHP requests to the PHP-FPM pool for this domain.
<FilesMatch "\.php$"> <FilesMatch "\.php$">
SetHandler "proxy:unix:///run/php/${domain}.sock|fcgi://${domain}" SetHandler "proxy:unix:///run/php/${domain}.sock|fcgi://${domain}"
Header set Cache-Control "no-store" Header set Cache-Control "no-store"
@ -158,47 +156,45 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
RewriteCond %{HTTP_USER_AGENT} ChatGPT-User RewriteCond %{HTTP_USER_AGENT} ChatGPT-User
RewriteRule ^ - [L,R=429] RewriteRule ^ - [L,R=429]
# In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first # In `RewriteCond`, `RewriteRule` gets evaluated *before `RewriteCond`, so `$1` refers to the first match in `RewriteRule`.
# match in RewriteRule # Rewrite POST `/some/url` -> POST `/some/url/post.php`.
# Rewrite POST /some/url -> POST /some/url/post.php
RewriteCond expr "tolower(%{REQUEST_METHOD}) =~ /^(post|delete|put)$/" RewriteCond expr "tolower(%{REQUEST_METHOD}) =~ /^(post|delete|put)$/"
RewriteCond %{DOCUMENT_ROOT}/$1/%1.php -f RewriteCond %{DOCUMENT_ROOT}/$1/%1.php -f
RewriteRule ^([^\.]+)$ $1/%1.php [L] RewriteRule ^([^\.]+)$ $1/%1.php [L]
# In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # In case of 404, serve the 404 page specified by `ErrorDocument`, not the default FPM error page.
# Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # Note that we can't use `ProxyErrorOverride on` because that catches *all* 4xx and 5xx HTTP headers and serves the default Apache page for them.
# and serves the default Apache page for them.
RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteRule (.*) - [H=text/html] RewriteRule (.*) - [H=text/html]
# Received: /filename.php and /filename.php exists in filesystem; Result: 301 redirect to /filename and restart request # Received `/filename.php` and `/filename.php` exists in filesystem -> 301 redirect to `/filename` and restart request.
RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} -f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} -f
RewriteRule ^/(.+)\.php$ /$1 [R=301,L] RewriteRule ^/(.+)\.php$ /$1 [R=301,L]
# Received: /filename and /filename.php exists in filesystem; Result: change /filename to /filename.php and continue processing # Received `/filename` and `/filename.php` exists in filesystem -> change `/filename` to `/filename.php` and continue request.
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-d RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-d
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}.php -f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}.php -f
RewriteRule ^(.+)$ $1.php [QSA] RewriteRule ^(.+)$ $1.php [QSA]
# End PHP-FPM configuration # End PHP-FPM configuration
# Received: /filename and /filename.xml exists in filesystem; Result: rewrite to /filename.xml # Received: `/filename` and `/filename.xml` exists in filesystem -> rewrite to `/filename.xml` and continue request.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f
RewriteRule (.*) $1.xml RewriteRule (.*) $1.xml
# Remove trailing slashes # Remove trailing slashes.
RewriteRule ^/(.+?)/$ /$1 [R=301,L] RewriteRule ^/(.+?)/$ /$1 [R=301,L]
# Redirect ToC of XHTML representation of books # Redirect ToC of XHTML representation of books.
RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/toc.xhtml [L] RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/toc.xhtml [L]
# Received: /filename and /filename.xhtml exists in filesystem; Result: rewrite to /filename.xhtml # Received: `/filename` and `/filename.xhtml` exists in filesystem -> rewrite to `/filename.xhtml` and continue request.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f
RewriteRule (.*) $1.xhtml RewriteRule (.*) $1.xhtml
# Redirect index pages # Redirect index pages.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f
RewriteRule (.*) $1/index.php RewriteRule (.*) $1/index.php
@ -207,7 +203,7 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f
RewriteRule (.*) $1/index.xml RewriteRule (.*) $1/index.xml
# Remove newline characters inserted by accident in some email clients # Remove newline characters inserted by accident in some email clients.
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N] RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N] RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N] RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
@ -221,24 +217,24 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
Include ${conf_rewrite_root}/users.conf Include ${conf_rewrite_root}/users.conf
Include ${conf_rewrite_root}/projects.conf Include ${conf_rewrite_root}/projects.conf
# Specific config for /ebooks/<author>/<ebook>/downloads # `XSendFile` configuration for `/ebooks/<author>/<ebook>/downloads`.
<DirectoryMatch "^${web_root}/www/ebooks/.+"> <DirectoryMatch "^${web_root}/www/ebooks/.+">
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/ebooks XSendFilePath ${web_root}/www/ebooks
</DirectoryMatch> </DirectoryMatch>
# Specific config for /bulk-downloads # `XSendFile` configuration for `/bulk-downloads`.
<DirectoryMatch "^${web_root}/www/bulk-downloads/"> <DirectoryMatch "^${web_root}/www/bulk-downloads/">
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/bulk-downloads XSendFilePath ${web_root}/www/bulk-downloads
</DirectoryMatch> </DirectoryMatch>
# Specific config for /feeds # `XSendFile` configuration for `/feeds`.
<DirectoryMatch "^${web_root}/www/feeds/"> <DirectoryMatch "^${web_root}/www/feeds/">
# This must be defined at the top level /feeds/ directory # This must be defined at the top level `/feeds/` directory.
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/feeds XSendFilePath ${web_root}/www/feeds
</DirectoryMatch> </DirectoryMatch>

View file

@ -1,4 +1,4 @@
# Global configuration; see https://securityheaders.com # Global configuration; see <https://securityheaders.com>.
Header set X-Frame-Options "sameorigin" Header set X-Frame-Options "sameorigin"
Header set X-Content-Type-Options "nosniff" Header set X-Content-Type-Options "nosniff"
Header set X-Xss-Protection "1; mode=block" Header set X-Xss-Protection "1; mode=block"
@ -16,7 +16,7 @@ AddOutputFilterByType deflate image/vnd.microsoft.icon image/x-icon
TraceEnable off TraceEnable off
Protocols h2 h2c http/1.1 Protocols h2 h2c http/1.1
# Set up caching directives for infrequently changed files # Set up caching directives for infrequently changed files.
ExpiresActive on ExpiresActive on
ExpiresByType application/javascript "access plus 6 months" ExpiresByType application/javascript "access plus 6 months"
ExpiresByType text/javascript "access plus 6 months" ExpiresByType text/javascript "access plus 6 months"
@ -30,9 +30,8 @@ ExpiresByType image/vnd.microsoft.icon "access plus 6 months"
ExpiresByType image/x-icon "access plus 6 months" ExpiresByType image/x-icon "access plus 6 months"
ExpiresByType text/css "access plus 6 months" ExpiresByType text/css "access plus 6 months"
# These lines are a workaround for an Apache bug that prevents mod_deflate, etags, and ExpiresByType working at the same time. # These lines are a workaround for an Apache bug that prevents `mod_deflate`, etags, and `ExpiresByType` working at the same time.
# This is probably still broken in 18.04. See https://stackoverflow.com/questions/896974/apache-is-not-sending-304-response-if-mod-deflate-and-addoutputfilterbytype-is # This can only be fixed in Ubuntu 24.04 and later using <https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag>.
# Can possibly be fixed in Ubuntu 22.04 using https://httpd.apache.org/docs/trunk/mod/mod_deflate.html#deflatealteretag
FileETag All FileETag All
RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\"" RequestHeader edit "If-None-Match" "^\"(.*)-gzip\"$" "\"$1\""
Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\"" Header edit "ETag" "^\"(.*[^g][^z][^i][^p])\"$" "\"$1-gzip\""
@ -44,8 +43,8 @@ SSLHonorCipherOrder on
SSLCompression off SSLCompression off
SSLSessionTickets off SSLSessionTickets off
SSLStaplingCache shmcb:/var/run/ocsp(128000) SSLStaplingCache shmcb:/var/run/ocsp(128000)
# SSL Stapling should be off for testing to prevent errors in log files, and on for live # SSL Stapling should be off for testing to prevent errors in log files, and on for live.
SSLUseStapling off SSLUseStapling on
SSLStaplingResponderTimeout 5 SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off SSLStaplingReturnResponderErrors off
@ -76,50 +75,49 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline';" Header set Content-Security-Policy "default-src 'self'; style-src 'self' 'unsafe-inline';"
<Directory "${web_root}/www/"> <Directory "${web_root}/www/">
# Disable .htaccess files # Disable `.htaccess` files.
AllowOverride none AllowOverride none
# Disable unneeded options # Disable unneeded options.
Options none Options none
# Allow access to www/ # Allow access to `www/`.
Require all granted Require all granted
# Pass HTTP Authorization headers to PHP-FPM # Pass HTTP Authorization headers to PHP-FPM.
CGIPassAuth on CGIPassAuth on
</Directory> </Directory>
AddType application/x-mobi8-ebook .azw3 AddType application/x-mobi8-ebook .azw3
# We explicitly set the content-type for items in the /vocab/ directory, because Apache doesn't set it for us, # We explicitly set the content-type for items in the `/vocab/` directory, because Apache doesn't set it for us, and we need a `Content-Type` header when using the `Nosniff` header. See <https://bugzilla.mozilla.org/show_bug.cgi?id=1547076>.
# and we need a content-type header when using the "nosniff" header. See https://bugzilla.mozilla.org/show_bug.cgi?id=1547076
<LocationMatch "^/vocab/.+$"> <LocationMatch "^/vocab/.+$">
Header set Content-Type "text/plain" Header set Content-Type "text/plain"
</LocationMatch> </LocationMatch>
# Enable HTTP CORS so that browser-based readers like Readium can access opds and ebooks # Enable HTTP CORS so that browser-based readers like Readium can access OPDS and ebooks.
# Allow fonts for newsletter emails # Allow fonts for newsletter emails.
# See https://github.com/standardebooks/tools/issues/2 # See <https://github.com/standardebooks/tools/issues/2>.
<LocationMatch "/(ebooks|feeds/opds|fonts)"> <LocationMatch "/(ebooks|feeds/opds|fonts)">
Header set Access-Control-Allow-Origin "*" Header set Access-Control-Allow-Origin "*"
</LocationMatch> </LocationMatch>
# We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS # We use a different CSP policy for single-page files because our default one doesn't allow inline images or CSS.
<LocationMatch "/text/single-page$"> <LocationMatch "/text/single-page$">
Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';" Header set Content-Security-Policy "default-src 'self'; img-src 'self' data:; style-src 'self' 'unsafe-inline';"
</LocationMatch> </LocationMatch>
# Remove www from requests # Remove `www.` from requests.
RewriteCond %{HTTP_HOST} ^www\.(.+) [NC] RewriteCond %{HTTP_HOST} ^www\.(.+) [NC]
RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L] RewriteRule ^ https://%1%{REQUEST_URI} [R=301,L]
# PHP-FPM configuration # PHP-FPM configuration
# See https://serverfault.com/questions/450628/apache-2-4-php-fpm-proxypassmatch/510784 # See <https://serverfault.com/questions/450628/apache-2-4-php-fpm-proxypassmatch/510784>.
# Required for FPM to receive POST data sent with Transfer-Encoding: chunked # Required for FPM to receive POST data sent with `Transfer-Encoding: chunked`.
SetEnv proxy-sendcl 1 SetEnv proxy-sendcl 1
# Forward all PHP requests to the php-fpm pool for this domain. # Forward all PHP requests to the PHP-FPM pool for this domain.
<FilesMatch "\.php$"> <FilesMatch "\.php$">
SetHandler "proxy:unix:///run/php/${domain}.sock|fcgi://${domain}" SetHandler "proxy:unix:///run/php/${domain}.sock|fcgi://${domain}"
Header set Cache-Control "no-store" Header set Cache-Control "no-store"
@ -140,47 +138,45 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
RewriteCond %{HTTP_USER_AGENT} ChatGPT-User RewriteCond %{HTTP_USER_AGENT} ChatGPT-User
RewriteRule ^ - [L,R=429] RewriteRule ^ - [L,R=429]
# In RewriteCond, RewriteRule gets evaluated BEFORE RewriteCond, so $1 refers to the first # In `RewriteCond`, `RewriteRule` gets evaluated *before `RewriteCond`, so `$1` refers to the first match in `RewriteRule`.
# match in RewriteRule # Rewrite POST `/some/url` -> POST `/some/url/post.php`.
# Rewrite POST /some/url -> POST /some/url/post.php
RewriteCond expr "tolower(%{REQUEST_METHOD}) =~ /^(post|delete|put)$/" RewriteCond expr "tolower(%{REQUEST_METHOD}) =~ /^(post|delete|put)$/"
RewriteCond %{DOCUMENT_ROOT}/$1/%1.php -f RewriteCond %{DOCUMENT_ROOT}/$1/%1.php -f
RewriteRule ^([^\.]+)$ $1/%1.php [L] RewriteRule ^([^\.]+)$ $1/%1.php [L]
# In case of 404, serve the 404 page specified by ErrorDocument, not the default FPM error page. # In case of 404, serve the 404 page specified by `ErrorDocument`, not the default FPM error page.
# Note that we can't use `ProxyErrorOverride on` because that catches ALL 4xx and 5xx HTTP headers # Note that we can't use `ProxyErrorOverride on` because that catches *all* 4xx and 5xx HTTP headers and serves the default Apache page for them.
# and serves the default Apache page for them.
RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteRule (.*) - [H=text/html] RewriteRule (.*) - [H=text/html]
# Received: /filename.php and /filename.php exists in filesystem; Result: 301 redirect to /filename and restart request # Received `/filename.php` and `/filename.php` exists in filesystem -> 301 redirect to `/filename` and restart request.
RewriteCond %{REQUEST_FILENAME} \.php$ RewriteCond %{REQUEST_FILENAME} \.php$
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} -f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} -f
RewriteRule ^/(.+)\.php$ /$1 [R=301,L] RewriteRule ^/(.+)\.php$ /$1 [R=301,L]
# Received: /filename and /filename.php exists in filesystem; Result: change /filename to /filename.php and continue processing # Received `/filename` and `/filename.php` exists in filesystem -> change `/filename` to `/filename.php` and continue request.
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-f
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-d RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI} !-d
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}.php -f RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_URI}.php -f
RewriteRule ^(.+)$ $1.php [QSA] RewriteRule ^(.+)$ $1.php [QSA]
# End PHP-FPM configuration # End PHP-FPM configuration
# Received: /filename and /filename.xml exists in filesystem; Result: rewrite to /filename.xml # Received: `/filename` and `/filename.xml` exists in filesystem -> rewrite to `/filename.xml` and continue request.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xml -f
RewriteRule (.*) $1.xml RewriteRule (.*) $1.xml
# Remove trailing slashes # Remove trailing slashes.
RewriteRule ^/(.+?)/$ /$1 [R=301,L] RewriteRule ^/(.+?)/$ /$1 [R=301,L]
# Redirect ToC of XHTML representation of books # Redirect ToC of XHTML representation of books.
RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/toc.xhtml [L] RewriteRule ^/ebooks/(.+?)/text$ /ebooks/$1/toc.xhtml [L]
# Received: /filename and /filename.xhtml exists in filesystem; Result: rewrite to /filename.xhtml # Received: `/filename` and `/filename.xhtml` exists in filesystem -> rewrite to `/filename.xhtml` and continue request.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}.xhtml -f
RewriteRule (.*) $1.xhtml RewriteRule (.*) $1.xhtml
# Redirect index pages # Redirect index pages.
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} -d
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.php -f
RewriteRule (.*) $1/index.php RewriteRule (.*) $1/index.php
@ -189,7 +185,7 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.xml -f
RewriteRule (.*) $1/index.xml RewriteRule (.*) $1/index.xml
# Remove newline characters inserted by accident in some email clients # Remove newline characters inserted by accident in some email clients.
RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N] RewriteRule ^(.*)\r\n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N] RewriteRule ^(.*)/r/n[\ ]?(.*)$ $1$2 [R=301,N]
RewriteRule ^(.*)/[rn]$ $1 [R=301,N] RewriteRule ^(.*)/[rn]$ $1 [R=301,N]
@ -203,24 +199,24 @@ Define conf_rewrite_root ${web_root}/config/apache/rewrites
Include ${conf_rewrite_root}/users.conf Include ${conf_rewrite_root}/users.conf
Include ${conf_rewrite_root}/projects.conf Include ${conf_rewrite_root}/projects.conf
# Specific config for /ebooks/<author>/<ebook>/downloads # `XSendFile` configuration for `/ebooks/<author>/<ebook>/downloads`.
<DirectoryMatch "^${web_root}/www/ebooks/.+"> <DirectoryMatch "^${web_root}/www/ebooks/.+">
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/ebooks XSendFilePath ${web_root}/www/ebooks
</DirectoryMatch> </DirectoryMatch>
# Specific config for /bulk-downloads # `XSendFile` configuration for `/bulk-downloads`.
<DirectoryMatch "^${web_root}/www/bulk-downloads/"> <DirectoryMatch "^${web_root}/www/bulk-downloads/">
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/bulk-downloads XSendFilePath ${web_root}/www/bulk-downloads
</DirectoryMatch> </DirectoryMatch>
# Specific config for /feeds # `XSendFile` configuration for `/feeds`.
<DirectoryMatch "^${web_root}/www/feeds/"> <DirectoryMatch "^${web_root}/www/feeds/">
# This must be defined at the top level /feeds/ directory # This must be defined at the top level `/feeds/` directory.
# Both directives are required # Both directives are required.
XSendFile on XSendFile on
XSendFilePath ${web_root}/www/feeds XSendFilePath ${web_root}/www/feeds
</DirectoryMatch> </DirectoryMatch>