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 :
| Section | Role |
|---|---|
network | Global parameters: domain, locale, VPN coordination. |
zones | Subnets: IP prefix, gateway, non-NixOS devices. |
users | Accounts, common to all zones. |
hosts | Machines to deploy. |
Section “network”
Section titled “Section “network””This optional section defines the global settings of our network.
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| Key | Role |
|---|---|
domain | Top-level DNS domain (services, Headscale, certificates). |
default.locale | Default values, possibly overridden per zone. |
default.timezone | Default values, possibly overridden per zone. |
coordination.enable | Enables VPN coordination. false → local zones only. |
coordination.hostname | Headscale host and subdomain. |
coordination.domain | Headscale 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).
Section “zones”
Section titled “Section “zones””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.
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)| Key | Role |
|---|---|
description | Zone label. |
locale / timezone | Locale overrides (otherwise network.default). |
ipPrefix | First two octets of an RFC1918 /16 (e.g. 10.0). |
gateway | Gateway configuration (see below). |
extraHosts | Non-NixOS devices resolved by name (see below). |
The gateway
Section titled “The gateway”| Key | Role |
|---|---|
wan.interface | Network interface to the Internet (required). |
lan.interfaces | List of internal interfaces (required), joined into the lan0 bridge. |
lan.dhcp-range | DHCP range (optional; default <préfixe>.3.200,<préfixe>.3.249,24h). |
vpn.ipv4 | Gateway tailnet IP, collected after just tailnet-enroll (details). |
Non-NixOS devices (extraHosts)
Section titled “Non-NixOS devices (extraHosts)”Phones, printers, IoT devices: resolved by name and fixed on DHCP.
The common key is merged into each zone (devices present everywhere).
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"Section “users”
Section titled “Section “users””Shared accounts across all zones. Each account receives a profile Home Manager and groups.
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"]| Key | Type | Role |
|---|---|---|
| (key) | Account identifier (login) ([a-z]…). | |
uid | integer | Stable numeric identifier (required). |
name | text | Display name (required). |
email | text | Email address (also used for SSO identity), defaults to <login>@<domain.tld>. |
profile | text | User profile (default minimal). |
groups | list | Installs the user on hosts with the same group. |
“hosts” section
Section titled ““hosts” section”hosts is a list of entries (- hostname: …). A machine can be declared in three ways depending on the need.
Static type: one host per entry
Section titled “Static type: one host per entry”One entry = one machine. The simplest and most common form.
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:Collection type: similar machines
Section titled “Collection type: similar machines”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).
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"Range type: identical machines
Section titled “Range type: identical machines”Generates N identical hosts numbered sequentially. range: [start, end] (inclusive bounds). Template tokens (similar to printf substitutions 🡕) are replaced by the index :
| Token | Effect | Example (i=3) |
|---|---|---|
%d or %s | The index | vm-%d → vm-3 |
%'02s | Padded index (char + width) | vm-%'02s → vm-03 |
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"Key list
Section titled “Key list”| Key | Type | Role |
|---|---|---|
hostname | text | DNS identifier (required); templates %s/%d/%'02s. |
name | text | Readable name (required). |
profile | text | Host profile (gateway, server, desktop, laptop, hcs…). |
zone | text | Zone and IP (see below). |
ipv4 | map | External host: external (public IP) + internal (VPN IP). |
users | list | Logins authorized to open a session. |
groups | list | Host groups (add corresponding members). |
tags | list | Colmena tags (just apply @tag). |
features | list | Non-service flags (see below). |
services | map | Enabled services (see below). |
mac | text/map | Internal interface MAC (static), map by index (range). |
aliases | list | Additional DNS names. |
arch | text | Architecture (default x86_64-linux). |
disko | map | Disk scheme (see below). |
range | list | [start, end] for a range. |
hosts | map | Members (collection) or per-index overrides (range). |
Assigning a zone
Section titled “Assigning a zone”The zone key sets the network membership and the IP address :
| Form | Effect |
|---|---|
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 :
- hostname: "hcs" name: "Coordination" profile: "hcs" ipv4: external: "203.0.113.26" # IP publique (zone externe) internal: "10.0.0.2" # IP dans le VPNAssigning features
Section titled “Assigning features”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" zonefeatures: ["monitoring-node:main"]Available features:
monitoring-node: the host exposes its metrics (node-exporter) to the zone’s monitoring.nfs-client: the host mounts thenfsserver shares of the zone (a server must exist in that zone).
Declare services
Section titled “Declare services”The services key holds a collection of services to automatically install on the
host. Values are optional and allow service customization.
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| Field | Role |
|---|---|
| (key) | Service to enable (e.g. immich). |
title | Name displayed on the portal. |
description | Subtitle on the portal. |
domain | Subdomain (default: service name). |
global | Exposes publicly via the HCS: <domain>.domain.tld, without the zone. |
icon | Portal icon. |
Declaring the partitioning
Section titled “Declaring the partitioning”The disko key describes the partitioning for the automatic installation.
profilerefers to ausr/hosts/disko/<profile>.nixfile, otherwisednf/hosts/disko/<profile>.nix(the local profile overrides the framework’s).devicesis required : one real device per disk named in the profile, no more, no less, otherwisejust generatefails.
disko: profile: "btrfs-1-disk" devices: main: "/dev/disk/by-id/nvme-Samsung_SSD_990_PRO_2TB_S7DNNJ0W000000"Useful links
Section titled “Useful links”For the full machine installation walkthrough, see Initial installation.