
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
sudoprivileges (never run production web servers as root) - Firewall:
firewalldmust 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-corepackage available (needed fordnf config-manager) - Network: Internet connectivity to reach
nginx.orgfor 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 thednf config-managersubcommand you need to enable repositoriesyum-utils: Providesyum-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.gpgkeyURL: Points to Nginx’s official signing key. The key fingerprint is573B 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.baseurlpath: Usescentos/$releasevereven 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 fileenabled: Service will start on bootactive (running): Service is currently runningMain 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 canonicalhttpservice definition (port 80) to the firewall--add-service=https: Adds the canonicalhttpsservice 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 withoutsudochmod -R 755: Sets directory permissions to 755, giving Nginx (running as thenginxuser) 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 tohttpd_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 IPv4listen [::]:80;: Binds to port 80 on IPv6server_name: Defines the domain names this server block responds toroot: Sets the document root directory where website files liveindex: Specifies the default file to serve when a directory is requestedtry_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/nginxdirectory
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]