
Most sysadmins who run a Linux server eventually hit the same wall: they need a fast, private tunnel between machines, and every solution they find is either too complex to configure or too slow to be practical. WireGuard solves that. It lives in the Linux kernel, needs almost no configuration to get working, and performs faster than OpenVPN by a wide margin.
This guide shows you exactly how to install WireGuard on Fedora 44, from the first package install all the way to a running, persistent VPN tunnel. Every command comes with a clear explanation of what it does and why you need it. No hand-waving, no skipping steps.
Fedora 44 ships with Linux kernel 6.19, which includes the WireGuard module natively. That is important: you do not need any external COPR repository or DKMS driver. The kernel already has everything built in.
What Is WireGuard and Why It Fits Fedora 44
Before running any commands, it is worth understanding what you are installing and why it is the right tool for the job.
WireGuard is a VPN protocol implemented directly inside the Linux kernel. It has been part of the mainline kernel since version 5.6, which means it is not a third-party add-on. It is a first-class citizen of the Linux networking stack.
The design philosophy is minimalism. WireGuard’s full codebase sits at roughly 4,000 lines. OpenVPN’s is closer to 400,000. A smaller codebase means fewer places for bugs to hide and a dramatically smaller attack surface.
WireGuard vs. OpenVPN vs. IPsec
| Feature | WireGuard | OpenVPN | IPsec |
|---|---|---|---|
| Kernel integration | Yes (native) | No (userspace) | Partial |
| Config complexity | Low | Medium | High |
| Codebase size | ~4,000 lines | ~400,000 lines | Very large |
| Cryptography | Modern (Curve25519, ChaCha20) | Configurable (can be weak) | Configurable |
| Setup time | Minutes | 30-60 minutes | Hours |
Why Fedora 44 Makes This Even Easier
Fedora 44 runs kernel 6.19 with WireGuard compiled in by default. It also ships DNF5 as the default package manager, which resolves dependencies faster than its predecessor. You only need to install the userspace tools, which is a single command.
NetworkManager on Fedora 44 also supports WireGuard natively, which gives you both command-line and GUI options for managing your tunnel. You get flexibility depending on whether you are running a headless server or a desktop workstation.
Prerequisites
Before you start, confirm your environment matches these requirements:
- Fedora 44 installed (Workstation, Server, or Minimal edition)
- A user account with sudo privileges
- An active internet connection for package download
- Basic terminal comfort: you will use
nanoorvimto edit one config file - A second device to test the tunnel (another server, a VM, or a phone)
- UDP port 51820 reachable from the internet (or a custom port if you prefer)
- Kernel 6.19 or newer confirmed:
uname -r
Expected output: something like 6.19.x-200.fc44.x86_64
If you see anything below 6.19, update your system first (Step 1 covers this).
Step 1: Update Your Fedora 44 System
Always update before installing anything. This step ensures your kernel, glibc, and networking libraries are at their latest state.
sudo dnf update -y
Why this matters: A stale kernel can cause a version mismatch. If dnf installs a newer kernel image during the update, your running kernel and that image will differ. After the update, check whether a new kernel was installed and reboot if so.
rpm -q kernel | sort
If you see a new version listed, reboot:
sudo reboot
After rebooting, confirm you are now running the updated kernel:
uname -r
DNF5, which is the default on Fedora 44, runs noticeably faster than older DNF versions. The dnf update -y command here resolves all dependencies in one pass and applies updates without prompting.
Step 2: Install WireGuard on Fedora 44
This is the only package you need. The kernel module is already built in.
sudo dnf install wireguard-tools -y
Why only wireguard-tools? On Fedora 31 and newer, the WireGuard kernel module ships inside the mainline Linux kernel. The old method of installing wireguard-dkms and enabling a COPR repository is outdated and no longer needed on Fedora 44. Do not install wireguard-dkms. It will create unnecessary conflicts.
The wireguard-tools package gives you three binaries you will use throughout this guide:
wg: The main configuration and status toolwg-quick: A helper script that brings interfaces up and down using a config filewg showconf: Reads the current live interface state and outputs it in config format
Verify the installation:
wg --version
Expected output:
wireguard-tools v1.0.20210914 - https://git.zx2c4.com/wireguard-tools/
The exact version number may differ, but you should see that output without any errors.
Confirm the Kernel Module Loads
Even though the module is built in, load it explicitly and confirm:
sudo modprobe wireguard
lsmod | grep wireguard
Expected output from lsmod:
wireguard 102400 0
Why this step? Loading the module manually before creating any interfaces catches potential issues early. If modprobe wireguard returns an error here, you need to investigate kernel compatibility before continuing. An empty result from lsmod means the module is not active, and wg-quick up will fail silently later.
Step 3: Generate WireGuard Cryptographic Keys
WireGuard uses a public/private key pair for authentication. Every machine in your VPN (server and each client) needs its own pair. Generate the server’s pair now.
First, set strict permissions and navigate to the config directory:
sudo mkdir -p /etc/wireguard
sudo chmod 700 /etc/wireguard
cd /etc/wireguard
Why chmod 700? This restricts access to /etc/wireguard so only root can read or write files inside it. Private keys stored here must never be world-readable.
Now generate both keys in one command:
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
Breaking down this command:
wg genkey: Generates a random 256-bit Curve25519 private keytee /etc/wireguard/privatekey: Writes the private key to a file AND passes it through the pipewg pubkey: Reads the private key from stdin and computes the matching public keytee /etc/wireguard/publickey: Writes the public key to its own file
Lock down the private key file immediately:
sudo chmod 600 /etc/wireguard/privatekey
Why chmod 600? If wg-quick detects that your private key file is readable by anyone other than root, it prints a security warning and may refuse to start. Fixing permissions after the fact is possible, but setting them correctly now is cleaner.
Verify both files exist with the right permissions:
sudo ls -la /etc/wireguard/
Expected output:
-rw------- 1 root root 45 Jun 16 18:00 privatekey
-rw-r--r-- 1 root root 45 Jun 16 18:00 publickey
You need the private key content in the next step. Read it with:
sudo cat /etc/wireguard/privatekey
Copy that output. You will paste it into the config file.
Step 4: Create the WireGuard Interface Configuration File
The wg0.conf file is the heart of your WireGuard setup. It defines the interface, the cryptographic identity of the server, and every peer that is allowed to connect.
Open a new file:
sudo nano /etc/wireguard/wg0.conf
Paste this configuration, replacing the placeholder values:
[Interface]
Address = 10.0.0.1/24
ListenPort = 51820
PrivateKey = PASTE_YOUR_PRIVATE_KEY_HERE
SaveConfig = false
PostUp = firewall-cmd --permanent --zone=public --add-port=51820/udp; firewall-cmd --permanent --zone=public --add-masquerade; firewall-cmd --reload
PostDown = firewall-cmd --permanent --zone=public --remove-port=51820/udp; firewall-cmd --permanent --zone=public --remove-masquerade; firewall-cmd --reload
[Peer]
PublicKey = PASTE_CLIENT_PUBLIC_KEY_HERE
AllowedIPs = 10.0.0.2/32
Why each directive exists:
Address = 10.0.0.1/24: Assigns a private IP to thewg0interface. The/24subnet supports up to 254 peers on the10.0.0.xrange. This is internal VPN addressing, completely separate from your server’s public IP.ListenPort = 51820: The UDP port WireGuard listens on. WireGuard uses UDP specifically because it handles its own packet ordering and retransmission. Using TCP would create a “TCP-over-TCP” tunneling problem that destroys performance under packet loss.PrivateKey: The server’s private key. This is what cryptographically signs outgoing handshakes. Never share this value or commit it to any version control system.SaveConfig = false: Preventswg-quickfrom overwriting your config file with runtime state when the interface shuts down. Keeping this asfalsemeans your file on disk always reflects your intended configuration, not a snapshot of current connections.PostUp/PostDown: Shell commands that run automatically when the interface starts or stops. Tying the firewall rules to the interface lifecycle ensures they stay in sync. If WireGuard is down, the firewall port closes too.AllowedIPs = 10.0.0.2/32: This serves a dual purpose. It tells WireGuard to route packets destined for10.0.0.2through this peer, and it also acts as an access control rule. Only traffic from10.0.0.2is accepted from this peer.
Set strict permissions on the config file:
sudo chmod 600 /etc/wireguard/wg0.conf
Step 5: Enable IPv4 Forwarding for Packet Routing
By default, the Linux kernel drops any packet that is not addressed directly to the host. That is the right behavior for a regular workstation, but a VPN server needs to forward packets between its WireGuard interface and its outbound network interface. You need to enable IP forwarding.
echo "net.ipv4.ip_forward = 1" | sudo tee /etc/sysctl.d/99-wireguard-forward.conf
sudo sysctl -p /etc/sysctl.d/99-wireguard-forward.conf
Why write to /etc/sysctl.d/ instead of /etc/sysctl.conf?
Drop-in files under /etc/sysctl.d/ persist across reboots and survive system upgrades without being overwritten. The main /etc/sysctl.conf file can be modified or replaced by package updates. Using a dedicated drop-in file is the correct Fedora practice.
Confirm the setting is active right now:
sysctl net.ipv4.ip_forward
Expected output:
net.ipv4.ip_forward = 1
If this returns 0, the sysctl change did not apply. Run sudo sysctl --system to reload all sysctl configs from disk.
What happens if you skip this step? Clients will connect to the WireGuard tunnel successfully, but they will get no internet access through it. The server will accept their packets and then throw them away because forwarding is disabled. This is one of the most common mistakes in WireGuard setups.
Step 6: Configure firewalld on Fedora 44 for WireGuard
Fedora 44 uses firewalld as its default firewall manager. You must open UDP port 51820 and enable masquerading (NAT) so that VPN clients can access the internet through the server.
Do not edit raw iptables rules directly on a Fedora system running firewalld. Direct iptables edits conflict with firewalld’s zone management and vanish on the next firewalld reload.
Run these commands:
# Open the WireGuard UDP port permanently
sudo firewall-cmd --permanent --zone=public --add-port=51820/udp
# Enable NAT masquerading so VPN clients can reach the internet
sudo firewall-cmd --permanent --zone=public --add-masquerade
# Apply all permanent rules to the running configuration
sudo firewall-cmd --reload
# Confirm everything is in place
sudo firewall-cmd --list-all
Why each flag matters:
--permanent: Without this flag, rules only exist until the nextfirewall-cmd --reloador system reboot. Always use--permanentfor rules you intend to keep.--add-masquerade: This enables Network Address Translation on the public zone. Your VPN clients have private IP addresses (10.0.0.x). When their traffic exits the server, masquerading rewrites the source IP to the server’s public IP. Without it, responses from the internet never know where to go back.--reload: Applies permanent rules to the live firewall without dropping active connections. Always run this after making permanent changes.
Verify the output of firewall-cmd --list-all:
Look for these lines in the output:
ports: 51820/udp
masquerade: yes
If either is missing, the corresponding command did not complete correctly. Re-run it and check for error messages.
Step 7: Start WireGuard and Enable It at Boot with systemd
Bring the wg0 interface up and make it start automatically on every reboot.
# Bring up the WireGuard interface immediately
sudo wg-quick up wg0
# Enable the systemd service so it starts at boot
sudo systemctl enable wg-quick@wg0
# Start the service through systemd (for consistency)
sudo systemctl start wg-quick@wg0
# Check the current service status
sudo systemctl status wg-quick@wg0
Why each command:
wg-quick up wg0: Reads/etc/wireguard/wg0.conf, creates thewg0network interface in the kernel, assigns the IP address, sets up routing tables, and runs thePostUpcommands. It is the fastest way to get the tunnel running.systemctl enable wg-quick@wg0: Creates a systemd symlink so the service starts automatically after every reboot. Without this, you have to manually runwg-quick up wg0every time the server restarts.systemctl start wg-quick@wg0: Starts the service through systemd explicitly so that the systemd dependency tree and journal logs are properly populated from the start.
What the correct systemctl status output looks like:
wg-quick@wg0.service - WireGuard via wg-quick(8) for wg0
Loaded: loaded (/lib/systemd/system/wg-quick@.service; enabled; vendor preset: disabled)
Active: active (exited) since Tue 2026-06-16 18:00:00 WIB; 5s ago
The active (exited) state is correct and expected. wg-quick runs once to configure the interface and then exits cleanly. The interface stays up even after the process exits.
Step 8: Verify the WireGuard Interface Is Running
Run three checks to confirm the tunnel is fully operational.
# Show WireGuard interface status
sudo wg show
# Confirm the kernel sees the wg0 interface
ip addr show wg0
# Ping the WireGuard interface IP from the server itself
ping -c 4 10.0.0.1
What to look for in sudo wg show:
interface: wg0
public key: <your server public key>
private key: (hidden)
listening port: 51820
If a peer has connected and completed a handshake, you will also see:
peer: <client public key>
allowed ips: 10.0.0.2/32
latest handshake: X seconds ago
transfer: 1.23 KiB received, 4.56 KiB sent
A latest handshake timestamp that is under 3 minutes old means the peer is actively connected. No handshake listed means the client has not connected yet, which is expected until you configure a client device.
ip addr show wg0 output should show:
4: wg0: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1420 qdisc noqueue state UNKNOWN
inet 10.0.0.1/24 scope global wg0
The UP,LOWER_UP flags confirm the interface is active and the kernel is routing through it.
Optional: Manage WireGuard via NetworkManager (nmcli) on Fedora 44 Workstation
If you are running Fedora 44 Workstation with GNOME 50, you can import your WireGuard config directly into NetworkManager. This lets you toggle the VPN from the GNOME network settings panel.
Import the existing config:
sudo nmcli connection import type wireguard file /etc/wireguard/wg0.conf
Or create a new WireGuard connection manually:
sudo nmcli connection add type wireguard con-name "wg-vpn" ifname wg0 autoconnect no
Why autoconnect no? On a workstation, you usually want to connect the VPN on demand, not automatically on every network change. Set autoconnect yes only on headless servers where the tunnel should always be up.
This method is entirely optional for server setups. The wg-quick + systemd approach from Steps 7 covers everything a server needs.
Troubleshooting Common WireGuard Issues on Fedora 44
Interface Fails to Start
Symptom: sudo wg-quick up wg0 returns an error immediately.
Fix: Check these in order:
- Confirm the private key in
wg0.confhas no extra whitespace or newline characters - Verify file permissions:
sudo ls -la /etc/wireguard/(bothprivatekeyandwg0.confmust be600) - Run
sudo journalctl -u wg-quick@wg0 --no-pagerto see the full systemd error log
Clients Connect But Have No Internet Access
Symptom: The VPN tunnel is up and the handshake completes, but the client cannot browse the web.
Fix:
# Check IP forwarding is on
sysctl net.ipv4.ip_forward
# Check masquerade is active
sudo firewall-cmd --list-all | grep masquerade
If ip_forward returns 0, re-apply Step 5. If masquerade: no, re-apply the masquerade command from Step 6.
UDP Port 51820 Not Reachable from Outside
Symptom: Clients time out during handshake and never connect.
Fix:
sudo firewall-cmd --list-ports
Confirm 51820/udp appears. If you are behind a home router or cloud firewall (security groups), also open UDP 51820 at the network level, not just on the OS firewall. WireGuard will not respond on TCP, so TCP port scanners will always show the port as “filtered.”
SELinux Blocking WireGuard Operations
Symptom: Interface starts but behaves unexpectedly, or PostUp commands fail silently.
Fix: Check SELinux audit log for WireGuard denials:
sudo ausearch -c 'wireguard' --raw | head -40
If you see AVC denial messages, generate a policy module to allow the blocked operation:
sudo ausearch -c 'wireguard' --raw | audit2allow -M wireguard-local
sudo semodule -i wireguard-local.pp
Never set SELinux to permissive mode permanently in a production environment. Investigate and write a proper policy instead.
Config File Changes Not Taking Effect
Symptom: You edited wg0.conf but the running interface does not reflect the change.
Fix: You must bring the interface down and back up to reload the config:
sudo wg-quick down wg0
sudo wg-quick up wg0
Alternatively, use wg set for live changes that do not require a full restart (for example, adding a new peer public key without disrupting existing connections).
Security Hardening After Installation
Getting WireGuard running is step one. These steps close the gaps that default configurations leave open.
Rotate keys periodically. Generate a new server key pair and update wg0.conf without downtime:
wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey
sudo wg set wg0 private-key /etc/wireguard/privatekey
Use a preshared key for each peer. This adds a second layer of symmetric encryption on top of the Curve25519 handshake, providing resistance against future quantum computing attacks:
wg genpsk | sudo tee /etc/wireguard/preshared.key
Add PresharedKey = <output> to the relevant [Peer] block in wg0.conf.
Audit active peers regularly:
sudo wg show
Remove any peer whose latest handshake is stale for weeks. Delete their [Peer] block from wg0.conf and restart the service. An unused peer with a valid key is an open door.
Restrict SSH access to the WireGuard subnet. If this server is VPN-only, remove SSH from the public firewalld zone and only allow it on the wg0 interface IP range. This ensures administrative access only works through the tunnel.
[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]