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