Skip to content

The config.yaml file

config.yaml is a simple, high-level configuration. It is the source of truth of 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 settings of our network.

etc/config.yaml
network:
domain: "domain.tld" # domaine DNS racine (services, VPN, certificats)
default:
locale: "fr_FR.UTF-8" # locale par défaut de chaque hôte
timezone: "Europe/Paris" # fuseau par défaut
coordination:
enable: true # active le maillage VPN (Headscale)
hostname: "hcs" # nom court de l'hôte de coordination
domain: "headscale" # sous-domaine → headscale.domain.tld
KeyRole
domainTop-level DNS domain (services, Headscale, certificates).
default.localeDefault values, possibly overridden per zone.
default.timezoneDefault values, possibly overridden per zone.
coordination.enableEnables VPN coordination. false → local zones only.
coordination.hostnameHeadscale host and subdomain.
coordination.domainHeadscale host and subdomain.

The locale also sets the keyboard, in console as well as on the desktop: the one given by dnf/config/locales.json (en_GB.UTF-8: uk in console, gb under GNOME), otherwise the country code (ru_RU.UTF-8: ru).

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

etc/config.yaml
zones:
main:
description: "Réseau principal"
locale: "fr_FR.UTF-8" # optionnel (défaut : network.default.locale)
timezone: "Europe/Paris" # optionnel
ipPrefix: "10.0" # la zone utilise 10.0.0.0/16
gateway:
wan:
interface: "enp1s0" # interface vers Internet (requis)
lan:
interfaces: ["enp2s0"] # interface(s) interne(s) (requis)
vpn:
ipv4: "100.64.0.1" # IP tailnet de la passerelle (après enrôlement)
KeyRole
descriptionZone label.
locale / timezoneLocale 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 the Internet (required).
lan.interfacesList of internal interfaces (required), joined into the lan0 bridge.
lan.dhcp-rangeDHCP range (optional; default <préfixe>.3.200,<préfixe>.3.249,24h).
vpn.ipv4Gateway tailnet IP, collected after just tailnet-enroll (details).

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-%d → vm-3
%'02sPadded index (char + width)vm-%'02s → vm-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 on 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" # IP publique (zone externe)
internal: "10.0.0.2" # IP dans le 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 monitoring (monitoring-node)
# and NFS client (requires a server in the zone)
features: ["monitoring-node", "nfs-client"]
# Machine monitored 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 the nfs server shares of the zone (a server must exist in that zone).

The services key holds a collection of services to automatically install on the host. Values are optional and allow service customization.

etc/config.yaml
services:
immich:
title: "Photos"
description: "Mes photos & vidéos"
domain: "photos" # sous-domaine
global: true # → https://photos.domain.tld (public)
nextcloud:
domain: "cloud" # → cloud.<zone>.domain.tld (non global)
restic: # valeurs par défaut
FieldRole
(key)Service to enable (e.g. immich).
titleName displayed on the portal.
descriptionSubtitle on the portal.
domainSubdomain (default: service name).
globalExposes publicly via the HCS: <domain>.domain.tld, without the zone.
iconPortal icon.

The disko key describes the partitioning for the automatic installation.

  • profile refers to a usr/hosts/disko/<profile>.nix file, otherwise dnf/hosts/disko/<profile>.nix (the local profile overrides the framework’s).
  • devices is required : one real device per disk named in the profile, no more, no less, otherwise just generate fails.
etc/config.yaml
disko:
profile: "btrfs-1-disk"
devices:
main: "/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_2TB_S7DNNJ0W000000"

For the full machine installation walkthrough, see Initial installation.