Posts and how to...
Many useful articles and instructions!
- Installing LXC
- Creating a Container
- Basic Management
- Network Configuration: Local Network Access
- SSH Access
- Btrfs Backend via Loop File
- Snapshots and Cloning
- Backup and Restore
- Useful Commands
- Troubleshooting
How to install and configure an LXC container with the latest LTS 24.04 version on Ubuntu 20.04 and 24.04, create backups, and configure it so that the data is stored in a single .img file
LXC Containers Installation and Configuration Guide on Ubuntu
P.S. How do I install the latest LTS version of Ubuntu (24.04) on Ubuntu 20.04 and run applications in a container sandboxed environment?
Tested on: Ubuntu 20.04 / 24.04 (amd64)
LXC: Classic (not LXD)
Table of Contents
Installing LXC
# Update packages and install LXC
sudo apt update
sudo apt install lxc lxc-templates btrfs-progs
# Check kernel support
lxc-checkconfig
# Check LXC network interfaces
ip ad | grep lxc
Note: If
lxc-checkconfigshows warnings, ensure the kernel has enabled:CONFIG_VETH,CONFIG_MACVLAN,CONFIG_BRIDGE,CONFIG_NET_NS.
Creating a Container
Universal Template
sudo lxc-create -t download -n <NAME> -- \
--dist <distribution> \
--release <version> \
--arch <architecture>
Examples
# Ubuntu 24.04 (Noble)
sudo lxc-create -t download -n bulxc -- \
--dist ubuntu \
--release noble \
--arch amd64
# Ubuntu 22.04 (Jammy)
sudo lxc-create -t download -n mylxc-ubuntu -- \
--dist ubuntu \
--release jammy \
--arch amd64
| Parameter | Description |
|---|---|
-t download |
Download template for OS images |
-n <name> |
Container name |
--dist |
Distribution (ubuntu, debian, alpine) |
--release |
Release version (noble, jammy, focal) |
--arch |
Architecture (amd64, arm64) |
Basic Management
# List all containers
sudo lxc-ls
# List with details (status, IP, type)
sudo lxc-ls -f
# Start container (in background)
sudo lxc-start -n bulxc -d
# Start in foreground (for debugging)
sudo lxc-start -n bulxc -F
# Attach to container console
sudo lxc-attach -n bulxc
# Exit container
exit
# Stop container
sudo lxc-stop -n bulxc
# Force stop container
sudo lxc-stop -n bulxc --force
# Container information (status, IP, resource usage)
sudo lxc-info -n bulxc
# Delete container (must be stopped first!)
sudo lxc-stop -n bulxc 2>/dev/null
sudo lxc-destroy -n bulxc
Network Configuration: Local Network Access
By default, LXC containers use NAT networking and receive addresses like 10.0.3.x. To make the container visible on your local network (192.168.0.x), configure a bridge.
Step 1: Configure Bridge on Host (Netplan)
-
Find your physical interface name:
ip addr # Find the interface with your current IP, e.g., eth0 or enp3s0 -
Edit Netplan configuration:
sudo nano /etc/netplan/00-installer-config.yaml -
Replace configuration (use spaces for indentation, critical!):
network: version: 2 renderer: networkd ethernets: eth0: # Your interface name dhcp4: no dhcp6: no bridges: br0: interfaces: - eth0 # Your interface name dhcp4: yes # Host gets IP via bridge dhcp6: no -
Apply settings:
sudo netplan apply -
Verify:
ip addr show br0 # br0 should have your local IP (192.168.0.31)
Step 2: Configure Container
-
Stop the container:
sudo lxc-stop -n bulxc -
Edit container config:
sudo nano /var/lib/lxc/bulxc/config -
Find the network section and replace with:
lxc.net.0.type = veth lxc.net.0.link = br0 lxc.net.0.flags = up lxc.net.0.hwaddr = 00:16:3e:xx:xx:xx
Step 3: Static IP Inside Container
-
Attach to container:
sudo lxc-attach -n bulxc -
Edit Netplan inside (
/etc/netplan/*.yaml):network: version: 2 ethernets: eth0: dhcp4: no addresses: - 192.168.0.32/24 # Desired static IP routes: - to: default via: 192.168.0.1 # Your router/gateway IP nameservers: addresses: - 8.8.8.8 - 1.1.1.1 -
Apply:
netplan apply -
Verify:
ping -c 3 8.8.8.8 exit
SSH Access
Installing SSH Server Inside Container
# Attach to container
sudo lxc-attach -n bulxc
# Install openssh-server
apt update
apt install openssh-server -y
# Enable auto-start
systemctl enable ssh
systemctl start ssh
Allow Root Login (Optional)
Warning: Root login via password reduces security. Use SSH keys in production.
# Inside container, edit sshd_config
nano /etc/ssh/sshd_config
Find and modify:
PermitRootLogin yes
PasswordAuthentication yes
Restart SSH:
systemctl restart ssh
exit
Connect from External Device
# From host or another device on the network
ssh root@192.168.0.32
Helpful resources:
Btrfs Backend via Loop File
Enables Btrfs snapshots without a dedicated partition.
Quick Method (Single Command)
sudo lxc-create -t download -n bulxc5 -B loop --fssize 10G --fstype btrfs -- \
--dist ubuntu --release noble --arch amd64
| Parameter | Description |
|---|---|
-B loop |
Backend: file image as block device |
--fssize 10G |
Size of the image file |
--fstype btrfs |
Filesystem inside the image |
Manual Method (Full Control)
# 1. Create sparse file (10 GB)
sudo fallocate -l 10G /var/lib/lxc/lxc.img
# 2. Attach to loop device
sudo losetup -f --show /var/lib/lxc/lxc.img
# Output: /dev/loop15 remember this device
# 3. Format as Btrfs
sudo mkfs.btrfs -f /dev/loop15
# 4. Mount to separate directory
sudo mkdir -p /var/lib/lxc/btrfs
sudo mount /dev/loop15 /var/lib/lxc/btrfs
# 5. Verify
df -T /var/lib/lxc/btrfs
# Type should be: btrfs
# 6. Create container in this directory
sudo lxc-create -t download -n bulxc-btrfs -B btrfs -- \
--dist ubuntu --release noble --arch amd64
Verify Btrfs
# Check filesystem inside container
sudo lxc-attach -n bulxc5 -- df -T /
# Check subvolumes (on host)
sudo btrfs subvolume list /var/lib/lxc/bulxc5/rootfs
Snapshots and Cloning
Only works if container was created on Btrfs (backend
btrfsorloop+--fstype btrfs)
Create Snapshot
sudo lxc-snapshot -n bulxc5
List Snapshots
sudo lxc-snapshot -n bulxc5 -L
Example output:
snap0 (2024-03-14 10:30:15)
snap1 (2024-03-14 12:45:22)
Restore from Snapshot
# Restore current container to snap0 state
sudo lxc-snapshot -n bulxc5 -r snap0
Clone (New Container from Snapshot)
# Create new container "bulxc5-clone" from snap0
sudo lxc-snapshot -n bulxc5 -r snap0 -N bulxc5-clone
Delete Snapshot
sudo lxc-snapshot -n bulxc5 -d snap0
Helpful resource:
LXC Snapshots and Clones
Backup and Restore
Method 1: Full Archive (tar) Universal
# Stop container for consistency
sudo lxc-stop -n bulxc
# Create backup
sudo tar -czpf /home/ubuntu/lxc/bulxc-$(date +%F).tar.gz \
-C /var/lib/lxc bulxc
# Start container again
sudo lxc-start -n bulxc -d
Restore:
# Extract (container must be stopped and deleted first)
sudo lxc-stop -n bulxc 2>/dev/null
sudo lxc-destroy -n bulxc 2>/dev/null
sudo tar -xzpf /home/ubuntu/lxc/bulxc-2024-03-09.tar.gz \
-C /var/lib/lxc
# Start
sudo lxc-start -n bulxc -d
Method 2: rsync for Incremental Backups
# Stop container
sudo lxc-stop -n bulxc
# Sync with backup directory
sudo rsync -aHAX --delete \
/var/lib/lxc/bulxc/ \
/backup/bulxc-live/
# Start
sudo lxc-start -n bulxc -d
Automation: Backup Script
Create /usr/local/bin/lxc-backup-bulxc.sh:
#!/bin/bash
set -e
CONTAINER="bulxc"
BACKUP_DIR="/home/ubuntu/lxc"
DATE=$(date +%F)
ARCHIVE="$BACKUP_DIR/${CONTAINER}-${DATE}.tar.gz"
# Stop container
lxc-stop -n $CONTAINER 2>/dev/null || true
# Create archive
tar -czpf "$ARCHIVE" -C /var/lib/lxc "$CONTAINER"
# Start container
lxc-start -n $CONTAINER -d
# Clean old backups (keep last 7)
ls -t $BACKUP_DIR/${CONTAINER}-*.tar.gz 2>/dev/null | \
tail -n +8 | xargs -r rm
echo " Backup completed: $ARCHIVE"
Make executable and add to cron:
sudo chmod +x /usr/local/bin/lxc-backup-bulxc.sh
# Edit crontab
sudo crontab -e
# Add line (daily at 03:00):
0 3 * * * /usr/local/bin/lxc-backup-bulxc.sh
Useful Commands
Information and Monitoring
# Container directory size
du -hs /var/lib/lxc/bulxc
# Image file size (for loop backend)
ls -lh /var/lib/lxc/bulxc/rootfs.disk
# Resize image (loop backend)
sudo lxc-storage-disk-resize bulxc 20G
# Active loop devices
losetup -a
# Container network interfaces
sudo lxc-attach -n bulxc -- ip addr
Resource Management
# Limit CPU (in container config)
# /var/lib/lxc/bulxc/config
lxc.cpu.cfs_quota_us = 50000
lxc.cpu.cfs_period_us = 100000
# Limit memory
lxc.memory.limit = 1GB
Network
# Check container IP
sudo lxc-attach -n bulxc -- hostname -I
# Port forwarding (in container config)
# Access container port 80 from host port 8080
lxc.net.0.ipv4.address = 192.168.0.32/24
Troubleshooting
systemd fails to start: Failed to fork off sandboxing environment
Cause: cgroups v1 (host) vs v2 (Ubuntu 24.04 container) conflict.
Solution: Enable cgroups v2 on host:
# 1. Edit GRUB
sudo nano /etc/default/grub
# Add to line:
GRUB_CMDLINE_LINUX_DEFAULT="quiet splash systemd.unified_cgroup_hierarchy=1"
# 2. Update and reboot
sudo update-grub
sudo reboot
# 3. Verify
mount | grep cgroup
# Should show: cgroup2 on /sys/fs/cgroup type cgroup2
Alternative: Use Ubuntu 22.04 in container it's more compatible with cgroups v1.
Container Has No Network Access
# Check network config
sudo nano /var/lib/lxc/bulxc/config
# Ensure: lxc.net.0.link = br0
# Check bridge on host
ip addr show br0
brctl show br0 # if bridge-utils installed
# Check AppArmor
sudo dmesg | grep -i apparmor
# If needed, temporarily:
# lxc.apparmor.profile = unconfined
Btrfs: is not a valid backing storage type
Cause: btrfs backend requires /var/lib/lxc to be on a Btrfs partition.
Solution: Use loop backend with --fstype btrfs:
sudo lxc-create -t download -n bulxc -B loop --fstype btrfs -- \
--dist ubuntu --release noble --arch amd64
No SSH Access
# Inside container, check:
systemctl status ssh
ss -tlnp | grep :22
ufw status # if firewall enabled
# Allow port (if needed)
ufw allow 22/tcp
Helpful Links
- Official LXC Documentation
- LXC Installation on Ubuntu (Bayrell Blog)
- SSH root Setup
- LXC Snapshots and Clones
LXC File Structure
/var/lib/lxc/
<container-name>/
config # Container configuration
rootfs/ # Root filesystem (or link to loop file)
rootfs.disk # Image file (for loop backend)
snaps/ # Snapshots (for Btrfs)
snap0/
snap1/
lxc.conf # Global config (rarely used)
/etc/lxc/
default.conf # Template for new containers
lxc-net.conf # Network service settings
Tip: Always test restore from backup on a test container before deleting the original. A backup without restore verification is not a backup.







