Nginx Mainline provides the latest features, performance improvements, and bug fixes before they reach the stable branch. Whether you’re setting up a reverse proxy, serving static sites, or load balancing web applications, the mainline version delivers new modules, updated TLS support, and security patches ahead of the stable release cycle. This guide walks you through installing Nginx Mainline from the official nginx.org repository on Ubuntu.
Choose Your Nginx Version
The nginx.org repository offers two release branches. Understanding the differences helps you choose the right version for your environment:
| Version | Release Cycle | Best For | Trade-offs |
|---|---|---|---|
| Mainline | Frequent updates with new features | Development, testing, users who want latest capabilities | More frequent updates, potential for newer bugs |
| Stable | Only critical fixes backported | Production servers prioritizing stability | Slower access to new features |
For most users, mainline is recommended by the Nginx team because it receives all bug fixes, including those that may not be backported to stable. The mainline branch is well-tested before release and suitable for production use.
Update System Packages
Before installing new software, ensure your Ubuntu system has the latest package information and security updates:
sudo apt update && sudo apt upgrade
Install Prerequisites
Next, install the packages required to add and verify the nginx.org repository:
sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring -y
Remove Existing Nginx Installation (Optional)
If you have a previous Nginx installation from Ubuntu’s default repositories, remove it to prevent package conflicts. First, back up your existing configuration:
sudo cp -r /etc/nginx/ /etc/nginx.backup/
Then, stop the running service and remove the existing packages:
sudo systemctl stop nginx
sudo apt purge nginx nginx-common nginx-core -y
sudo apt autoremove -y
If you skip removal and install directly over an existing nginx, dpkg will prompt you about modified config files. Choose N (keep your version) to preserve your existing configuration, then manually review any differences afterward.
Import the Nginx GPG Key
Now, download and add the official Nginx signing key to verify package authenticity:
curl -fsSL https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Then, verify the downloaded key contains the correct fingerprint:
gpg --dry-run --quiet --no-keyring --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
The output should display the full fingerprint 573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62 along with additional signing keys:
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 Repository
With the GPG key in place, add the nginx.org mainline repository to your system. This command creates a repository configuration file using the modern DEB822 format:
cat <<EOF | sudo tee /etc/apt/sources.list.d/nginx.sources
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
EOF
If you prefer the stable branch instead of mainline, replace
mainline/ubuntuwithubuntuin the URIs line above.
Verify the repository was added correctly:
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
Additionally, set up APT pinning to prioritize nginx.org packages over Ubuntu’s default repositories:
cat <<EOF | sudo tee /etc/apt/preferences.d/99nginx
Package: *
Pin: origin nginx.org
Pin-Priority: 900
EOF
This pinning configuration takes effect during the next apt update. The priority value of 900 ensures nginx.org packages are preferred over Ubuntu’s default nginx packages (which have a priority of 500).
Install Nginx Mainline
Finally, update your package list to include the new repository, then install Nginx:
sudo apt update
sudo apt install nginx
During the update, you should see the nginx.org repository listed:
Get:1 https://nginx.org/packages/mainline/ubuntu noble InRelease Get:2 https://nginx.org/packages/mainline/ubuntu noble/nginx amd64 Packages
Confirm the pinning is working correctly:
apt-cache policy nginx | head -8
nginx:
Installed: (none)
Candidate: 1.29.3-1~noble
Version table:
1.29.3-1~noble 900
900 https://nginx.org/packages/mainline/ubuntu noble/nginx amd64 Packages
1.24.0-2ubuntu7 500
500 http://archive.ubuntu.com/ubuntu noble/main amd64 Packages
The nginx.org version shows priority 900, while Ubuntu’s version shows 500, confirming pinning works correctly.
Verify the Installation
Once installation completes, confirm Nginx installed correctly by checking the version:
nginx -v
The output displays the mainline version (version number will vary as nginx.org releases updates):
nginx version: nginx/1.29.x
Next, start the Nginx service and enable it to launch at boot:
sudo systemctl start nginx
sudo systemctl enable nginx
Then, verify the service is running:
systemctl status nginx
● nginx.service - nginx - high performance web server
Loaded: loaded (/lib/systemd/system/nginx.service; enabled)
Active: active (running)
Finally, test the configuration file syntax before making changes:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful
Configure Firewall Rules (Optional)
If you use UFW firewall, allow HTTP and HTTPS traffic to reach Nginx:
sudo ufw allow 'Nginx Full'
Afterward, verify the rule was added:
sudo ufw status
Status: active To Action From -- ------ ---- Nginx Full ALLOW Anywhere Nginx Full (v6) ALLOW Anywhere (v6)
This opens both ports 80 (HTTP) and 443 (HTTPS). Alternatively, to allow only HTTP traffic, use sudo ufw allow 'Nginx HTTP' instead.
Next Steps
With Nginx Mainline installed, consider these guides to extend your setup:
Ubuntu-specific stacks:
- Install WordPress with Nginx, MariaDB, and PHP to set up a complete CMS stack
- Set up FastCGI caching to dramatically improve PHP application performance
- Install Matomo with Nginx for self-hosted, privacy-focused analytics
- Install phpMyAdmin with LEMP for a web-based database management interface
- Build Nginx from source if you need custom modules or compile-time options
Nginx configuration:
- Enable Gzip compression to reduce bandwidth and improve page load times
- Configure security headers to protect against XSS, clickjacking, and other attacks
- Set up rate limiting to protect against brute-force attacks and abuse
- Create a reverse proxy to route traffic to backend applications
- Configure www/non-www redirects to standardize your domain format
Remove Nginx Mainline
To completely remove Nginx and the nginx.org repository from your system:
sudo systemctl stop nginx
sudo apt purge nginx -y
sudo apt autoremove -y
Afterward, remove the repository configuration and GPG key:
sudo rm /etc/apt/sources.list.d/nginx.sources
sudo rm /etc/apt/preferences.d/99nginx
sudo rm /usr/share/keyrings/nginx-archive-keyring.gpg
Note that configuration files in
/etc/nginx/remain after package removal. Therefore, delete this directory only if you no longer need your server blocks and settings.
Conclusion
You now have Nginx Mainline installed from the official nginx.org repository with APT pinning ensuring future updates come from nginx.org. To maintain your installation, keep it current with sudo apt update && sudo apt upgrade, and always test configuration changes with nginx -t before reloading. From here, consider enabling Gzip compression to improve page load times or setting up FastCGI caching if you’re serving PHP applications.
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.