Make LXD use your server's public network interface


By default LXD creates an internal network bridge called lxdbr0 which new containers are attached to (a network bridge in Linux is similar to a physical LAN switch). That way containers can talk to each other on the same network. Even the LXD host is connected to the same bridge. To make a service in a container reachable from the outside world, a proxy is used in most cases, e.g. Nginx for web services and HAProxy for any other services.

But what if you cannot or do not like to connect a service via a proxy? No problem! LXD can not only make use of a “host internal” network bridge, but any network bridge on your system. So let’s set up a network bridge that is linked to a public interface! The container’s network configuration will be similar to the one on your container host. A public IP address can be used directly.

Set up LXD host

First we need to prepare the LXD host. Probably you have a network configuration similar to the following (ens3 is the public interface):

/etc/network/interfaces

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug ens3
iface ens3 inet static
       address 1.2.3.2/24
       gateway 1.2.3.1
       dns-nameservers 1.2.3.1
       dns-search mydomain.tld

iface ens3 inet6 static
       address fd00::2/64
       gateway fd00::1
       dns-nameservers fd00::1
       dns-search mydomain.tld

By default your network looks like this:

LXD internal bridge netwrk

Your container environment (including the lxdbr0 bridge) is entirely separated from the internet. Let’s change that!

We need to introduce a new network bridge interface br0 on the host system and configure it similar to the ens3 interface. The configuration of the ens3 interface is removed and the old interface it is just attached to the bridge.

Make sure bridge-utils are installed:

apt install bridge-utils

New network configuration (ens3 is replaced by br0 + some extra attributes):

source /etc/network/interfaces.d/*

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug ens3

auto br0
iface br0 inet static
	address 1.2.3.2/24
	gateway 1.2.3.1
	dns-nameservers 1.2.3.1
	dns-search mydomain.tld
	bridge_ports ens3
	bridge_fd 5
	bridge_stp yes

iface br0 inet6 static
	address fd00::2/64
	gateway fd00::1
	dns-nameservers fd00::1
	dns-search mydomain.tld
	bridge_ports ens3
	bridge_fd 5
	bridge_stp yes

Create a new container profile

Create new LXD container profile which will give containers direct access to the public bridge (we’ll call the new profile “extbridge”):

lxc profile create extbridge
EDITOR=nano lxc profile edit extbridge

Change the “description” attribute and the “devices” YAML tree:

config: {}
description: Lets containers use public network interface
devices:
  eth0:
    name: eth0
    nictype: bridged
    parent: br0
    type: nic
name: extbridge
used_by: []

Use new container profile

When creating new containers, assign the default profile and the new extbridge profile:

lxc launch -p default -p extbridge images:debian/9 mydebiancontainer

To assign the new profile to existing containers use:

lxc profile assign myexistingcontainer default,extbridge

Configure network in container

Example for configuration:

allow-hotplug eth0
iface ens3 inet static
	address 1.2.3.3/24
	gateway 1.2.3.1
	dns-nameservers 1.2.3.1
	dns-search mydomain.tld

iface eth0 inet6 static
	address fd00::3
	gateway fd00::1
	dns-nameservers fd00::1
	dns-search mydomain.tld

Also add your network’s DNS resolver (usually the gateway) to /etc/resolv.conf (because resolvconf package is not installed, yet, so DNS sresolvers are not read from /etc/network/interfaces file)

/etc/resolv.conf

nameserver 1.2.3.1
nameserver fd00::1

Restart networking:

systemctl restart networking

Now you should have a working internet connection. Don’t forget to install resolvconf:

apt update
apt install resolvconf

Your network now looks like this:

LXD public bridge

Done! :-)