Quick Start¶
Prerequisites¶
- TrueNAS SCALE 25.04+ — the JSON-RPC 2.0 API is required
- Omni instance with an infrastructure provider service account
- ZFS pool with available space
- Network interface for VM traffic — a bridge (e.g.,
br0), VLAN, or physical NIC
Create the Omni Service Account¶
omnictl serviceaccount create --role=InfraProvider infra-provider:truenas
# Save the output — it contains OMNI_SERVICE_ACCOUNT_KEY
Deployment Options¶
Run the container directly on your TrueNAS host via Apps > Discover > Install via YAML. Create an API key first — see TrueNAS Setup > API Key for the recommended dedicated non-root user + scoped roles. Do not use the root user's key.
services:
omni-infra-provider-truenas:
image: ghcr.io/bearbinary/omni-infra-provider-truenas:latest
restart: unless-stopped
network_mode: host
environment:
OMNI_ENDPOINT: "https://omni.example.com"
OMNI_SERVICE_ACCOUNT_KEY: "<your-key>"
TRUENAS_HOST: "localhost"
TRUENAS_API_KEY: "<truenas-api-key>"
TRUENAS_INSECURE_SKIP_VERIFY: "true"
DEFAULT_POOL: "default"
DEFAULT_NETWORK_INTERFACE: "br0"
helm install omni-infra-provider deploy/helm/omni-infra-provider-truenas \
--namespace omni-infra-provider --create-namespace \
--set omniEndpoint="https://omni.example.com" \
--set truenasHost="truenas.local" \
--set secrets.omniServiceAccountKey="<your-key>" \
--set secrets.truenasApiKey="<your-api-key>" \
--set defaults.pool="default"
See deploy/helm/omni-infra-provider-truenas/values.yaml for all options.
Configuration Reference¶
Required¶
| Variable | Description |
|---|---|
OMNI_ENDPOINT |
Omni instance URL (e.g., https://omni.example.com) |
OMNI_SERVICE_ACCOUNT_KEY |
Omni infra provider service account key |
TrueNAS Connection¶
| Variable | Default | Description |
|---|---|---|
TRUENAS_HOST |
— | Required. TrueNAS hostname or IP (use localhost when running the container on the TrueNAS host itself) |
TRUENAS_API_KEY |
— | Required. TrueNAS API key from a dedicated non-root user with scoped roles (setup). |
TRUENAS_INSECURE_SKIP_VERIFY |
false |
Skip TLS verification for self-signed certs (recommended true for localhost) |
Note
TrueNAS 25.10 removed implicit Unix socket authentication, so an API key is required in all deployments.
Provider Defaults¶
| Variable | Default | Description |
|---|---|---|
DEFAULT_POOL |
default |
ZFS pool for VM zvols and ISO cache |
DEFAULT_NETWORK_INTERFACE |
— | Network interface for VM NICs |
DEFAULT_BOOT_METHOD |
UEFI |
VM boot method (UEFI or BIOS) |
CONCURRENCY |
4 |
Max parallel provision/deprovision workers |
LOG_LEVEL |
info |
Log level: debug, info, warn, error |
Operational¶
| Variable | Default | Description |
|---|---|---|
GRACEFUL_SHUTDOWN_TIMEOUT |
30 |
Seconds to wait for ACPI shutdown before force-stop |
MAX_ERROR_RECOVERIES |
5 |
Max consecutive ERROR recoveries before auto-replacing a VM (set to -1 to disable) |
HEALTH_LISTEN_ADDR |
:8081 |
Address for /healthz and /readyz HTTP endpoints |
MachineClass Config¶
These fields go in the MachineClass configpatch:
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
cpus |
int | Yes | 2 |
Virtual CPUs (min: 1). For control planes, see Sizing Guide. |
memory |
int | Yes | 4096 |
Memory in MiB (min: 1024). For control planes, see Sizing Guide. |
disk_size |
int | Yes | 40 |
Root disk in GiB (min: 10). For control planes, see Sizing Guide. |
pool |
string | Yes | DEFAULT_POOL |
ZFS pool for zvols and ISOs |
network_interface |
string | Yes | DEFAULT_NETWORK_INTERFACE |
Bridge, VLAN, or physical interface |
boot_method |
string | Yes | UEFI |
UEFI or BIOS |
architecture |
string | Yes | amd64 |
amd64 or arm64 |
encrypted |
bool | No | false |
Enable ZFS encryption (AES-256-GCM) on the root disk |
dataset_prefix |
string | No | — | Nested dataset path (e.g., prod/k8s → pool/prod/k8s/omni-vms/) |
extensions |
list | No | — | Additional Talos extensions (e.g., siderolabs/iscsi-tools) |
advertised_subnets |
string | No | — | Pin etcd/kubelet to specific CIDRs for multi-NIC setups |
additional_disks |
list | No | — | Extra data disks — see below |
additional_nics |
list | No | — | Extra NICs for network segmentation — see below |
additional_disks items¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
size |
int | Yes | — | Disk size in GiB |
pool |
string | No | primary pool | ZFS pool override for this disk |
dataset_prefix |
string | No | MachineClass prefix | Per-disk dataset prefix override |
encrypted |
bool | No | false |
Per-disk encryption toggle |
name |
string | No | data-N (1-indexed) |
Talos UserVolumeConfig name — the disk is formatted and mounted at /var/mnt/<name> inside the guest. Set to longhorn to match Longhorn's defaultDataPath. storage_disk_size auto-sets this to longhorn. |
filesystem |
string | No | xfs |
Filesystem for the emitted UserVolumeConfig — xfs (default) or ext4. |
Each additional disk is attached to the VM and made usable inside the guest:
the provider emits a Talos UserVolumeConfig per disk (selector keyed by exact
zvol byte-size) so Talos formats it and mounts it at /var/mnt/<name>. Without
this, the disk shows up as a raw unformatted block device and Kubernetes
storage drivers can't see it.
additional_nics items¶
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
network_interface |
string | Yes | — | Bridge, VLAN, or physical interface |
type |
string | No | VIRTIO |
VIRTIO or E1000 |
mtu |
int | No | host default | MTU size (set to 9000 for jumbo frames) |
All NICs (primary and additional) get a deterministic MAC derived from the machine request ID, so DHCP reservations survive reprovisioning.