From 12d719f222fae1ea0c2b25793aeb1d040947ebbe Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Fri, 3 Jul 2026 19:05:04 -0300 Subject: [PATCH 1/2] [feature] Added support for pre-compressed gzip/brotli files #560 Closes #560 --- docs/user/settings.rst | 8 ++++ images/openwisp_dashboard/module_settings.py | 4 -- images/openwisp_nginx/Dockerfile | 42 ++++++++++++++++++- images/openwisp_nginx/nginx.template.conf | 2 + .../openwisp_nginx/openwisp.ssl.template.conf | 3 +- images/openwisp_nginx/openwisp.template.conf | 2 + 6 files changed, 55 insertions(+), 6 deletions(-) diff --git a/docs/user/settings.rst b/docs/user/settings.rst index a2425c8c..950bd231 100644 --- a/docs/user/settings.rst +++ b/docs/user/settings.rst @@ -951,6 +951,14 @@ Nginx application/x-font-ttf font/opentype``. - **Default:** ``\*``. +``NGINX_BROTLI_SWITCH`` +~~~~~~~~~~~~~~~~~~~~~~~ + +- **Explanation:** Enables or disables serving precompressed Brotli files + from the static files directory. +- **Valid Values:** ``on``, ``off``. +- **Default:** ``on``. + ``NGINX_HTTPS_ALLOWED_IPS`` ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/images/openwisp_dashboard/module_settings.py b/images/openwisp_dashboard/module_settings.py index 6c092abf..0fb7faba 100644 --- a/images/openwisp_dashboard/module_settings.py +++ b/images/openwisp_dashboard/module_settings.py @@ -85,10 +85,6 @@ "BACKEND": "openwisp_utils.storage.CompressStaticFilesStorage", }, } -BROTLI_STATIC_COMPRESSION = False -# pregenerate static gzip files to save CPU -GZIP_STATIC_COMPRESSION = True - HTTP_SCHEME = request_scheme() HTTP_PORT = ( os.getenv("NGINX_SSL_PORT", "443") diff --git a/images/openwisp_nginx/Dockerfile b/images/openwisp_nginx/Dockerfile index 1210fdb6..38bda115 100644 --- a/images/openwisp_nginx/Dockerfile +++ b/images/openwisp_nginx/Dockerfile @@ -1,7 +1,46 @@ -FROM nginx:1.31.2-alpine +ARG NGINX_VERSION=1.31.2 + +# Build the nginx brotli module against nginx.org's nginx package used by this image. +# Alpine's nginx module packages target Alpine's own nginx build. +FROM nginx:${NGINX_VERSION}-alpine AS brotli-builder + +ARG NGINX_VERSION +ARG NGX_BROTLI_VERSION=v1.0.0rc + +# hadolint ignore=DL3003,DL3018 +RUN apk add --update --no-cache \ + brotli-dev \ + build-base \ + git \ + linux-headers \ + openssl-dev \ + pcre2-dev \ + zlib-dev && \ + git clone --depth 1 --branch ${NGX_BROTLI_VERSION} --recurse-submodules \ + https://github.com/google/ngx_brotli.git /tmp/ngx_brotli && \ + wget -q https://nginx.org/download/nginx-${NGINX_VERSION}.tar.gz \ + -O /tmp/nginx-${NGINX_VERSION}.tar.gz && \ + tar xzf /tmp/nginx-${NGINX_VERSION}.tar.gz -C /tmp && \ + cd /tmp/nginx-${NGINX_VERSION} && \ + ./configure \ + --with-compat \ + --with-cc-opt='-Wno-error=unterminated-string-initialization -Wno-error=vla-parameter' \ + --add-dynamic-module=/tmp/ngx_brotli && \ + make modules + +FROM nginx:${NGINX_VERSION}-alpine + +ARG NGINX_VERSION + +RUN mkdir -p /etc/nginx/modules + +COPY --from=brotli-builder \ + /tmp/nginx-${NGINX_VERSION}/objs/ngx_http_brotli_static_module.so \ + /etc/nginx/modules/ngx_http_brotli_static_module.so # hadolint ignore=DL3018 RUN apk add --update --no-cache \ + brotli-libs \ py3-pip \ certbot \ certbot-nginx \ @@ -41,6 +80,7 @@ ENV MODULE_NAME=nginx \ NGINX_GZIP_PROXIED=any \ NGINX_GZIP_MIN_LENGTH=1000 \ NGINX_GZIP_TYPES='text/plain image/svg+xml application/json application/javascript text/xml text/css application/xml application/x-font-ttf font/opentype' \ + NGINX_BROTLI_SWITCH=on \ NGINX_CUSTOM_FILE=False \ NGINX_WORKER_PROCESSES=1 \ NGINX_WORKER_CONNECTIONS=1024 \ diff --git a/images/openwisp_nginx/nginx.template.conf b/images/openwisp_nginx/nginx.template.conf index bf5e15e2..aad7f3f8 100644 --- a/images/openwisp_nginx/nginx.template.conf +++ b/images/openwisp_nginx/nginx.template.conf @@ -3,6 +3,8 @@ # Changes in given http block reflect in # all openwisp server blocks. +load_module modules/ngx_http_brotli_static_module.so; + user nginx; worker_processes ${NGINX_WORKER_PROCESSES}; worker_rlimit_nofile ${NGINX_WORKER_RLIMIT_NOFILE}; diff --git a/images/openwisp_nginx/openwisp.ssl.template.conf b/images/openwisp_nginx/openwisp.ssl.template.conf index 1d9259c1..8b5ff47e 100644 --- a/images/openwisp_nginx/openwisp.ssl.template.conf +++ b/images/openwisp_nginx/openwisp.ssl.template.conf @@ -27,7 +27,6 @@ server { # GZIP Configurations gzip ${NGINX_GZIP_SWITCH}; - gzip_static ${NGINX_GZIP_SWITCH}; gzip_comp_level ${NGINX_GZIP_LEVEL}; gzip_proxied ${NGINX_GZIP_PROXIED}; gzip_min_length ${NGINX_GZIP_MIN_LENGTH}; @@ -62,6 +61,8 @@ server { deny all; } location /static/ { + gzip_static ${NGINX_GZIP_SWITCH}; + brotli_static ${NGINX_BROTLI_SWITCH}; try_files /custom${DOLLAR}uri /${DOLLAR}uri; } location / { diff --git a/images/openwisp_nginx/openwisp.template.conf b/images/openwisp_nginx/openwisp.template.conf index 2c162c65..4ab8276d 100644 --- a/images/openwisp_nginx/openwisp.template.conf +++ b/images/openwisp_nginx/openwisp.template.conf @@ -34,6 +34,8 @@ server { proxy_set_header Connection "upgrade"; } location /static/ { + gzip_static ${NGINX_GZIP_SWITCH}; + brotli_static ${NGINX_BROTLI_SWITCH}; try_files /custom${DOLLAR}uri /${DOLLAR}uri; } location / { From d0931d5dc689ec7862778c0181f429d0eb4493c5 Mon Sep 17 00:00:00 2001 From: Federico Capoano Date: Sat, 4 Jul 2026 16:38:22 -0300 Subject: [PATCH 2/2] [fix] Serve precompressed static files in nginx --- images/openwisp_nginx/openwisp.ssl.template.conf | 7 ++++++- images/openwisp_nginx/openwisp.template.conf | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/images/openwisp_nginx/openwisp.ssl.template.conf b/images/openwisp_nginx/openwisp.ssl.template.conf index 8b5ff47e..d4d75cae 100644 --- a/images/openwisp_nginx/openwisp.ssl.template.conf +++ b/images/openwisp_nginx/openwisp.ssl.template.conf @@ -60,10 +60,15 @@ server { allow $NGINX_ADMIN_ALLOW_NETWORK; deny all; } + location /static/custom/ { + alias /opt/openwisp/public/custom/static/custom/; + gzip_static ${NGINX_GZIP_SWITCH}; + brotli_static ${NGINX_BROTLI_SWITCH}; + } location /static/ { + alias /opt/openwisp/public/static/; gzip_static ${NGINX_GZIP_SWITCH}; brotli_static ${NGINX_BROTLI_SWITCH}; - try_files /custom${DOLLAR}uri /${DOLLAR}uri; } location / { try_files /custom/maintenance.html ${DOLLAR}uri ${DOLLAR}uri/index.html @uwsgi; diff --git a/images/openwisp_nginx/openwisp.template.conf b/images/openwisp_nginx/openwisp.template.conf index 4ab8276d..9d4f29df 100644 --- a/images/openwisp_nginx/openwisp.template.conf +++ b/images/openwisp_nginx/openwisp.template.conf @@ -33,10 +33,15 @@ server { proxy_set_header Upgrade ${DOLLAR}http_upgrade; proxy_set_header Connection "upgrade"; } + location /static/custom/ { + alias /opt/openwisp/public/custom/static/custom/; + gzip_static ${NGINX_GZIP_SWITCH}; + brotli_static ${NGINX_BROTLI_SWITCH}; + } location /static/ { + alias /opt/openwisp/public/static/; gzip_static ${NGINX_GZIP_SWITCH}; brotli_static ${NGINX_BROTLI_SWITCH}; - try_files /custom${DOLLAR}uri /${DOLLAR}uri; } location / { error_page 403 = @deny;