Countless hours has gone by trying to make this seemingly simple task work on my setup.

I have this small little server, well it's an old AMD FX-8150 running in a Sabertooh motherboard. Anyway, this server is handling some basic tasks like hosting files and other stuff. Having tried out ESXi XEN and proxmox before but not liking them, I picked a barebone Debian install to have full control of everything.

I wanted to extend it's responsibilities by allowing it to run virtual machines next to it's current workload of docker containers.

I am using Cockpit for most easy to access tasks. I created my virtual machines in there (Qemu/KVM). Easy management, attaching to console, start/stop and having them start on host boot.

But what fell short is the option to select the bridged network mode to allow access to the virtual machines from other hosts on the network.

Cockpit UI, not allowing "Bridge to LAN" to be selected.

Going down the whole rabbit hole of stuff trying to get that selectable in the UI, including allowing management of interfaces via NetworkManager to no avail.

Making it work

So after more time that I'd like to admit, these are the steps needed to be done.

Edit /etc/network/interfaces.
Remove the configuration of the default network adapter, leaving the new bridge interface to take it's place.

auto br0
iface br0 inet static
  bridge_ports enp8s0 # your main network adapter
  bridge_maxwait  4
  address 1.2.3.4
  netmask 255.255.255.0
  network 1.2.3.0
  broadcast 1.2.3.255
  gateway 1.2.3.1
  dns-nameservers 1.2.3.1
/etc/network/interfaces§

Remeber that using the Cockpit UI to change this doesn't work (that's the next problem to tackle). So doing it via command line via "virsh": "virsh edit [guest name]". ("source bridge" matching name picked in interfaces file)

<interface type='bridge'>
  <mac address='52:54:00:5e:bb:2c'/>
  <source bridge='br0'/>
  <model type='virtio'/>
  <address type='pci' domain='0x0000' bus='0x01' slot='0x00' function='0x0'/>
</interface>
virsh guest network setting

A simpler way is to use the "Virtual Machine Manager". Install it, enable root login with ssh-keys and connect to the server over ssh.

Root login with ssh-keys:
On server: "nano /etc/ssh/sshd_config", find: "PermitRootLogin" and set to "Yes", then restart sshd "/etc/init.d/ssh restart"
On your pc: "ssh-keygen", "ssh-copy-id root@server".
On server again: "nano /etc/ssh/sshd_config", find: "PermitRootLogin" and set to "prohibit-password", then restart sshd "/etc/init.d/ssh restart".

Good times

Now comes the fun part! It still doesn't work! So this led me to trying different things and questioning everything I thought I knew...
The problem is that the guests doesn't get ip addresses.

The magic that makes it work is two iptables lines (that I haven't bothered trying to convert to nftables yet...). It's quite logical when you are rested and look at this from a new angle...

#Where br0 is the bridge created in interfaces file
iptables -I FORWARD -i br0 -j ACCEPT
iptables -I FORWARD -o br0 -j ACCEPT
Allow traffic to and from br0

I am sure there are better and more ways of having these iptables commands run on boot and you'd think it's as easy as to put this to cron in @reboot statements, but the network isn't up yet.

My choice was to create a script with these statements and revisit the /etc/network/interfaces file and add one more row that is calling the script when the "br0" interface is brought up.

#!/bin/bash
iptables -I FORWARD -i br0 -j ACCEPT
iptables -I FORWARD -o br0 -j ACCEPT
/root/bridge_forwarding (don't forget to chmod +x)
# same file as before context
auto br0
iface br0 inet static
  bridge_ports enp8s0 # your main network adapter
  bridge_maxwait  4
  address 1.2.3.4
  netmask 255.255.255.0
  network 1.2.3.0
  broadcast 1.2.3.255
  gateway 1.2.3.1
  dns-nameservers 1.2.3.1
  # adding this new line calling the script listed above
  post-up /root/bridge_forwarding
/etc/network/interfaces

With these steps done the guests can communicate with the outside world and things are beautiful again.