ce-infra/docs/incus/research.md

236 lines
7.4 KiB
Markdown

# Incus Research Notes
Research conducted 2026-03-17. Incus development moves fast — verify against latest docs before implementing.
## Incus Version & Status
- **Latest**: Incus 6.22 (February 28, 2026)
- **LTS**: Incus 6.0 (5 years support)
- **Release cadence**: Monthly feature releases
- **Debian 13 (Trixie)**: Native packages available (`apt install incus`)
## OCI Container Support
- **Added in**: Incus 6.3 (July 2024) — 18+ months mature
- **How it works**: Pulls Docker/OCI images from registries, converts them, runs natively
- **Setup**: `incus remote add docker https://docker.io --protocol=oci`
- **Usage**: `incus launch docker:postgres:16-alpine my-postgres`
- **Dependencies**: `skopeo` and `umoci` (included in Debian packages)
- **Maturity**: Stable for production use, actively improved each release
## System Containers vs OCI Containers
| Aspect | System Containers | OCI Containers |
|---|---|---|
| Purpose | Full OS simulation | Single application |
| Init | systemd (runs until stopped) | Entrypoint process only |
| Image size | 150-500MB per container | Smaller, layered |
| RAM overhead | ~50-100MB more than OCI | Comparable to Docker |
| Use case | Legacy apps, multi-process, full sysadmin | Microservices, pre-built images |
## Networking
### Managed Bridges
- Incus creates bridges with dnsmasq for DHCP + DNS
- Containers get DNS entries for their instance name automatically
- Container-to-container by name works out of the box
- Default bridge: `incusbr0` (created during `incus admin init`)
### Port Forwarding — Proxy Devices
```bash
# Single port
incus config device add container http proxy \
listen=tcp:0.0.0.0:80 connect=tcp:127.0.0.1:80
# Port range
incus config device add container ports proxy \
listen=tcp:0.0.0.0:8080-9000 connect=tcp:127.0.0.1:8080-9000
# UDP (for HTTP/3)
incus config device add container h3 proxy \
listen=udp:0.0.0.0:443 connect=udp:127.0.0.1:443
```
### Network Forwards (alternative to proxy devices)
```bash
incus network forward create <network_name> <listen_address>
```
## Storage
### Pool Backends
| Backend | Pros | Cons |
|---|---|---|
| `dir` | Simple, no setup | Slower, no snapshots |
| `zfs` | Fast snapshots, dedup, compression | Complex setup |
| `btrfs` | CoW, snapshots | Less tooling than ZFS |
| `lvm` | Reliable, mature | Block-level only |
### Volume Operations
```bash
# Create volume
incus storage volume create <pool> <name>
# Attach to container
incus config device add <container> <device-name> disk \
pool=<pool> source=<volume-name> path=<mount-path>
# Mount host directory into container
incus config device add <container> <device-name> disk \
source=/host/path path=/container/path
```
## Ansible Integration
### Connection Plugin (community.general.incus)
- Exec commands inside containers without SSH
- Install: `ansible-galaxy collection install community.general`
- Usage: `ansible_connection: community.general.incus`
- Variables: `ansible_incus_remote`, `ansible_incus_project`, `ansible_host`
### Inventory Plugin (community.general.incus_inventory)
- Auto-discovers running Incus instances
- Dynamic inventory source
### Third-Party: kmpm.incus Collection
- Dedicated modules: `incus_instance`, `incus_network`, `incus_profile`
- Status: Beta/WIP, actively maintained
- Install: `ansible-galaxy collection install git+https://github.com/kmpm/ansible-collection-incus.git`
### Practical Approach for This Project
Use `ansible.builtin.command` with `incus` CLI directly. Simpler, more transparent, easier to debug than collections. Connection plugin useful for exec-inside-container tasks.
## Incus Initialization (Preseed)
Non-interactive setup via `incus admin init --preseed`:
```yaml
config: {}
networks:
- config:
ipv4.address: auto
ipv4.nat: "true"
ipv6.address: none
name: incusbr0
type: bridge
storage_pools:
- config:
source: /var/lib/incus/storage-pools/default
name: default
driver: dir
profiles:
- config: {}
devices:
eth0:
name: eth0
network: incusbr0
type: nic
root:
path: /
pool: default
type: disk
name: default
```
## Environment Variables in OCI Containers
Pass via `--config` flags at launch time:
```bash
incus launch docker:postgres:16-alpine gitea-db \
--config environment.POSTGRES_DB=gitea \
--config environment.POSTGRES_USER=gitea \
--config environment.POSTGRES_PASSWORD=secretpass
```
Update existing container:
```bash
incus config set gitea-db environment.POSTGRES_PASSWORD=newpass
incus restart gitea-db
```
## Backup & Restore
### Snapshots (fast, local only)
```bash
incus snapshot create <instance> <snapshot-name>
incus snapshot restore <instance> <snapshot-name>
incus snapshot list <instance>
```
### Exports (portable, for off-site backup)
```bash
incus export <instance> backup.tar.gz --optimized-storage
incus import backup.tar.gz <new-instance-name>
```
### Volume Exports
```bash
incus storage volume snapshot <pool> <volume> <snapshot-name>
incus storage volume export <pool> <volume> volume-backup.tar.gz
incus storage volume import <pool> volume-backup.tar.gz <new-volume-name>
```
### Database Dumps (same pattern as Docker)
```bash
incus exec gitea-db -- pg_dump -U gitea gitea > gitea-db.sql
incus exec outline-db -- pg_dump -U outline outline > outline-db.sql
```
### 6.22 Enhancements
- Direct backup streaming (no temporary disk files)
- Disk-only snapshot restore (revert storage without config)
## Auto-Start / Restart Policy
```bash
# Start container on host boot
incus config set <container> boot.autostart true
# Set start order (lower = earlier)
incus config set <container> boot.autostart.priority 10
# Start delay (seconds, for dependency ordering)
incus config set <container> boot.autostart.delay 5
```
No automatic restart on crash (unlike Docker's `restart: unless-stopped`). Options:
- Accept manual restart for crashes (rare)
- Add a systemd watchdog timer on the host
- Use `incus monitor` to watch for state changes
## Running Docker Inside Incus (for Gitea Runner)
If needed for the runner:
```bash
incus launch images:debian/13/cloud gitea-runner-host
incus config set gitea-runner-host security.nesting true
incus exec gitea-runner-host -- apt install docker.io
# Then run act_runner inside this system container
```
## Cloud-init Support
System containers with `/cloud` images support cloud-init:
```bash
incus launch images:debian/13/cloud my-container \
--config cloud-init.user-data="#cloud-config
packages:
- curl
- git
"
```
Note: Cloud-init runs only on first boot. Not applicable to OCI containers.
## Sources
- [Incus Documentation](https://linuxcontainers.org/incus/docs/main/)
- [Incus 6.22 Release](https://linuxcontainers.org/incus/news/)
- [Incus OCI Support (FOSDEM 2025)](https://archive.fosdem.org/2025/schedule/event/fosdem-2025-5742-bringing-application-containers-to-incus/)
- [Incus Ansible Connection Plugin](https://docs.ansible.com/projects/ansible/latest/collections/community/general/incus_connection.html)
- [kmpm/ansible-collection-incus](https://github.com/kmpm/ansible-collection-incus)
- [lxc/incus-deploy](https://github.com/lxc/incus-deploy)
- [Incus Backup Strategy (Forum)](https://discuss.linuxcontainers.org/t/incus-backup-strategy-incus-export-or-zfs-snapshot/25188)
- [Running OCI Images in Incus (blog.simos.info)](https://blog.simos.info/running-oci-images-i-e-docker-directly-in-incus/)
- [Incus Debian Wiki](https://wiki.debian.org/Incus)