Skip to content

The config.yaml file

config.yaml is a simple, high-level configuration. It is the source of truth for the network. The generator reads it and produces var/generated/*.nix, consumed by the framework.

The file has four sections :

SectionRole
networkGlobal parameters: domain, locale, VPN coordination.
zonesSubnets: IP prefix, gateway, non-NixOS devices.
usersAccounts, common to all zones.
hostsMachines to deploy.

This optional section defines the global parameters of our network.

etc/config.yaml
network:
domain: "domain.tld" # root DNS domain (services, VPN, certificates)
default:
locale: "fr_FR.UTF-8" # default locale for every host
timezone: "Europe/Paris" # default timezone
coordination:
enable: true # enables VPN mesh (Headscale)
hostname: "hcs" # short name of the coordination host
domain: "headscale" # subdomain → headscale.domain.tld
KeyRole
domainRoot DNS domain (services, Headscale, certificates).
default.localeDefault values, possibly overridden by zone.
default.timezoneDefault values, possibly overridden by zone.
coordination.enableEnables VPN coordination. false → local zones only.
coordination.hostnameHeadscale host and subdomain.
coordination.domainHeadscale host and subdomain.

A zone is a subnet (home LAN, guest network, remote site…). Each zone has an IP /16 prefix, a gateway and, optionally, non-NixOS devices.

etc/config.yaml
zones:
main:
description: "Main network"
locale: "fr_FR.UTF-8" # optional (default: network.default.locale)
timezone: "Europe/Paris" # optional
ipPrefix: "10.0" # the zone uses 10.0.0.0/16
gateway:
wan:
interface: "enp1s0" # interface to Internet (required)
lan:
interfaces: ["enp2s0"] # internal interface(s) (required)
vpn:
ipv4: "10.0.0.1" # gateway VPN IP (after registration)
KeyRole
descriptionZone label.
locale / timezoneLocal overrides (otherwise network.default).
ipPrefixFirst two octets of an RFC1918 /16 (e.g. 10.0).
gatewayGateway configuration (see below).
extraHostsNon-NixOS devices resolved by name (see below).
KeyRole
wan.interfaceNetwork interface to Internet (required).
lan.interfacesList of internal interfaces (required), integrated into the lan0 bridge.
lan.dhcp-rangeDHCP range (optional; default <prefix>.3.200,<prefix>.3.249,24h).
vpn.ipv4Gateway VPN IP, to fill in after Headscale registration.

Phones, printers, IoT devices: resolved by name and fixed on DHCP. The common key is merged into each zone (devices present everywhere).

etc/config.yaml
zones:
main:
# ...
extraHosts:
printer:
ip: "4.1" # suffix → 10.0.4.1
name: "Living room printer"
mac: "aa:bb:cc:dd:ee:01"
common:
extraHosts: # added to ALL zones
phone-alice:
ip: "5.1"
name: "Alice's phone"
mac: "aa:bb:cc:dd:ee:02"

Shared accounts across all zones. Each account receives a profile Home Manager and groups.

etc/config.yaml
users:
alice:
uid: 1000
name: "Alice Martin"
email: "alice@domain.tld"
profile: "nix-admin"
groups: ["zone-main", "global", "idm-admins"]
bob:
uid: 1001
name: "Bob Durand"
profile: "normal"
groups: ["zone-main"]
KeyTypeRole
(key)Account identifier (login) ([a-z]…).
uidintegerStable numeric identifier (required).
nametextDisplay name (required).
emailtextEmail address (also used for SSO identity), defaults to <login>@<domain.tld>.
profiletextUser profile (default minimal).
groupslistInstalls the user on hosts with the same group.

hosts is a list of entries (- hostname: …). A machine can be declared in three ways depending on the need.

One entry = one machine. The simplest and most common form.

etc/config.yaml
hosts:
- hostname: "gw"
name: "Main gateway"
zone: "main:1.1" # fixed IP 10.0.1.1 → gateway
profile: "gateway"
tags: ["main"]
features: ["monitoring-node"]
services:
adguardhome:
homepage:
- hostname: "server"
name: "Home server"
zone: "main:1.2" # fixed IP 10.0.1.2
profile: "server"
users: ["alice"]
services:
nextcloud:
restic:

A common config + a sub-map hosts:: each member (key) inherits the group’s keys (profile, groups, features, tags, disko) and specifies its own name, zone, MAC address. The %s in the group’s hostname/name is replaced by the member’s key (and by its name).

etc/config.yaml
hosts:
- hostname: "%s-laptop" # %s → member key
name: "Portable de %s" # %s → member's name
profile: "laptop"
groups: ["zone-main"]
hosts:
alice: # → hostname "alice-laptop"
name: "Alice"
zone: "main:2.4"
mac: "aa:bb:cc:dd:ee:10"
bob: # → hostname "bob-laptop"
name: "Bob"
zone: "main:2.5"
mac: "aa:bb:cc:dd:ee:11"

Generates N identical hosts numbered sequentially. range: [start, end] (inclusive bounds). Template tokens (similar to printf substitutions 🡕) are replaced by the index :

TokenEffectExample (i=3)
%d or %sThe indexvm-%dvm-3
%'02sPadded index (char + width)vm-%'02svm-03
etc/config.yaml
hosts:
- hostname: "desktop-%'02s" # desktop-01 … desktop-04
name: "Guest workstation n°%'02s"
zone: "main:11.%d" # 10.0.11.1 … 10.0.11.4
profile: "desktop"
range: [1, 4]
groups: ["zone-main"]
features: ["nfs-client"]
mac: # MAC by index
1: "aa:bb:cc:dd:ee:21"
2: "aa:bb:cc:dd:ee:22"
3: "aa:bb:cc:dd:ee:23"
4: "aa:bb:cc:dd:ee:24"
KeyTypeRole
hostnametextDNS identifier (required); templates %s/%d/%'02s.
nametextReadable name (required).
profiletextHost profile (gateway, server, desktop, laptop, hcs…).
zonetextZone and IP (see below).
ipv4mapExternal host: external (public IP) + internal (VPN IP).
userslistLogins authorized to open a session.
groupslistHost groups (add corresponding members).
tagslistColmena tags (just apply @tag).
featureslistNon-service flags (see below).
servicesmapEnabled services (see below).
mactext/mapInternal interface MAC (static), map by index (range).
aliaseslistAdditional DNS names.
archtextArchitecture (default x86_64-linux).
diskomapDisk scheme (see below).
rangelist[start, end] for a range.
hostsmapMembers (collection) or per-index overrides (range).

The zone key sets the network membership and the IP address :

FormEffect
zone: "main:1.2"Fixed IP <ipPrefix>.1.2 (e.g. 10.1.1.2 in zone main in 10.1).
zone: "main:11.%d"Fixed IP with range index (e.g. 10.1.11.1, 10.1.11.2…).
zone: "main"Dynamic address (DHCP) in the zone.

An external host (the HCS) has no zone but an ipv4 block :

etc/config.yaml
- hostname: "hcs"
name: "Coordination"
profile: "hcs"
ipv4:
external: "203.0.113.26" # public IP (external zone)
internal: "10.0.0.2" # IP in the VPN

The features key enables specific behaviors or features. A :<zone> suffix targets a specific zone (otherwise the host’s zone is used). Examples:

# Machine under supervision (monitoring-node)
# and NFS client (a server must exist in the zone)
features: ["monitoring-node", "nfs-client"]
# Machine supervised by the "main" zone
features: ["monitoring-node:main"]

Available features:

  • monitoring-node : the host exposes its metrics (node-exporter) to the zone’s monitoring.
  • nfs-client : the host mounts shares from the zone’s nfs server (a server must exist in the zone).

The services key contains a collection of services to be automatically installed on the host. Values are optional and allow service customization.

etc/config.yaml
services:
immich:
title: "Photos"
description: "My photos & videos"
domain: "photos" # sub-domain
global: true # → https://photos.domain.tld (public)
nextcloud:
domain: "cloud" # → cloud.<zone>.domain.tld (non global)
restic: # default values
FieldRole
(key)Service to enable (e.g. immich).
titleName displayed on the portal.
descriptionSubtitle on the portal.
domainSub-domain (default: service name).
globalExposes publicly via the HCS: <domain>.domain.tld, without the zone.
iconPortal icon.

The disko key describes partitioning for automatic installation.

  • profile designates a (usr|dnf)/hosts/disko/<profile>.nix file.
  • devices maps the profile’s named disks to actual devices.
etc/config.yaml
disko:
profile: "btrfs-1-disk"
devices:
main: "/dev/nvme0n1"

For the full machine installation walkthrough, see Initial installation.