diff --git a/Containers/apache/Dockerfile b/Containers/apache/Dockerfile index 690b186b..22f100c9 100644 --- a/Containers/apache/Dockerfile +++ b/Containers/apache/Dockerfile @@ -60,6 +60,19 @@ RUN set -ex; \ grep -q '' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ # ServerLimit needs to be set to MaxRequestWorkers divided by ThreadsPerChild which is set to 25 by default sed -i '//a\ \ \ \ ServerLimit 200' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ +# Pin ThreadsPerChild so the value is deterministic regardless of the httpd base-image +# defaults; 25 threads per process balances concurrency against per-process memory use. + sed -i 's|ThreadsPerChild.*|ThreadsPerChild 25|' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ +# Start two server processes on boot to absorb the first requests without spawning +# new processes on the critical path, while avoiding unnecessary memory overhead. + sed -i 's|StartServers.*|StartServers 2|' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ +# Keep at least 25 idle threads (one full process worth) so traffic bursts can be +# absorbed immediately without triggering new process creation. + sed -i 's|MinSpareThreads.*|MinSpareThreads 25|' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ +# Retire idle threads above 50 to reclaim memory during quiet periods. 50 is the +# minimum valid value (MinSpareThreads + ThreadsPerChild = 25 + 25) and is enough +# to absorb typical bursts without respawning a new process. + sed -i 's|MaxSpareThreads.*|MaxSpareThreads 50|' /usr/local/apache2/conf/extra/httpd-mpm.conf; \ \ rm -rf /usr/local/apache2/conf/original /var/www; \ mkdir -p /var/www; \ diff --git a/Containers/apache/nextcloud.conf b/Containers/apache/nextcloud.conf index 728d19dc..fea0c08a 100644 --- a/Containers/apache/nextcloud.conf +++ b/Containers/apache/nextcloud.conf @@ -9,6 +9,34 @@ Listen 8000 ErrorLogFormat "[%t] [%l] [%E] [client: %{X-Forwarded-For}i] [%M] [%{User-Agent}i]" LogLevel warn + # KeepAlive On: allow the same TCP connection to carry multiple HTTP requests. + # Without this each asset (JS, CSS, image) would require a full TCP handshake, + # which is especially expensive on TLS connections and noticeably slows down + # Nextcloud's login page and file manager that load dozens of resources at once. + KeepAlive On + # KeepAliveTimeout: close an idle keep-alive connection after 5 seconds. + # A short timeout frees Apache worker threads quickly so they are available + # for new requests; 5 s is long enough to cover the gap between requests + # that a browser issues while rendering a page (typically < 1 s), yet short + # enough to avoid holding threads open for idle or slow clients. + KeepAliveTimeout 5 + # MaxKeepAliveRequests: allow at most 500 requests per persistent connection. + # 100 (the Apache default) is too low for Nextcloud: the desktop and mobile + # sync clients issue many small API calls (PROPFIND, GET, PUT, checksums …) + # per sync cycle and routinely exceed 100 requests on a single connection. + # Hitting the limit forces a new TCP/TLS handshake, adding latency and CPU + # overhead. 500 gives sync clients enough headroom while still periodically + # recycling threads to contain per-process memory growth. + MaxKeepAliveRequests 500 + + # sendfile(2) is disabled because it bypasses Apache's output-filter chain: with + # it enabled, mod_brotli is silently skipped for static files (JS, CSS, SVG), + # negating the compression configured below. MMAP is also + # disabled because files can be replaced by Nextcloud at any time and mmap'd + # pages could serve stale data. + EnableSendfile Off + EnableMMAP Off + # PHP match SetHandler "proxy:fcgi://${NEXTCLOUD_HOST}:9000" @@ -17,20 +45,25 @@ Listen 8000 - # Enable Brotli compression for js, css and svg files - other plain files are compressed by Nextcloud by default + # Compress JS, CSS and SVG responses with Brotli (quality 4 gives good + # compression with reasonable CPU cost; the default of 0 barely compresses). + # Other plain-text files are already compressed by Nextcloud itself. + # No deflate fallback is needed: every browser that Nextcloud supports + # (Chrome 49+, Firefox 44+, Safari 11+, Edge 15+ — all from 2016-2017) + # supports Brotli. Internet Explorer, the only browser that never gained + # Brotli support, was dropped by Nextcloud with NC15 (2019). + # Desktop and mobile sync clients never request JS/CSS/SVG assets. AddOutputFilterByType BROTLI_COMPRESS text/javascript application/javascript application/x-javascript text/css image/svg+xml - BrotliCompressionQuality 0 + BrotliCompressionQuality 4 # Nextcloud dir DocumentRoot /var/www/html/ - Options Indexes FollowSymLinks + Options FollowSymLinks MultiViews Require all granted AllowOverride All - Options FollowSymLinks MultiViews - Satisfy Any Dav off diff --git a/Containers/apache/supervisord.conf b/Containers/apache/supervisord.conf index 7ab935e4..693b0021 100644 --- a/Containers/apache/supervisord.conf +++ b/Containers/apache/supervisord.conf @@ -1,6 +1,5 @@ [supervisord] nodaemon=true -nodaemon=true logfile=/var/log/supervisord/supervisord.log pidfile=/var/run/supervisord/supervisord.pid childlogdir=/var/log/supervisord/