Container Virtualization Guide

    Deploying Incus (LXC/LXD)

    Run lightweight system containers and application containers on your RamNode KVM VPS with near-native performance and full isolation. Incus is the community-driven successor to LXD, forked under the Linux Containers project.

    Ubuntu 24.04 LTS
    Incus 6.x
    System Containers + VMs
    15–20 min setup

    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.

    FeatureIncus (LXC)DockerFull VM (KVM)
    IsolationKernel-level namespacesKernel-level namespacesHardware-level
    Overhead~5–10 MB/containerMinimal per container512 MB+ per VM
    Boot time< 1 second< 1 second10–30 seconds
    Use caseSystem containers (full OS)App containers (single process)Full OS with own kernel
    NetworkingFull network stack per containerPort mapping / overlayFull network stack
    PersistencePersistent by defaultEphemeral by defaultPersistent
    Init systemsystemd / OpenRCNot typicalAny

    💡 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
    1

    Prerequisites

    Recommended RamNode VPS Specifications

    SpecMinimumRecommended
    RAM1 GB2 GB+ (4 GB for VMs)
    Storage20 GB NVMe40 GB+ NVMe
    CPU1 vCPU2+ vCPU
    OSUbuntu 22.04 LTSUbuntu 24.04 LTS

    Initial Server Setup

    Update and secure the server
    # 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 status

    Verify Kernel Support

    Check cgroups v2 and namespaces
    # 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.

    2

    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:

    Add Zabbly repo and install Incus
    # 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-admin

    Verify Installation

    Check Incus version
    incus version
    # Example output: Client version: 6.x
    #                 Server version: 6.x
    3

    Initial Configuration

    The interactive initialization wizard configures storage, networking, and clustering:

    Run the init wizard
    sudo incus admin init

    Recommended Answers for Single-Node Setup

    PromptAnswerExplanation
    Clustering?noSingle-node setup
    Storage backenddir or zfsdir is simplest; zfs enables snapshots and CoW
    Create new ZFS pool?yesIf using ZFS — loopback file or dedicated partition
    Pool size20GB+Match your available disk space
    Network bridge?yesCreates incusbr0 for container networking
    IPv4 CIDRauto or 10.10.10.1/24Private subnet for containers
    IPv6 CIDRauto or noneOptional; set none if not needed
    Remote access?noSecure default; enable later if needed
    Stale images auto-update?yesKeeps base images current
    Print YAML?yesSave 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.

    Check storage pool status
    incus storage list
    incus storage info default
    4

    Working with Containers

    Launch your first 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-debian

    File Transfer

    Push and pull files
    # 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

    Remote commands
    # 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'
    5

    Virtual Machines

    Incus can launch lightweight QEMU-backed VMs for workloads that need kernel modules, custom kernels, or stronger isolation.

    Launch and manage VMs
    # 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.

    6

    Networking Configuration

    Default Bridge Network

    During initialization, Incus creates incusbr0, a managed bridge that provides NAT-based internet access to all containers.

    View network configuration
    incus network list
    incus network show incusbr0
    
    # View container IPs
    incus list -c ns4

    Port Forwarding (Proxy Devices)

    Expose container services to the internet by mapping host ports to container ports:

    Port forwarding
    # 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 http

    Static IP Assignment

    Assign static IP
    incus config device add my-webserver eth0 nic \
      nictype=bridged parent=incusbr0 \
      ipv4.address=10.10.10.100

    UFW Firewall Rules

    Allow forwarded ports
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw reload
    7

    Storage Pools & Volumes

    Managing Storage Pools

    Storage pool operations
    # List pools
    incus storage list
    
    # Create a new ZFS pool (loopback)
    incus storage create pool2 zfs size=20GiB
    
    # Pool usage stats
    incus storage info default

    Custom Storage Volumes

    Custom volumes are persistent storage that can be attached to any container, similar to Docker volumes:

    Volume management
    # 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/data
    8

    Resource Limits & Profiles

    Setting Resource Limits

    Per-container 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-webserver

    Using Profiles

    Profiles define reusable configuration templates:

    Profile management
    # 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 list

    Recommended Profile Templates

    ProfileCPUMemoryDiskUse Case
    micro1128 MiB2 GiBDNS, cron jobs, monitoring agents
    small1256 MiB5 GiBWeb servers, reverse proxies
    medium2512 MiB10 GiBApp servers, databases
    large21 GiB20 GiBCI/CD runners, build environments
    9

    Snapshots & Backups

    Container snapshots
    # 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-upgrade

    Scheduled Automatic Snapshots

    Auto-snapshot configuration
    # 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-%d

    Full Container Export / Import

    Export and import containers
    # 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.

    10

    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 security settings
    # 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 true

    AppArmor and Seccomp

    Incus applies AppArmor profiles and seccomp filters by default:

    Verify security profiles
    incus info my-webserver | grep -A5 Security

    Network Isolation

    Network security
    # 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.

    11

    Monitoring & Maintenance

    Real-time monitoring
    # Quick status overview
    incus list -c nsCPUmM
    
    # Detailed instance info
    incus info my-webserver --resources
    
    # Host-level resource usage (all containers)
    incus info --resources

    Log Access

    Viewing logs
    # Container logs
    incus info my-webserver --show-log
    
    # Incus daemon logs
    sudo journalctl -u incus.service -f

    Image Management

    Manage cached images
    # 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 refresh

    Updating Incus

    Update via apt
    sudo apt update && sudo apt upgrade -y
    incus version
    12

    Common Use Cases on RamNode

    Multi-Site Web Hosting

    Run multiple isolated web servers on a single VPS:

    Multi-site setup
    # 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 and snapshot for testing
    # 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-test

    CI/CD Build Runners

    Ephemeral CI containers
    # 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

    IssueCauseSolution
    Permission denied on incus commandsUser not in incus-admin groupsudo usermod -aG incus-admin $USER && newgrp incus-admin
    Container has no internetBridge NAT not configuredCheck incus network show incusbr0 and verify ipv4.nat is true
    Cannot launch VMsMissing /dev/kvmVerify: ls -la /dev/kvm. On RamNode KVM VPS, this should be present
    Storage pool fullDisk space exhaustedClean snapshots, remove unused images, consider upgrading VPS storage
    Slow container startupFirst-time image downloadSubsequent launches from cache are near-instant
    DNS not resolving in containersystemd-resolved conflictincus exec <name> -- bash -c 'echo nameserver 1.1.1.1 > /etc/resolv.conf'

    Getting Help

    Debug commands
    # 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