nginx 1.31.4 Mainline with HTTP/3 support has been added to the CodeIT repository. http2 and ngx_cache_purge are built in, and OpenSSL is linked dynamically against the official OpenSSL 4.0.1 with QUIC support. The Brotli compression module from Google and ngx_http_geoip2 ship as dynamic modules, in nginx-module-brotli and nginx-module-geoip2, which the nginx rpm pulls in automatically (kept as a dependency so that existing installations upgrade without losing those directives; it will be dropped in a few months, and both modules then become truly optional). The packages are built for RHEL, CentOS, AlmaLinux, Rocky Linux and Oracle Linux 7, 8, 9 and 10, and for Ubuntu 22.04 and 24.04.
More dynamic modules are packaged alongside and are optional: nginx-module-lua with lua-resty-core and lua-resty-lrucache, nginx-module-acme for automatic ACMEv2 certificates, nginx-module-njs, nginx-module-perl, nginx-module-xslt and nginx-module-image-filter. Each one ships its own load_module line in /etc/nginx/modules-enabled, so it works the moment it is installed and nothing has to be added to nginx.conf by hand. Lua and ACME are built for EL9, EL10 and Ubuntu; EL7 gets nginx-module-geoip instead, and njs, Perl, XSLT and image-filter are RPM only.
The same release is on Docker Hub as codeitus/nginx, built on AlmaLinux 9 from these packages and published for amd64 and arm64:
- the newest image, from whichever pool was released last: docker pull codeitus/nginx
- the newest Mainline image: docker pull codeitus/nginx:mainline
- this exact release: docker pull codeitus/nginx:1.31.4
HTTP/3 needs the UDP port published as well as the TCP ones: docker run -d -p 80:80 -p 443:443 -p 443:443/udp codeitus/nginx
Major changes:
- Feature: the “proxy_protocol” directive in the stream and mail modules now supports the PROXY protocol version 2.
- Change: now HTTP/2 and gRPC requests to backends are always sent with the “:authority” pseudo-header, and HTTP/1.1 requests – with the “Host” header.
- Bugfix: a segmentation fault might occur in a worker process if the “select” method was used.
- Bugfix: incomplete gRPC responses with a non-zero “Content-Length” header line are now treated as malformed.
- Bugfix: in binary compatibility with third-party modules using script codes; the bug had appeared in 1.31.3.
- Bugfix: in the ngx_http_perl_module.
- Bugfixes in HTTP/2, HTTP/3, ngx_http_image_filter_module, and ngx_http_grpc_module.

Hi Alexander,
I’ve noticed that doing a fresh install of the nginx-1.31.4 (mainline) package creates the user ‘apache’ instead:
# cat /etc/passwd | grep nginx
apache:x:994:994:nginx user:/var/cache/nginx:/sbin/nologin
This does not happen with the previous version (1.31.3), where the user created is ‘nginx’.
OS: Rocky Linux 10, x86_64
Could you please check whether this is a typo/bug or intended behavior?
Thank you.
Hi Alessio,
Thanks for the report — it was intended, but it was the wrong call. 1.31.4 came with a large packaging rework, and part of it made the package create the account our shipped nginx.conf has long named (user apache;), which otherwise left nginx refusing to start on hosts without httpd. Changing the account a package runs as in a minor bump only adds pain for everyone else, so we’re reverting to stock: user nginx; in the config and nginx created by the package, exactly as nginx.org does it. Build 2 of 1.31.4 ships today with that fix, plus a one-time %post correction that hands /var/cache/nginx back to nginx so upgrades from build 1 come across cleanly — nothing to do by hand.
Alexander