Configuration
Realm is configured through a YAML file. By default, Realm looks for a config.yaml file in the same directory as the executable. You can specify a custom path using the --config flag or the REALM_CONFIG_FILE environment variable.
File Structure
Section titled “File Structure”A Realm configuration file has four top-level sections:
agent: # Agent settingsnodes: # Remote nodes to manageloads: # Workloads to deploydiscovery: # Discovery settingsRoot config
Section titled “Root config”| Field | Type | Default | Description |
|---|---|---|---|
data_path |
string | /var/lib/realm |
Path to store client or agent data (ID file, database) |
data_path: ./dataNodes represent the machines where loads are deployed. Each node has a name (the map key), a URL pointing to its agent API, and a driver.
nodes: lab1: url: http://192.168.1.59:9000 driver: linux
lab2: url: http://192.168.1.51:9000 driver: linuxurl field can be also configured with a mDNS address:
nodes: lab1: url: http://lab1.local:9000...| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | URL of the node’s agent API |
driver |
string | Yes | Node driver type. Currently supported: linux |
driver_config |
object | No | Driver-specific configuration |
cloud_init |
object | No | Cloud init configuration |
registries |
list | No | Container registries used by the node |
Cloud init
Realm serves cloud-init configurations for any node with a cloud_init configuration. Currently Realm supports meta-dataand user-data structures.
An usage example using the VM node driver:
nodes: vm: url: http://localhost:9000 cloud_init: meta_data: instance-id: test01 local-hostname: testvm user_data: hostname: lab1 fqdn: lab1.local preserve_hostname: false apt: sources: bookworm-backports: source: "deb http://deb.debian.org/debian bookworm-backports main contrib non-free-firmware" runcmd: - apt-get update driver: vm driver_config: machine: q35 accel: hvf memory: 2048 smp: "2" serial: telnet:localhost:4444,server,nowait netdev: - type: user id: net0 drives: - file: /home/user/debian-12-generic-amd64.qcow2 format: qcow2 if: virtioContainer Registries
Section titled “Container Registries”Container registries can be configured per node:
nodes: lab1: url: http://192.168.1.59:9000 driver: linux registries: - host: ghcr.io auth: token: ghp_xxxxxxxxxxxx - host: registry.example.com:5000 insecure: true auth: username: admin password: secret - host: nexus.example.com ca_file: /etc/realm/certs/nexus-ca.pem auth: username: admin password: secretinsecure downgrades the connection to plain HTTP. For a registry that speaks
HTTPS but presents a certificate Go refuses (for example one that relies on the
legacy Common Name field instead of SANs), point ca_file at its CA bundle, or
set skip_tls_verify: true to bypass verification altogether.
| Field | Type | Description |
|---|---|---|
host |
string | Registry host (e.g., ghcr.io, docker.io) |
insecure |
bool | Allow HTTP instead of HTTPS |
skip_tls_verify |
bool | Do not verify the registry’s TLS certificate |
ca_file |
string | PEM bundle with extra CAs trusted for this registry |
auth.username |
string | Username (use with password) |
auth.password |
string | Password (use with username) |
auth.token |
string | Authentication token (alternative to username/password) |
Linux Node Driver
Section titled “Linux Node Driver”The linux driver runs on a host where Realm is installed as a agent. It supports optional Wake-On-LAN to power the host on remotely:
nodes: server: url: http://192.168.1.59:9000 driver: linux driver_config: wol: true MAC: "00:11:22:33:44:55"| Field | Type | Description |
|---|---|---|
wol |
bool | Enable Wake-On-LAN |
MAC |
string | MAC address (required when wol is true) |
Windows Node Driver
Section titled “Windows Node Driver”nodes: workstation: url: http://192.168.1.20:9000 driver: windows driver_config: wol: true MAC: "00:11:22:33:44:55"| Field | Type | Description |
|---|---|---|
wol |
bool | Enable Wake-On-LAN |
MAC |
string | MAC address (required when wol is true) |
VM Node Driver
Section titled “VM Node Driver”Experimental — Work in Progress
The VM driver is experimental and under active development. Its configuration schema, behavior, and defaults may change without notice, and it is not yet recommended for production use. Expect rough edges and please report issues you encounter.
The vm driver provisions guest nodes through a local libvirtd agent.
User running Realm must be allowed to run libvirt, set in /etc/libvirt/qemu.conf:
user = "<realm-user>"group = "<realm-user>"Now, restart libvirtd with sudo systemctl restart libvirtd so the overlay images under <data_path>/overlays/ are readable by the QEMU process.
nodes: vm: url: http://localhost:9000 driver: vm driver_config: machine: q35 accel: kvm cpu: host memory: 2048 smp: "2" serial: telnet:localhost:4444,server,nowait drives: - file: https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2 format: qcow2 if: virtio netdev: - type: user id: net0VMConfig Fields
Section titled “VMConfig Fields”The fields below describe a VM in driver-neutral terms; the driver translates them into a libvirt domain XML document. The emulator path is recorded as the <emulator> element, so libvirt invokes the binary you specify.
| Field | Type | Required | Description |
|---|---|---|---|
machine |
string | No | Machine type (e.g. q35, pc). Mapped to <os><type machine=...>. |
accel |
string or list | No | Accelerator selection. The first recognised entry (kvm, hvf, xen) chooses the libvirt domain type; otherwise qemu (TCG). |
cpu |
string | No | CPU model (e.g. host). Mapped to <cpu mode='custom'><model>...</model></cpu>. |
memory |
int | No | Memory in MiB. Mapped to <memory unit='MiB'>. |
smp |
string | No | vCPU count. Either an integer ("2") or a cpus=N,... form; the leading integer is used. |
serial |
string | No | Serial backend. stdio / pty produce a pty device; file:/path redirects to a file; none disables it. |
drives |
list | No | Drive definitions, see below. |
netdevs |
list | No | Netdev definitions, see below. |
Drive Fields
Section titled “Drive Fields”| Field | Type | Description |
|---|---|---|
file |
string | Path to the disk image. If it begins with http:// or https:// the image is downloaded and cached under <data_path>/images/ (keyed by URL hash). |
format |
string | Image format (e.g. qcow2, raw). |
if |
string | Drive interface (e.g. virtio, ide). |
media |
string | Media type (e.g. disk, cdrom). |
index |
string | Drive index. |
For each drive Realm copies the source image into a per-node overlay under <data_path>/overlays/<node>/<uuid> and points the libvirt <disk> at the copy, so the original image is never written to. Overlays are removed on deprovision.
Netdev Fields
Section titled “Netdev Fields”| Field | Type | Description |
|---|---|---|
type |
string | Netdev type (e.g. user, tap, bridge). |
id |
string | Netdev id (referenced by -device ...,netdev=<id>). |
ifname |
string | TAP interface name. |
script |
string | TAP up script. |
downscript |
string | TAP down script. |
br |
string | Bridge name (used by bridge type and for cloud-init host IP resolution). |
helper |
string | Bridge helper binary. |
net |
string | User-mode network range. |
dhcpstart |
string | First DHCP address for user-mode networking. |
hostfwd |
string | User-mode host port forwarding rule (e.g. tcp::2222-:22). |
Cloud-init
Section titled “Cloud-init”When the node has a cloud_init block, the guest’s cloud-init datasource fetches metadata from the Realm agent. The <host> is resolved as follows:
- If any non-
usernetdev is configured and itsbrinterface has an IPv4 address, that address is used. - Otherwise, the agent’s auto-detected IP is used.
- Otherwise, the configured
agent.listen_address(if not0.0.0.0) is used. - Fallback:
10.0.2.2(the QEMU user-mode gateway), which only works when the guest uses user-mode networking.
Per-VM logs are managed by libvirtd (typically under /var/log/libvirt/qemu/<node>.log). Inspect domain state with virsh list --all and virsh dominfo <node>.
Loads are the workloads deployed to nodes. Each load has a name (the map key), a target node, a driver (container or process), and driver-specific configuration.
loads: web: node: lab1 driver: container driver_config: image: docker.io/library/nginx:latest
my_service: node: lab2 driver: process driver_config: start_cmd: node start_args: "server.js" stop_signal: SIGTERM| Field | Type | Required | Description |
|---|---|---|---|
node |
string | Yes | Target node name or expression |
driver |
string | Yes | Load driver: container or process |
driver_config |
object | Yes | Driver-specific configuration |
depends_on |
list | No | List of load names this load depends on |
For detailed driver configuration, see Container Driver and Process Driver.
Dependencies
Section titled “Dependencies”Loads can declare dependencies on other loads using depends_on. Realm builds a dependency graph and ensures loads start and stop in the correct order. Circular dependencies are detected and rejected.
loads: database: node: lab1 driver: container driver_config: image: docker.io/library/postgres:15
api: node: lab1 driver: container driver_config: image: docker.io/library/myapi:latest depends_on: - databaseIn this example, database will always start before api, and api will stop before database.
Dynamic Node Selection
Section titled “Dynamic Node Selection”The node field supports expressions using expr-lang for dynamic node selection. The expression context provides:
nodes- array of all configured nodesselectAny(slice)- randomly select one item from a slice
nodes: vps-1: url: http://vps1:9000 driver: linux vps-2: url: http://vps2:9000 driver: linux
loads: web: node: selectAny(filter(nodes, .Name startsWith "vps-")) driver: container driver_config: image: docker.io/library/nginx:latestThe agent section configures the Realm agent. All fields are optional and have sensible defaults.
agent: listen_address: 0.0.0.0 listen_port: 9000 log_format: text log_level: infoGeneral
Section titled “General”| Field | Type | Default | Description |
|---|---|---|---|
listen_address |
string | 0.0.0.0 |
Address to bind the agent API |
listen_port |
int | 9000 |
Port to bind the agent API |
listen_socket |
string | Empty | Additional unix socket to expose the agent API on. Disabled when empty |
log_format |
string | text |
Log output format: text or json |
log_level |
string | info |
Minimum log level: debug, info, warn or error. The LOG_LEVEL environment variable overrides it |
Unix Socket
Section titled “Unix Socket”Besides the TCP listener, the agent API can optionally be exposed on a unix socket:
agent: listen_address: 0.0.0.0 listen_port: 9000 listen_socket: /run/realm/agent.sockContainer Runtime
Section titled “Container Runtime”| Field | Type | Default | Description |
|---|---|---|---|
containerd_sock |
string | /run/containerd/containerd.sock |
Containerd socket path |
containerd_namespace |
string | realm |
Containerd namespace |
cni_path |
string | /usr/lib/cni |
Path to CNI plugins |
volumes_pool |
string | realm_volumes |
ZFS pool name for container volumes |
zfs |
bool | false |
Enable ZFS for volume management |
Reverse Proxy (Experimental)
Section titled “Reverse Proxy (Experimental)”| Field | Type | Default | Description |
|---|---|---|---|
proxy_enabled |
bool | false |
Enable the reverse proxy |
local_caddy_url |
string | localhost:2019 |
Local Caddy proxy URL |
master_caddy_url |
string | localhost:2019 |
Master Caddy proxy URL |
Artifacts repository (Experimental)
Section titled “Artifacts repository (Experimental)”Realm agents can expose artifacts when configured.
| Field | Type | Default | Description |
|---|---|---|---|
artifacts |
ArtifactsRepository | Empty | Artifacts repository config |
artifacts field expects the following attributes:
| Field | Type | Default | Description |
|---|---|---|---|
auth_required |
bool | false | Endpoints available only for authed requests |
raw_path |
string | nil | Point to a local directory with raw artifacts (nesting not allowed) |
Database
Section titled “Database”Realm stores agent state in an embedded bbolt database at <data_path>/realm.db. No configuration is required.
Discovery
Section titled “Discovery”discovery: mdns: true| Field | Type | Default | Description |
|---|---|---|---|
mdns |
bool | false |
Enable mDNS discovery |
Environment Variables
Section titled “Environment Variables”All agent configuration fields can be set via environment variables using the REALM_ prefix. Nested fields use underscores as separators:
REALM_AGENT_LISTEN_ADDRESS=0.0.0.0REALM_AGENT_LISTEN_PORT=9000REALM_DATA_PATH=/opt/realmREALM_AGENT_ETCD_MODE=clientEnvironment variables take priority over config file values but are overridden by command-line flags.
Complete Example
Section titled “Complete Example”data_path: /opt/realm_dataagent: listen_address: 0.0.0.0 zfs: false
nodes: lab1: url: http://192.168.1.59:9000 driver: linux registries: - host: ghcr.io auth: token: ghp_xxxxxxxxxxxx lab2: url: http://192.168.1.51:9000 driver: linux
loads: database: node: lab1 driver: container driver_config: image: docker.io/library/postgres:15 env: - POSTGRES_PASSWORD=secret network: network: backend dns: true ip_masq: true mount_volume: - volume_mount_point: /var/lib/postgresql/data
api: node: lab1 driver: container driver_config: image: ghcr.io/myorg/api:latest env: - DB_HOST=database.realm network: network: backend dns: true ip_masq: true port_map: - host_port: 8080 container_port: 3000 protocol: tcp depends_on: - database
monitoring: node: lab2 driver: process driver_config: start_cmd: prometheus start_args: "--config.file=/etc/prometheus/prometheus.yml" working_dir: /opt/prometheus stop_signal: SIGTERM
discovery: mdns: true