Linux Container Primer (LXD/LXC and Multipass)

Quick Reference

LXD vs Incus

Please note that Canonical (maker of Ubuntu) created quite the disruption with the LXD team. As a result, Incus was created as a fork of LXD. All future ERP Academy use will involve Incus (not LXD). You can use all below commands by simply replacing "lxd" with "incus".

References:

LXC/LXD Linux Container Quick Start

If you are running Linux as your main operating system, LXC - Linux containers are an amazing tool! They are much lighter weight than virtual machines. Be aware that LXC/LXD has much overlap with Multipass functionality. If you are new to Linux, I would start with Multipass. More advanced users will want to start with LXC/LXD

Below are resources to help you get started with containers.

Incus Installation

See: https://github.com/zabbly/incus

Incus Cheatsheet

Docker

As of incus 6.3, you can run docker images straight from the incus cli. Said another way, you no longer need to create an incus image and install the docker tools. Here are some example commands.

Add docker as a remote:

incus remote add docker https://docker.io --protocol=oci

List remotes:

incus remote list

Launch your first docker (where 'console' shows text and 'ephemeral' said delete yourself after execution complete):

incus launch docker:hello-world --console --ephemeral

Connect to your instances as root:

incus exec instance-name-here -- bash

Launch a docker container with an environment file (incus 6.4 feature):

incus launch docker:mysql mysql --environment-file mysql.env

Launching in iDempiere instance:

incus launch docker:idempiereofficial/idempiere --console

Notes about iDempiere deployment:

Reference:

Github Container Registry

The Github Container Repository (ghcr.io) is like dockerhub in that it hosts containers.

To add the ghcr.io to your Incus:

incus remote add github https://ghcr.io --protocol=oci 

To launch an image from hgcr.oi:

incus launch github:open-webui/open-webui:main openwebui07 -d root,size=30GiB -c limits.cpu=2 -c limits.memory=4GiB --environment-file openwebui.env

Note: openwebui.env is where you put all the containers environment variables.

LXD Passthrough Route Making Services Accessible

Reference: https://www.youtube.com/watch?v=TmGvbXfwJEA&t=832s

Command to add pass through for 443 (https):

lxd config device add ContainerName www proxy listen=tcp:192.168.1.214:443 connect=tcp:0.0.0.0:443

Where:

Command to remove the above pass through:

lxd config device remove ContainerName www

Command to show pass through:

incus config device show ContainerName

LXD Profile Management

Create a new profile in LXD:

lxc profile create cloud-profile1

Apply a pre-created textfile to the new profile:

cat cloud-profile1.profile | lxc profile edit cloud-profile1

Apply the profile during incus launch with flag -p:

incus launch imageserver:image instancename -p cloud-profile1

More Information...

LXD/LXC GuiContainer Example Profile

The following profile enables you to run gui apps from inside your container as if they are actually running on your host machine. The advantage of this configuration is that you can install and run a vpn and firefox from within your container without touching your host networking configuration. Said another way, you can run many containers at the same time... Each running a different vpn to different destinations.

Notes about the following profile:

? incus profile show gui2
 config:
   environment.DISPLAY: :1
   raw.idmap: both 1000 1000
   security.nesting: "true"
   security.syscalls.intercept.mknod: "true"
   security.syscalls.intercept.setxattr: "true"
   user.user-data: |
     #cloud-config
     runcmd:
       # Create symlinks in expected locations (works even if /tmp is tmpfs)
       - mkdir -p /tmp/.X11-unix
       - ln -sf /mnt/host-x11/X1 /tmp/.X11-unix/X1
       - mkdir -p /tmp/.pulse-native
       - ln -sf /mnt/host-pulse/native /tmp/.pulse-native/
       - 'sed -i "s/; enable-shm = yes/enable-shm = no/g" /etc/pulse/client.conf'
       - 'echo export PULSE_SERVER=unix:/tmp/.pulse-native | tee --append /home/debian/.profile'
       - [su, debian, -c, "git clone https://github.com/chuboe/chuboe-system-configurator /home/debian/chuboe-system-configurator"]
       - [su, debian, -c, "cd /home/debian/chuboe-system-configurator/; ./init.sh"]
     packages:
       - x11-apps
       - mesa-utils
       - pulseaudio
       - git
       - ufw
 description: GUI LXD profile
 devices:
   PASocket:
     path: /mnt/host-pulse/
     source: /run/user/1000/pulse/
     type: disk
   X0:
     path: /mnt/host-x11/
     source: /tmp/.X11-unix/
     type: disk
   mygpu:
     type: gpu
 name: gui2

You can launch a new gui container with the following command:

incus launch images:debian/12/cloud YourInstanceName --profile default --profile gui2

Notes:

Cloud Init Details

Incus Shared Directory

keywords: drive,folder.map

Add a New Remote Server

#on the client - get/generate a certificate
incus remote get-client-certificate | tee /tmp/cert.txt

#on the server - add the client certificate
incus config trust add-certificate /path/to/cert.txt

#on the client - give the remote a meaningful name
incus remote add <remote-name> https://<server-ip>:<port:8443>

Connect and Manage Remote Clusters

Connect to a remote server:

incus remote switch some-remote

Confirm looking at remote to ensure you see different instances:

incus list

While in the remote cluster, you might belong to more than one project. To list projects:

incus project list

The table will indicate the current project. To switch projects:

incus project switch some-other-project

Switch back to your local cluster/server:

incus remote switch local

Incus Debian Desktop

Here are the steps to install a Debian 12 gnome desktop:

Incus on Mac/Apple

$brew install colima
$brew install incus
$colima start —runtime incus

INFO[0000] starting colima
INFO[0000] runtime: incus
INFO[0002] creating and starting … context=vm
INFO[0002] downloading disk image … context=vm
INFO[0033] provisioning … context=incus
INFO[0034] starting … context=incus
INFO[0035] done

Gives me:

$incus version
~> incus version
Client version: 6.17
Server version: 6.16
~> incus list
+------+-------+------+------+------+-----------+
| NAME | STATE | IPV4 | IPV6 | TYPE | SNAPSHOTS |
+------+-------+------+------+------+-----------+

Network Isolation Between Hosts/Projects/Bridges

Discussion: https://discuss.linuxcontainers.org/t/network-isolation-by-project-on-single-server-incus-host/19843

I have a single incus host server (not clustered). I want to be able to isolate instances (from a networking perspective) to only communicate with containers in the same project and still be able to communicate with the outside world. My assumption is that you can create a bridged network per project; however, I do not know the best way to prevent communication between network bridges.

I also believe that incus firewall management can interfere with any iptable rules that I create (and visa versa).

Block traffic:

sudo iptables -A FORWARD -i incusbr+ -o incusbr+ -j REJECT

Allow for exceptions if needed:

sudo iptables -A FORWARD -i incusbr4 -o incusbr8 -j ACCEPT

I know that you can create complete isolation using the following; however, I believe this leaves me using a tailscale type solution to support networking. Is this correct?

security.ipv4_filtering=true (prevents IPv4 spoofing)
security.ipv6_filtering=true (prevents IPv6 spoofing)
security.mac_filtering=true (prevents MAC spoofing)
security.port_isolation=true (prevents container to container traffic)

Here was Stephane's response to the above prompt. It includes an example of how to create and manipulate an ACL rule.

Quick experiment for isolating network bridging and incus backup - worth recording for future reference. This was execute in phoenixnap.com => bare metal server:

    9  sudo adduser ubuntu incus-admin
   10  exit
   17  incus admin init
   18  incus list
   19  incus network list
   20  incus network show incusbr0
   21  incus network create incusbr1
   22  incus network show incusbr1
   23  ip a
   25  df -h
   27  lsblk
   28  incus launch images:debian/12/cloud delme-01-br0
   30  incus list
   31  incus launch images:debian/12/cloud delme-02-br0
   32  incus list
   33  incus launch images:debian/12/cloud delme-02-br0 -n incusbr1
   34  incus launch images:debian/12/cloud delme-03-br1 -n incusbr1
   36  incus list
   37  incus network list
   38  incus instance show delme-01-br0
   39  incus show delme-01-br0
   42  incus exec delme-01-br0 -- bash
   46  incus network show incusbr0
   47  incus network show incusbr1
   48  sudo iptables -A FORWARD -i incusbr+ -o incusbr+ -j REJECT
   53  sudo shutdown -r now # reset iptables since not persisted
   56  incus network acl list
   57  incus network acl show
   59  incus network
   60  incus network show
   61  incus network list
   62  incus network acl create delme-acl-01
   63  incus network acl list
   64  incus network acl show
   65  incus network acl show delme-acl-01
   66  incus network list
   67  incus network show incusbr1
   69  incus network show incusbr1
   70  sudo iptables -A FORWARD -i incusbr+ -o incusbr+ -j REJECT
   74  sudo shutdown -r now
   81  cd
   82  mkdir delme
   83  cd delme
   84  incus admin sql local .dump > some_dump
   85  cat some_dump
   86  cat some_dump | grep inc
   87  incus admin sql global .dump > some_dump
   88  cat some_dump
   90  cat /etc/subgid

Multipass

This section was created before the above Incus announcement. I do not have an opinion on Multipass now that that I use Incus. I will update this section accordingly.

Multipass is a Canonical/Ubuntu product designed to allow Windows, Mac and Linux users to run Ubuntu servers. Eventually, Multipass will sit on top of LXD in the case of Linux. This is exciting because we may be able to share containers from Linux developers in LXD to Windows users of Multipass.

My experience with Multipass on both Mac and Windows is positive. It is much better the WSL in my experience. Be aware that Multipass is a terminal based tool where you issue commands like:

Even though Multipass is administered via a command line, the commands are easy to understand and well documented by most people.

Windows users can make use of VcXsrv to run applications in a Linux container and have the application appear near-natively in Windows. Ideally, a developer using Linux can create an development environment image that is consumed by a windows => multipass user. The windows user just fires up the container from the dev image, fires up the dev environment (eclipse for example) inside the container and uses it as if it was local to the machine.

References: