Network bridge with static IP on host

Solution

Ok I solved it. The problem was that gnome apparently autostarts network manager which interfered with my config. So what I did was to deactivate the network connection in the GUI and then use the following config:

  networking.useDHCP = false;
  networking.bridges = {
    "br0" = {
      interfaces = [ "enp8s0" ];
    };
  };
  networking.interfaces.br0.ipv4.addresses = [ {
    address = "10.10.10.10";
    prefixLength = 24;
  } ];
  networking.defaultGateway = "10.10.10.1";
  networking.nameservers = ["10.10.10.1" "8.8.8.8"];

With this everything works as expected. I can then set up a static IP in the VM and everything is working as specified.


Original message

My machine has one network interface enp8s0. I’d like to have the following setup:

  1. Host with static IP 10.10.10.10/24, reachable on the internal network (e. g. over ssh and xRDP)
  2. KVM Virtual machine with static IP 10.10.10.11/24, reachable on the internal network
  3. Both machines need to be connected to the internet

Tested configurations

Bridged DHCP

  networking.useDHCP = false;
  networking.interfaces.enp8s0.useDHCP = true;
  networking.interfaces.br0.useDHCP = true;
  networking.bridges = {
    "br0" = {
      interfaces = [ "enp8s0" ];
    };
  };

This is the closest I got: when using this configuration the VM is completely reachable in the internal network and both machines have an internet connection. However: now the host is not reachable. Also: this is obviously missing the static IP config.

Bridged with static IP

  networking.useDHCP = false;
  networking.interfaces.enp8s0.useDHCP = true;
  networking.interfaces.br0.useDHCP = false;
  networking.bridges = {
    "br0" = {
      interfaces = [ "enp8s0" ];
    };
  };
 networking.interfaces.br0.ipv4.addresses = [ {
   address = "10.10.10.11";
   prefixLength = 24;
 } ];
 networking.defaultGateway = "10.10.10.1";
 networking.nameservers = ["10.10.10.1" "8.8.8.8"];

With this config I neither have internet nor LAN access in the VM. On the host I have internet but no access to the LAN.

I tested 3 more combinations of the above but those were just desperate experiments.

Can someone enlighten me?

3 Likes

Since I had similar problems, I wanted to share my experience setting up a bridge to a containers.nextcloud:

  containers.nextcloud = {
    privateNetwork = true;
    hostBridge = "br0";
    localAddress = "192.168.1.100/16";

With the help of @mradke i also came to the following solution.

Dymanically:

networking.useDHCP = false;
networking.bridges."br0".interfaces = [ "enp42s0" ];
networking.interfaces."br0".useDHCP = true;

Static: (Its identical to yours)

networking.useDHCP = false;
networking.bridges."br0".interfaces = [ "enp42s0" ];
networking.interfaces."br0".ipv4.addresses = [{
  address = "192.168.1.10";
  prefixLength = 16;
}];
networking.defaultGateway = "192.168.1.1";
networking.nameservers = [ "192.168.1.1" ];

I don’t know why networking.useDHCP = false; is needed, but without it won’t work.

I also want to point out that the bridge is fully replacing the ethernet interface. So “enp42s0” in my case cannot have an ip. It even gives a warning when trying to set one:

networking.interfaces."enp42s0".ipv4.addresses = [{
  address = "192.168.1.5";
  prefixLength = 16;
}];

→ The networking.interfaces."enp42s0" must not have any defined ips when it is a slave.

And for those who are curious, the host now is using the IP of the bridge.
Also you cant create two bridges and assign it to one interface.

2 Likes

I think this is necessary in order to deactivate dhcpd which would otherwise try to get a dynamic IP at startup.

2 Likes

When you are using bridge interface you need to assign the IP to it and not to the physical interface that you attach into it. When you do not declare to ignore DHCP on the physical interface both will be able to pick up the same IP.