3

I'm using LXC containers, and resolving CONTAINERNAME.lxd to the IP of the specified container, using:

sudo resolvectl dns lxdbr0 $bridge_ip
sudo resolvectl domain lxdbr0 '~lxd'

This works great! But the changes don't persist over a host reboot.

(I've described 'things I've tried' as answers to this question, which have varying degrees of success.)

I'm on Pop!_OS 22.04, which is based on Ubuntu 22.04.

How should I be making these resolvectl changes persistent across reboots?

4 Answers 4

2

The LXD docs describe a solution:

Put this in /etc/systemd/system/lxd-dns-lxdbr0.service:

[Unit]
Description=LXD per-link DNS configuration for lxdbr0
BindsTo=sys-subsystem-net-devices-lxdbr0.device
After=sys-subsystem-net-devices-lxdbr0.device

[Service]
Type=oneshot
ExecStart=/usr/bin/resolvectl dns lxdbr0 BRIDGEIP
ExecStart=/usr/bin/resolvectl domain lxdbr0 '~lxd'
ExecStopPost=/usr/bin/resolvectl revert lxdbr0
RemainAfterExit=yes

[Install]
WantedBy=sys-subsystem-net-devices-lxdbr0.device

(Substituting your own BRIDGEIP, from lxc network show lxdbr0 | grep ipv4.address)

Then apply those settings without having to reboot using:

sudo systemctl daemon-reload
sudo systemctl enable --now lxd-dns-lxdbr0
1
  • This answer (a) works, (b) solves the original problem perfectly, and (c) is endorsed by the LXD project documentation. 5 stars. Commented Sep 27, 2022 at 21:13
1

I've hacked up a ghastly workaround: Created a script lxc-ip, that scrapes the container's IPv4 from the output of lxc list. An example use: ping $(lxc-ip mycontainer).

The script looks like:

#!/usr/bin/env bash

prog=$(basename $0)

function usage {
    echo "Usage: $prog CONTAINER" >&2
    echo "Outputs IPv4 address of given CONTAINER." >&2
}

container=""

while [[ $# -gt 0 ]]
do
  case "$1" in
  -h|--help)
    usage
    exit 0
    ;;
  *)
    if [ -z "$container" ]; then
        container=$1
    else
        echo "$prog error: Not multiple CONTAINERs" >&2
        usage
        exit 1
    fi
    ;;
  esac
  shift
done

if [ -z "$container" ]; then
    echo "$prog error: Must pass a CONTAINER" >&2
    usage
    exit 1
fi

table=$(lxc list -c ns4 -f csv)
line=$(echo "$table" | grep "$container")
if [ -z "$line" ]; then
    echo "$prog error: Container '$container' not found. Existing containers are:" >&2
    lxc list -c n -f compact >&2
    exit 2
fi

if ! grep -qs RUNNING <<<"$line" ; then
    echo "$prog error: Container is not running: $line" >&2
    exit 3
fi

ipv4=$(echo "$line" | cut -d',' -f3 | cut -d' ' -f1)
if [ -z "$ipv4" ]; then
    echo "$prog error: Container has no IPv4: $line" >&2
    exit 4
fi

echo "$ipv4"
1

In case anyone can refine or confirm, a colleague reports that he has solved this using some mechanism which involves this text in /etc/systemd/network/lxd.network:

[Match]
Name=lxdbr0

[Network]
Address=BRIDGEIP/24
DNS=BRIDGEIP
Domains=lxd

(Substituting your own BRIDGEIP, from lxc network show lxdbr0 | grep ipv4.address)

(This might also require running systemd-networkd and NetworkManager simultaneously)

1

I see a similar askubuntu.com question, in which the lone (-1) answer advises to persist other resolvectl changes by converting them into nmcli (Network Manager CLI) calls instead. This apparently stores the information somewhere persistent, which is used to populate the 'resolvectl' config on boot.

If I were to do that, I think I can see how I would convert the first of my resolvectl calls, using something like:

sudo nmcli connection modify lxdbr0 ipv4.dns $bridge_ip

But I am unable to translate my second resolvectl call, setting `domain=~lxd", into nmcli commands.

So this approach doesn't solve the problem.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .