How to Configure Networking for KVM Virtual Machines on Fedora (NAT, Bridge)

Configure KVM networking on Fedora using nmcli for bridges or virsh for default NAT to connect virtual machines.

You need the VM on the network

You just spun up a Fedora VM in virt-manager. The guest boots fine. You can ping the host from inside the guest. But you try to SSH into the VM from your laptop, and the connection times out. Or you need the VM to host a web server that other devices on your LAN can reach, and the default setup hides it behind a private subnet. The default network works for quick tests. It fails when you need real connectivity.

How KVM networking works

KVM uses libvirt to manage virtual networks. By default, libvirt creates a NAT network. Think of this like your home router. Your VM gets a private IP address in a range like 192.168.122.0/24. The host acts as the router, translating traffic between the VM and the outside world. The VM can reach the internet. The internet cannot reach the VM directly. Other devices on your LAN cannot see the VM.

A bridge works differently. A bridge connects the VM directly to the physical network interface. The VM gets an IP address from your real router, just like your laptop or phone. It sits on the same layer 2 network as the host. Other devices can talk to the VM directly. The trade-off is complexity. You have to reconfigure the host's network to share the physical connection with the VM. The host interface becomes a slave to the bridge, and the bridge takes the IP address.

Configure NAT for isolated access

NAT is the default and requires the least configuration. Use NAT when the VM only needs outbound internet access and does not need to be reachable from the LAN.

Check if the default network is active. Libvirt usually creates this automatically when you install libvirt and qemu-kvm.

virsh net-list --all
# --all shows inactive networks too
# look for 'default' in the list
# check the State column for 'active'

If the default network is inactive or missing, define and start it.

virsh net-define /usr/share/libvirt/networks/default.xml
# defines the network from the shipped XML template
# /usr/share/libvirt/ contains package defaults
# never edit files in /usr/share/, use virsh net-edit instead

virsh net-autostart default
# ensures the network starts automatically on boot
# prevents the VM from losing network after a reboot

virsh net-start default
# activates the network immediately
# creates the virbr0 interface on the host

Restart the network. The default network is the path of least resistance.

Configure a bridge for LAN access

Bridging requires reconfiguring the host network using nmcli. Fedora uses NetworkManager to manage interfaces. You will create a bridge interface and attach your physical interface to it.

Real-world stakes apply here. A botched bridge configuration can leave the host without network access. If you are working over SSH, ensure you have a backup connection or a way to access the console. Run these commands carefully.

First, identify your active physical interface.

nmcli connection show --active
# lists all active connections
# look for the connection type 'ethernet'
# note the NAME and DEVICE columns

Create the bridge connection. Replace enp1s0 with your actual interface name.

nmcli connection add type bridge ifname br0 con-name br0 ipv4.method auto
# creates a new bridge connection profile named br0
# sets the interface name to br0
# configures IPv4 via DHCP on the bridge
# the bridge will request an IP from your router

Attach the physical interface to the bridge. This turns the physical interface into a slave. It will no longer hold an IP address.

nmcli connection add type ethernet ifname enp1s0 master br0 con-name enp1s0-slave
# creates a slave connection for the physical interface
# attaches the physical interface to the bridge master
# disables IP configuration on the slave automatically
# the slave passes frames to the bridge

Bring the bridge up. This may cause a brief network interruption as the interface reconfigures.

nmcli connection up br0
# activates the bridge connection
# brings up br0 and the slave enp1s0-slave
# NetworkManager applies the new configuration
# wait for DHCP to assign an address to br0

Verify the bridge has an IP address and the physical interface does not.

ip addr show br0
# shows the bridge interface details
# look for an inet address assigned by DHCP
# confirms the bridge is functioning as the host's network endpoint

ip addr show enp1s0
# shows the physical interface details
# should have no inet address
# confirms the interface is enslaved to the bridge

Now edit the VM configuration to use the bridge.

virsh edit <vm-name>
# opens the VM configuration in your default editor
# changes are validated before saving
# replace <vm-name> with your actual VM name

Find the <interface> section and change it to use the bridge.

<interface type='bridge'>
  <source bridge='br0'/>
  <model type='virtio'/>
</interface>
# changes the interface type from network to bridge
# points the VM to the br0 interface on the host
# virtio model provides best performance for Fedora guests
# save and exit the editor to apply changes

Start or restart the VM. The guest will now request an IP address from your physical router and appear as a distinct device on the LAN.

Check the bridge IP. If br0 has an address and enp1s0 does not, the bridge is working correctly.

Verify the configuration

Run these checks to confirm everything is connected.

brctl show
# displays bridge topology
# confirms enp1s0 is a member of br0
# shows the MAC address of the bridge
# useful for troubleshooting link issues

ping -c 4 <vm-ip>
# tests connectivity from host to VM
# replace <vm-ip> with the address assigned to the VM
# should succeed if the bridge is working

From another device on the LAN, ping the VM's IP address. If it responds, the bridge is fully functional.

Run journalctl -xeu NetworkManager if you suspect issues. The x flag adds explanatory text and the e flag jumps to the end. Most sysadmins type journalctl -xeu <unit> muscle-memory style. Read the actual error before guessing.

Common pitfalls and errors

Bridge configuration fails for a few predictable reasons.

Error: Connection activation failed: Device not managed by NetworkManager

This happens when the interface is already claimed by another profile or is unmanaged. Delete the old connection for the physical interface.

nmcli connection delete enp1s0
# removes the old connection profile
# allows you to create the slave connection cleanly
# does not affect the running interface immediately
# run nmcli connection up br0 to apply changes

Bridge has no IP address

The bridge might fail to get DHCP if the router is slow or if there is a conflict. Check the device status.

nmcli device status
# shows state of all devices
# look for br0 state 'connected' or 'available'
# if state is 'unmanaged', check /etc/NetworkManager/NetworkManager.conf

NetworkManager stores configurations in /etc/NetworkManager/system-connections/. Editing files directly works but nmcli is safer because it validates and reloads the daemon. Always run nmcli connection up after edits.

Firewall blocks traffic

Fedora enables firewalld by default. The bridge usually inherits the zone of the physical interface. If you changed zones, reload the firewall.

firewall-cmd --reload
# applies persistent firewall rules to the runtime
# ensures the bridge zone matches your expectations
# run this after every rule change
# prevents runtime and persistent config divergence

SELinux denials show up in journalctl -t setroubleshoot with a one-line summary. Read those before disabling SELinux. Network bridges rarely trigger SELinux issues if configured via nmcli.

Read the journal. NetworkManager tells you exactly which device is unmanaged.

Choose the right network mode

Use NAT when you only need the VM to access the internet and do not care about inbound connections from the LAN. Use a bridge when you need the VM to host services accessible by other devices on your network. Use a macvlan when you want isolation from the host but direct LAN access without bridging the host interface. Use the default libvirt network when you are testing software and want zero configuration overhead.

Match the network to the workload. Over-engineering a bridge for a test VM wastes time.

Where to go next