How To Install LXD on Debian 11 Linux

You can install LXD pure-container hypervisor on Debian 11 Linux to run an unmodified version of Debian, Ubuntu, CentOS, Fedora, Alpine, Arch and many other Linux distro. You can mimic AWS or different cloud instance types with LXD for testing and deployment purposes on your development machine. You can also run a GUI app such as Firefox completely isolated using LXD for security or privacy reasons. Let us see how to set up and use LXD on the Debian Linux 11 server or desktop.

Installing and setting up LXD on Debian Linux 11 server or desktop

The procedure is as follows to install LXD with ZFS and configure both container and GUI VM Linux desktop.

Step 1 – Install LXD on Debian 11 Linux server

First, install nixcbz[failed to get contents] - contact @ [email protected] with the url using the apt command/apt-get command. For instance:
$ sudo apt update
$ sudo apt upgrade

Is a new Linux kernel installed? If so, you must nixcbz[failed to get contents] - contact @ [email protected] with the url box using the shutdown command or reboot command to get a new Linux kernel. For example:
$ sudo reboot
Currently, LXD is not part of any repos in the APT package format. However, Bookworm is the development codename for Debian 12, and it will ship with LXD in APT package form. Hence, you must first install snapd, and then you can install LXD.

Installing snap on Debian 11

Type:
$ sudo apt install snapd

Installing snap on Debian 11 using the APT

Click to enlarge

No snaps are installed by default. Next, install the core snap to get the latest snapd on the Debian 11 machine:
$ sudo snap install core
Outputs:

2023-03-30T07:37:17Z INFO Waiting for automatic snapd restart...
Warning: /snap/bin was not found in your $PATH. If you've not restarted your session since you
         installed snapd, try doing that. Please see https://forum.snapcraft.io/t/9469 for more
         details.

core 16-2.58.3 from Canonical installed

Ensure you log out and logging back again to avoid /snap/bin was not found in your $PATH message. Of course, you can add path using the export command as follows:
$ export PATH=$PATH:/snap/bin
The above path is automatically configured from the /etc//profile.d/apps-bin-path.sh file, so you don’t have to type the export command.

Installing LXD snap on Debian 11

Finally, run the snap command:
$ sudo snap install lxd
Outputs:

lxd 5.12-c63881f from Canonical installed

Installing ZFS support

Type the following commands to enable ZFS support on your Debian 11 to enable ZFS support and snapshots for LXD containers:
$ codename=$(lsb_release -cs);echo "deb http://deb.debian.org/debian $codename-backports main contrib non-free"|sudo tee -a /etc/apt/sources.list
$ sudo apt update
$ sudo apt install linux-headers-amd64
$ sudo apt install -t bullseye-backports zfsutils-linux

Step 2 – Add user to the LXD group for management purpose

No need to be the root user to manage LXD service on Debian. To manage LXD server add your username to lxd group using the adduser command:
$ sudo adduser {USER-Name-Here} lxd
# add regular user named 'vivek' to group lxd #
$ sudo adduser vivek lxd

Verify using the id command or grep command to query /etc/group:
$ id vivek
$ grep '^lxd' /etc/group

Finally, nixcbz[failed to get contents] - contact @ [email protected] with the url using the newgrp command as follows:
$ newgrp lxd
$ id vivek

Let us test it with the lxc command:
$ lxc list
Debian 11 LXD verification with lxc list command

Step 3 – Configuring LXD networking and storage options on Debian 11 server

Now that we installed LXD, it is time to set up the LXD server. You must configure networking and storage option such as directory, ZFS, Btrfs, and more, enter:
$ sudo -i
# lxd init
# exit
$ lxc list

Next, you must answer a series of questions on how to configure the LXD server, including storage and networking option. Here is a sample session. Feel free to choose options as per your needs:

Installing and configuring LXD on Debian 11 Linux server

Click to enlarge

We can verify information about LXD config by typing the following commands:
$ lxc profile list
$ lxc profile show default
$ lxc network list
$ lxc network show lxdbr0
$ lxc storage list
$ lxc storage show default

Verify and SEE LXD profile, storage, networking config options

Click to enlarge

Step 4 – Listing built-in LXD image for various Linux distros

To nixcbz[failed to get contents] - contact @ [email protected] with the url:
$ lxc image list images:
$ lxc image list images: | grep -i debian
$ lxc image list images: | grep -i -E 'centos|ubuntu|opensuse'
$ lxc image list images: alpine

Outputs from the last command:

+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
|            ALIAS             | FINGERPRINT  | PUBLIC |             DESCRIPTION              | ARCHITECTURE |      TYPE       |   SIZE   |          UPLOAD DATE          |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14 (3 more)         | 5c3aa1b914ba | yes    | Alpine 3.14 amd64 (20230329_13:01)   | x86_64       | VIRTUAL-MACHINE | 95.59MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14 (3 more)         | 88d69be29ed5 | yes    | Alpine 3.14 amd64 (20230329_13:01)   | x86_64       | CONTAINER       | 3.10MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/arm64 (1 more)   | 36b0a48f2f2f | yes    | Alpine 3.14 arm64 (20230329_13:01)   | aarch64      | CONTAINER       | 2.82MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/arm64 (1 more)   | 8008f7708b58 | yes    | Alpine 3.14 arm64 (20230329_13:01)   | aarch64      | VIRTUAL-MACHINE | 85.11MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/armhf (1 more)   | 3e0e97dd55d3 | yes    | Alpine 3.14 armhf (20230329_13:00)   | armv7l       | CONTAINER       | 2.79MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/cloud (1 more)   | 111f71c7d6ed | yes    | Alpine 3.14 amd64 (20230329_13:02)   | x86_64       | CONTAINER       | 19.32MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/cloud (1 more)   | fb9c403d4958 | yes    | Alpine 3.14 amd64 (20230329_13:02)   | x86_64       | VIRTUAL-MACHINE | 121.94MB | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/3.14/cloud/arm64      | 067900e7f831 | yes    | Alpine 3.14 arm64 (20230329_13:01)   | aarch64      | CONTAINER       | 18.60MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
...
.....
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud (1 more)   | ec84ef6aff47 | yes    | Alpine edge amd64 (20230329_13:00)   | x86_64       | CONTAINER       | 21.61MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud/arm64      | 1f4e1cc01337 | yes    | Alpine edge arm64 (20230329_13:01)   | aarch64      | CONTAINER       | 20.88MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud/arm64      | ad2c7953e24a | yes    | Alpine edge arm64 (20230329_13:01)   | aarch64      | VIRTUAL-MACHINE | 133.60MB | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud/armhf      | 87d6f71b6b1a | yes    | Alpine edge armhf (20230329_13:01)   | armv7l       | CONTAINER       | 20.21MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud/i386       | f1a0a4ed651f | yes    | Alpine edge i386 (20230329_13:01)    | i686         | CONTAINER       | 22.01MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/cloud/ppc64el    | ffaa2b50b2c5 | yes    | Alpine edge ppc64el (20230329_13:00) | ppc64le      | CONTAINER       | 21.58MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/i386 (1 more)    | 196cb7ac6487 | yes    | Alpine edge i386 (20230329_13:01)    | i686         | CONTAINER       | 3.00MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/ppc64el (1 more) | 22b57b081183 | yes    | Alpine edge ppc64el (20230329_13:01) | ppc64le      | CONTAINER       | 2.85MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+
| alpine/edge/s390x (1 more)   | 6c178bd70e54 | yes    | Alpine edge s390x (20230329_13:00)   | s390x        | CONTAINER       | 2.61MB   | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------+--------------+--------+--------------------------------------+--------------+-----------------+----------+-------------------------------+

Step 5 – Creating your first Linux container

Creating your first container is straightforward. The syntax is:
$ lxc launch images:{distro}/{version}/{arch} {container-name-here}

Getting a public cloud instance on your Debian development machine

Do you want to understand how your app on a Debian development workstation would behave on a cloud instance? Fear not. You can quickly spin up an LXD container that matches the desired cloud instance type. The syntax is:
$ lxc launch -t {type} {os/version} {container-name}
$ lxc launch -t {type} images:{os/version/arch} {container-name}

For example, here is how to create EC2-like t2.micro instance (1 CPU and 1024GiB ram) with Debian 11/Ubuntu image, named aws-dev-t2-micro-{ubuntu,debian}:
$ lxc launch -t t2.micro ubuntu:22.04 aws-dev-t2-micro-ubuntu
OR Debian 11 image:
$ lxc launch -t t2.micro images:debian/11/amd64 aws-dev-t2-micro-debian
Verification:
$ lxc list
Outputs:

+-------------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
|          NAME           |  STATE  |         IPV4         |                     IPV6                      |   TYPE    | SNAPSHOTS |
+-------------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| aws-dev-t2-micro-debian | RUNNING | 10.44.150.95 (eth0)  | fd42:4a93:501f:fd8b:216:3eff:fe2e:cd27 (eth0) | CONTAINER | 0         |
+-------------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+
| aws-dev-t2-micro-ubuntu | RUNNING | 10.44.150.250 (eth0) | fd42:4a93:501f:fd8b:216:3eff:fe67:b5e6 (eth0) | CONTAINER | 0         |
+-------------------------+---------+----------------------+-----------------------------------------------+-----------+-----------+

Here is what I see about the aws-dev-t2-micro-debian:
$ lxc info aws-dev-t2-micro-debian

Name: aws-dev-t2-micro-debian
Status: RUNNING
Type: container
Architecture: x86_64
PID: 4423
Created: 2023/03/30 09:25 UTC
Last Used: 2023/03/30 09:26 UTC
 
Resources:
  Processes: 8
  Disk usage:
    root: 2.24MiB
  CPU usage:
    CPU usage (in seconds): 0
  Memory usage:
    Memory (current): 30.80MiB
  Network usage:
    eth0:
      Type: broadcast
      State: UP
      Host interface: veth70d00609
      MAC address: 00:16:3e:2e:cd:27
      MTU: 1500
      Bytes received: 3.65kB
      Bytes sent: 4.13kB
      Packets received: 31
      Packets sent: 39
      IP addresses:
        inet:  10.44.150.95/24 (global)
        inet6: fd42:4a93:501f:fd8b:216:3eff:fe2e:cd27/64 (global)
        inet6: fe80::216:3eff:fe2e:cd27/64 (link)
    lo:
      Type: loopback
      State: UP
      MTU: 65536
      Bytes received: 0B
      Bytes sent: 0B
      Packets received: 0
      Packets sent: 0
      IP addresses:
        inet:  127.0.0.1/8 (local)
        inet6: ::1/128 (local)

Finally, log into it and run top/htop:
$ lxc exec aws-dev-t2-micro-debian -- top

Running top command on EC2 like instance on Debian 11 dev machine

Running top command on EC2 like instance on Debian 11 dev machine (click to enlarge)

Testing your container resources locally on a Debian 11-based dev machine helps with accurate capacity planning and avoiding over-provisioning with AWS EC2/Lightsail and cloud instance. Thus, you will save some money.

Alpine Linux 3.17 container

Your container here is called ‘alpine’ using version 3.17:
$ lxc launch images:alpine/3.17/amd64 d-c1-alpine
Next, try to list and log into the newly created ‘d-c1-alpine’ container:
$ lxc list
$ lxc exec d-c1-alpine sh
# cat /etc/os-release
# ping -c2 www.cyberciti.biz
# exit from the container and delete it #
# exit
$ lxc stop d-c1-alpine
$ lxc delete d-c1-alpine
$ lxc list

Creating your First Alpine Linux CONTAINER on Debian Linux 11 LXD server

Creating your First Alpine Linux CONTAINER on Debian Linux 11 LXD server (click to enlarge)

CentOS Linux 9 Stream container

$ lxc launch images:centos/9-Stream/amd64 d-c1-cenots

Ubuntu Linux 18.04 or 20.04 or 22.04 LTS container

$ lxc launch images:ubuntu/bionic/amd64 d-c1-ubuntu-bionic
$ lxc launch images:ubuntu/focal/amd64 d-c1-ubuntu-focal
$ lxc launch images:ubuntu/jammy/amd64 d-c1-ubuntu-jammy

Debian Linux 10.x / 11.x container

$ lxc launch images:debian/10/amd64 d-c1-debian-10
$ lxc launch images:debian/11/amd64 d-c1-debian-11

Arch Linux container

$ lxc launch images:archlinux/amd64 d-c1-arch

Gentoo Linux container

You can choose between openrc or systemd as init for Gentoo:
$ lxc launch images:gentoo/openrc/amd64 d-c1-gentoo-rc
OR
$ lxc launch images:gentoo/systemd/amd64 d-c1-gentoo-systemd

Fedora Linux 37 container

$ lxc launch images:fedora/37/amd64 d-c1-fedora-37

OpenSUSE Linux 15.x container

$ lxc launch images:opensuse/15.4/amd64 d-c1-opensuse15-4

Oracle Linux 9.x container

$ lxc launch images:oracle/9/amd64 d-c1-oracle-9

Step 6 – Managing LXD based containers using the lxc CLI

Let us dive into essential commands to manage containers

List Linux container instances

We can list the existing containers using the following syntax and grep command/egrep command as pipe:
$ lxc list --fast
$ lxc list | grep RUNNING
$ lxc list | grep STOPPED
$ lxc list | grep -i opensuse
$ lxc list "*gentoo*"
$ lxc list "*fedora*"
$ lxc list

Look ma, we have a tiny IT/dev lab running on Debian 11 as per our app need:

+-------------------------+---------+--------------+----------------------+----------+-----------+
|          NAME           |  STATE  | ARCHITECTURE |      CREATED AT      | PROFILES |   TYPE    |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| aws-dev-t2-micro-debian | RUNNING | x86_64       | 2023/03/30 09:25 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| aws-dev-t2-micro-ubuntu | RUNNING | x86_64       | 2023/03/30 09:24 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-arch               | RUNNING | x86_64       | 2023/03/30 09:41 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-cenots             | RUNNING | x86_64       | 2023/03/30 09:38 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-debian-10          | RUNNING | x86_64       | 2023/03/30 09:40 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-debian-11          | RUNNING | x86_64       | 2023/03/30 09:41 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-fedora-37          | RUNNING | x86_64       | 2023/03/30 09:43 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-gentoo-rc          | RUNNING | x86_64       | 2023/03/30 09:41 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-gentoo-systemd     | RUNNING | x86_64       | 2023/03/30 09:42 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-opensuse15-4       | RUNNING | x86_64       | 2023/03/30 09:44 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-oracle-9           | RUNNING | x86_64       | 2023/03/30 09:44 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-ubuntu-bionic      | RUNNING | x86_64       | 2023/03/30 09:39 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-ubuntu-focal       | RUNNING | x86_64       | 2023/03/30 09:40 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+
| d-c1-ubuntu-jammy       | RUNNING | x86_64       | 2023/03/30 09:40 UTC | default  | CONTAINER |
+-------------------------+---------+--------------+----------------------+----------+-----------+

How to execute/run the specified command in a container

We run or execute commands in containers using the exec command as follows:
$ lxc exec containerName -- command
$ lxc exec containerName -- /path/to/script
$ lxc exec containerName --env EDITOR=/usr/bin/vim -- command
### run date, ip a, ip rm and other commands on various containers ###
$ lxc exec d-c1-cenots -- date
$ lxc exec d-c1-cenots -- ip a
$ lxc exec d-c1-ubuntu-jammy -- ip r
$ lxc exec d-c1-fedora-37 -- dnf -y update
$ lxc exec d-c1-debian-11 -- cat /etc/debian_version

Running commands for LXD based containers

Click to enlarge

How to get the bash shell access in a container

Want to gain login/shell access in a container named debian-10-www, enter:
$ lxc exec {container-name} {shell-name}
$ lxc exec d-c1-debian-11 bash
$ lxc exec d-c1-ubuntu-jammy sh

Now you can run commands or install packages. For instance, use the apt command/apt-get command inside container:
# cat /etc/*issue*
# apt update
# apt upgrade

Simply type exit to get back to host:
# exit

Start my containers command

$ lxc start {container-name}
$ lxc start d-c1-oracle-9

Stop my containers command

$ lxc stop {container-name}
$ lxc stop aws-dev-t2-micro-ubuntu

Restart my containers

$ lxc restart {container-name}
$ lxc restart d-c1-gentoo-rc

Delete LXD containers

The command is as follows. Be careful as the LXD containers are deleted immediately without any confirmation prompt. In other words, always keep backups:
$ lxc delete {container-name}
$ lxc delete d-c1-gentoo-rc

You may get the following error while deleting the container:

The container is currently running, stop it first or pass –force.

To fix this:
$ lxc stop d-c1-gentoo-rc && lxc delete d-c1-gentoo-rc

How do I show information on LXD servers and containers?

Type the following command:
$ lxc info
$ lxc info {container-name}
$ lxc info d-c1-opensuse15-4

Pull a file from the container

$ lxc file pull {continer-nane}/{path/to/file} {/path/to/local/dest}
$ lxc file pulld-c1-opensuse15-4/var/www/nginx/app/config.py .

Push a file to the container

$ lxc file push {/path/to/file} {continer-nane}/path/to/dest/dir/
$ lxc file push config.py d-c1-opensuse15-4/var/www/nginx/app/

Step 7 – Forwarding incoming connections to the Linux container

First install the nginx server inside d-c1-ubuntu-jammy:
$ lxc exec d-c1-ubuntu-jammy bash
# apt update && apt upgrade && apt install nginx
# systemctl enable nginx
# systemctl status nginx
### update/create the default html file
# cat /var/www/html/index.nginx-debian.html

Sample file:

<!DOCTYPE html>
<html>
<head>
 <title>Welcome to nginx running on LXD VM!</title>
</head>
<body>
 <h1><h1>Welcome to nginx running on LXD VM!</h1>
</body>
</html>

Finally logout from the LXD vm:
# logout
Find ubuntu-nginx IP address:
$ lxc list d-c1-ubuntu-jammy
Sample outputs:

+-------------------+---------+--------------------+-----------------------------------------------+-----------+-----------+
|       NAME        |  STATE  |        IPV4        |                     IPV6                      |   TYPE    | SNAPSHOTS |
+-------------------+---------+--------------------+-----------------------------------------------+-----------+-----------+
| d-c1-ubuntu-jammy | RUNNING | 10.44.150.2 (eth0) | fd42:4a93:501f:fd8b:216:3eff:fe4a:8ef2 (eth0) | CONTAINER | 0         |
+-------------------+---------+--------------------+-----------------------------------------------+-----------+-----------+

You need to redirect/forward all incoming traffic on port 80 to Fedora Linux 28 public IP address say 104.20.187.5 to LXD private IP address 10.44.150.2 using the iptable command or ufw command or use the lxd proxy protocol. The syntax for lxd proxy protocol is:

lxc config device add {container-name} {device_name_here} proxy listen=tcp:${src_IP}:${src_port} connect=tcp:${dest_ip}:${dest_port}

In this example redirect http/80 (Nginx) traffic to container named d-c1-ubuntu-jammy:

lxc config device add d-c1-ubuntu-jammy http-reditect proxy listen=tcp:1.2.3.4:80 connect=tcp:10.44.150.2:80
## OR if your NIC listing to public IPv{4,6} ##
lxc config device add d-c1-ubuntu-jammy http-reditect proxy listen=tcp:104.20.187.5:80 connect=tcp:10.44.150.2:80

Where,

  • d-c1-ubuntu-jammy – LXD container or instance vm name.
  • http-reditect – Unique name per LXD container or instance name.
  • listen=tcp:1.2.3.4:80 – Public or private IPv4/IPv6 and port to listen on (host’s IP:PORT)
  • connect=tcp:10.44.150.2:80 – Forward traffic to this LXD instance’s IP:PORT

Test it. Fire the web browser and type the url:
http://104.20.187.5
FirewallD forwarding Incoming Connections to the Nginx Container VM

Step 8 – Running Linux Desktop VM (not container) using LXD

If you run LXD on a dedicated Debian Linux 11 server or desktop/laptop, running a Linux desktop VM (Virtual Machine) for isolated workloads is possible. For example, one can run work-related Firefox/Chrome browser on Ubuntu v22.10 desktop and OpenSUSE v15.4 KDE desktop for personal stuff isolated from your primary Debian 11 host for security and privacy reasons. Here is how to list desktop VM images:
$ lxc image list images: desktop
$ lxc image list images: desktop | grep opensuse

Desktop VM images supported by LXD:

+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
|                  ALIAS                   | FINGERPRINT  | PUBLIC |                DESCRIPTION                 | ARCHITECTURE |      TYPE       |   SIZE    |          UPLOAD DATE          |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| archlinux/desktop-gnome (3 more)         | 6c697c1b3422 | yes    | Archlinux current amd64 (20230330_04:18)   | x86_64       | VIRTUAL-MACHINE | 1395.10MB | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| opensuse/15.4/desktop-kde (1 more)       | 5c8260047a50 | yes    | Opensuse 15.4 amd64 (20230330_04:20)       | x86_64       | VIRTUAL-MACHINE | 790.97MB  | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| opensuse/15.4/desktop-kde (1 more)       | 7a678911b501 | yes    | Opensuse 15.4 amd64 (20230330_04:20)       | x86_64       | CONTAINER       | 46.46MB   | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| opensuse/tumbleweed/desktop-kde (1 more) | 4c88abcb7fb2 | yes    | Opensuse tumbleweed amd64 (20230330_04:20) | x86_64       | VIRTUAL-MACHINE | 791.62MB  | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| opensuse/tumbleweed/desktop-kde (1 more) | bf76d64db45a | yes    | Opensuse tumbleweed amd64 (20230330_04:20) | x86_64       | CONTAINER       | 43.68MB   | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/22.10/desktop (3 more)            | 427b1e357464 | yes    | Ubuntu kinetic amd64 (20230329_07:42)      | x86_64       | VIRTUAL-MACHINE | 1033.45MB | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/focal/desktop (3 more)            | 20c1cb384f12 | yes    | Ubuntu focal amd64 (20230329_07:42)        | x86_64       | VIRTUAL-MACHINE | 982.71MB  | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/jammy/desktop (3 more)            | ed98f1eaeb8c | yes    | Ubuntu jammy amd64 (20230330_07:42)        | x86_64       | VIRTUAL-MACHINE | 952.65MB  | Mar 30, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+
| ubuntu/lunar/desktop (3 more)            | 48049f3a99e9 | yes    | Ubuntu lunar amd64 (20230329_10:43)        | x86_64       | VIRTUAL-MACHINE | 1127.12MB | Mar 29, 2023 at 12:00am (UTC) |
+------------------------------------------+--------------+--------+--------------------------------------------+--------------+-----------------+-----------+-------------------------------+

Make sure remote-viewer installed to see desktop console on Debian 11 desktop:
$ sudo apt install virt-viewer
Here is how launce Arch Linux GNOME desktop using LXD with 4 vCPU and 4GiB RAM:
$ lxc launch images:archlinux/desktop-gnome archlinuxdesktop \
--vm \
-c security.secureboot=false \
-c limits.cpu=4 \
-c limits.memory=4GiB \
--console=vga

Another example abour running OpenSUSE KDE desktop:
$ lxc launch images:opensuse/15.4/desktop-kde opensusekde
--vm \
-c limits.cpu=4 \
-c limits.memory=4GiB \
--console=vga

Please note that these VM images are bigger. Hence, it will take some time to download and install it. However, once installed, you should see a remote viewer window with your desktop VM, as shown below:

OpenSUSE-LXD-VM

OpenSUSE Linux KDE VM created using LXD for desktop usage (click to enlarge)

How cool is that? There are no passwords or anything. You need to lock down these VM desktops and configure them further with passwords, firewall, and install apps such as Firefox with an Adblocker, like an actual Linux desktop. Then, you can start/stop VM again as follows:
$ lxc stop opensusekde
$ lxc start opensusekde --console=vga
$ lxc restart opensusekde --console=vga
$ lxc info opensusekde

Step 9 – Getting help about lxc commands

Getting help is easy. Try the passing the --help option as follows:
$ lxc --help
$ lxc {command} --help
$ lxc list --help

Conclusion

In this in-depth tutorial, you learned how to install and set up LXD on Debian 11 server or workstation to run various Linux distros including desktop VMs. For further information see lxc commands and docs here.

About the author: Vivek Gite is Editor-in-Chief and the man behind nixCraft and OpensourceFlare ✨. He creates and maintains content on both sites as accurately as possible. Since 2000 Vivek has written over 7k+ posts that have been read many times. He is a die-hard fan of FLOSS and a full-time Linux desktop user since 1996. OpensourceFlare provides in-depth guides about Linux, BSD, programming, and other IT topics for Patreon subscribers without any ads or tracking. Get the latest tutorials on Linux, Open Source & DevOps via RSS feed or weekly email newsletter.

0 comments… add one

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre> for code samples. All comments must be on the topic, and offtopic comments will be automatically removed.