LXD/LXC Basic Setup
LXD Initial Setup
First add your Linux user to the lxd
group in order to operate with the containers without sudo
– note you nay need to cog-out and log-in.
sudo usermod -aG lxd <user>
Initialize LXD.
lxd init
Would you like to use LXD clustering? (yes/no) [default=no]: no
Do you want to configure a new storage pool? (yes/no) [default=yes]: yes
Name of the new storage pool [default=default]: default
Name of the storage backend to use (dir, lvm, zfs, ceph, btrfs) [default=zfs]: dir
Would you like to connect to a MAAS server? (yes/no) [default=no]: no
Would you like to create a new local network bridge? (yes/no) [default=yes]: yes
What should the new bridge be called? [default=lxdbr0]: lxdbr0
What IPv4 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: auto
What IPv6 address should be used? (CIDR subnet notation, “auto” or “none”) [default=auto]: auto
Would you like the LXD server to be available over the network? (yes/no) [default=no]: no
Would you like stale cached images to be updated automatically? (yes/no) [default=yes]: yes
Would you like a YAML "lxd init" preseed to be printed? (yes/no) [default=no]: yes
config: {}
networks:
- config:
ipv4.address: auto
ipv6.address: auto
description: ""
name: lxdbr0
type: ""
project: default
storage_pools:
- config: {}
description: ""
name: default
driver: dir
profiles:
- config: {}
description: ""
devices:
eth0:
name: eth0
network: lxdbr0
type: nic
root:
path: /
pool: default
type: disk
name: default
projects: []
cluster: null
List the available images by the following commands and find the name of an image of a desired distribution – in this case Ubuntu Server 22.04.
lxc image list
lxc image list ubuntu:22.04
lxc image list ubuntu:22.04 | grep x86_64
Install a certain image. We will name the container lxc-webserver
. We will add a capability to the container to run other containers inside, for more details read the article Nested containers in LXD.
lxc launch ubuntu:22.04 lxc-webserver -c security.nesting=true
Creating lxc-webserver
Starting lxc-webserver
In order to add (or remove) the nesting option to an existing LXC, use:
lxc config set lxc-webserver security.nesting true
List the containers available within the LXD in use.
lxc list --columns ns4 # name, state and IPv4
+---------------+---------+-----------------------+
| NAME | STATE | IPV4 |
+---------------+---------+-----------------------+
| lxc-webserver | RUNNING | 10.127.198.222 (eth0) |
+---------------+---------+-----------------------+
Configure the container to obtain a static IP assignment.
lxc config device override lxc-webserver eth0
Device eth0 overridden for lxc-webserver
lxc config device set lxc-webserver eth0 ipv4.address 10.127.198.222 # no output mean everything is fine
lxc restart lxc-webserver
lxc list --columns ns4 | grep eth0 # check the ip
| lxc-webserver | RUNNING | 10.127.198.222 (eth0) |
LXD Basic operation
Restart the service.
sudo snap restart lxd
Mount a host directory to a directory inside a container. Map the permissions.
printf "lxd:$(id -u):1\nroot:$(id -u):1\n" | sudo tee -a /etc/subuid # Allow LXD’s use of our user uid
printf "lxd:$(id -g):1\nroot:$(id -g):1\n" | sudo tee -a /etc/subgid # Allow LXD’s use of our user gid
sudo snap restart lxd # Restart LXD to have it load the new map
printf "uid $(id -u) 1000\ngid $(id -g) 1000" | lxc config set lxc-webserver raw.idmap - # Set a custom map for our container
lxc restart lxc-webserver # Restart the container to have the new map apply
lxc config device add lxc-webserver Git disk source=/home/<user>/Git path=/home/<user>/Git # Mount the directory
Do the actual share (mount) of some directories.
lxc config device add lxc-webserver Git disk source=/home/<user>/Git path=/home/<user>/Git
lxc config device add lxc-webserver VSC disk source=/home/<user>/.vscode-server path=/home/<user>/.vscode-server
LXC Basic operations
List available containers.
lxc list
lxc list -c ns4
Login to a container (note lxc-webserver
is a container name).
lxc shell lxc-webserver
Execute a command against the container from the host.
lxc exec lxc-webserver -- apt install apache2
Start, stop or delete container.
lxc (start|stop|delete) container-name
Create a snapshot.
lxc snapshot lxc-webserver snapshot-name
Delete a snapshot.
lxc delete lxc-webserver/snapshot-name
Restore a snapshot.
lxc restore lxc-webserver snapshot-name
Create a backup.
lxc export lxc-webserver ./lxc-webserver-backup.tar.gz
Restore a backup.
lxc import ./lxc-webserver-backup.tar.gz
Get info about the container (and its snapshots at the bottom).
lxc info lxc-webserver
Limit the container's memory usage.
lxc config set lxc-webserver limits.memory 1GB
Auto-start a container.
lxc config set lxc-webserver boot.autostart 1
Set an auto-start delay for a container.
lxc config set lxc-webserver boot.autostart.delay 30
Set an auto-start order number for a container.
lxc config set lxc-database boot.autostart.order 2
lxc config set lxc-webserver boot.autostart.order 3
Disable IPv6 for the containers – reference.
lxc network set lxdbr0 ipv6.address none
Backup LXC Containers
Here are provided notes about backing up the containers,
Local export approach
You can use a crontab
entry as the follow.
* */12 * * * /snap/bin/lxc export lxc-webserver $HOME/backups/lxc-webserver-backup.tar.gz >/tmp/crontab.${USER}.lxc-webserver-backup.tar.gz.log 2>&1
The command could be a part of your backup script. Also they say it is better to export a snap shot… Then a remote instance can fetch it by rsync
via SSH.
References
- Linux containers LXD: Backing up a LXD server
- CiberCity: How to move/migrate LXD VM to another host on Linux
- NixCraft: How to backup and restore LXD containers
- StackOverflow: Copy lxd containers between hosts
Remote export approach
In this section, the LXD that is running the actual LXC that we want to backup will be called remote-lxd.host
. The LXD that will fetch (export) the backups will be called local-lxd.host
. Here is used the most simple settings and the connection between the servers will be carry out via SSH tunnel.
1. First, at the remote-lxd.host
run the following command.
lxc config set core.https_address :8443
lxc config set core.trust_password 'p@s$********wD'
2. Then at the local server local-lxd.host
add the necessary entry for a connection with port forwarding of port 8443
in the file ~/.ssh/config
. For more details read the SSH section below. After that test the connection by the following commands.
ssh fwd.remote-lxd.host -fTN
sudo netstat -tnupa | grep 8443
3. If everything looks fine, do the Init setup for this instance – local-lxd.host
, answer with no at all questions if wont run local LXCs, and then execute the following command to add the remote server.
# Default auth type: TLS + password
lxc remote add remote-lxd.host 127.0.0.1:8443
ficate fingerprint: 1778ec79530...
ok (y/n/[fingerprint])? y
Admin password for remote-lxd.host: ***
Client certificate now trusted by server: remote-lxd.host
Then you can switch the default remote server and list the running containers as follow.
lxc remote list
lxc remote switch remote-lxd.host
lxc list
The above procedure must be done for all users that will manipulate the remote instance – in this count the root
account if needed!
4. In order to export a backup from the remote instance you can perform the following steps.
lxc snapshot remote-lxd.host:lxc-webserver backup # Create a remote snapshot
lxc export remote-lxd.host:lxc-webserver/backup ./remote.lxc-webserver.tar.gz # Create a local backup of the remote snapshot
Note you need to have enough space at the remote instance, because the snapshots are created there. Also when yo create remote backups they will be created as temporary file at the remote instance and ten will be transferred to the local one.
lxc export remote-lxd.host:lxc-webserver ./remote.lxc-webserver.tar.gz # Create a backup of the remote LXC withot a snapshot
References
- Linux containers LXD: Advanced guide Introduction, Section: Remote LXD Server
- Linux containers LXD: Backing up a LXD server
- Mi blog lah: How to use LXC remote with the LXD snap
Automate the Remote export approach
sudo nano /usr/local/bin/backup.remote-lxd.sh && chmod +x /usr/local/bin/backup.remote-lxd.sh
#!/bin/bash
# @author Spas Z. Spasov <spas.z.spasov@metalevel.tech>
# @copyright 2022 Spas Z. Spasov
# @license https://www.gnu.org/licenses/gpl-3.0.html GNU General Public License, version 3 (or later)
#
# @desc Create a local backup of an remote LXC, create a local backup of the remote LXD's settings,
# fetch other backup files.
# Some of the parameters still hard coded - this should ne improoved:
# - remote-lxd.host
# - fwd.remote-lxd.host
# - lxc-webserver
# Define the input parameters.
TODAY="$(date +%Y-%m-%d)"
BACKUP_DIR="/mnt/backups/remote-lxd.host"
LOG="$BACKUP_DIR/backup.${TODAY}.log"
SYSTEM="remote-lxd.host"
BACKUP_FILE_LXC="${BACKUP_DIR}/${SYSTEM}.lxc-webserver-backup-${TODAY}.tar.gz"
BACKUP_FILE_LXD="${BACKUP_DIR}/${SYSTEM}.lxd-init-backup-${TODAY}.yaml"
# Create the backup directory if doesn't exist
[[ ! -d $BACKUP_DIR ]] && mkdir "$BACKUP_DIR"
# Remove all backup files older than 14 days
find "$BACKUP_DIR" -mtime +14 -type f -delete
# Get the remote backup
main_ssh_export() {
echo -e "***** $TODAY *****\n"
# Establish a connection to the remote server
while ! (netstat -tnpau 2>/dev/null | grep -q '8443')
do
autossh -o "ExitOnForwardFailure yes" fwd.remote-lxd.host -TNf
done
while ! (/snap/bin/lxc list 2>/dev/null | grep -q lxc-webserver)
do
sleep 1
done
# Export the container
if (netstat -tnpau 2>/dev/null | grep -q '8443') && (/snap/bin/lxc list 2>/dev/null | grep -q lxc-webserver)
then
/snap/bin/lxc export remote-lxd.host:lxc-webserver "$BACKUP_FILE_LXC"
else
echo "Failed to establish a connection to the remote server"
exit 1;
fi
# Wait a while
sleep 3
# Terminate the connection, try to kill the parrent first
sudo kill -9 $(ps -ef | grep autossh | grep fwd.remote-lxd.host | awk '{print $2}' | head -n 1) 2>/dev/null
for pid in $(sudo netstat -tnpau 2>/dev/null | grep '8443' | awk '{print $NF}' | awk -F'/' '{print $1}');
do
sudo kill -9 "$pid" 2>/dev/null;
done
# Dump the LXD configuration. It is intentionally done in this way.
# Otherwise, when we do a dump via the remote management,
# some parameters as 'core.https_address: :8443' will be omitted.
ssh remote-lxd.host 'lxd init remote-lxd.host --dump' > "$BACKUP_FILE_LXD"
# Download the remote portable backup
rsync --progress -avr -e "ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" remote-lxd.host:"/backups/"* "${BACKUP_DIR}/"
echo -e "\n******************\n"
}
main_ssh_export #> "$LOG" 2>&1
Then you can use a crontab
entry as the follow.
* 1 * * * /usr/local/bin/backup.remote-lxd.sh >/tmp/crontab.$USER.backup.remote-lxd.sh.log 2>&1
Forward the HTTP Traffic from the LXD host to a LXC
First install the iptables-persistent
package and migrate to iptables-nft
.
- RedHat Developers: iptables: The two variants and their relationship with nftables
- Ask Ubuntu: Warning: iptables-legacy tables present
sudo apt install iptables-persistent # iptables-save > /etc/iptables/rules.{v4,v6}
sudo apt install ipset-persistent # ipset save > /etc/ipset/ipsets
sudo update-alternatives --set iptables /usr/sbin/iptables-nft
sudo update-alternatives --remove iptables /usr/sbin/iptables-legacy
sudo modprobe -r iptable_filter iptable_nat iptable_mangle iptable_raw iptable_security
The second step is to add and make persistent the Iptables rules that will redirect the traffic at ports 80
and 433
on the remote-lxd.host
to the lxc-webserver
container with IP 10.127.198.222
.
Let's assume remote-lxd.host
the server has the following IP addresses:
- eth0:
158.113.3.106
: The public address of the server, we are using Floating IP137.112.134.165
for the domainremote-lxd.host
, so we do not expect any traffic at the web ports on this IP. - eth0:
10.14.1.5
: The Floating IP137.112.134.165
redirects everything to this interface so we will forward the traffic at this port. - eth1:
10.123.1.2
: This is the IP in the private virtual network at DigitalOcean – so probably in the future other resources could access the droplet vi this interface so we will forward the traffic at this port.
sudo iptables -t nat -I PREROUTING -i $IFACE -p TCP -d $PUBLIC_IP --dport $PORT -j DNAT --to-destination $CONTAINER_IP:$PORT -m comment --comment "forward to lxc-webserver"
It should be executed for each set of the following values.
PORT=80 PUBLIC_IP=10.14.1.5 CONTAINER_IP=10.127.198.222 IFACE=eth0
PORT=443 PUBLIC_IP=10.14.1.5 CONTAINER_IP=10.127.198.222 IFACE=eth0
PORT=80 PUBLIC_IP=10.123.1.2 CONTAINER_IP=10.127.198.222 IFACE=eth0
PORT=443 PUBLIC_IP=10.123.1.2 CONTAINER_IP=10.127.198.222 IFACE=eth0
sudo iptables -t nat -L PREROUTING
# sudo iptables -t nat -F PREROUTING
sudo iptables-save | sudo tee /etc/iptables/rules.v4
# sudo iptables-restore < /etc/iptables/rules.v4
SSH ProxyJump to LXC via LXD
Follow the guide SSH Connection Setup and setup SSH connection from you local machine to the server where the LXD is hosted. Then setup SSH connection from the LXD host to the LXC at its virtual network interface. You can use the same .pub
in key – by populating the ~/.ssh/authorized_keys
file of the LXD host to the LXC.
To access the container directly via SSH we can use the Proxy Jump option in this way.
nano ~/.ssh/config
Host remote-lxd.host
HostName 158.113.3.106
IdentityFile ~/.ssh/id_ed25519
User <user>
Port 22
Host remote-lxd.host.lxc-webserver
HostName 10.127.198.222
IdentityFile ~/.ssh/id_ed25519
User <user>
Port 22
ProxyJump remote-lxd.host
Host fwd.remote-lxd.host
HostName 158.113.3.106
IdentityFile ~/.ssh/id_ed25519
User <user>
Port 22
LocalForward 8443 localhost:8443
# Compression yes
Now we have the following short SSH commands within the command line.
ssh remote-lxd.host # Connect to the remote LXD host
ssh remote-lxd.host.lxc-webserver # Connect to the remote LXC via the LXD host
ssh fwd.remote-lxd.host -fTN # Forward ports from/to the remote LXD host
For persistent port forwarding read the guide SSH Persistent Tunnel and SSHFS Mount via "systemd" units.
References
- Linux containers LXD: Server configuration settings
- Linux containers LXD: Getting Started with LXD
- DigitalOcean: How To Install and Configure LXD on Ubuntu 20.04
- LearnLinuxTV at YouTube: Getting started with LXD Containerization (Full Guide!)
- Canonical Ubuntu Server: LXD
- Canonical Ubuntu Blog: Custom user mappings in LXD containers
- Canonical Ubuntu Blog: Mounting your home directory in LXD
- Ask Ubuntu: Adding a shared host directory to an LXC/LXD Container (for privileged container)
- Ask Ubuntu: apt-key deprecation warning when updating system
- Ask Ubuntu: At what point is the ~/.bashrc file created?