Skip to content

Unattended cluster install

An unattended single-node install takes both stages from files on a STRATUM-labelled medium or a web server. A cluster uses the same files. Only these differ. As there, the one manual step is removing the install medium and pressing enter when stage 1 says Installed.

install.yaml names the kind. The rest is as for a single node.

kind: new-cluster
disks:
- /dev/disk/by-id/nvme-EXAMPLE_SSD_1TB_SN0001
nic:
name: enp1s0
mode: static
address: 192.0.2.11/24
gateway: 192.0.2.1
hostname: node-1.example.com
root:
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... admin@workstation
wipe_other_disks: true # wipe every other disk that holds data

wipe_other_disks: true wipes every other disk of the machine that holds data and is not the install medium, mounted, removable or a multipath path. The key is the confirmation. Without it only the OS disks are wiped. Check what it would take with stratum-installer stage1 plan --config install.yaml.

node.yaml beside it founds the cluster. Its mode is ha-init, and it must match the install.yaml kind: a node.yaml for another mode is refused (kind: new-cluster goes with mode: ha-init). A complete file for a machine with one NIC, whose storage and overlay networks ride the management network:

mode: ha-init
identity:
role: hybrid
self_ip: 192.0.2.11
vip_interface: enp1s0
provider:
topology: routed-host
upstream_interface: enp1s0
network:
default_vpc_cidr: 172.31.0.0/16
floating_ip_cidrs: [198.51.100.0/24]
cluster:
ha_enabled: true
region: local-1
name: lab
planned_size: 3
networks:
mgmt: {cidr: 192.0.2.0/24}
vips:
api: 192.0.2.240
postgres: 192.0.2.241
openbao: 192.0.2.242
ovn_nb: 192.0.2.243
ovn_sb: 192.0.2.244
vmselect: 192.0.2.245
provider_gw: 192.0.2.246
iam:
admin_email: admin@example.com
dns:
parent_domain: cloud.example.com
storage:
ceph_osd_disks:
- /dev/disk/by-id/nvme-EXAMPLE_B

routed-host needs the extra service address provider_gw: your router routes the floating IP range through it. identity.node_id is optional: add n- and 8 lowercase letters or digits to keep a node id across rebuilds, or leave it out and one is made. cluster.region is fixed once installed.

With two NICs, a bond of both carries the provider trunk and the storage and overlay VLANs. Its provider, network and cluster.networks differ, and it needs no provider_gw. The complete file:

mode: ha-init
identity:
role: hybrid
self_ip: 192.0.2.11
vip_interface: enp1s0
provider:
topology: bridged
vlan: 2000
upstream_interface: bond0
network:
default_vpc_cidr: 172.31.0.0/16
floating_ip_cidrs: [198.51.100.0/24]
connections:
- {name: bond0, kind: bond, interface: bond0, mtu: 9000, addresses: [], zone: trusted,
bond: {mode: active-backup, miimon_ms: 100}, purposes: [provider]}
- {name: bond0-enp2s0f0, interface: enp2s0f0, controller: bond0, mtu: 9000, addresses: [], zone: trusted}
- {name: bond0-enp2s0f1, interface: enp2s0f1, controller: bond0, mtu: 9000, addresses: [], zone: trusted}
- {name: vlan90, kind: vlan, interface: vlan90, parent: bond0, vlan_id: 90, mtu: 9000,
addresses: [192.168.90.1/24], zone: trusted, never_default: true, purposes: [storage]}
- {name: vlan91, kind: vlan, interface: vlan91, parent: bond0, vlan_id: 91, mtu: 9000,
addresses: [192.168.91.1/24], zone: trusted, never_default: true, purposes: [overlay]}
cluster:
ha_enabled: true
region: local-1
name: lab
planned_size: 3
networks:
mgmt: {cidr: 192.0.2.0/24}
storage: {cidr: 192.168.90.0/24, vlan: 90, mtu: 9000}
overlay: {cidr: 192.168.91.0/24, vlan: 91, mtu: 9000}
vips:
api: 192.0.2.240
postgres: 192.0.2.241
openbao: 192.0.2.242
ovn_nb: 192.0.2.243
ovn_sb: 192.0.2.244
vmselect: 192.0.2.245
iam:
admin_email: admin@example.com
dns:
parent_domain: cloud.example.com
storage:
ceph_osd_disks:
- /dev/disk/by-id/nvme-EXAMPLE_B

Both files were checked with the installer’s own validation against a machine with these NICs and disks; yours must name your NICs (stratum-installer hardware), your addresses, and your disks by their /dev/disk/by-id paths. A few more keys are optional (time.ntp_servers, dns.upstream_servers, services.disabled, dev_mode, upgrades): see CLI and node.yaml.

Writing that file by hand is error-prone. Fill the first node’s answers once in the web installer or with the structured config, then take the file the install would write:

Terminal window
stratum-installer config get --yaml > node-1.yaml

This needs the install code and the installer’s address, as for every stratum-installer command (Stage 2), and it works only during the install and for 5 minutes after it. Later, download it with stratumctl admin nodes config <node-id>: its secrets read <redacted>, and the loader refuses the placeholder until you replace each value or delete the key. See Rebuild the cluster from files.

The structured config’s mode is hyperconverged-init; see CLI and node.yaml for the commands.

A joiner needs only install.yaml: it has no node.yaml. Its kind is join-cluster, with the address and code from the join code:

kind: join-cluster
join:
endpoint: 192.0.2.240 # host or host:port; 9444 by default
code: 4F7K-2Q9M-ABD # or the stratum-join:// URL, without endpoint
# skip_check: true # the first node is not up yet; the join agent checks after the reboot
disks:
- /dev/disk/by-id/nvme-EXAMPLE_SSD_1TB_SN0002
nic:
name: enp1s0
mode: static
address: 192.0.2.12/24
gateway: 192.0.2.1
hostname: node-2.example.com
root:
ssh_authorized_keys:
- ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAA... admin@workstation
wipe_other_disks: true

The installer checks the code before wiping anything, over the management NIC. install.yaml can serve many machines with disk_select, nic.match and a {mac6} host name, but a static address is per machine. A code is reusable until it expires (at most 7 days).

The machine still registers and waits. Approve it as usual. With the cluster up, a script can create the code, wait for the machine and approve it with --serial and a file.

To keep every node’s files for a later rebuild, stratum-installer stage1 export prints an install.yaml from a node’s install record. See Rebuild the cluster from files.