How to Use LXC System Containers with Incus (A Lightweight VM for Each Service)

Docker containers run one process. A system container (LXC) runs a whole Ubuntu or Debian — init, systemd, SSH, cron, apt — sharing the host's kernel, so it starts in two seconds and uses almost no memory, but behaves like a separate machine with its own IP. Incus is the modern manager for them (the community fork of LXD). It's the right tool for things that don't fit Docker well: a Pi-hole that should look like a separate device, a Samba server for one group, a sandbox to try something on, a service that insists on installing from apt.
Quick reference
| Task | Command |
|---|---|
| Install | sudo apt install incus -y && sudo incus admin init |
| Launch a container | incus launch images:ubuntu/24.04 pihole |
| A shell inside | incus exec pihole -- bash |
| List | incus list |
| Give it a LAN IP | a macvlan or bridged profile |
| Snapshot / restore | incus snapshot create pihole pre-update · incus snapshot restore pihole pre-update |
| Copy or export | incus copy pihole pihole2 · incus export pihole backup.tar.gz |
1. Install Incus
Ubuntu 24.04 and later have it in the repositories (older releases: the Zabbly repo):
sudo apt install incus -y
sudo usermod -aG incus-admin $USER # log out and in
incus admin init
Accept the defaults: a new storage pool (dir is fine; zfs if you have a pool), a bridge incusbr0 with NAT. Containers on that bridge get private addresses and reach the internet; you'll add a LAN option next.
2. Launch one
incus launch images:ubuntu/24.04 sandbox
incus list
incus exec sandbox -- bash
Two seconds, and you're root inside a fresh Ubuntu with its own hostname. apt update, install things, break things. exit, then incus delete sandbox --force and it never happened. incus image list images: | grep -i debian shows the other distributions available.
3. A container with its own LAN address
For a service that should be a device on your network (Pi-hole, a Samba server), make a profile that attaches containers to your physical NIC with macvlan:
incus profile create lan
incus profile device add lan eth0 nic nictype=macvlan parent=enp3s0 name=eth0
incus launch images:ubuntu/24.04 pihole --profile default --profile lan
incus list
The container asks your router for an address and gets one like any laptop — reserve it (tutorial 8). (As with Docker's macvlan, the host can't talk to macvlan containers directly; a bridged setup over br0 from tutorial 81 avoids that if you need host-to-container traffic.)
4. Run something in it
incus exec pihole -- bash
apt update && apt install curl -y
curl -sSL https://install.pi-hole.net | bash
Inside the container, everything from this series applies: systemctl, ufw, cron, Docker if you want (security.nesting=true). It's a small Ubuntu machine. SSH into it directly at its LAN IP, or incus exec from the host.
5. Snapshots, copies, limits
incus snapshot create pihole pre-update
incus snapshot restore pihole pre-update
incus copy pihole pihole-test
incus config set pihole limits.memory=512MiB limits.cpu=1
incus config set pihole boot.autostart=true
Snapshots are instant on ZFS/btrfs pools. incus export pihole /mnt/backup/pihole.tar.gz makes a portable backup; incus import restores it on any Incus host.
6. Mount host folders in
incus config device add samba data disk source=/mnt/data/files path=/srv/files shift=true
shift=true maps the ownership so the container's users see the files as their own.
LXC or Docker?
| Want | Use |
|---|---|
| A packaged web app with a compose file | Docker (25) |
| Something that wants apt, systemd, several processes, its own IP | Incus container |
| A different kernel or OS, Windows, a GPU passthrough | a VM (81, 141) |
Incus also runs VMs (incus launch images:ubuntu/24.04 vm1 --vm) with the same commands, which makes it a neat alternative to tutorial 81's Cockpit for people who prefer the terminal.
Troubleshooting
Container has no network. The bridge isn't up, or with macvlan the parent NIC name is wrong (ip link). incus network list.
"Permission denied" on incus commands. Not in incus-admin; log out and in.
Docker inside the container fails. incus config set name security.nesting=true and restart it.
Can't reach a macvlan container from the host. Expected; use the bridge profile or another device to test.
Wrapping up
Install, incus admin init, incus launch. A full Ubuntu in a container in two seconds, with its own address, snapshots and exports, for the services that don't fit Docker's one-process mould. It's the middle layer most home servers end up wanting once they've got the other two.
