Linux LXD/incus container with webserver, external accessible

Introduction

In this post I describe my experience with installing LXD/Incus containers on Arch Linux.

LXD is an ultra fast linux only hypervisor. LXD containers share the kernel. So not the whole OS is shared,like with Docker containers.

Unlike Docker - all data in every container instance is persistent, and any changes you make are permanent unless you revert to a backup. In short, shutting down the container will not erase any issues you might have introduced. This means that you can for instance start an interactive shell in the container, install some packages and then stop the container. When you restart the container the packages you just installed are still present. So the container feels like a VM.

The LXD project is no longer part of the Linux Containers project but can now be found directly on Canonical’s websites. A community fork of LXD, Incus, is now part of the Linux Containers project.

On Arch Linux Incus is now the default software for Linux containers. This is also the reason I used incus in stead of LXD.

Used sources

  • https://blog.simos.info/how-to-get-lxd-containers-get-ip-from-the-lan-with-routed-network/

Installation

The installion of incus is straightforward. For me the most difficult part was to get internet access from within the running container, so the networking part.

Install and init incus.

    pacman -S incus
    systemctl start incus
    incus admin init

Now you get an amount of questions you have to answer. For most questions the default value is good. For the networking part, answer that you do not need a bridge. We use a routed NIC instead of connecting the instance to the lxdbr0 bridge. For simplicity we assign a static IP address to the container. Because we can use an address that belongs to the LAN the host is on, the web server in the container will be easily accesble from outside.

incus profile create routed_192.168.1.30
EDITOR=vim incus profile edit routed

and insert the following is this profile:

    config:
      user.network-config: |
        version: 2
        ethernets:
            eth0:
                addresses:
                - 192.168.1.30/32
                nameservers:
                    addresses:
                    - 8.8.8.8
                    search: []
                routes:
                -   to: 0.0.0.0/0
                    via: 169.254.0.1
                    on-link: true
    description: Default LXD profile
    devices:
      eth0:
        ipv4.address: 192.168.1.30
        nictype: routed
        parent: end0
        type: nic
    name: routed_192.168.1.30
    used_by: []

NB: the parent above, must match the device name of the host

You have a course to adapt the above IP address to fit in your LAN; and use an IP-address outside the range of you DHCP-server.

Now create and launch an arch linux container named arch1.

incus  launch images:archlinux arch1 -c security.privileged=true --profile default --profile routed_192.168.1.30

This line first applies the default profile, and then the routed profile on top. security.privileged is necessary to make the container accessible from the outside. With the command incus list you can see what IP-address to assigned to container arch1.

To start an interactive shell in the container arch1, use following command:

incus exec arch1 -- bash

No internet access from within the container

A problem that occurs regulary is that there is no internet access from within the container. Note that if your system supports and uses nftables, LXD detects this during installation and switches to nftables mode. In this mode, LXD adds its rules into the nftables, using its own nftables namespace.

If you do not have internet access then go back to the host system, and try following commands

nft flush ruleset
systemctl restart incus

This fushes the rules of the firewall nft, and restarts incus. Especially if you also use Docker on the host system, docker adds some rules to the nft firewall. If you have internet access in the container after flushing the nft firewall rules, you know where to search the cause of the problem. Most times is has to do with the FORWARD chain, where packets are not accepted. The order of starting Incus, own fw and Docker can influence what fw-rules are active.

Now can install packages etc, which are persistant after stopping the container. So you can also easily install a webserver, like nginx.

incus exec arch1 -- bash
# pacman -Suy
# pacman -S nginx

Now you can configure a website in nginx, and add the file to /srv/http/

To stop the container:

incus stop arch1
Written on January 23, 2024