Incus vs LXD vs Docker
Incus is the community-driven successor to Canonical's LXD, forked under the Linux Containers project. Unlike Docker's application containers, Incus runs full system containers that share the host kernel with near-zero overhead — a single 2 GB VPS can run 10–20 lightweight containers.
| Feature | Incus (LXC) | Docker | Full VM (KVM) |
|---|---|---|---|
| Isolation | Kernel-level namespaces | Kernel-level namespaces | Hardware-level |
| Overhead | ~5–10 MB/container | Minimal per container | 512 MB+ per VM |
| Boot time | < 1 second | < 1 second | 10–30 seconds |
| Use case | System containers (full OS) | App containers (single process) | Full OS with own kernel |
| Networking | Full network stack per container | Port mapping / overlay | Full network stack |
| Persistence | Persistent by default | Ephemeral by default | Persistent |
| Init system | systemd / OpenRC | Not typical | Any |
💡 Tip
Incus also supports lightweight VMs (using QEMU under the hood) for workloads that need a separate kernel, giving you the best of both worlds on a single platform.
Why RamNode for Incus
- KVM virtualization — full root access to a real kernel (no OpenVZ limitations)
- Dedicated resources with no overselling, high-performance NVMe storage
- Starting at $4/month with $500 annual credit option
- Multiple datacenter locations (US, NL) for low-latency deployments
Prerequisites
Recommended RamNode VPS Specifications
| Spec | Minimum | Recommended |
|---|---|---|
| RAM | 1 GB | 2 GB+ (4 GB for VMs) |
| Storage | 20 GB NVMe | 40 GB+ NVMe |
| CPU | 1 vCPU | 2+ vCPU |
| OS | Ubuntu 22.04 LTS | Ubuntu 24.04 LTS |
Initial Server Setup
# Update the system
sudo apt update && sudo apt upgrade -y
sudo reboot
# Configure a non-root user (if not already done)
adduser deploy
usermod -aG sudo deploy
su - deploy
# Set up a basic firewall
sudo ufw allow OpenSSH
sudo ufw enable
sudo ufw statusVerify Kernel Support
# Ensure cgroups v2 is active (required for Incus)
stat -fc %T /sys/fs/cgroup
# Should output: cgroup2fs
# Verify namespaces are available
ls /proc/self/ns/📌 Note
RamNode KVM VPS instances run a full Linux kernel with all required namespace and cgroup support out of the box. No kernel modifications are needed.
Installing Incus on Ubuntu 24.04
Option A: Zabbly Repository (Recommended)
The Zabbly repository, maintained by the Incus project lead, provides the latest stable packages:
# Install prerequisites
sudo apt install -y curl gpg
# Add Zabbly GPG key
curl -fsSL https://pkgs.zabbly.com/key.asc | sudo gpg \
--dearmor -o /etc/apt/keyrings/zabbly.gpg
# Add repository
sudo sh -c 'echo "deb [signed-by=/etc/apt/keyrings/zabbly.gpg] \
https://pkgs.zabbly.com/incus/stable $(lsb_release -cs) main" \
> /etc/apt/sources.list.d/zabbly-incus-stable.list'
# Install Incus
sudo apt update
sudo apt install -y incus
# Add your user to the incus-admin group
sudo usermod -aG incus-admin $(whoami)
newgrp incus-adminVerify Installation
incus version
# Example output: Client version: 6.x
# Server version: 6.xInitial Configuration
The interactive initialization wizard configures storage, networking, and clustering:
sudo incus admin initRecommended Answers for Single-Node Setup
| Prompt | Answer | Explanation |
|---|---|---|
| Clustering? | no | Single-node setup |
| Storage backend | dir or zfs | dir is simplest; zfs enables snapshots and CoW |
| Create new ZFS pool? | yes | If using ZFS — loopback file or dedicated partition |
| Pool size | 20GB+ | Match your available disk space |
| Network bridge? | yes | Creates incusbr0 for container networking |
| IPv4 CIDR | auto or 10.10.10.1/24 | Private subnet for containers |
| IPv6 CIDR | auto or none | Optional; set none if not needed |
| Remote access? | no | Secure default; enable later if needed |
| Stale images auto-update? | yes | Keeps base images current |
| Print YAML? | yes | Save for reproducibility |
💡 Tip
Save the YAML output from the init wizard. You can replay it later with: incus admin init --preseed < config.yaml
ZFS vs Directory Backend
For production on RamNode, ZFS is strongly recommended — copy-on-write clones, built-in compression, and snapshot support.
incus storage list
incus storage info defaultWorking with Containers
# Launch an Ubuntu 24.04 container
incus launch images:ubuntu/24.04 my-webserver
# Launch Alpine (minimal footprint — ~8 MB)
incus launch images:alpine/3.20 my-alpine
# Launch Debian 12
incus launch images:debian/12 my-debianFile Transfer
# Push a file into the container
incus file push ./nginx.conf my-webserver/etc/nginx/nginx.conf
# Pull a file from the container
incus file pull my-webserver/var/log/syslog ./syslog.txt
# Push an entire directory
incus file push -r ./myapp/ my-webserver/opt/myapp/Running Commands Without a Shell
# Run a single command
incus exec my-webserver -- apt update
incus exec my-webserver -- systemctl status nginx
# Run as a specific user
incus exec my-webserver -- su -l www-data -c 'whoami'Virtual Machines
Incus can launch lightweight QEMU-backed VMs for workloads that need kernel modules, custom kernels, or stronger isolation.
# Launch a VM (note the --vm flag)
incus launch images:ubuntu/24.04 my-vm --vm
# Launch with specific resources
incus launch images:ubuntu/24.04 my-vm --vm \
-c limits.cpu=2 -c limits.memory=2GiB
# Access VM console
incus console my-vm
# Access via shell (once agent is running)
incus exec my-vm -- bash⚠️ Warning
VMs require more resources than containers. On a 2 GB RamNode VPS, limit yourself to 1–2 small VMs. For container-only workloads, you can run significantly more instances.
Networking Configuration
Default Bridge Network
During initialization, Incus creates incusbr0, a managed bridge that provides NAT-based internet access to all containers.
incus network list
incus network show incusbr0
# View container IPs
incus list -c ns4Port Forwarding (Proxy Devices)
Expose container services to the internet by mapping host ports to container ports:
# Forward host port 80 → container port 80
incus config device add my-webserver http proxy \
listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
# Forward host port 443 → container port 443
incus config device add my-webserver https proxy \
listen=tcp:0.0.0.0:443 connect=tcp:127.0.0.1:443
# Remove a proxy device
incus config device remove my-webserver httpStatic IP Assignment
incus config device add my-webserver eth0 nic \
nictype=bridged parent=incusbr0 \
ipv4.address=10.10.10.100UFW Firewall Rules
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reloadStorage Pools & Volumes
Managing Storage Pools
# List pools
incus storage list
# Create a new ZFS pool (loopback)
incus storage create pool2 zfs size=20GiB
# Pool usage stats
incus storage info defaultCustom Storage Volumes
Custom volumes are persistent storage that can be attached to any container, similar to Docker volumes:
# Create a volume
incus storage volume create default my-data
# Attach to a container
incus config device add my-webserver data disk \
pool=default source=my-data path=/mnt/data
# Detach from container
incus config device remove my-webserver data
# Move data between containers
incus config device remove container-a data
incus config device add container-b data disk \
pool=default source=my-data path=/mnt/dataResource Limits & Profiles
Setting Resource Limits
# Limit CPU to 1 core
incus config set my-webserver limits.cpu 1
# Limit memory to 512 MB
incus config set my-webserver limits.memory 512MiB
# Limit root disk to 5 GB
incus config device set my-webserver root size=5GiB
# View current limits
incus config show my-webserverUsing Profiles
Profiles define reusable configuration templates:
# Create a web server profile
incus profile create web-server
incus profile set web-server limits.cpu 1
incus profile set web-server limits.memory 256MiB
# Apply profile when launching
incus launch images:ubuntu/24.04 web01 -p default -p web-server
# Apply profile to existing container
incus profile add my-webserver web-server
# List all profiles
incus profile listRecommended Profile Templates
| Profile | CPU | Memory | Disk | Use Case |
|---|---|---|---|---|
| micro | 1 | 128 MiB | 2 GiB | DNS, cron jobs, monitoring agents |
| small | 1 | 256 MiB | 5 GiB | Web servers, reverse proxies |
| medium | 2 | 512 MiB | 10 GiB | App servers, databases |
| large | 2 | 1 GiB | 20 GiB | CI/CD runners, build environments |
Snapshots & Backups
# Create a snapshot
incus snapshot create my-webserver pre-upgrade
# List snapshots
incus snapshot list my-webserver
# Restore a snapshot
incus snapshot restore my-webserver pre-upgrade
# Delete a snapshot
incus snapshot delete my-webserver pre-upgradeScheduled Automatic Snapshots
# Snapshot every day, keep last 7
incus config set my-webserver snapshots.schedule @daily
incus config set my-webserver snapshots.schedule.stopped false
incus config set my-webserver snapshots.expiry 7d
incus config set my-webserver snapshots.pattern daily-%dFull Container Export / Import
# Export container as tarball (for offsite backup)
incus export my-webserver /backup/my-webserver.tar.gz
# Import on same or different Incus host
incus import /backup/my-webserver.tar.gz
# Import with a new name
incus import /backup/my-webserver.tar.gz new-webserver💡 Tip
Combine Incus exports with RamNode's snapshot feature for defense-in-depth backups. Export critical containers to a mounted backup volume or remote storage.
Security Hardening
Unprivileged Containers
By default, Incus containers run unprivileged — root inside the container is mapped to a non-root UID on the host:
# Verify container is unprivileged
incus config get my-webserver security.privileged
# Should return empty (false) or false
# NEVER do this in production:
# incus config set my-webserver security.privileged trueAppArmor and Seccomp
Incus applies AppArmor profiles and seccomp filters by default:
incus info my-webserver | grep -A5 SecurityNetwork Isolation
# Restrict container-to-container traffic
incus network set incusbr0 bridge.hwaddr random
# Disable IPv6 if not needed
incus network set incusbr0 ipv6.address none📌 Note
Always set resource limits to prevent a compromised container from exhausting host resources. See Section 8 for detailed limit configuration.
Monitoring & Maintenance
# Quick status overview
incus list -c nsCPUmM
# Detailed instance info
incus info my-webserver --resources
# Host-level resource usage (all containers)
incus info --resourcesLog Access
# Container logs
incus info my-webserver --show-log
# Incus daemon logs
sudo journalctl -u incus.service -fImage Management
# List cached images
incus image list
# Remove unused images
incus image list --format csv | grep -v FINGERPRINT | \
awk -F, '{print $2}' | xargs -I{} incus image delete {}
# Manually refresh cached images
incus image refreshUpdating Incus
sudo apt update && sudo apt upgrade -y
incus versionCommon Use Cases on RamNode
Multi-Site Web Hosting
Run multiple isolated web servers on a single VPS:
# Launch 3 isolated web servers
incus launch images:ubuntu/24.04 site-a -p default -p web-server
incus launch images:ubuntu/24.04 site-b -p default -p web-server
incus launch images:ubuntu/24.04 site-c -p default -p web-server
# Install Nginx in each
for c in site-a site-b site-c; do
incus exec $c -- apt update
incus exec $c -- apt install -y nginx
done
# Use an Nginx reverse proxy on the host or in a
# dedicated container to route traffic by domain name.Development and Staging Environments
# Clone production container for staging
incus copy my-production staging-env
incus start staging-env
# Snapshot before risky changes
incus snapshot create staging-env pre-test
# Test, then restore if needed
incus snapshot restore staging-env pre-testCI/CD Build Runners
# Script for CI runner
incus launch images:ubuntu/24.04 build-$
incus exec build-$ -- /opt/run-build.sh
incus delete build-$ --force💡 Use Cases
Popular self-hosted applications to run in Incus containers: Nextcloud, Gitea, Uptime Kuma, Vaultwarden, Pi-hole, and WireGuard — each fully isolated with its own network stack.
Troubleshooting
| Issue | Cause | Solution |
|---|---|---|
| Permission denied on incus commands | User not in incus-admin group | sudo usermod -aG incus-admin $USER && newgrp incus-admin |
| Container has no internet | Bridge NAT not configured | Check incus network show incusbr0 and verify ipv4.nat is true |
| Cannot launch VMs | Missing /dev/kvm | Verify: ls -la /dev/kvm. On RamNode KVM VPS, this should be present |
| Storage pool full | Disk space exhausted | Clean snapshots, remove unused images, consider upgrading VPS storage |
| Slow container startup | First-time image download | Subsequent launches from cache are near-instant |
| DNS not resolving in container | systemd-resolved conflict | incus exec <name> -- bash -c 'echo nameserver 1.1.1.1 > /etc/resolv.conf' |
Getting Help
# Incus built-in help
incus --help
incus <command> --help
# Check Incus daemon status
sudo systemctl status incus
# Verbose daemon logs
sudo journalctl -u incus.service --since '1 hour ago'🎉 Next Steps
- Explore multi-host clustering with Incus for high availability
- Set up remote image servers for custom golden images
- Integrate Incus with Terraform for infrastructure-as-code workflows
- Scale from a single development node to a multi-server container cluster
