Installing Nginx Mainline on Ubuntu from the nginx.org APT repository gives you upstream mainline packages instead of the release-frozen Nginx builds in Ubuntu’s default archive. Use this path when you specifically want nginx.org mainline updates delivered through APT with repository pinning, while keeping the package separate from Ubuntu’s older archive version.
Mainline is a branch choice, not always the highest visible version number at every point in the Nginx release cycle. If you want nginx.org’s current stable branch instead, use the guide on how to install Nginx on Ubuntu.
Compare Nginx Mainline, Stable, and Ubuntu Packages
Nginx packages for Ubuntu can come from three practical sources: Ubuntu’s own archive, the nginx.org stable repository, or the nginx.org mainline repository. The source controls how quickly you receive upstream changes and which packaging assumptions apply.
| Package Source | Branch or Version Cadence | Best Fit | Trade-off |
|---|---|---|---|
| Ubuntu repository package | Release-frozen package series, such as 1.28.x on 26.04, 1.24.x on 24.04, and 1.18.x on 22.04 | Servers that prioritize Ubuntu archive integration and fewer upstream branch changes | Older Nginx feature set on long-term support releases |
| nginx.org stable repository | Current upstream stable branch, currently 1.30.x | Servers that want upstream Nginx packages but prefer the stable branch | New feature work waits for the next stable branch |
| nginx.org mainline repository | Mainline branch packages, currently 1.29.x until the next mainline branch opens | Servers that intentionally track mainline branch updates from nginx.org | New features can affect third-party module compatibility sooner |
The installation path here uses the nginx.org Linux package repository for mainline packages on Ubuntu 26.04, 24.04, and 22.04. Current nginx.org metadata publishes separate suites for resolute, noble, and jammy, so no older-suite workaround is needed.
If you came here for the Ondrej PPA, keep the source distinction clear.
ppa:ondrej/nginxis third-party packaging that Launchpad currently labels as NGINX Stable, and Launchpad now labels the oldppa:ondrej/nginx-mainlinebuilds as deprecated. This installation flow uses nginx.org directly instead.
Install Nginx Mainline on Ubuntu
Update Ubuntu and Install Prerequisites
Refresh your package lists before adding the nginx.org repository:
sudo apt update && sudo apt upgrade
Commands that need root privileges use
sudo. If your account is not configured for sudo yet, follow the guide on how to add a new user to sudoers on Ubuntu.
Install the tools needed to fetch the signing key, inspect the key, and detect your Ubuntu codename:
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y
The lsb-release package provides lsb_release, and gnupg2 provides the gpg commands used to convert and verify the repository key.
Remove Existing Ubuntu Nginx Packages (Optional)
If Ubuntu’s archive Nginx package is already installed, back up the configuration before switching package sources:
sudo cp -a /etc/nginx /etc/nginx.backup
Stop the service and purge the archive packages. Skip this block on fresh systems where Nginx is not installed yet.
sudo systemctl stop nginx
sudo apt purge nginx nginx-common nginx-core
Review optional dependency cleanup separately so unrelated packages are not removed by surprise:
sudo apt autoremove --dry-run
If the preview only lists packages you no longer need, run the cleanup without forcing automatic confirmation:
sudo apt autoremove
If you install over an existing Nginx package without purging first, dpkg may ask whether to keep modified configuration files. Choose the keep-current-file option when you need to preserve existing server blocks, then compare any package-provided changes afterward.
Import the Nginx Signing Key
Fetch the official Nginx signing key, convert it to a binary keyring, and place it where the repository definition can reference it:
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg > /dev/null
Inspect the imported key before trusting the repository:
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
Relevant output should include the Nginx signing fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62. The key file can also contain newer signing keys used by nginx.org.
pub rsa4096 2024-05-29 [SC]
8540A6F18833A80E9C1653A42FD21310B49F6B46
uid nginx signing key <signing-key-2@nginx.com>
pub rsa2048 2011-08-19 [SC] [expires: 2027-05-24]
573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62
uid nginx signing key <signing-key@nginx.com>
pub rsa4096 2024-05-29 [SC]
9E9BE90EACBCDE69FE9B204CBCDCD8A38D88A2B3
uid nginx signing key <signing-key-3@nginx.com>
Add the Nginx Mainline Repository
Create a DEB822 source file for the nginx.org mainline repository:
printf '%s\n' \
'Types: deb' \
'URIs: https://nginx.org/packages/mainline/ubuntu' \
"Suites: $(lsb_release -cs)" \
'Components: nginx' \
"Architectures: $(dpkg --print-architecture)" \
'Signed-By: /usr/share/keyrings/nginx-archive-keyring.gpg' | sudo tee /etc/apt/sources.list.d/nginx.sources > /dev/null
The codename and architecture are inserted automatically. On supported Ubuntu LTS releases, that resolves to resolute on 26.04, noble on 24.04, and jammy on 22.04.
Confirm that the source file points at the mainline repository and the correct suite:
cat /etc/apt/sources.list.d/nginx.sources
Types: deb URIs: https://nginx.org/packages/mainline/ubuntu Suites: noble Components: nginx Architectures: amd64 Signed-By: /usr/share/keyrings/nginx-archive-keyring.gpg
Configure APT Pinning for Nginx
Pin nginx.org packages at priority 900 so APT prefers them over Ubuntu’s archive packages when package names overlap:
printf '%s\n' \
'Package: *' \
'Pin: origin nginx.org' \
'Pin-Priority: 900' | sudo tee /etc/apt/preferences.d/99nginx > /dev/null
Priority 900 keeps nginx.org ahead of Ubuntu archive packages, which normally appear at priority 500. It does not make unrelated third-party repositories safer, so keep this pin tied to the nginx.org origin only.
Install the Nginx Mainline Package
Update package metadata after adding the source:
sudo apt update
Check the candidate before installation so you can confirm APT is selecting nginx.org at priority 900:
apt-cache policy nginx
nginx:
Installed: (none)
Candidate: 1.29.x-1~noble
Version table:
1.29.x-1~noble 900
900 https://nginx.org/packages/mainline/ubuntu noble/nginx amd64 Packages
1.24.0-2ubuntu7.x 500
500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
Install Nginx when the candidate comes from nginx.org:
sudo apt install nginx
Verify Nginx Mainline on Ubuntu
Confirm the installed Nginx version:
nginx -v
nginx version: nginx/1.29.x
The nginx.org package may not start the service automatically. Start it now and enable it for future boots:
sudo systemctl start nginx
sudo systemctl enable nginx
Use narrow service checks for normal verification:
systemctl is-active nginx
systemctl is-enabled nginx
active enabled
Test the configuration syntax:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Probe the local listener when Nginx is running on the default port:
curl -I http://127.0.0.1/
HTTP/1.1 200 OK Server: nginx/1.29.x Content-Type: text/html
Configure UFW Firewall Rules for Nginx
If you use UFW firewall on Ubuntu, allow HTTP and HTTPS traffic to reach Nginx. The nginx.org package does not ship Ubuntu’s Nginx Full, Nginx HTTP, or Nginx HTTPS UFW application profiles, so open the ports directly.
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
Verify the rules:
sudo ufw status
Status: active To Action From -- ------ ---- 80/tcp ALLOW Anywhere 443/tcp ALLOW Anywhere 80/tcp (v6) ALLOW Anywhere (v6) 443/tcp (v6) ALLOW Anywhere (v6)
Open only the ports your site needs. HTTP-only sites need port 80, HTTPS sites need port 443, and most certificate issuance workflows still need port 80 available for validation or redirects.
Troubleshoot Nginx Mainline on Ubuntu
Nginx Fails to Start with Address Already in Use
If Nginx cannot bind to port 80, check which process owns the listener:
sudo ss -tlnp | grep ':80'
If Apache or another web server is already using the port, stop that service before starting Nginx:
sudo systemctl stop apache2
sudo systemctl disable apache2
sudo systemctl start nginx
APT Reports a Nginx GPG Key Error
If sudo apt update reports a signature error for the nginx.org repository, recreate the keyring and refresh package metadata:
sudo rm -f /usr/share/keyrings/nginx-archive-keyring.gpg
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg > /dev/null
sudo apt update
Nginx Reports CPU ISA Level Is Lower Than Required
On some Ubuntu 26.04 amd64 systems, especially virtual machines that do not expose AVX and related CPU flags, the current nginx.org package can fail with a CPU ISA message:
nginx: CPU ISA level is lower than required
This error means the installed binary needs CPU features your environment is not exposing. On a VM, enable host CPU passthrough or AVX/AVX2 support if your hypervisor offers it. If the host cannot expose those features, purge the failed nginx.org package and use Ubuntu’s archive package or a source-build path instead.
sudo apt purge nginx
Ubuntu Brotli Module Package Does Not Install with Nginx Mainline
Ubuntu dynamic module packages are built for Ubuntu’s Nginx ABI, not the nginx.org mainline ABI. For example, Ubuntu 24.04’s libnginx-mod-http-brotli-filter package depends on nginx-abi-1.24.0-1, so it cannot be installed beside nginx.org mainline 1.29.x.
sudo apt install nginx libnginx-mod-http-brotli-filter
libnginx-mod-http-brotli-filter : Depends: nginx-abi-1.24.0-1 E: Unable to correct problems, you have held broken packages.
If you need Brotli or another third-party module with nginx.org mainline, use a module path that matches that Nginx build, or consider building Nginx from source on Ubuntu. Do not force Ubuntu ABI module packages onto nginx.org mainline.
Nginx Config Test Shows Errors After Switching Packages
If sudo nginx -t reports errors after switching from Ubuntu’s package to nginx.org mainline, compare your configuration with the backup and check the Nginx changelog for branch changes that affect directives or modules:
diff /etc/nginx/nginx.conf /etc/nginx.backup/nginx.conf
Update Nginx Mainline on Ubuntu
Because nginx.org is configured as an APT source, normal package upgrades deliver future mainline updates:
sudo apt update
sudo apt upgrade
To update only the Nginx package while leaving other upgrades for a later maintenance window, target the package directly:
sudo apt install --only-upgrade nginx
Extend Your Nginx Mainline Setup on Ubuntu
After Nginx Mainline is installed, these related guides cover common web-server stacks, tuning tasks, and security layers:
Nginx Web Application Stacks on Ubuntu
- Install WordPress with Nginx, MariaDB, and PHP on Ubuntu for a complete CMS stack
- Set up Nginx FastCGI caching on Ubuntu to improve PHP application performance
- Install Matomo with Nginx on Ubuntu for self-hosted analytics
- Install phpMyAdmin with LEMP on Ubuntu for browser-based database administration
- Build Nginx from source on Ubuntu when packaged modules do not cover your requirements
Nginx Performance and Security on Ubuntu
- Enable Gzip compression in Nginx to reduce transfer size
- Configure security headers in Nginx to harden browser responses
- Set up rate limiting in Nginx to reduce abuse against exposed endpoints
- Create a reverse proxy in Nginx to pass traffic to backend services
- Configure www/non-www redirects in Nginx to standardize your canonical host
- Install Fail2Ban on Ubuntu to block repeated malicious requests
Remove Nginx Mainline from Ubuntu
Stop and disable the service before removing the package:
sudo systemctl disable --now nginx
sudo apt purge nginx
Remove the nginx.org source and pinning file. Delete the keyring only if no other nginx.org repository on the system uses it.
sudo rm -f /etc/apt/sources.list.d/nginx.sources
sudo rm -f /etc/apt/preferences.d/99nginx
sudo rm -f /usr/share/keyrings/nginx-archive-keyring.gpg
sudo apt update
Confirm that the nginx.org source is gone and no Nginx package remains installed:
dpkg-query -W -f='${db:Status-Abbrev} ${binary:Package}\n' nginx 2>/dev/null | grep '^ii' || echo "nginx package is not installed"
apt-cache policy nginx
nginx package is not installed
nginx:
Installed: (none)
Candidate: 1.24.0-2ubuntu7.x
Version table:
1.24.0-2ubuntu7.x 500
500 http://archive.ubuntu.com/ubuntu noble-updates/main amd64 Packages
If you no longer need any server blocks, TLS snippets, or local site configuration, remove the remaining configuration directory after reviewing its contents:
sudo rm -rf /etc/nginx
Preview optional dependency cleanup before running it:
sudo apt autoremove --dry-run
If the preview only includes packages you intend to remove, run the cleanup interactively:
sudo apt autoremove
Conclusion
Nginx Mainline is now installed from nginx.org with APT pinning, so future branch updates arrive through normal package management. Keep configuration checks part of each change cycle with sudo nginx -t, and use the related Nginx tuning and stack guides when you are ready to add caching, reverse proxy rules, security headers, or a full application stack.


Thanks so much for this guide. It was excellent! I used this to upgrade from 1.24.0 on Ubuntu 24.04 to 1.27.1.
I chose to
cp -rp /etc/nginx /etc/nginx.bak
rather than
mv /etc/nginx /etc/nginx.old
I wasn’t sure if a running Nginx service would have an issue moving the directory.
When I ran
apt autoremove nginx*
I got
E: Unable to locate package nginx.bak
E: Couldn’t find any package by glob ‘nginx.bak’
That may have been because I ran it from the /etc directory, and it picked up the nginx.bak directory I created there. So, instead, I ran
apt autoremove nginx nginx-common nginx-doc
which were all of the packages I had installed.
There may need to be a note at the end stating that if you upgraded from a prior install and you moved the /etc/nginx directory to /etc/nginx.old, you must selectively copy some or all of the files from /etc/nginx.old into the newly created/etc/nginx directory to restore the previous website functionality. Some changes may also be needed if the nginx configuration changes between releases.
If you choose to copy rather than move the /etc/nginx directory, there will be a prompt during installation:
Configuration file ‘/etc/nginx/nginx.conf’
==> Modified (by you or by a script) since installation.
==> Package distributor has shipped an updated version.
What would you like to do about it ? Your options are:
Y or I : install the package maintainer’s version
N or O : keep your currently-installed version
D : show the differences between the versions
Z : start a shell to examine the situation
The default action is to keep your current version.
*** nginx.conf (Y/I/N/O/D/Z) [default=N] ? n
I could not install Brotli Compression. The package libnginx-mod-brotli seems to exist in nginx 1.25.1 but not in 1.27.1. I found a suggestion that it is now in libnginx-mod-http-brotli-filter and libnginx-mod-http-brotli-static, but when I try to install them, they have unmet dependencies.
Thanks for the detailed feedback, Craig. Your observations about the upgrade process are spot on, and the article has since been updated to address several of these points.
You are correct about using
cp -rpinstead ofmv. The updated guide now usescp -rto preserve the original directory during upgrades. The glob expansion issue you encountered withapt autoremove nginx*is a common pitfall. The shell expandsnginx*to match files in the current directory before apt sees it. The guide now specifies exact package names to avoid this.Regarding Brotli, you are right that
libnginx-mod-brotliis unavailable from nginx.org packages. The nginx.org repository provides a minimal package set without third-party modules. For Brotli support with mainline nginx, you would need to compile from source with the Brotli module included.Your tip about the dpkg config prompt is valuable. Users upgrading from an existing installation should generally keep their current version (N) when prompted, then manually merge any needed changes afterward.