diff --git a/_modules/scripts/new_options.sh b/_modules/scripts/new_options.sh index 840700148..7d67799ba 100644 --- a/_modules/scripts/new_options.sh +++ b/_modules/scripts/new_options.sh @@ -60,6 +60,7 @@ adapt_new_options() { "ACME_DNS_CHALLENGE" "ACME_DNS_PROVIDER" "ACME_ACCOUNT_EMAIL" + "NGINX_MAX_BODY_SIZE" ) sed -i --follow-symlinks '$a\' mailcow.conf @@ -309,6 +310,11 @@ adapt_new_options() { echo '# Account email for ACME DNS-01 challenge registration' >> mailcow.conf echo 'ACME_ACCOUNT_EMAIL=me@example.com' >> mailcow.conf ;; + NGINX_MAX_BODY_SIZE) + echo '# Maximum request size for SOGo webmail, CalDAV/CardDAV and ActiveSync, e.g. 128m or 1g - 0 means unlimited' >> mailcow.conf + echo '# Keep it above the message size limit of Postfix (100 MB by default). The mailcow UI and API stay limited to 64m.' >> mailcow.conf + echo 'NGINX_MAX_BODY_SIZE=128m' >> mailcow.conf + ;; *) echo "${option}=" >> mailcow.conf ;; diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index 97ce7a4e1..b48b26f50 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -1,4 +1,5 @@ import os +import re import subprocess from jinja2 import Environment, FileSystemLoader @@ -44,6 +45,11 @@ def prepare_template_vars(): ipv4_network = os.getenv("IPV4_NETWORK", "172.22.1") additional_server_names = os.getenv("ADDITIONAL_SERVER_NAMES", "") trusted_proxies = os.getenv("TRUSTED_PROXIES", "") + # nginx size syntax, invalid values fall back to the default + max_body_size = os.getenv("NGINX_MAX_BODY_SIZE", "128m").strip() + if not re.fullmatch(r'[0-9]+[kKmMgG]?', max_body_size): + print(f"Invalid NGINX_MAX_BODY_SIZE '{max_body_size}', using 128m") + max_body_size = "128m" template_vars = { 'IPV4_NETWORK': ipv4_network, @@ -60,6 +66,7 @@ def prepare_template_vars(): 'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"), 'ENABLE_IPV6': os.getenv("ENABLE_IPV6", "true").lower() != "false", 'HTTP_REDIRECT': os.getenv("HTTP_REDIRECT", "n").lower() in ("y", "yes"), + 'NGINX_MAX_BODY_SIZE': max_body_size, } ssl_dir = '/etc/ssl/mail/' diff --git a/data/conf/nginx/templates/sites-default.conf.j2 b/data/conf/nginx/templates/sites-default.conf.j2 index 9cd60a343..2082c6822 100644 --- a/data/conf/nginx/templates/sites-default.conf.j2 +++ b/data/conf/nginx/templates/sites-default.conf.j2 @@ -22,7 +22,8 @@ add_header Referrer-Policy strict-origin; index index.php index.html; -client_max_body_size 0; +# PHP accepts no larger requests (post_max_size), SOGo webmail, CalDAV/CardDAV and ActiveSync use NGINX_MAX_BODY_SIZE +client_max_body_size 64m; gzip on; gzip_disable "msie6"; @@ -182,6 +183,8 @@ location /sogo-auth-verify { proxy_set_header Content-Length ""; proxy_pass http://127.0.0.1:65510/sogo-auth; proxy_pass_request_body off; + # The subrequest checks the size of the original request against this limit, the body is never read here + client_max_body_size {{ NGINX_MAX_BODY_SIZE }}; } location ^~ /Microsoft-Server-ActiveSync { @@ -205,7 +208,7 @@ location ^~ /Microsoft-Server-ActiveSync { proxy_busy_buffers_size 512k; proxy_set_header Host $http_host; client_body_buffer_size 512k; - client_max_body_size 0; + client_max_body_size {{ NGINX_MAX_BODY_SIZE }}; } location ^~ /SOGo { @@ -256,7 +259,7 @@ location ^~ /SOGo { proxy_send_timeout 3600; proxy_read_timeout 3600; client_body_buffer_size 128k; - client_max_body_size 0; + client_max_body_size {{ NGINX_MAX_BODY_SIZE }}; break; } diff --git a/docker-compose.yml b/docker-compose.yml index c77c7baaa..4e2598ed8 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -427,7 +427,7 @@ services: - php-fpm-mailcow - sogo-mailcow - rspamd-mailcow - image: ghcr.io/mailcow/nginx:1.30.6-1 + image: ghcr.io/mailcow/nginx:1.30.6-2 dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: @@ -447,6 +447,7 @@ services: - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - NGINX_USE_PROXY_PROTOCOL=${NGINX_USE_PROXY_PROTOCOL:-n} - TRUSTED_PROXIES=${TRUSTED_PROXIES:-} + - NGINX_MAX_BODY_SIZE=${NGINX_MAX_BODY_SIZE:-128m} volumes: - ./data/web:/web:ro,z - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z diff --git a/generate_config.sh b/generate_config.sh index fe525b91b..5d76e5ea5 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -215,6 +215,10 @@ HTTPS_BIND= # Redirect HTTP connections to HTTPS - y/n HTTP_REDIRECT=y +# Maximum request size for SOGo webmail, CalDAV/CardDAV and ActiveSync, e.g. 128m or 1g - 0 means unlimited +# Keep it above the message size limit of Postfix (100 MB by default). The mailcow UI and API stay limited to 64m. +NGINX_MAX_BODY_SIZE=128m + # ------------------------------ # Other bindings # ------------------------------