How to use LXD container hostnames on the host in Ubuntu 18.04

Update: 12 Oct 2018The systemd service file and the LXD lxdbr0 configuration have been updated according to the comment by mDfRgmd. Please check again and verify that you are using the updated version.

If you have two LXD containers, mycontainer1 and mycontainer2, then you can reference each other with those handy *.lxd hostnames like this,

$ lxc exec mycontainer1 -- sudo --user ubuntu --login
ubuntu@mycontainer1:~$ ping mycontainer2.lxd
PING mycontainer2.lxd(mycontainer2.lxd (fd42:cba6:557e:1a5a:24e:3eff:fce2:8d3)) 56 data bytes
64 bytes from mycontainer2.lxd (fd42:cba6:557e:1a5a:24e:3eff:fce2:8d3): icmp_seq=1 ttl=64 time=0.125 ms
^C
--- mycontainer2.lxd ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.125/0.125/0.125/0.000 ms
ubuntu@mycontainer1:~$

Those hostnames are provided automatically by LXD when you use a default private bridge like lxdbr0. They are provided by the dnsmasq service that LXD starts for you, and it’s a service that binds specifically on that lxdbr0 network interface.

LXD does not make changes to the networking of the host, therefore you cannot use those hostnames from your host,

ubuntu@mycontainer1:~$ exit
$ ping mycontainer2.lxd
ping: unknown host mycontainer2.lxd
Exit 2

In this post we are going to see how to set up the host on Ubuntu 18.04 (any Linux distribution that uses systemd-resolve) so that the host can access the container hostnames.

The default configuration per systemd of the lxdbr0 bridge on the host is

$ systemd-resolve --status lxdbr0
Link 2 (lxdbr0)
      Current Scopes: none
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no

The goal is to add the appropriate DNS server entries to appear in that configuration.

Let’s get first the IP address of LXD’s dnsmasq server for the network interface lxdbr0.

$ ip addr show dev lxdbr0
2: lxdbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether fe:2b:da:d9:49:4a brd ff:ff:ff:ff:ff:ff
inet 10.10.10.1/24 scope global lxdbr0
valid_lft forever preferred_lft forever
inet6 fd42:6a89:42d0:60b::1/64 scope global 
valid_lft forever preferred_lft forever
inet6 fe80::10cf:51ff:fe05:5383/64 scope link 
valid_lft forever preferred_lft forever

The IP address of the lxdbr0 interface in this case is 10.10.10.1 and that is the IP of LXD’s DNS server.

Now we can move on by configuring the host to consult LXD’s DNS server. In the following, you need to make the additions to the lxdbr0 bridge interface, and then select whether to perform the temporary or permanent systemd network configuration.

Additions to the lxdbr0 bridge interface (new!)

The following additions to the lxdbr0 bridge interface are required so that you avoid a DNS loop. A DNS loop may happen if there are two DNS servers and they end up asking each other for a name resolution. The following additions avoid a potential DNS loop.

First, let’s verify the name of the network interface. It is lxdbr0, and it’s a managed network interface.

$ lxc network list
+-----------+----------+---------+-------------+---------+
| NAME | TYPE | MANAGED | DESCRIPTION | USED BY |
+-----------+----------+---------+-------------+---------+
| lxdbr0 | bridge | YES | | 15 |
+-----------+----------+---------+-------------+---------+
..

What is the existing (and default) configuration of the network interface lxdbr0?

$ lxc network show lxdbr0
config:
ipv4.address: 10.100.1.1/24
ipv4.nat: "true"
ipv6.address: fd42:d282:a2d:f60a::1/64
ipv6.nat: "true"
description: ""
name: lxdbr0
type: bridge
used_by: []
managed: true
status: Created
...snip...

We need to add in there specific instructions to dnsmasq (the DNS server that is used in LXD for the managed network interfaces) so that dnsmasq

  1. knows it is the authoritative DNS Zone for the .lxd domain (auth-zone=lxd)
  2. adds protection against loops (dns-loop-detect)
    –dns-loop-detect,
    Enable code to detect DNS forwarding loops; ie the situation where a query sent to one of the upstream server eventually returns as a new query to the dnsmasq instance. The process works by generating TXT queries of the form .test and sending them to each upstream server. The hex is a UID which encodes the instance of dnsmasq sending the query and the upstream server to which it was sent. If the query returns to the server which sent it, then the upstream server through which it was sent is disabled and this event is logged. Each time the set of upstream servers changes, the test is re-run on all of them, including ones which were previously disabled.

You can add these two options with the following command.

$ echo -e "auth-zone=lxd\ndns-loop-detect" | lxc network set lxdbr0 raw.dnsmasq -

Let’s verify the change.

$ lxc network show lxdbr0
config:
ipv4.address: 10.100.1.1/24
ipv4.nat: "true"
ipv6.address: fd42:d282:a2d:f60a::1/64
ipv6.nat: "true"
raw.dnsmasq: |
auth-zone=lxd
dns-loop-detect
description: ""
name: lxdbr0
type: bridge
used_by: []
managed: true
status: Created
...

We have now edited the LXD managed network interface and are ready to configure systemd-resolved to resolve those .lxd domain names.

Temporary systemd network configuration

Run the following command to configure temporarily the interface and add the DNS service details.

$ sudo systemd-resolve --interface lxdbr0 --set-dns 10.10.10.1 --set-domain lxd

In this command,

  1. we specify the network interface lxdbr0
  2. we set the DNS server to the IP address of the lxdbr0, the interface that dnsmasq is listening on.
  3. we set the domain to lxd, as the hostnames are of the form mycontainer.lxd.

Now, the configuration looks like

$ systemd-resolve --status lxdbr0
Link 2 (lxdbr0)
      Current Scopes: DNS
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
         DNS Servers: 10.10.10.1
          DNS Domain: lxd

You can now verify that you can, for example, get the IP address of the container by name:

$ host mycontainer1.lxd
mycontainer.lxd has address 10.10.10.88
mycontainer.lxd has IPv6 address fd42:8196:99f3:52ad:216:3eff:fe0f:bacb
$

Note: The first time that you try to resolve such a hostname, it will take a few seconds for systemd-resolved to complete the resolution. You will get the result shown above, but the command will not return immediately. The reason is that systemd-resolved is waiting to get a resolution from your default host’s DNS server, and you are waiting for that resolution to timeout. The next attempts will be cached and return immediately.

You can also revert these settings with the following command,

$ systemd-resolve --interface lxdbr0 --revert
$ systemd-resolve --status lxdbr0
Link 3 (lxdbr0)
      Current Scopes: none
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
$

In general, this is a temporary network configuration and nothing has been saved to a file. When we reboot the computer, the configuration is gone.

Permanent systemd network configuration (updated)

We are going to set up systemd to run automatically the temporary network configuration whenever LXD starts. That is, as soon as lxdbr0 is up, our additional script will run and configure the per-link network.

First, create the following auxiliary script files.

$ cat /usr/local/bin/lxdhostdns_start.sh 
#!/bin/sh

LXDINTERFACE=lxdbr0
LXDDOMAIN=lxd
LXDDNSIP=`ip addr show lxdbr0 | grep -Po 'inet \K[\d.]+'`

/usr/bin/systemd-resolve --interface ${LXDINTERFACE} \
                         --set-dns ${LXDDNSIP} \
                         --set-domain ${LXDDOMAIN}

$ cat /usr/local/bin/lxdhostdns_stop.sh 
#!/bin/sh

LXDINTERFACE=lxdbr0

/usr/bin/systemd-resolve --interface ${LXDINTERFACE} --revert

Second, make them executable.

$ sudo chmod +x /usr/local/bin/lxdhostdns_start.sh /usr/local/bin/lxdhostdns_stop.sh

Third, create the following systemd service file. NOTE: the following has been updated (12 Oct 2018) according to the comment by mDfRgmd. The two changes are shown in bold/italic.

$ sudo cat /lib/systemd/system/lxd-host-dns.service 
[Unit]
Description=LXD host DNS service
After=multi-user.target

[Service]
Type=simple
ExecStart=/usr/local/bin/lxdhostdns_start.sh
RemainAfterExit=true
ExecStop=/usr/local/bin/lxdhostdns_stop.sh
StandardOutput=journal

[Install]
WantedBy=multi-user.target

This file

  • will activate after the lxd-containers.service service (therefore, lxdbr0 is up).
  • it is a oneshot (runs until completion before the next service).
  • it runs the respective scripts on ExecStart and ExecStop.
  • the RemainAfterExit is true, which means that it appears as running in systemd.
  • if something is wrong, it will be reported in the journal.
  • it gets installed in the multi-user target (same as the LXD service).

Fourth, now we reload systemd and enable the new service. The service is enabled so that when we reboot, it will start automatically.

$ sudo systemctl daemon-reload 
$ sudo systemctl enable lxd-host-dns.service 
Created symlink /etc/systemd/system/multi-user.target.wants/lxd-host-dns.service → /lib/systemd/system/lxd-host-dns.service. 
$

Note: This should work better than the old (next section) instructions. Those old instructions would fail if the lxdbr0 network interface was not up. Still, I am not completely happy with this new section. It appears that when you explicitly start or stop the new service, the action may not run. To be tested.

Troubleshooting

The first name resolution for each container takes long!

Indeed, when we try to resolve a name such as mycontainer.lxd, it takes some time for the resolution to complete. The reason is that systemd-resolved waits for the default DNS server (which has no knowledge of the *.lxd names) to try to resolve the name. The wait is the timeout time for the default DNS server to resolve the name. Ideally, systemd-resolved should understand that we used the .lxd suffix to the hostname, do a match with the Domains field in the per-link configuration, and only query the per-link DNS server.

It is not clear how to configure systemd to do just that, to not attempt to query the default DNS server for names that already have the .lxd suffix. If you have figure out a way for this, please write below.

Note though that subsequent queries for the same name return immediately with the correct answer because the answer is cached.

(old section, not working) Permanent network configuration

In systemd, we can add per network interface configuration by adding a file in /etc/systemd/network/.

It should be a file with the extension .network, and the appropriate content.

Add the following file

$ cat /etc/systemd/network/lxd.network 
[Match]
Name=lxdbr0

[Network]
DNS=10.100.100.1
Domains=lxd

We chose the name lxd.network for the filename. As long as it has the .network extension, we are fine.

The [Match] section matches the name of the network interface, which is lxdbr0. The rest will only apply if the network interface is indeed lxdbr0.

The [Network] section has the specific network settings. We set the DNS to the IP of the LXD DNS server. And the Domains to the domain suffix of the hostnames. The lxd in Domains is the suffix that is configured in LXD’s DNS server.

Now, let’s restart the host and check the network configuration.

$ systemd-resolve --status
...
Link 2 (lxdbr0)
      Current Scopes: DNS
       LLMNR setting: yes
MulticastDNS setting: no
      DNSSEC setting: no
    DNSSEC supported: no
         DNS Servers: 10.100.100.1
                      fe80::a405:eade:4376:3817
          DNS Domain: lxd

Everything looks fine. By doing the configuration this way, systemd-resolve also picked up automatically the IPv6 address.

Conclusion

We have seen how to setup the host on a LXD installation so that processes on the host are able to see the hostnames of the containers. For Ubuntu 18.04 or any distribution that uses systemd for the DNS client needs.

If you use Ubuntu 16.04, then it requires a different way involving the dnsmasq-base configuration. There are instructions on this on the Internet, ask if you cannot find them.

Permanent link to this article: https://blog.simos.info/how-to-use-lxd-container-hostnames-on-the-host-in-ubuntu-18-04/

32 comments

1 ping

Skip to comment form

    • Rudi Servo on September 25, 2018 at 15:36
    • Reply

    On ubuntu 18.04 resolved stays at 100% cpu usage causo of DNSMASQ
    Adding this DNSMASQ_EXCEPT=lo to /etc/default/dnsmasq will solve the problem has stated in

    https://askubuntu.com/questions/909591/systemd-resolve-high-cpu-usage-after-update-to-17-04/968309

      • Rudi Servo on September 25, 2018 at 15:59
      • Reply

      sorry it didnt work has expected still debugging :/

    1. The discussion has moved to this thread, https://discuss.linuxcontainers.org/t/ubuntu-18-04-infinite-loop-dnsmasq-systemd-resolved/2768/

      Thanks for narrowing it down to an issue with IPv6. Specifically, if IPv6 is not (fully?) available, then there are excessive requests with lead to high CPU usage.

  1. The /lib/systemd/system/lxd-host-dns.service syntax didn’t work for me under Ubuntu 18.04. Here is what worked:

    [Unit]
    Description=LXD host DNS service
    After=multi-user.target

    [Service]
    Type=simple
    ExecStart=/usr/local/bin/lxdhostdns_start.sh
    RemainAfterExit=true
    ExecStop=/usr/local/bin/lxdhostdns_stop.sh
    StandardOutput=journal

    [Install]
    WantedBy=multi-user.target

    Notice the Type=simple and After= change.

    Thank you for your blog. There are little information about LXD and what you provide is very informative.

    1. Many thanks mDfRgmd!

      I have updated the post to include
      1. the additions in the LXD managed network interface (auth-zone=lxd, detect-dns-loop)
      2. the changes the systemd service file.

  2. Hi,

    Thank you for sharing your fix. I have an issue with this… Once I apply your fix (lxc network configuration + systemd), name resolution works from my host machine to containers (host xxx.lxd works fine from host). The problem is that when it works, my containers cannot resolve DNS queries (host google.com from inside containers for instance). If I stop the systemd service, containers can do DNS resolution but my host cannot do lxd domain resolution to containers. Any idea of what is going on?

    Btw, instead of having two scripts, I have merged them into this:

    #!/bin/sh

    ACTION=$1
    #LXDINTERFACE=lxdbr0
    LXDINTERFACE=`/snap/bin/lxc network list --format csv | egrep '^(.*),(.*),YES,(.*),(.*)$' | head -n 1 | cut -d ',' -f1 -`
    #LXDDOMAIN=lxd
    LXDDOMAIN=`/snap/bin/lxc network get ${LXDINTERFACE} dns.domain`
    LXDDNSIP=`ip addr show ${LXDINTERFACE} | grep -Po 'inet \K[\d.]+'`

    if [ "$ACTION" = "start" ]
    then
    /usr/bin/systemd-resolve --interface ${LXDINTERFACE} \
    --set-dns ${LXDDNSIP} \
    --set-domain ${LXDDOMAIN}

    elif [ "$ACTION" = "stop" ]
    then
    /usr/bin/systemd-resolve --interface ${LXDINTERFACE} --revert

    else
    echo "Unknown action $ACTION, use start or stop"
    exit 1
    fi

    File is /usr/local/bin/lxdhostdns.sh, and you can use it with start or stop as argument. This way systemd script will call it as /usr/local/bin/lxdhostdns.sh start or /usr/local/bin/lxdhostdns.sh stop.

      • Javier Matos Odut on November 2, 2018 at 18:03
      • Reply

      Ups, sorry, everything is working now. Thank you for your solution to this issue! 🙂

      1. Thanks for coming back and confirming that the instructions in the post work!

      2. What was the solution, Javier? I have the exact same problem. I can’t see the solution in the tree, however

  3. Thanks for the awesome tutorial.
    Though I faced problem that nslookup mycontainer2.lxd not contacting new lxd-host-dns
    systemd-resolve --flush-caches fixed this

    1. Sorry I was wrong, the reason wast that hetzner vps cloud ubuntu instance had /etc/network/interfaces.d/50-cloud-init.cfg with dns-nameservers defined for resolv.conf.
      After commenting that out resolv.conf started to look as expected:

      nameserver 127.0.0.53
      search lxd

    • Alexander K. on January 5, 2019 at 05:52
    • Reply

    I have the exact same problem that javier had. Namely…

    “Thank you for sharing your fix. I have an issue with this… Once I apply your fix (lxc network configuration + systemd), name resolution works from my host machine to containers (host xxx.lxd works fine from host). The problem is that when it works, my containers cannot resolve DNS queries (host google.com from inside containers for instance). If I stop the systemd service, containers can do DNS resolution but my host cannot do lxd domain resolution to containers. Any idea of what is going on?”

    My system is using lxd 3.0.3 (from apt) on Ubuntu 18.04 Server.

    I can’t figure out how to solve it.

    1. I’m in the exact same boat as you. Same issue, desperate for some help since this whole DNS resolution bit is a bit beyond my experience. Maybe Javier Matos Odut will come back and fill us in on his solve?

    • Alexander K. on January 5, 2019 at 06:03
    • Reply

    In particular, it does this (maybe has something to do):

    systemctl start lxd-host-dns.service

    nslookup news.com 10.19.181.1

    ** server can’t find news.com: REFUSED

    systemctl stop lxd-host-dns.service

    nslookup news.com 10.19.181.1

    Address: 64.30.224.82

    Am I doing something wrong? I’m on a fresh server on hetzner

  4. Using the “broken” section worked with the lxd.network file for me, all that I had to do was enable systemd-networkd and all was well. No need for the script or custom systemd service.

    • Stephen Czetty on March 27, 2019 at 18:57
    • Reply

    I had the same issue that Javier, Alexander, and others had. My solution was to add some arguments to dnsmasq:

    echo -e "auth-zone=lxd\ndns-loop-detect\nserver=<nameserver ip>\nno-resolv" | lxc network set lxdbr0 raw.dnsmasq -

    So instead of using resolv.conf, it uses the nameserver specified. This might remove the need for dns-loop-detect, I’m not sure; I haven’t tested it.

  5. Thanks so much for this, I love it. I plan to work through your other lxc tutorials too! FYI, there’s a typo in this article, some missing newlines, around the command: sudo systemctl enable lxd-host-dns.service

  6. and maybe more than a typo? The command quoted in my comment above (a) doesn’t work for me, name resolution is lost on reboot, and (b) ends with a mysterious ‘$’. Could whatever mangled the newlines have also truncated some extra required commands?

  7. hi, with this i can not ping google.com inside of container

  8. Works great!

    As a nitpick – /lib/systemd/ is for vendor packages, so the service should be under /etc/systemd (per man 5 file-hierarchy). It works either way, but /etc/ has priority over /lib/

    • Peter Goodall on February 2, 2020 at 07:21
    • Reply

    In the last hour this was working now it is not. It looks like everything is configured properly:

    systemd-resolve --status lxdbr0
    Link 3 (lxdbr0)
    Current Scopes: DNS
    LLMNR setting: yes
    MulticastDNS setting: no
    DNSSEC setting: no
    DNSSEC supported: no
    DNS Servers: 10.19.75.1
    DNS Domain: lxd

    % lxc ls
    +----------+---------+---------------------+-----------------------------------------------+-----------+-----------+
    | NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
    +----------+---------+---------------------+-----------------------------------------------+-----------+-----------+
    | bionic | STOPPED | | | CONTAINER | 0 |
    +----------+---------+---------------------+-----------------------------------------------+-----------+-----------+
    | ssh-test | RUNNING | 10.19.75.191 (eth0) | fd42:73f7:f9a1:12ed:216:3eff:fe1e:cf7a (eth0) | CONTAINER | 1 |
    +----------+---------+---------------------+-----------------------------------------------+-----------+-----------+

    host ssh-test.lxd
    Host ssh-test.lxd not found: 3(NXDOMAIN)

    I have rebooted and restarted everything I can think of. I would like some help on diagnosis please.
    Im on Ubuntu 18.04.3

    • Bram on March 25, 2020 at 21:38
    • Reply

    Thanks for the excellent article!

    Experienced the same problem that resolving did notwork anymore after a reboot. It turned out the script fires too early, before the bridge is actually up. At that point, it can’t determine the ip address of the dns service. (using Ubuntu 19.04 here, btw)

    I’ve built in an extra wait and poll to check if lxdbr0 is up. Even a tool that has been made to solve these kind of problems, does not work: /lib/systemd/systemd-networkd-wait-online --interface=lxdbr0 --operational-state=routable. It returns just a fraction second before the bridge is up.

    I’m using this version of the script, with a simple wait loop included:

    #!/bin/bash

    echo Invoked | systemd-cat -t $(basename $0) -p info

    LXDINTERFACE=lxdbr0
    LXDDOMAIN=lxd

    # operational-state routable is not up yet.... so not using systemd-networkd-wait-online
    # /lib/systemd/systemd-networkd-wait-online --interface=$LXDINTERFACE --operational-state=routable --timeout=120
    # also this won't help in this case
    # https://askubuntu.com/questions/972215/a-start-job-is-running-for-wait-for-network-to-be-configured-ubuntu-server-17-1/1160483#1160483

    # wait for the lxd interface to come up
    counter=0
    while ! grep -q up /sys/class/net/$LXDINTERFACE/operstate 2>/dev/null
    do
    sleep 1
    counter=$((counter + 1))
    if [ $counter -ge 120 ]
    then
    echo Gave up waiting for the LXD interface $LXDINTERFACE to come up | systemd-cat -t $(basename $0) -p err
    exit 1
    fi
    done

    # determine dns ip
    LXDDNSIP=`ip addr show lxdbr0 | grep -Po 'inet \K[\d.]+'`

    echo IP of LXD dns server is $LXDDNSIP | systemd-cat -t $(basename $0) -p info

    /usr/bin/systemd-resolve --interface ${LXDINTERFACE} --set-dns ${LXDDNSIP} --set-domain ${LXDDOMAIN}

    exit 0

    Bests,

    Bram

    • Skyrider on July 21, 2020 at 23:34
    • Reply

    While it does appear to be working. Many of my sites inside containers started to die with a 502 bad gateway error . Not only that, the sites that did work had a major increased loading time. Once I reverted back, the sites were running normally again.

    Any idea as to why?

    1. Thanks!

      See Bram’s reply just above. There appears to be at least a race condition that affects some users.

  9. I modified the script and systemd unit to use a systemd unit template

    $ cat /etc/systemd/system/lxd-host-dns@.service

    [Unit]
    Description=LXD host DNS service for Interface %I
    After=snap.lxd.daemon.service
    PartOf=snap.lxd.daemon.service
    After=sys-subsystem-net-devices-%i.device
    BindsTo=sys-subsystem-net-devices-%i.device

    [Service]
    Type=simple
    ExecStart=/usr/local/bin/lxdhostdns_start.sh %i
    RemainAfterExit=true
    ExecStop=/usr/local/bin/lxdhostdns_stop.sh %i
    StandardOutput=journal

    [Install]
    WantedBy=snap.lxd.daemon.service
    WantedBy=sys-subsystem-net-devices-%i.device

    $ cat /usr/local/bin/lxdhostdns_start.sh

    #!/bin/sh

    [ $# -eq 1 ] || exit 1

    LXDINTERFACE=$1
    [ -d /sys/class/net/${LXDINTERFACE} ] || exit 1
    LXDDOMAIN=$(lxc network get ${LXDINTERFACE} dns.domain)
    LXDDNSIP=$(lxc network get ${LXDINTERFACE} ipv4.address | sed 's;/.*;;')

    /usr/bin/resolvectl dns ${LXDINTERFACE} ${LXDDNSIP}
    /usr/bin/resolvectl domain ${LXDINTERFACE} ~${LXDDOMAIN:-lxd}

    $ cat /usr/local/bin/lxdhostdns_stop.sh

    #!/bin/sh

    [ $# -eq 1 ] || exit 1
    LXDINTERFACE=$1
    [ -d /sys/class/net/${LXDINTERFACE} ] || exit 0

    /usr/bin/resolvectl revert ${LXDINTERFACE}

    Then run: systemctl daemon-reload && systemctl enable --now lxd-host-dns@lxdbr0 (replace lxdbr0 for whichever LXD bridge you want.

    I substituted ip addr show for lxd network get to avoid race condition mentioned above. This approach would not be possible if bridge is not managed by LXD, but then, name resolution would not be done by LXD’s dnsmasq in the first place.

  10. Adfter following this guide I was sucessfully able to resolve container hostname on the host machine but it stopped containers from resolving. To address this I ammended the start script to:

    #!/bin/sh

    HOSTINTERFACE=wlan0
    HOSTDNSIP=systemd-resolve --status wlan0 | grep -Po 'DNS Servers: \K[\d.]+'

    LXDINTERFACE=lxdbr0
    LXDDOMAIN=lxd
    LXDDNSIP=ip addr show lxdbr0 | grep -Po 'inet \K[\d.]+'

    /usr/bin/systemd-resolve –interface ${LXDINTERFACE} \
    –set-dns ${LXDDNSIP} \
    –set-dns ${HOSTDNSIP} \
    –set-domain ${LXDDOMAIN}

    Where HOSTINTERFACE needs to be set to your hosts connected interface.

  11. This stopped working immediately after a reboot so it must just have been the cache making it work. Even more simply appending the LXD domain with ‘~’ makes the permenant solution work and enables the host to resolve containers hostnames and containers to resolve external domains.

    So simply changing:

    LXDDOMAIN=lxd

    To:

    LXDDOMAIN=’~lxd’

    Was all that was required. There are details of this here under ‘Intergration with systemd-resolvd’:

    https://lxd.readthedocs.io/en/stable-4.0/networks/

    “Note the ~ before the domain name is important; it tells resolved to use this nameserver to look up only this domain; no matter what your actual domain name is”.

    • tedkerncanonical on March 30, 2021 at 09:12
    • Reply

    Can confirm this works – if you’re using bionic or earlier the resolvectl invocation may cause problems however. Substitute systemd-resolve on older distros (ones that use systemd<239).

  12. Below is a similar solution based on a suggestion from Stéphane Graber, the technical lead for LXD at Canonical Ltd. See the following GitHub comment for details:

    https://github.com/lxc/lxd/issues/3391#issuecomment-859686669

    The Systemd file is:

    [Unit]
    Description=Per-link DNS configuration for lxdbr0
    BindsTo=sys-subsystem-net-devices-lxdbr0.device
    After=sys-subsystem-net-devices-lxdbr0.device systemd-resolved.service

    [Service]
    Type=oneshot
    ExecStart=/usr/bin/resolvectl dns lxdbr0 10.178.4.1
    ExecStart=/usr/bin/resolvectl domain lxdbr0 ‘~lxd’

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

    You’ll need to change the IP address on the first ExecStart= line.

  13. This setup was woking fine for me until yesterday 17 June. I think due to system updating something automatically.

    When I looked at my system logs I could see a startup error for dnsmasq:
    “–auth-server required when an auth zone is defined”

    So I modified the lxdbr0 network interface config command, to set googe as the auth server:

    “echo -e “auth-zone=lxd\nauth-server=8.8.8.8\ndns-loop-detect” | lxc network set lxdbr0 raw.dnsmasq -”

    Now its working again : )

  14. @stewymac07, that might have been the LXD Snap package update yesterday. See here:

    dnsmask process exited prematurely if raw.dnsmasq auth-zone set when using core20 snap
    https://github.com/lxc/lxd/issues/8905

    Note that the section “Integration with systemd-resolved” in the LXD Network configuration page has been updated now to include the solution to the problems in this blog post:

    LXD Network configuration – Integration with systemd-resolved
    https://linuxcontainers.org/lxd/docs/master/networks.html

  15. thanks John. I’ll have a look at those links.

  1. […] to set-up functionality to enable container hostname resolution on the vagrant box as described in How to use LXD container hostnames on the host in Ubuntu 18.04, but this caused a lot of headaches. It caused DNS loops that were correctly cut, but prevented the […]

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.