How To Install Nginx Mainline Version on Fedora 44

Install Nginx Mainline Version on Fedora 44

Fedora 44 ships with a Fedora-maintained Nginx package that is not the upstream mainline build from nginx.org. This version gap means you miss critical features like HTTP/3, QUIC support, and newest performance improvements. If you need the latest Nginx capabilities, you must install from the official Nginx repository instead of using the default Fedora package.

This guide shows you exactly how to install Nginx Mainline Version on Fedora 44 using the upstream repository. You will configure the official Nginx repo, enable the mainline channel, install the binary, configure firewalld and SELinux, set up a server block, and verify everything works. As a sysadmin who runs Nginx on RPM-based systems daily, this approach prevents version drift between your development and production environments.

The process takes about 15 minutes on a fresh Fedora 44 installation. Let’s get your server running the latest Nginx mainline build.

Prerequisites

Before you start installing Nginx Mainline Version on Fedora 44, verify your system meets these requirements. Skipping this check is the number one cause of failed installations.

System Requirements:

  • Operating System: Fedora 44 (bare metal, virtual machine, or cloud instance)
  • User Permissions: Non-root user with sudo privileges (never run production web servers as root)
  • Firewall: firewalld must be active (this is the default on Fedora 44)
  • SELinux: Must be set to Enforcing mode (Fedora 44 default). Do NOT disable SELinux
  • DNF Plugins: dnf-plugins-core package available (needed for dnf config-manager)
  • Network: Internet connectivity to reach nginx.org for package downloads

Why prerequisites matter: Confirming sudo access, firewall state, and SELinux mode before touching any packages saves you 30 minutes of rollback work. Fedora 44 defaults to SELinux enforcing and firewalld active by design. Disabling these security layers creates vulnerable servers.

Check your current SELinux mode:

sudo getenforce

Expected output: Enforcing

Check firewalld status:

sudo systemctl is-active firewalld

Expected output: active

If either check fails, fix it before continuing. A broken security configuration now will cause problems later when Nginx tries to bind ports or read files.

Step 1: Update Your Fedora 44 System

Refresh Package Metadata Before Installation

Command:

sudo dnf upgrade --refresh

What this command does: The dnf upgrade --refresh command forces DNF to pull fresh metadata from all enabled repositories before making any package changes. This ensures you install the latest available versions of dependencies.

Why you need this step: Without the --refresh flag, DNF may resolve dependencies against stale cached data. This can pull older versions of packages that conflict with the mainline Nginx build. The --refresh flag invalidates your local cache before the upgrade scan, which is specific to Fedora and DNF (different from a plain dnf update).

Expected output: You’ll see a list of available upgrades or a confirmation that your system is already up to date:

Fedora 44 - x86_64                                     12 MB/s | 15 MB     00:01    
Processing keys...
Dependencies resolved.
================================================================================
 Package                    Arch       Version          Repository         Size
================================================================================
Updating:
 kernel                     x86_64     6.10.0-1.fc44    fedora             15 MB
...
Transaction Summary
Update  15 packages

If you see “Nothing to do,” your system is already updated. That’s fine. Continue to the next step.

Why update before installing packages: Installing Nginx on an outdated system can cause dependency conflicts. The mainline Nginx build requires specific versions of libraries like openssl and pcre. Updated system packages ensure these dependencies are compatible.

Step 2: Install Required DNF Dependencies

Add dnf-plugins-core and yum-utils Packages

Command:

sudo dnf install dnf-plugins-core yum-utils -y

What this command does: This installs two essential packages:

  • dnf-plugins-core: Provides the dnf config-manager subcommand you need to enable repositories
  • yum-utils: Provides yum-config-manager, referenced in official Nginx documentation for RHEL derivatives

Why you need these packages: On a minimal Fedora 44 installation, neither package is guaranteed to be present. The dnf config-manager command is critical for the next step where you enable the mainline repository. Without dnf-plugins-core, you get a “no such command” error that confuses first-time installers.

Expected output:

Fedora 44 - x86_64                                     8 MB/s | 9 MB     00:01    
dnf-plugins-core-5.2.0-1.fc44.noarch.rpm               120 kB/s | 45 kB     00:00    
yum-utils-4.2.0-1.fc44.noarch.rpm                      95 kB/s | 38 kB     00:00    
Dependencies resolved.
================================================================================
 Package                      Arch       Version        Repository         Size
================================================================================
Installing:
 dnf-plugins-core             noarch     5.2.0-1.fc44   fedora            120 kB
 yum-utils                    noarch     4.2.0-1.fc44   fedora             95 kB

Transaction Summary
Install  2 packages
Total download size: 215 kB
Installed size: 450 kB
Is this ok [y/N]: y

The -y flag automatically confirms the installation, saving you from typing y manually.

Why install dependencies before the repo: Repository configuration (dnf config-manager) requires dnf-plugins-core to be present. If you try to enable the mainline repo without this package, the command fails. Install these first to avoid that error.

Step 3: Configure the Official Nginx Mainline Repository

Create the nginx.repo File in /etc/yum.repos.d/

This is the most important step in the entire guide. Most tutorials get this wrong, causing your system to install the Fedora package instead of the mainline build.

Command to open the file:

sudo nano /etc/yum.repos.d/nginx.repo

Paste this content exactly:

[nginx-stable]
name=nginx stable repo
baseurl=https://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=https://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

What this repository file does: This file defines two repository sections:

  • [nginx-stable]: The stable branch, enabled by default (enabled=1)
  • [nginx-mainline]: The mainline branch, disabled by default (enabled=0)

Why this exact structure matters: The stable repo is enabled by default and the mainline is disabled. This is intentional. Nginx uses this pattern so you flip the mainline repo on with a command rather than editing the file directly. This reduces human error and keeps your configuration auditable.

Key security settings explained:

  • gpgcheck=1: This enables GPG signature verification for all downloaded RPM packages. Every package must be cryptographically verified against Nginx’s signing key before installation.
  • gpgkey URL: Points to Nginx’s official signing key. The key fingerprint is 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62. Without this verification, a compromised mirror could serve malicious packages.
  • module_hotfixes=true: This disables DNF module stream filtering that would otherwise block upstream Nginx RPMs on RHEL-derivative systems. Fedora shares the RPM ecosystem with RHEL, so this setting is required.
  • baseurl path: Uses centos/$releasever even though you’re on Fedora. Nginx’s upstream repo does not publish a Fedora-specific path. The RHEL/CentOS path works because Fedora and RHEL share compatible RPM packages.

Enable the Mainline Repository Using DNF Config-Manager

Command:

sudo dnf config-manager --enable nginx-mainline

What this command does: This flips the enabled setting from 0 to 1 for only the [nginx-mainline] repository block. It does not touch the stable repository or modify the repo file manually.

Why use this command instead of editing the file: Using dnf config-manager --enable is the Nginx-recommended workflow. It reduces human error (no typos in the file) and keeps your configuration change easily reversible. You can disable it later with --disable nginx-mainline.

Verify the repository is enabled:

sudo dnf repolist --all | grep nginx

Expected output:

nginx-mainline                          nginx mainline repo                   enabled=1
nginx-stable                            nginx stable repo                     enabled=1

Both repositories show as enabled, but mainline has higher priority for package resolution.

Why add the official repo instead of using Fedora’s package: The Fedora default package (nginx-1.30.0-1.fc44) is a Fedora-maintained build, not the upstream mainline binary. It may lag behind nginx.org releases by weeks or months. If you need HTTP/3, QUIC, or any feature from a recent mainline release (odd-numbered minor version like 1.27.x), you must use the upstream repository.

Step 4: Install Nginx Mainline Version from Upstream Repository

Install the Nginx Package Using DNF

Command:

sudo dnf install nginx -y

What this command does: DNF resolves the nginx package name against all enabled repositories. Because the mainline repo is now enabled and has higher priority than the Fedora default package, DNF installs the upstream mainline build instead of the Fedora-packaged version.

Why you see a GPG key prompt: When DNF downloads packages from a new repository, it asks you to accept the repository’s GPG key. This is your trust anchor. Before accepting, verify the fingerprint matches 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62. This confirms the key comes from nginx.org, not a malicious mirror.

Expected output during installation:

nginx-mainline                          12 MB/s | 2.5 MB     00:00    
Importing GPG key 0x7BD9BF62:
 Userid     : "nginx signing key (release key)" <nginx-dev@nginx.org>
 Fingerprint: 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62
 From       : /etc/pki/rpm-gpg/RPM-GPG-KEY-nginx
Is this ok [y/N]: y
Dependencies resolved.
================================================================================
 Package                  Arch       Version        Repository             Size
================================================================================
Installing:
 nginx                    x86_64     1.27.1-1       nginx-mainline        1.2 MB

Transaction Summary
Install  1 package
Total download size: 1.2 MB
Installed size: 3.5 MB
Is this ok [y/N]: y

Critical verification step: After installation completes, confirm you are running the mainline binary, not the Fedora package:

nginx -v

Expected output:

nginx version: nginx/1.27.1

If you see nginx version: nginx/1.30.0 or nginx-1.30.0-1.fc44, the Fedora package won the dependency resolution. This means the mainline repo was not enabled correctly, or you have a conflicting repository with higher priority.

Double-check with RPM query:

rpm -q nginx

Expected output:

nginx-1.27.1-1

Not nginx-1.30.0-1.fc44. The version number confirms you installed the upstream mainline build.

Why verify the version: Celebrating a successful dnf install without checking the actual version is a false positive. You might have the Fedora package instead of mainline. The nginx -v command shows the exact binary version that will serve requests.

Step 5: Enable and Start the Nginx Service with Systemd

Configure Nginx to Start Automatically on Boot

Command:

sudo systemctl enable --now nginx

What this command does: This combines two operations:

  • enable: Creates systemd symlinks so Nginx starts automatically when the system boots
  • --now: Starts the Nginx service immediately without waiting for reboot

Why Fedora does not auto-start services on install: Fedora’s security policy prevents package managers from automatically starting network-facing services. Unlike some Debian-based systems, dnf install does not launch Nginx. The package manager should not decide when a web server goes live on your system.

Verify the service is enabled and running:

sudo systemctl is-enabled nginx
sudo systemctl is-active nginx

Expected output:

enabled
active

Both commands return positive status. If you see disabled or inactive, the service is not running.

Check detailed service status:

sudo systemctl status nginx

Expected output:

● nginx.service - A high performance web server and reverse proxy server
     Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; preset: disabled)
     Active: active (running) since Wed 2026-06-17 19:45:12 WIB
   Main PID: 12345 (nginx)
      Tasks: 3 (limit: 11408)
     Memory: 15.2M (peak: 15.2M)

Key indicators:

  • Loaded: loaded: Systemd found the service file
  • enabled: Service will start on boot
  • active (running): Service is currently running
  • Main PID: The process ID of the master Nginx process

Test Nginx is Responding to HTTP Requests

Command:

curl -fsI http://127.0.0.1/

What this command does: The curl command sends an HTTP request to localhost and displays the response headers. Flags:

  • -f: Fail silently if the server returns an error
  • -s: Silent mode (no progress meter)
  • -I: Only fetch headers, not the full body

Expected output:

HTTP/1.1 200 OK
Server: nginx/1.27.1
Date: Wed, 17 Jun 2026 19:45:30 GMT
Content-Type: text/html
Connection: keep-alive

The Server: nginx/1.27.1 header confirms the mainline binary is serving requests. If you see nginx/1.30.0, you installed the wrong package.

Why the curl check matters: A running systemctl status output does not guarantee Nginx is actually serving HTTP requests. The service could be running but misconfigured (wrong port, firewall blocking, SELinux denying). The curl test confirms the web server responds to requests.

Step 6: Configure Firewalld to Allow HTTP and HTTPS Traffic

Open Port 80 and 443 Using Firewall-Cmd

Fedora 44 runs firewalld in the public zone by default. Without explicitly opening ports 80 and 443, all external HTTP/HTTPS traffic is silently dropped. Nginx will appear to not respond even when the service is active.

Add HTTP service to firewall:

sudo firewall-cmd --permanent --add-service=http

Add HTTPS service to firewall:

sudo firewall-cmd --permanent --add-service=https

Reload firewalld to apply changes:

sudo firewall-cmd --reload

What these commands do:

  • --permanent: Writes rules to the persistent firewalld configuration. Without this flag, rules disappear on reboot.
  • --add-service=http: Adds the canonical http service definition (port 80) to the firewall
  • --add-service=https: Adds the canonical https service definition (port 443)
  • --reload: Applies permanent rules to the running firewall without interrupting existing connections

Why use named services instead of raw port numbers: Using http and https service names instead of --add-port=80/tcp ties your rule to the canonical service definition. This makes firewall audits more readable. When you see --add-service=http in a configuration, you immediately know it’s web traffic.

Verify the services are enabled:

sudo firewall-cmd --query-service=http
sudo firewall-cmd --query-service=https

Expected output:

yes
yes

Both commands return yes. If you see no, the service is not allowed.

Check which services are currently allowed:

sudo firewall-cmd --list-services

Expected output:

ssh dhcpv6-client http https

HTTP and HTTPS appear in the list alongside SSH and DHCP.

Why firewalld is required: Without these rules, external clients cannot reach your Nginx server. You can test locally with curl http://127.0.0.1/ but remote requests fail. This is the most common reason new Nginx installations appear broken. The service runs, but no traffic reaches it.

Step 7: Configure SELinux File Contexts for Nginx

Apply Correct SELinux Labels to Your Document Root

This is where most Nginx tutorials fail Fedora users completely. SELinux blocks Nginx from reading files outside the default directory even when file permissions look correct.

Why SELinux matters: Fedora 44 runs SELinux in Enforcing mode by default. SELinux uses mandatory access control labels (file contexts) to restrict which processes can read which files. If your document root is outside /usr/share/nginx/html (for example, /var/www/mysite.com), SELinux blocks Nginx from reading those files and returns a 403 Forbidden error.

The wrong fix: Many tutorials suggest setting SELinux to Permissive mode. This disables your entire MAC (Mandatory Access Control) policy. Never do this in production.

Install SELinux management tools if missing:

sudo dnf install policycoreutils-python-utils -y

What this command does: Installs the semanage command, which is required to modify SELinux file context policies. This package is not included in minimal Fedora installations.

Create your document root directory:

sudo mkdir -p /var/www/example.com/html

Set ownership and permissions:

sudo chown -R $USER:$USER /var/www/example.com
sudo chmod -R 755 /var/www/example.com

What these commands do:

  • chown -R $USER:$USER: Changes ownership to your current user so you can deploy files without sudo
  • chmod -R 755: Sets directory permissions to 755, giving Nginx (running as the nginx user) read and execute access to traverse directories while you retain write control

Apply the correct SELinux file context:

sudo semanage fcontext -a -t httpd_sys_content_t "/var/www/example.com(/.*)"

What this command does: The semanage fcontext -a command adds a new file context rule to the SELinux policy:

  • -t httpd_sys_content_t: Sets the file type to httpd_sys_content_t, which Nginx is allowed to read
  • /var/www/example.com(/.*)?: Matches the directory and all files within it (the regex (/.*)? means “optionally match everything after this path”)

Apply the rule to existing files:

sudo restorecon -Rv /var/www/example.com

What this command does: semanage fcontext defines the policy rule, but restorecon physically applies the label to existing files. Both steps are required. Without restorecon, the rule exists but files remain unlabelled.

Flags:

  • -R: Recursive (apply to all files in the directory)
  • -v: Verbose (show what changed)

Expected output:

resetting MBZ to 00000000000000000000
/reset/var/www/example.com/html    replaced

Verify the file context is correct:

ls -Zd /var/www/example.com/html

Expected output:

unconfined_u:object_r:httpd_sys_content_t:s0 /var/www/example.com/html

The type field shows httpd_sys_content_t. This confirms SELinux allows Nginx to read the directory.

Why SELinux configuration is critical: Without the correct file context, Nginx returns 403 Forbidden even with perfect file permissions (755 directories, 644 files). The error log shows Permission denied but the issue is SELinux, not standard Unix permissions. This confuses many administrators who disable SELinux instead of fixing the label.

Step 8: Create Your First Nginx Server Block

Set Up a Custom Website Configuration

Fedora’s Nginx package uses the conf.d/ include pattern, not the Debian-style sites-available/sites-enabled symlink pattern. Place your configuration in /etc/nginx/conf.d/ so Nginx loads it.

Create the server block configuration file:

sudo nano /etc/nginx/conf.d/example.com.conf

Paste this configuration:

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    root /var/www/example.com/html;
    index index.html index.htm;

    location / {
        try_files $uri $uri/ =404;
    }
}

What each directive does:

  • listen 80;: Binds to port 80 on IPv4
  • listen [::]:80;: Binds to port 80 on IPv6
  • server_name: Defines the domain names this server block responds to
  • root: Sets the document root directory where website files live
  • index: Specifies the default file to serve when a directory is requested
  • try_files: Attempts to serve the requested file, then the directory, then returns 404

Why place the file in conf.d: Fedora’s main Nginx configuration (/etc/nginx/nginx.conf) includes all files in /etc/nginx/conf.d/ using the directive include conf.d/*.conf;. Configurations outside this directory are never loaded.

Test Configuration and Reload Nginx

Validate the configuration syntax:

sudo nginx -t

What this command does: nginx -t tests the configuration file for syntax errors without starting or reloading the service. It parses all included files and checks for missing directives, invalid values, or bracket mismatches.

Expected output:

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

If you see errors, they show the exact line number and problem. Fix syntax errors before reloading.

Why test before reload: A syntax error in your configuration causes systemctl restart nginx to fail. This can take your server offline if the old configuration stops but the new one won’t start. Always validate with nginx -t first.

Reload Nginx to apply changes:

sudo systemctl reload nginx

What this command does: reload gracefully restarts Nginx by spawning new worker processes and shutting down old ones. This keeps existing connections alive during the reload. Unlike restart, which stops then starts (dropping connections), reload is safe for production.

Verify the server block is active:

Create a test file:

echo "Welcome to example.com on Nginx Mainline" > /var/www/example.com/html/index.html

Test locally:

curl --resolve example.com:80:127.0.0.1 http://example.com/

Expected output:

Welcome to example.com on Nginx Mainline

The --resolve flag tells curl to treat example.com as localhost without needing actual DNS setup.

Troubleshooting Common Nginx Mainline Installation Errors

Problem 1: 403 Forbidden Error When Accessing Your Site

Root cause: Wrong SELinux file context on your document root directory.

Solution:

sudo restorecon -Rv /var/www/example.com

Then verify:

ls -Zd /var/www/example.com/html

Expected: httpd_sys_content_t in the type field.

Why this happens: SELinux blocks Nginx from reading files outside the default /usr/share/nginx/html directory. Even with perfect Unix permissions (755/644), the MAC policy denies access.

Problem 2: Fedora Package Installs Instead of Mainline

Root cause: Mainline repository not enabled or has lower priority than the Fedora package repository.

Solution:

sudo dnf config-manager --enable nginx-mainline
sudo dnf remove nginx  # Remove Fedora package first
sudo dnf install nginx -y

Then verify:

nginx -v

Expected: nginx/1.27.x (not 1.30.0-1.fc44).

Why this happens: If you skip the --enable nginx-mainline command, DNF resolves to the Fedora default package because the stable repo is enabled by default.

Problem 3: Port 80/443 Not Reachable From External Clients

Root cause: Firewalld missing permanent rules for HTTP and HTTPS services.

Solution:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
sudo firewall-cmd --query-service=http
sudo firewall-cmd --query-service=https

Both queries should return yes.

Why this happens: Fedora blocks all inbound traffic by default. Without explicit firewall-cmd rules, external clients cannot reach your web server even though Nginx runs locally.

Problem 4: nginx -t Fails After Configuration Edit

Root cause: Syntax error in your server block configuration file.

Solution:

Check the exact error:

sudo nginx -t

Common errors:

  • Missing closing brace }
  • Missing semicolon ; at end of directive
  • Invalid directive name

Fix the error in /etc/nginx/conf.d/example.com.conf and retest:

sudo nginx -t
sudo systemctl reload nginx

Why this happens: Nginx configuration files require exact syntax. A single typo prevents the entire server from starting.

Problem 5: Default Fedora Page Shows Instead of Your Site

Root cause: server_name mismatch or DNS not updated to point to your server.

Solution:

Test locally without DNS:

curl --resolve example.com:80:127.0.0.1 http://example.com/

If this works but external requests fail, your DNS is not pointing to your server yet. Wait for DNS propagation or update your DNS records.

Why this happens: The default Nginx page at /usr/share/nginx/html/index.html serves when no server block matches the requested domain name.

How to Keep Nginx Mainline Updated on Fedora 44

Because the upstream Nginx repository is registered in /etc/yum.repos.d/nginx.repo, all future updates come through DNF automatically. You do not need to manually download new packages.

Update Nginx specifically:

sudo dnf upgrade --refresh nginx

Why update Nginx individually: Isolating the Nginx upgrade lets you review release notes for the specific version jump before accepting changes on a production server. A full dnf upgrade might update dozens of packages simultaneously.

Check available Nginx updates:

sudo dnf list updates nginx

Expected output:

Last metadata expiration check: 0:15:23 ago on Wed 17 Jun 2026 19:30:00 WIB.
Installed Packages
 Name         Version      Repository         Size
================================================================================
Updating:
 nginx        1.27.2-1     nginx-mainline     1.2 MB

Backup your configuration before major updates:

sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.bak
sudo tar -czf ~/nginx-backup-$(date +%F).tar.gz -C /etc nginx

What these commands do:

  • First command creates a timestamped backup of the main configuration file
  • Second command creates a compressed archive of the entire /etc/nginx directory

Why backup before updates: If a new Nginx version changes configuration syntax, your server might fail to start. A backup lets you restore the previous working configuration immediately.

Automatic TLS certificate renewal: Fedora includes the certbot-renew.timer systemd unit that handles automatic TLS certificate renewal. Install Certbot with Nginx plugin:

sudo dnf install python3-certbot-nginx -y

[su_box title=”VPS Manage Service Offer” style=”bubbles” box_color=”#000000″ radius=”10″]If you don’t have time to do all of this stuff, or if this is not your area of expertise, we offer a service to do “VPS Manage Service Offer”, starting from $10 (Paypal payment). Please contact us to get the best deal![/su_box]

r00t is a Linux Systems Administrator and open-source advocate with over ten years of hands-on experience in server infrastructure, system hardening, and performance tuning. Having worked across distributions such as Debian, Arch, RHEL, and Ubuntu, he brings real-world depth to every article published on this blog. r00t writes to bridge the gap between complex sysadmin concepts and practical, everyday application — whether you are configuring your first server or optimizing a production environment. Based in New York, US, he is a firm believer that knowledge, like open-source software, is best when shared freely.

Related Posts