The fleet file¶
fleet.yaml describes every machine kiwi-server should build. It has two keys:
defaults, which applies to every host, and hosts, with one entry per
machine. Anything a host sets overrides the defaults. kiwi-server init writes
a commented starting point. The full reference is
examples/fleet.yaml
in the repository.
A host has a target (what gets installed) and a role (what it becomes):
Defaults¶
defaults:
target: ucore
role: bare
domain: home # host "sh3" becomes sh3.home; names are service.sh3.home
timezone: Europe/Berlin
locale: en_US.UTF-8
keyboard: de
disk: /dev/sda # WIPED by the ISO without asking. nvme: /dev/nvme0n1
admin:
user: core # passwordless sudo on every target
password: change-me # hashed at render time; or password_hash: $6$...
ssh_keys: [~/.ssh/id_ed25519.pub] # a key, or a file containing keys
groups: [docker]
ssh_password_auth: false # keys only; the password is for the console
network:
dhcp: true # or dhcp: false with address/gateway/dns per host,
# iprange: 192.168.1.20-192.168.1.99 # or an iprange handing out addresses in file order
updates: # updates install continuously; this is when a REBOOT may happen
enabled: true
days: [Sun] # [] = any day
time: "03:30" # local time
length_minutes: 90
tls:
auto: true # one fleet CA, a *.<hostname> certificate per host
ca_dir: secrets/ca
name_constraints: [home] # the CA may only sign names under the fleet's domain (default: [])
ucore:
image: ghcr.io/ublue-os/ucore:stable # ucore-minimal / ucore / ucore-hci (+ -nvidia, -zfs)
debian:
release: trixie
partitioning: lvm # regular | lvm | crypto (with encrypt: true + passphrase:)
packages: [vim, htop]
Hosts¶
hosts:
gate: # the kiwi-master, on Debian
role: master
target: debian
disk: /dev/vda
master:
vpn-client:
vpn_provider: mullvad
wireguard_private_key: "<from your Mullvad WireGuard config>"
wireguard_addresses: 10.66.1.2/32
server_countries: Germany
vpn-server:
wg_host: vpn.example.org # what clients and nodes connect to
wg_password: change-me-too # wg-easy admin
dns:
pihole_password: change-me-three
m1: # a gateway node, on uCore (the default)
role: node-gw
node-gw:
pub_iface: eth0 # the LAN side
vpn-client:
wireguard_config: secrets/m1.home.conf # the client config wg-easy issued
dns: { pihole_password: … }
downloader: { download_dir: /mnt/data/downloads, transmission_password: … }
sftp: { sftp_password: … }
portainer: { admin_password: … }
sh3: # a cloud node on uCore HCI
role: node-cloud
ucore: { image: ghcr.io/ublue-os/ucore-hci:stable }
node-cloud:
vpn_ip: 10.8.0.25
vpn-client: { wireguard_config: secrets/sh3.home.conf }
cloud: { nextcloud_datadir: /mnt/nvme_2tb/docker/knnc-data, memory_limit: 8192M }
vault: { signups_allowed: true } # for the first account; turn it off afterwards
lab1: # just the base system
target: coreos
role: bare
How settings combine¶
- Hosts override defaults key by key. The lists
admin.ssh_keys,debian.packagesand thecoreos.*lists add to the defaults instead of replacing them. - A module role's block (
master:,node-gw:,node-cloud:) holds the stack settings at the top (vpn_ip,pub_iface,docker_dir,service_user,docker_subnet,master_ip, the VPN restart and update times) and then one block per module. modules:inside the role block replaces the preset's module list. A cloud node that also downloads ismodules: [vpn-client, reverse-proxy, cloud, vault, downloader]plus the downloader's settings.- File settings (WireGuard configs, certificates) are paths relative to the fleet file. Their content is embedded into the host's role script.
key:with no value means the default.
Values kiwi-server works out for you¶
- A node's
vpn_ipis read from its WireGuard config'sAddresswhen it is not set. When both are given and differ,validatewarns. master_ip(the master's mesh address, the nodes' DNS upstream) comes from the fleet's master host.- Static addresses without typing them:
network: { dhcp: false, gateway: …, iprange: 192.168.1.20-192.168.1.99 }in the defaults hands each static host the next free address in file order. A host's ownaddress:is reserved first. - The data directories belong to
service_user, which is the admin user unless set (uid 1000 on a fresh install, matching the containers'PUIDdefaults). The rendered files stay root's.
Checking what you wrote¶
kiwi-server validate fleet.yaml # errors and warnings
kiwi-server show fleet.yaml sh3 # the effective config of one host, secrets masked
kiwi-server roles -v # every role and stack setting with its default
kiwi-server modules -v # every module setting with its default
Migrating a v1 machine in place¶
A machine that ran one of the old v1 stacks (kiwi-master, kiwi-node-gw, kiwi-cloud) can be taken over without losing data. Before the first start:
- Set
docker_subnetto what the old stack used (e.g.172.129.0.0/24), so the containers keep their addresses and wg-easy keeps its peers. - Rename the data directories to the module names:
kmvpn-server→km-vpn-server,knvault→kn-vault,kntransmission→kn-transmission, and so on.
SSH to a node over the mesh is one DNAT rule:
vpn-client: { extra_dnat_rules: ["2222/tcp:172.128.0.1:22"] } (the docker
gateway is the host).