Testing DebianEdu with LXD

1. Introduction

DebianEdu aka Skolelinux is a Linux distribution based on Debian providing an out-of-the box environment of a completely configured school network.

Debian Edu Network
Figure 1. Typical topology of a DebianEdu network

After installation of a main server all services needed for a school network are set up and the system is ready to be used. Only users and machines need to be added via GOsa², a comfortable Web-UI, or any other LDAP editor.

A netbooting environment using PXE/iPXE has also been prepared, so after initial installation of the main server (from CD, Blu-ray disc or USB flash drive) all other machines can be installed via the network. This includes "roaming workstations" (ones that can be taken away from the school network, usually laptops or netbooks).

Also, machines can be booted via PXE/iPXE as diskless workstations or thin clients.

Several educational applications like GeoGebra, Kalzium, KGeography, GNU Solfege and Scratch are included in the default desktop setup, which can be extended easily and almost endlessly via the Debian universe.

2. Setup

2.1. Install LXD

On the server (ubuntu:22.04) I have installed LXD with snap, like this:

apt install snapd
snap --version
snap install lxd --channel=latest/stable
snap list
lxc list
lxd init
I have used a btrfs storage backend and more than 30GB storage size. I have also disabled IPv6 for the containers. Other than that, everything else was the default setting.
Installation on Debian

If using Debian (tested with Debian 10 "buster"), the snap package core needs to be installed before lxd:

snap install core --channel=latest/stable
snap install lxd --channel=latest/stable

2.2. Access LXD from non-root user

  1. Create a user first:

    adduser user1
  2. Enable remote connection on the server:

    lxc config set core.https_address "[::]"
    lxc config set core.trust_password pass1234
  3. As user1, add a remote, like this:

    su - user1
    lxc remote add localhost 127.0.0.1

    This will prompt you to confirm the fingerprint and then ask you for the password (pass1234).

  4. Make it the default remote and test it:

    lxc remote list
    lxc remote switch localhost
    lxc remote list
    lxc ls
  5. Unset core.trust_password, for security reasons:

    exit    # from user1 account
    
    lxc config get core.trust_password
    lxc config set core.trust_password ""
    lxc config get core.trust_password

2.3. Disable firewalld

Somehow firewalld interferes with the network communication in the virtual environment that we are creating. It should be possible to setup its configuration so that everything works correctly, but I have not been able yet to do it properly. So, we need to disable it.

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

Also, make sure that the default policy for the FORWARD chain of iptables is ACCEPT, otherwise the containers will not be able to access the internet.

iptables -L
iptables -P FORWARD ACCEPT

2.4. Setup Xpra

We need Xpra to access the graphical displays (VGA consoles) of the virtual machines remotely (for example from a laptop).

  1. Let’s install it first (on the server):

    apt install xpra virt-viewer \
        tilix dbus-x11
  2. On the user account, let’s create a script for starting it:

    su - user1
    
    cat << EOF >> xpra-start.sh
    #!/bin/bash -x
    killall xpra
    xpra start :100 \
        --start-new-commands=yes
        #--sharing=yes --readonly=no \
    EOF
    
    chmod +x xpra-start.sh
  3. To access xpra remotely, we need ssh access to this account. Let’s create an ssh key:

    ssh-keygen -t ecdsa -q -N '' -f xprakey
    s
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
    touch ~/.ssh/authorized_keys
    chmod 600 ~/.ssh/authorized_keys
    cat xprakey.pub >> ~/.ssh/authorized_keys
  4. Let’s set also the env variable XDG_RUNTIME_DIR:

    echo 'export XDG_RUNTIME_DIR=$HOME/.xpra' >> ~/.bashrc
    echo 'export XDG_RUNTIME_DIR=$HOME/.xpra' >> ~/.profile
    
    exit
  5. On the client (laptop), create the script xpra-attach.sh with a content like this:

    #!/bin/bash -x
    
    user=user1
    server=10.11.12.13
    port=2201
    display=100
    
    keyfile=$(mktemp)
    sed -n -e '/^----/,/^-----/p' $0 > $keyfile
    
    xpra attach ssh:$user@$server:$display \
        --ssh="ssh -i $keyfile -p $port" \
        --sharing=yes --readonly=no
    
    rm -f $keyfile
    exit 0
    
    -----BEGIN OPENSSH PRIVATE KEY-----
    b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAaAAAABNlY2RzYS
    1zaGEyLW5pc3RwMjU2AAAACG5pc3RwMjU2AAAAQQTSUZv73bV7X7SbDdbYznjw5MvNtNoo
    Ysvle3E3V78K7z+cl8l1SH7PAbKj6tsdCuy5jrAg50RMBzeJvWogJM2FAAAAqH+0ui1/tL
    otAAAAE2ViZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBNJRm/vdtXtftJsN
    1tjOePDky8202ihiy+V7cTdXvwrvP5yXyXVHfs8BsqPq2x0K7LeOsCDnREwHN4m9aiAkzY
    UAAAAgJrRz4MHjtrsIkyaf/MG7qr2L+5Bnhvc1XaaxFT/zo38AAAANdXNlcjFAc2VydmVy
    MQECAw==
    -----END OPENSSH PRIVATE KEY-----

    Here server is the public IP (or hostname) of the server where Xpra is installed; port is the SSH port on the server; user is the account where we created the script xpra-start.sh; display is the same display number that is used on xpra-start.sh; and the private key is the content of the file xprakey that was generated on the server.

To start Xpra we run the script xpra-start.sh on the server:

su - user1
./xpra-start.sh

To connect to it we run the script xpra-attach.sh from the client (laptop). We should get a tilix terminal by default, but if not, we can start it from the Xpra icon (click it and keep it pressed, then go to "Server", then to "Run a command" and release the mouse button, type "tilix" and press Enter). From this terminal we can type LXC commands, and when we try to access the display of a virtual machine it will be shown on the laptop.

See also the related section on appendix.

3. Install the main server

3.1. Create an external switch

All the containers and VMs are connected by default to a bridge (usually named lxdbr0), which provides them with DHCP and allows them to connect to the internet (acting like a gateway). However we need a gateway that does not provide DHCP, since the DHCP is going to be provided by the main server. This requirement is discussed in the docs.

gateway

In LXC, a switch can be implemented by a virtual network. However we should make sure that this virtual network does not provide DHCP and has IP 10.0.0.1/8. We can do it like this:

lxc network list
lxc network create switch0 \
    ipv4.address=10.0.0.1/8 \
    ipv4.dhcp=false \
    ipv4.nat=true
lxc network list
lxc network show switch0

3.2. Create an internal switch

mainserver
Figure 2. Network topology of the main server

According to the topology of the network, the main server is connected to an internal switch as well, which is used for the LTSP clients. So, let’s create another switch:

lxc network list
lxc network create switch1 \
    ipv4.address=none ipv4.nat=false
lxc network show switch1
lxc network unset switch1 ipv4.address
lxc network unset switch1 ipv4.nat
lxc network show switch1

This network (switch1) should not provide DHCP, because it should be provided by the main server itself, so we have disabled it.

3.3. Install from iso

3.3.1. Define a VM

lxc init main-server --empty --vm \
    --network=switch0 \
    -c limits.memory=4GB -c limits.cpu=2
lxc network attach \
    switch1 main-server
lxc config device override \
    main-server root size=60GB

With the option --network=switch0 we replace the default network connection (which is lxdbr0) by switch0. So, the first network interface of main-server will be connected to the switch switch0. We also attach main-server to switch1, so it is going to have a second network interface connected to this switch.

With the last command we also make the size of the disk bigger than the default one.

Notice (on the first command) that instead of providing an image for the VM, we have used the option --empty, which means that nothing will be installed by default on the disk. We need to download the installation iso of DebianEdu and access it from the VM like a CDROM:

wget https://get.debian.org/cdimage/release/current/amd64/iso-bd/debian-edu-11.4.0-amd64-BD-1.iso

lxc config device add \
    main-server cdrom disk \
    source=/root/debian-edu-11.4.0-amd64-BD-1.iso \
    boot.priority=1
lxc config set \
    main-server security.secureboot=false

The options boot.priority=1 and security.secureboot=false are needed to make sure that we actually boot the system from this iso.

lxc config device show main-server
lxc config show main-server | less

3.3.2. Install the server

Let’s start the main-server VM:

lxc start main-server --console=vga

Through Xpra, the console of the virtual machine will be displayed on our laptop. The VM will boot from the iso that we downloaded, and we can follow the installation steps.

After finishing the installation, we should remove the cdrom device from the VM and start it again:

lxc stop -f main-server
lxc config device rm main-server cdrom
lxc config device show main-server

lxc start main-server
lxc console main-server --type=vga

3.3.3. Install the lxd-agent

The VM that we just installed from an iso cannot be managed easily with lxc commands — some functionality is not available. For example we cannot do lxc exec main-server — bash to get a shell inside the VM.

To fix this, we need to install lxd-agent inside the VM. The steps are described in this post, but I have written this snippet to facilitate the installation.

From the VGA console, get a root terminal and do:

wget https://gitlab.com/-/snippets/2390048/raw/main/install-lxd-agent-in-debian.sh
chmod +x install-lxd-agent-in-debian.sh
./install-lxd-agent-in-debian.sh
rm install-lxd-agent-in-debian.sh

Using a short url makes it a bit more convenient:

wget https://t.ly/QCLN -O install-lxd-agent.sh
less install-lxd-agent.sh
chmod +x install-lxd-agent.sh
./install-lxd-agent.sh
rm install-lxd-agent.sh
For security reasons, don’t skip checking the content of the downloaded script, before running it.

3.4. Upgrade packages

In order to upgrade packages, first of all we need to modify /etc/apt/sources.list. Because we installed from a CD, it contains a source like this:

deb cdrom:[Debian GNU/Linux 11.4.0 _Bullseye_ - Official amd64 BD Binary-1 20220709-10:33]/ bullseye main

We should comment it out and make sure that it contains source lines like these:

deb http://deb.debian.org/debian bullseye main contrib non-free
deb http://deb.debian.org/debian bullseye-updates main contrib non-free
deb http://deb.debian.org/debian-security/ bullseye-security main contrib non-free
deb http://deb.debian.org/debian/ bullseye-backports main contrib non-free
lxc exec main-server -- bash
vim /etc/apt/sources.list

Then, according to these instructions, we can do:

apt update
LC_ALL=C apt full-upgrade -y
apt autoremove
Disable proxy for apt

Since the VM that we are using for testing has a small disk, there is not enough space in it for caching the packages. So, we should better disable it. Edit /etc/apt/apt.conf.d/03debian-edu-config and comment out all the lines:

# Acquire::http::Proxy "http://webcache:3128";
# Acquire::ftp::Proxy "http://webcache:3128";
# Acquire::https::Proxy "http://webcache:3128";

Let’s also disable apt proxy for the installation of workstations. Edit the file /etc/debian-edu/www/debian-edu-install.dat and comment out these lines:

#d-i     mirror/http/proxy       string  http://webcache:3128
#d-i     mirror/ftp/proxy        string  http://webcache:3128

We can also do these things (optionally):

ls -ltr /etc/cfengine3/debian-edu/
LC_ALL=C cf-agent -D installation

debian-edu-ltsp-install --diskless_workstation yes
The ltsp command takes a lot of time to generate the LTSP images.

4. Test LTSP clients

4.1. On the LTSP network

Let’s create a diskless VM, connected to switch1, that boots from the network interface:

lxc init ltsp01 --empty --vm \
    --network=switch1 \
    -c limits.memory=2GB -c limits.cpu=1 \
    -c security.secureboot=false
lxc config device set \
    ltsp01 eth0 boot.priority=1
lxc config show ltsp01 | less
lxc config device show ltsp01

The last command should give an output like this:

eth0:
  boot.priority: "1"
  name: eth0
  network: switch1
  type: nic
A diskless client with 1GB RAM does not work properly, so it is recommended to have at least 2GB RAM.

Now let’s start it.

lxc start ltsp01 --console=vga

It should start booting from the main server, through PXE, until we get the boot menu. Leave the default selection (diskless workstation) and press enter.

Stop it with: lxc stop -f ltsp01

4.2. On the main network

According to the network architecture diagram, we should be able to start a diskless client even if it is connected to switch0. Let’s test it:

lxc init ltsp02 --empty --vm \
    --network=switch0 \
    -c limits.memory=2GB -c limits.cpu=1 \
    -c security.secureboot=false
lxc config device set \
    ltsp02 eth0 boot.priority=1
lxc config show ltsp02

lxc start ltsp02 --console=vga

lxc stop -f ltsp02

4.3. Test a thin client

On a diskless workstation, programs and applications run on the RAM of the client. For example when we start Firefox, it is loaded on the RAM of the client. Only the home directory is on the server (mounted with NFS).

On a thin client, on the other hand, everything runs on the server, only the display is shown to the client. For this reason we don’t need much RAM for a VM that simulates a thin client.

lxc init ltsp03 --empty --vm \
    --network=switch1 \
    -c limits.memory=512MB \
    -c security.secureboot=false
lxc config device set \
    ltsp03 eth0 boot.priority=1
lxc config show ltsp03

lxc start ltsp03 --console=vga

lxc stop -f ltsp03

It would still work with -c limits.memory=256MB. By the way, the default value for this option is 1GB.

5. Test workstations

5.1. Install a workstation

Let’s create an empty VM, with 25GB disk, connected to the main switch (switch0), which boots from the network:

lxc init ws01 --empty --vm \
    --network=switch0 \
    -c limits.memory=2GB \
    -c security.secureboot=false
lxc config device override \
    ws01 root size=25GB
lxc config device set \
    ws01 eth0 boot.priority=1

lxc config show ws01
lxc start ws01 --console=vga

On the iPXE boot menu select the first option (Install Debian Edu/amd64b). Then follow the installation steps and select the Workstation profile (which is selected by default).

After installation is done, shut it down, remove the boot priority from the network interface, and start it again:

lxc stop -f ws01
lxc config device unset ws01 eth0 boot.priority
lxc config show ws01
lxc start ws01 --console=vga

We can login as user root, get a terminal, and install lxd-agent like this:

wget https://t.ly/QCLN -O install-lxd-agent.sh
less install-lxd-agent.sh
chmod +x install-lxd-agent.sh
./install-lxd-agent.sh
rm install-lxd-agent.sh

Now that we installed lxd-agent, we can access ws01 with the command lxc exec ws01 — bash.

5.2. Connect workstation to the main server

The DHCP of the main server can assign a hostname and a fixed IP to this workstation, but we need to register it first on GOsa. We can open the web interface of GOsa, go to "Systems" and add a workstation manually, but a more convenient way is to use the tool sitesummary2ldapdhcp from the server, like this:

sitesummary2ldapdhcp -a -i ether-00:16:3e:8a:fd:83

Here we are using the MAC address of the workstation, which we can find with a command like this:

# lxc exec ws01 -- ip link show eth0
lxc exec ws01 -- cat /sys/class/net/eth0/address

The command sitesummary2ldapdhcp is going to ask for the root password, and it will add a workstation entry on LDAP. However this entry needs to be modified/customized. So, open it on GOsa and modify it as shown in the figure.

gosa systems edit host 1

Now you can reboot the workstation and it will take the IP and hostname specified in GOsa.

If you notice that the workstation does not get the specified hostname and IP, try the command ldap2bind to update DNS manually. Normally this command is executed from a cron job every hour.

However we can still login only as root, not as any user that is registed in Gosa. To enable this, we need to run this command on the workstation:

/usr/share/debian-edu-config/tools/copy-host-keytab

It is going to ask for the root password of the server, in order to copy the keytab file from the server to the workstation.

Now we can reboot the workstation and test that we are able to login as any user that is registered in GOsa. The home directory of the user is also mounted from the server.

6. Test a roaming workstation

A roaming workstation is similar to a workstation, except that you can use it outside the school network as well. For example a laptop that you can use both at school and at home. A roaming workstation works by caching in the local machine the authentication credentials and the home directory of the user.

  1. Installation is exactly the same as that of a workstation, except that you choose the Roaming Workstation profile, instead of the Workstation profile.

    lxc init ws02 --empty --vm \
        --network=switch0 \
        -c limits.memory=2GB \
        -c security.secureboot=false
    lxc config device override \
        ws02 root size=25GB
    lxc config device set \
        ws02 eth0 boot.priority=1
    
    lxc config show ws02
    lxc start ws02 --console=vga

    On the iPXE boot menu select the first option (Install Debian Edu/amd64b). Then follow the installation steps and select the Roaming Workstation profile.

  2. After installation is done, shut it down, remove the boot priority from the network interface, and start it again:

    lxc stop -f ws02
    lxc config device unset ws02 eth0 boot.priority
    lxc config show ws02
    lxc start ws02 --console=vga
  3. Login as user root, get a terminal, and install lxd-agent:

    wget https://t.ly/QCLN -O install-lxd-agent.sh
    less install-lxd-agent.sh
    chmod +x install-lxd-agent.sh
    ./install-lxd-agent.sh
    rm install-lxd-agent.sh
  4. Add this workstation to LDAP, on the main server:

    # lxc exec ws02 -- ip link show eth0
    lxc exec ws02 -- cat /sys/class/net/eth0/address
    sitesummary2ldapdhcp -a -i ether-00:16:3e:8a:fd:83

    Edit it from the GOsa interface, set a hostname, an IP, etc. Run also ldap2bind to update DNS manually.

  5. Copy the keytab file from the server to the workstation:

    lxc exec ws02 -- bash
    /usr/share/debian-edu-config/tools/copy-host-keytab
    exit
  6. Reboot the workstation and check that you can login as a normal user (not as root):

    lxc stop -f ws02
    lxc start ws02 --console=vga
  7. Change the network of the workstation (use a network that is different from switch0, which is the school network). Then boot it and test that you can login with the same user as before:

    lxc stop -f ws02
    lxc config device show ws02
    lxc config device set ws02 eth0 network lxdbr0
    lxc config device show ws02
    lxc start ws02 --console=vga
With a Roaming Workstation, once you login on a school network, a local user account is created on the workstation, with a local home directory. If you login with the same username from an LTSP client or from a normal Workstation, then you will access the home directory on the server, which has a different content from the one on the Roaming Workstation.

7. Separate LTSP server

An extra LTSP server is installed outside the main server. It is useful for isolating the LTSP traffic from the rest of the network. An LTSP server has two network interfaces, one connected to the main switch, and the other connected to an internal switch, where all the LTSP clients are connected as well.

The installation of an LTSP server is very similar to the installation of a workstation, except that the profile "LTSP Server" is selected instead. After installation, the LTSP server must be connected to the main server the same way as a workstation. Then, some extra steps need to be done for generating the client images, PXE menu, etc.

  1. Let’s create first an internal switch, named switch2, that does not provide DHCP or gateway:

    lxc network list
    lxc network create switch2 \
        ipv4.address=none ipv4.nat=false
    lxc network show switch2
    lxc network unset switch2 ipv4.address
    lxc network unset switch2 ipv4.nat
    lxc network show switch2
  2. Now let’s create a VM and install it from the network. Installation is exactly the same as that of a workstation, except that we choose the LTSP Server profile.

    lxc init ltsp-server-1 --empty --vm \
        --network=switch0 \
        -c limits.memory=4GB \
        -c security.secureboot=false
    lxc network attach \
        switch2 ltsp-server-1
    lxc config device override \
        ltsp-server-1 root size=40GB
    lxc config device set \
        ltsp-server-1 eth0 boot.priority=1
    
    lxc config show ltsp-server-1
    lxc start ltsp-server-1 --console=vga

    On the iPXE boot menu select the first option (Install Debian Edu/amd64b). Then follow the installation steps and select the LTSP Server profile.

  3. After installation is done, shut it down, remove the boot priority from the network interface, and start it again:

    lxc stop -f ltsp-server-1
    lxc config device unset ltsp-server-1 eth0 boot.priority
    lxc config show ltsp-server-1
    lxc start ltsp-server-1 --console=vga
  4. Login as user root, get a terminal, and install lxd-agent:

    wget https://t.ly/QCLN -O install-lxd-agent.sh
    less install-lxd-agent.sh
    chmod +x install-lxd-agent.sh
    ./install-lxd-agent.sh
    rm install-lxd-agent.sh
  5. Add this system to LDAP, on the main server:

    # lxc exec ltsp-server-1 -- ip link show eth0
    lxc exec ltsp-server-1 -- cat /sys/class/net/eth0/address
    
    lxc exec main-server -- bash
    sitesummary2ldapdhcp -a -i ether-00:16:3e:8a:fd:83

    Edit it from the GOsa interface, set a hostname, an IP, etc. Run also ldap2bind to update DNS manually.

  6. Reboot the machine and copy the keytab file from the server, then reboot it again:

    lxc stop -f ltsp-server-1
    lxc start ltsp-server-1
    
    lxc exec ltsp-server-1 -- bash
    /usr/share/debian-edu-config/tools/copy-host-keytab
    exit
    
    lxc stop -f ltsp-server-1
    lxc start ltsp-server-1
  7. Generate a SquashFS image (server filesystem) for the diskless clients, and install PXE:

    lxc exec ltsp-server-1 -- bash
    debian-edu-ltsp-install --diskless_workstation yes
    debian-edu-pxeinstall
    exit
    The command that generates the image takes a long time.

    We need another reboot:

    lxc stop -f ltsp-server-1
    lxc start ltsp-server-1

Now let’s start a diskless client on the internal LAN of ltsp-server-1:

lxc init ltsp04 --empty --vm \
    --network=switch2 \
    -c limits.memory=2GB -c limits.cpu=1 \
    -c security.secureboot=false
lxc config device set \
    ltsp04 eth0 boot.priority=1
lxc config device show ltsp04
lxc start ltsp04 --console=vga

We should be able to boot from the network, then authenticate with GOsa user accounts, and access the home directories that are stored on the main server.

8. Misc

8.1. Modify iPXE boot menu

If we want, for example, to remove the i386 installation option from the boot menu, we can edit /srv/tftp/ltsp/ltsp.ipxe on the main server and comment out this line:

# item --key i i386                 Install Debian Edu/i386  (32-Bit)

If we want to change the desktop that is installed on the workstations, for example to LXQT, we can edit this part:

# Based upon locale, keymap and desktop values used during main-server installation; auto URL added.
:amd64
set params auto url=http://www/debian-edu-install.dat hostname=pxeinstall domain=intern  locale=en_US.UTF-8 keymap=us desktop=lxqt vga=788 --- quiet
kernel /debian-installer/amd64/linux initrd=initrd.gz ${params}
initrd /debian-installer/amd64/initrd.gz
boot || goto failed

Other kernel options can be changed here as well, like the locale, keyboard keymap, etc.

The preseeding file that is used for installing workstations is /etc/debian-edu/www/debian-edu-install.dat.

9. Appendices

9.1. Connect to LXD remotely

We can connect to the LXD from a local machine, for example a laptop, and manage it remotely.

  • Install LXD on the local machine (without initializing it with lxc init):

    apt install snapd
    snap install lxd --channel=latest/stable
    snap list
    lxc list
  • Enable remote connection on the server:

    lxc config set core.https_address "[::]"
    lxc config set core.trust_password some-password
  • The port 8443 on the server should be open as well:

    firewall-cmd --zone=public --add-port=8443/tcp --permanent
    firewall-cmd --reload
    firewall-cmd --zone=public --list-ports
  • On the local machine add a remote, like this:

    lxc remote add lxd1 11.12.13.14

    This will prompt you to confirm the remote server fingerprint and then ask you for the password.

  • Make it the default remote and test it:

    lxc remote list
    lxc remote switch lxd1
    lxc remote list
    lxc ls

    Now all the lxc commands on the laptop will be executed by default on the remote LXD server.

  • Once we can connect remotely to the LXD server, we should unset core.trust_password on the server, for security reasons:

    lxc config get core.trust_password
    lxc config set core.trust_password ""
    lxc config get core.trust_password
  • On the client machine (laptop) install also virt-viewer (or spice-client-gtk), which is needed to access the VGA console of the virtual machines:

    apt install virt-viewer
    Be aware that without Xpra, the GUI interface displayed by virt-viewer is not smooth but slow and lagish.

9.2. Setup Xpra

We can use Xpra in order to access the VGA console of a virtual machine remotely. We need to install it both on the server and on the client (on the laptop):

apt install xpra

On the server we also need to install the package virt-viewer (which provides remote-viewer):

apt install virt-viewer

Then we can start Xpra on the server, like this:

xpra start :7
DISPLAY=:7 tmux
Instead of 7 you can use any other port for the display.

From the client, we can attach to the Xpra server like this:

xpra attach ssh:user@example.com:7
Give the identity file and port of the ssh command

If we use a non-standard key and port for accessing the SSH of the server, then we can use the option --ssh, like this:

xpra attach ssh:user@10.11.12.13:7 \
     --ssh="ssh -i ssh-key -p 222"

Now, from the tmux on the server we can start any GUI application, and it will be displayed on the local machine.

9.3. Install the gateway

All the containers and VMs are connected by default to a bridge (usually named lxdbr0), which provides them with DHCP, DNS, and allows them to connect to the internet (acting like a gateway). However we need a gateway that does not provide DHCP, since the DHCP is going to be provided by the main server. This requirement is discussed in the docs. So, we are going to build a VM for the gateway, as shown in the network topology diagram.

gateway

This gateway needs to be connected to lxdbr0 (which provides access to the internet) and to another switch, which connects it to the main server and to the LTSP servers. Let’s call it switch0.

9.3.1. Create switch0

In LXC, a switch can be implemented by a virtual network. However we should make sure that this virtual network does not provide DHCP and does not act as a gateway for the VMs that are connected to it (by default it does). We can do it like this:

lxc network list
lxc network create switch0 --type=bridge
lxc network show switch0
lxc network unset switch0 ipv4.address
lxc network unset switch0 ipv4.nat
lxc network show switch0

9.3.2. Create the virtual machine

Now let’s create the gateway VM:

lxc init images:debian/11 gateway --vm
lxc network attach switch0 gateway
lxc start gateway
lxc ls

By default it is connected to lxdbr0, but we are also connecting it to switch0.

9.3.3. Fix networking

lxc exec gateway -- ip addr
lxc exec gateway -- ping 8.8.8.8

Somehow firewalld interferes with the network communication in the virtual environment that we are creating. It should be possible to setup its configuration so that everything works correctly, but I have not been able yet to do it properly. So, we need to disable it.

systemctl stop firewalld
systemctl disable firewalld
systemctl mask firewalld

Also, make sure that the default policy for the FORWARD chain of iptables is ACCEPT, otherwise the containers will not be able to access the internet.

iptables -L
iptables -P FORWARD ACCEPT

Test it:

lxc restart gateway
lxc ls
lxc exec gateway -- bash
ip addr
ip ro
ping 8.8.8.8
ping google.com

It should work.

9.3.4. Fix the configuration

Now let’s fix the configuration of the virtual machine so that it serves as a gateway:

  • Set IP 10.0.0.1 to the second (internal) interface:

    lxc exec gateway -- bash
    ip addr
    
    cat <<EOF > /etc/systemd/network/enp6s0.network
    [Match]
    Name=enp6s0
    [Network]
    Address=10.0.0.1
    DNS=10.0.2.2
    EOF
    
    systemctl restart systemd-networkd
    ip addr
  • Make sure that the hostname is gateway:

    hostname gateway
    hostname > /etc/hostname
  • Enable masquerading using firewalld:

    apt install firewalld
    firewall-cmd --permanent --zone=external --add-interface=enp5s0
    firewall-cmd --permanent --zone=dmz --add-interface=enp60
    firewall-cmd --reload

9.4. Install main-server from a base image

When we start the installation from a base debian image (provided by the LXD infrastructure), it is faster and more convenient. One reason is that the base image already has the LXD agent installed by default, which makes its management easier. Another reason is that the installation process becomes scriptable (no manual intervention needed) and this is more suitable for testing purposes.

So, let’s see also how to install a main-server starting from a base debian image.

9.4.1. Create a VM

First let’s stop the current main-server, so that it doesn’t interfere with the new one, and let’s call the new server main-server-1:

lxc stop -f main-server

lxc init images:debian/11 main-server-1 --vm \
    --network=switch0 \
    -c limits.memory=4GB -c limits.cpu=2
lxc network attach switch1 main-server-1
lxc config device override main-server-1 root size=100GB
lxc start main-server-1

lxc ls
lxc exec main-server-1 -- bash
ip addr
ip ro

9.4.2. Fix the network configuration

The default network configuration of the image is to get the settings by DHCP, but there is no DHCP server connected to switch0, as a result there is no network configuration.

lxc exec main-server-1 -- bash
ls /etc/systemd/network
cat /etc/systemd/network/enp5s0.network

We need to fix this, before we can continue with other installations and configurations:

cat <<EOF > /etc/systemd/network/enp5s0.network
[Match]
Name=enp5s0
[Network]
Address=10.0.2.2/8
Gateway=10.0.0.1
DNS=8.8.8.8
EOF

systemctl restart systemd-networkd

ip addr
ip ro
ping 8.8.8.8
ping google.com

9.4.3. Resize the filesystem

If you check the size of the filesystem, you will notice that it is much smaller than the size that we have allocated to the VM:

df -h .
df -h

This is the size of the base image. We have to enlarge the size of the filesystem to fill all the available disk space:

apt install fdisk cloud-guest-utils
df -h .
growpart /dev/sda 2    # notice the space in front of 2; it is not a typo
resize2fs /dev/sda2    # no space in this case
df -h .
apt purge fdisk cloud-guest-utils
apt autoremove

9.4.4. Install the Main-Server profile

Now we get the package debian-edu-config which contains installation/configuration scripts, and perform an installation of the profile Main-Server:

apt install debian-edu-config
cd /usr/share/debian-edu-config/

#PROFILE=Main-Server DESKTOP=none bash -x tools/debian-edu-bless
PROFILE=Main-Server,Workstation DESKTOP=lxde bash -x tools/debian-edu-bless

# add also a user
adduser user1

# set a password for the root
passwd

# reboot
exit
lxc stop main-server-1
lxc start main-server-1

Now we can access its desktop:

lxc console main-server-1 --type=vga