Notes from trying out incus

Context

Looking into LXC containers. Considering a move from my monolithic debian server.

HOST MACHINE

Alpine linux

I wanted low footprint and satisfy my own curiosity.

Vlans

Essence of the setup :

# /etc/network/interfaces

## host access on that vlan
auto eth0.98
iface eth0.98 inet dhcp

## vlan 77 for containers, layer 2 only
auto eth0.77
iface eth0.77 inet manual

auto br77
iface br77 inet manual
  bridge_ports eth0.77
  bridge_stp off ## no spanning tree, assume no loop
  bridge_fd 0 ## immediate forwarding, no delay for stp

Incus initial setup

# incus admin init
  • single node setup
  • locale storage pool
  • default nat bridge created (incusbr0) BUT not to be used
  • incus api not exposed over LAN

Container setup

Example mount:

incus config device add dev repos disk \
    source=/srv/dev/repos \
    path=/home/user/repos

dev box

Some commands that I ran, some might have been useful, some not

ip addr show eth0
ip link set eth0 up
udhcpc -i eth0
ping 192.168.1.2
cat /etc/network/interfaces

apk add doas
addgroup -g 1000 dev
adduser -u 1000 -G dev -D dev

echo "permit persist :dev as root" > /etc/doas.d/doas.conf

apk add openssh
rc-update add sshd default
service sshd start

Homeassistant

A bit more “infra as code”:

  • ad hoc incus profile
  • cloud-init for initial provisioning
cat << 'EOF' > ha-profile.yaml
config:
  cloud-init.user-data: |
    #cloud-config
    ssh_genkeytypes: []
    ssh_pwauth: false
    package_update: true
    packages:
      - python3
      - py3-pip
      - python3-dev
      - build-base
      - git
      - curl
      - jq
      - ffmpeg
      - openssl
      - ca-certificates
      - tzdata
      - libffi-dev

    users:
      - name: homeassistant
        groups: [audio, dialout, video]
        shell: /bin/sh
        home: /home/homeassistant
        system: true
        setup_home: true

    write_files:
      - path: /tmp/hass-install.sh
        permissions: '0755'
        owner: root:root
        content: |
          #!/bin/sh
          set -e
          # Ensure home dir exists just in case
          mkdir -p /home/homeassistant
          chown homeassistant:homeassistant /home/homeassistant
          cd /home/homeassistant
          
          # Setup VENV
          python3 -m venv .
          ./bin/pip install --upgrade pip wheel
          ./bin/pip install homeassistant aiohasupervisor
          mkdir -p .homeassistant
          chown -R homeassistant:homeassistant /home/homeassistant

      - path: /etc/init.d/homeassistant
        permissions: '0755'
        owner: root:root
        content: |
          #!/sbin/openrc-run
          name="homeassistant"
          description="Home Assistant"
          supervisor=supervise-daemon
          command="/home/homeassistant/bin/hass"
          command_args="-c /home/homeassistant/.homeassistant --log-file /var/log/homeassistant.log"
          command_user="homeassistant:homeassistant"
          directory="/home/homeassistant"
          
          depend() {
              need net
              after firewall
          }
          
          start_pre() {
              checkpath -d -m 0755 -o homeassistant:homeassistant /home/homeassistant/.homeassistant
              checkpath -f -m 0644 -o homeassistant:homeassistant /var/log/homeassistant.log
          }

    runcmd:
      - ln -sf /usr/share/zoneinfo/Europe/Helsinki /etc/localtime
      # Wait a beat for user creation to settle, then run from /tmp
      - /tmp/hass-install.sh
      - rc-update add homeassistant default
      - rc-service homeassistant start

  limits.cpu: "2"
  limits.memory: 2GB
  security.nesting: "true"

description: Home Assistant Core on Alpine Edge
devices:
  root:
    path: /
    pool: default
    type: disk
    size: 20GB
  eth0:
    name: eth0
    nictype: bridged
    parent: br101
    type: nic
EOF

# Then recreate
incus stop homeassistant --force 2>/dev/null || true
incus delete homeassistant
incus profile edit homeassistant < ha-profile.yaml
incus launch images:alpine/edge/cloud homeassistant --profile homeassistant

Note that specific image is used to have cloud-init already installed. See linuxcontainers.org doc .

Warning : this profile was generated by llm, better double check.