Using static IPs with LXD

LXD’s dnsmasq does not appear to have a setting to expire the leases.
Do these leases never practically expire?

Great, thanks.

lxc network set lxdbr0 ipv6.dhcp.stateful true

And adding iface eth0 inet6 dhcp to the ct’s /etc/network/interfaces did the job. :+1:

For some reason, I can’t change the IPv6 after setting it up the first time. The CT keeps the first IPv6. Is it an issue on the CT’s side or something about the leases?

I am still stuck at where is /etc/default/lxd-bridge. Using Ubuntu Server 17.10, no snap. Can I install the snap on top of the current system or do In need to remvoe local lxd first?

$ which lxd
/usr/bin/lxd

$ uname -r
4.13.0-36-generic

If the host has multiple static IP addresses, is it possible to assign one to a container?

/etc/default/lxd-bridge only exists in LXD 2.0.x, all newer releases, starting with LXD 2.1 have a in-LXD network management API which replaces it.

Those are the lxc network commands and you can find out about all the options here:
http://lxd.readthedocs.io/en/latest/networks/

To pass public IPs from the host to the container, you can either have them added to your host and NAT to your container’s IP, or (usually cleaner), route the IPs or subnets to your bridge, using the ipv4.routes option on the bridge and then adding it to the container with something like ip -4 addr add ADDRESS/32 dev eth0 (or the distribution network equivalent of that).

I am running 17.10 which has lxc/lxd v2.0.11. This does use lxc network. I think my installation got corrupted. I tied to unstall lxd lxc and got this.

$ sudo apt remove lxc lxd
Package ‘lxc’ is not installed, so not removed
The following packages will be REMOVED:
lxd

When I installed lxd from snapcraft
$ lxd --version
2.21
$ lxc --version
2.18
$ lxc start c2
Connection refused; is LXD running?
$ sudo service lxd start
Failed to start lxd.service: Unit lxd.service is masked.

I am going to rebuild the host and try again.

You need to remove lxd and lxd-client. It looks like you still have lxd-client installed which would explain your symptoms.

@stgraber thanks for all of the help, I finally got static ip to work. Here are my steps so that I can find this next time I want to add a static ip.

  1. Add static ip to host
    sudo ip -4 addr add 10.0.0.209/24 dev ens2

  2. Add static ip to bridge
    lxc network set lxdbr0 ipv4.routes 10.0.0.208/29

  1. Add static ip to vm
    sudo ip -4 addr add 10.0.0.209/32 dev eth0
2 Likes

For anyone with the same issue:
After upgrading from 2.0.x to 3.0.x (xenial -> bionic) then to 3.3 (snap), I was unable to get externally set static ip addresses to work, until I removed the following settings from the bridge config:
lxc network unset lxdbr0 raw.dnsmasq
lxc network unset lxdbr0 dns.mode

2 Likes

Hi all, so going on the 2 posts above from @simos, am I right to assume that the internal IP addresses given to containers by lxdbr0 are static for all practical intents and purposes?

I’m thinking about running commands like this to enable ssh access from my laptop to a specific container

lxc config device add <container-name> sshproxy proxy listen=tcp:<public-ip>:23 connect=tcp:<container-ip>:22 bind=host

or using haproxy to forward http and https to other containers…

Presumably LXD will retain the internal IP of the container in question in perpetuity?

Hi!

In practice I have not seen a container get a different IP address when it was restarted.
It is quite important to keep check of IP changes when you use iptables to forward connections from the host to a container (Because from container to container you can just use the hostnames).
In your case I would perform tests such as changing the time of the system when a container is about to start again to see whether it gets a new IP address.

However, if you are going to use the LXD proxy device, you do not need to worry about the IP address of the container. Because instead of specifying the IP address of the container, you can just type localhost.
For the host IP address, if you specify 0.0.0.0, then LXD will bind to all interfaces (as long as the port is free on each interface). If you have many network interfaces, you may want to just be explicit here.

That is, your SSH example would look like:

lxc config device add <container-name> sshproxy proxy listen=tcp:0.0.0.0:2222 connect=tcp:localhost:22 bind=host

Hi Simos, thank you, interesting… I’ll have a play around… I want to ssh into various containers on the same host, so I suspect I’ll need to have different ports for ssh on each container…

You either use different ports for each container.

Or, you can set up a bastion host for SSH. You can google for the bastion host and get some nice tutorials.

1 Like

Great, thank you…

The default expiration time for the “managed” lxdbr0 is actually 1h, check the output of:

lxc network get lxdbr0 ipv4.dhcp.expiry

If you check the parameters with which a dnsmasq instance is started you’ll notice the lease expiration set as part of the “--dhcp-range” parameter. According to dnsmasq man pages the parameter accepts a value of “infinite” so this should work for an infinite lease expiration time:

lxc network set lxdbr0 ipv4.dhcp.expiry=infinite

I presume that @stgraber might come up with some edge cases where using this is not advisable or cases when LXD might reinitialize /var/snap/lxd/common/lxd/networks/lxdbr0/dnsmasq.leases leading to loss of “infinite” leases.

That worked for me perfectly to set the IP address to a fixed value for the container, but since I’ve updated to LXD 5.6 / 5.7 that commands are no longer working:

lxc network attach lxdbr0 wireguard eth0 eth0
Error: Failed add validation for device “eth0”: Instance DNS name “wireguard” already used on network

lxc config set wireguard eth0 ipv4.address=10.0.5.102
Error: Invalid config: Unknown configuration key: eth0

Do you have any ideas?

You should be using lxc config device set ...
This hasn’t changed in LXD 5.7.

Thanks! This was the solution for me as well. :wink:

In case you need to create an instance from scratch (the way I understand it):

# determine the bridge's ip
$ lxc network get lxdbr0 ipv4.address
10.99.10.1/24
# as such the network's address range is apparently 10.99.10.0/24

# create an instance
$ lxc init images:debian/12 d12

# attach lxdbr0 to d12 as a NIC device
$ lxc network attach lxdbr0 d12 eth0 eth0

# set ip for the device
$ lxc config device set d12 eth0 ipv4.address 10.99.10.2

$ lxc start d12
$ lxc list
+------+---------+-------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| d12  | RUNNING | 10.99.10.2 (eth0) | ...  | CONTAINER | 0         |
+------+---------+-------------------+------+-----------+-----------+
$ lxc delete --force d12

But lxc network attach is a shortcut for lxc config device add, as such:

$ lxc init images:debian/12 d12
$ lxc config device add d12 eth0 nic network=lxdbr0 ipv4.address=10.99.10.2
$ lxc start d12
$ lxc list
+------+---------+-------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| d12  | RUNNING | 10.99.10.2 (eth0) | ...  | CONTAINER | 0         |
+------+---------+-------------------+------+-----------+-----------+
$ lxc delete --force d12

Or even this way:

$ lxc launch -d eth0,ipv4.address=10.99.10.2 images:debian/12 d12
$ lxc list
+------+---------+-------------------+------+-----------+-----------+
| NAME |  STATE  |       IPV4        | IPV6 |   TYPE    | SNAPSHOTS |
+------+---------+-------------------+------+-----------+-----------+
| d12  | RUNNING | 10.99.10.2 (eth0) | ...  | CONTAINER | 0         |
+------+---------+-------------------+------+-----------+-----------+
$ lxc delete --force d12

I didn’t find a way to determine the network’s ip range, but determining it via the bridge’s ip is probably fine. I’m not sure what’s the difference between a device name and a interface name (lxc network attach). And generally I’m not an expert at LXD, so I might be missing something.

Useful links:

UPD Particularly, I don’t understand why exactly I can’t use eth1 in place of eth0. E.g. how do I create an instance without eth0 and with eth1 that has a static ip? Or with eth0 (dynamic ip) and eth1 (static ip)? Not that that is important. Rather out of curiosity. To better understand how it works.