diff --git a/data/Dockerfiles/nginx/bootstrap.py b/data/Dockerfiles/nginx/bootstrap.py index f294e7cce..aa85c8b2b 100644 --- a/data/Dockerfiles/nginx/bootstrap.py +++ b/data/Dockerfiles/nginx/bootstrap.py @@ -58,6 +58,7 @@ def prepare_template_vars(): 'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"), 'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"), 'DISABLE_IPv6': os.getenv("DISABLE_IPv6", "n").lower() in ("y", "yes"), + 'HTTP_REDIRECT': os.getenv("HTTP_REDIRECT", "n").lower() in ("y", "yes"), } ssl_dir = '/etc/ssl/mail/' diff --git a/data/conf/nginx/templates/nginx.conf.j2 b/data/conf/nginx/templates/nginx.conf.j2 index b35aeeea3..2bb601c50 100644 --- a/data/conf/nginx/templates/nginx.conf.j2 +++ b/data/conf/nginx/templates/nginx.conf.j2 @@ -41,15 +41,42 @@ http { https https; } + {% if HTTP_REDIRECT %} + # HTTP to HTTPS redirect + server { + root /web; + listen {{ HTTP_PORT }} default_server; + listen [::]:{{ HTTP_PORT }} default_server; + + server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES | join(' ') }}; + + if ( $request_uri ~* "%0A|%0D" ) { return 403; } + location ^~ /.well-known/acme-challenge/ { + allow all; + default_type "text/plain"; + } + location / { + return 301 https://$host$uri$is_args$args; + } + } + {%endif%} + # Default Server Name server { listen 127.0.0.1:65510; # sogo-auth verify internal + + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate /etc/ssl/mail/cert.pem; @@ -64,12 +91,19 @@ http { {% for SERVER_NAME in ADDITIONAL_SERVER_NAMES %} server { listen 127.0.0.1:65510; # sogo-auth verify internal + + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate /etc/ssl/mail/cert.pem; @@ -127,12 +161,18 @@ http { {% for cert in valid_cert_dirs %} server { + {% if not HTTP_REDIRECT %} listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; + {% if not DISABLE_IPv6 %} + {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; + {%endif%} listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; {%endif%} + http2 on; ssl_certificate {{ cert.cert_path }}cert.pem; diff --git a/docker-compose.yml b/docker-compose.yml index 626c957c0..421610bac 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -385,6 +385,7 @@ services: - SKIP_SOGO=${SKIP_SOGO:-n} - SKIP_RSPAMD=${SKIP_RSPAMD:-n} - DISABLE_IPv6=${DISABLE_IPv6:-n} + - HTTP_REDIRECT=${HTTP_REDIRECT:-n} - PHPFPMHOST=${PHPFPMHOST:-} - SOGOHOST=${SOGOHOST:-} - RSPAMDHOST=${RSPAMDHOST:-} diff --git a/generate_config.sh b/generate_config.sh index 8f03e3899..e3faf7bb7 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -267,6 +267,9 @@ HTTP_BIND= HTTPS_PORT=443 HTTPS_BIND= +# Redirect HTTP connections to HTTPS - y/n +HTTP_REDIRECT=n + # ------------------------------ # Other bindings # ------------------------------ diff --git a/update.sh b/update.sh index 4240dad37..c11179c5e 100755 --- a/update.sh +++ b/update.sh @@ -352,6 +352,7 @@ adapt_new_options() { "SPAMHAUS_DQS_KEY" "SKIP_UNBOUND_HEALTHCHECK" "DISABLE_NETFILTER_ISOLATION_RULE" + "HTTP_REDIRECT" ) sed -i --follow-symlinks '$a\' mailcow.conf @@ -637,7 +638,13 @@ adapt_new_options() { echo '# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n' >> mailcow.conf echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf - fi + fi + elif [[ ${option} == "HTTP_REDIRECT" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" + echo '# Redirect HTTP connections to HTTPS - y/n' >> mailcow.conf + echo 'HTTP_REDIRECT=n' >> mailcow.conf + fi elif ! grep -q ${option} mailcow.conf; then echo "Adding new option \"${option}\" to mailcow.conf" echo "${option}=n" >> mailcow.conf