Added network management.

This commit is contained in:
2026-05-08 22:26:37 +02:00
parent 09d2522bfd
commit bd41a33bae
11 changed files with 591 additions and 29 deletions
+80 -14
View File
@@ -42,7 +42,9 @@
| **Initial configuration (`initial-configuration.nix`)** | Prepare an LXC container so it can update itself via Git. | Self-sufficient containers. | | **Initial configuration (`initial-configuration.nix`)** | Prepare an LXC container so it can update itself via Git. | Self-sufficient containers. |
| **Secret management with `agenix`** | Encrypt secrets (passwords, keys) for secure storage. | Enhanced security for sensitive data. | | **Secret management with `agenix`** | Encrypt secrets (passwords, keys) for secure storage. | Enhanced security for sensitive data. |
| **Unprivileged LXC containers (`--unprivileged 0`)** | NixOS requires privileges to function correctly in LXC. | Functional containers with NixOS. | | **Unprivileged LXC containers (`--unprivileged 0`)** | NixOS requires privileges to function correctly in LXC. | Functional containers with NixOS. |
| **IPv4, IPv6, VLAN support** | Final target is IPv6-first, or even IPv6-only. | IP plan management to be designed. | | **Centralised network data** | A single declarative network data source (`network/`) consumed by NixOS configs and scripts. | VLANs, subnets, host addresses defined once in `network/hosts.nix`. |
| **IPv6-first with dual-stack** | Both ULA (fdb2:) and GUA (2a01:) prefixes defined per VLAN. | Consistent internal addressing + global reachability for DMZ services. |
| **DHCP-based IPv4 assignment** | LXC containers use `useDHCP = true`. Addresses are reserved in `hosts.nix` as source of truth. | Centralised address management, no static IPs in per-host configs. |
--- ---
@@ -82,6 +84,13 @@ nixos-infra/
│ └── gaia/ # Xavier's laptop (audio) │ └── gaia/ # Xavier's laptop (audio)
│ └── configuration.nix │ └── configuration.nix
├── network/ # Centralised network data (VLANs, subnets, hosts)
│ ├── default.nix # Aggregator — imports vlans, subnets, hosts
│ ├── vlans.nix # VLAN definitions
│ ├── subnets.nix # Subnet prefix allocations
│ ├── hosts.nix # Per-machine IP/address assignments
│ └── README.md # Network architecture documentation
├── modules/ # Autonomous modules ├── modules/ # Autonomous modules
│ ├── machine-types/ # Machine types │ ├── machine-types/ # Machine types
│ │ ├── hypervisor.nix # Module for hypervisors │ │ ├── hypervisor.nix # Module for hypervisors
@@ -157,20 +166,35 @@ nixos-infra/
### **1. Machine List** ### **1. Machine List**
| Name | Machine Type | Services | IPv4 | IPv6 Token | | Name | Machine Type | VLAN | IPv4 | IPv6 Token |
| ----------| --------------------| -------------| ------| ------------| | ----------| --------------------| ---------| ------------------| ------------|
| hyper01 | Hypervisor | Proxmox | | | | hyper01 | Hypervisor | ADMIN | 10.10.128.10/16 | ::10 |
| hyper02 | Hypervisor | Proxmox | | | | hyper02 | Hypervisor | ADMIN | 10.10.128.11/16 | ::11 |
| dns01 | LXC Container | DNS | | | | dns01 | LXC Container | DMZ | 10.40.128.10/16 | ::10 |
| git01 | LXC Container | Git forge | | | | dns02 | LXC Container | DMZ | 10.40.128.11/16 | ::11 |
| pass01 | LXC Container | Password mgr| | | | git01 | LXC Container | DMZ | 10.40.128.20/16 | ::20 |
| rp01 | LXC Container | Reverse proxy| | | | pass01 | LXC Container | DMZ | 10.40.128.30/16 | ::30 |
| sting | Workstation | | | | | rp01 | LXC Container | DMZ | 10.40.128.199/16 | ::199 |
| PC-FRIDA | Workstation | | | | | sting | Workstation | INTERNAL | 10.50.128.10/16 | ::10 |
| PC-FRIDA | Workstation | INTERNAL | 10.50.128.11/16 | ::11 |
| gaia | Workstation | INTERNAL | 10.50.128.12/16 | ::12 |
--- ---
### **2. List of User Profiles** ### **2. VLANs**
| VLAN | ID | Effective ID | IPv4 Prefix | IPv6 ULA | IPv6 GUA |
| ----------| ---| --------------| -----------------| ----------------------------------| ----------------------------------|
| INET | 1 | 1 | Out of scope | Out of scope | Out of scope |
| ADMIN | 90 | **100** | 10.10.0.0/16 | fdb2:ae63:d45:d941::/64 | 2a01:e0a:2ea:d941::/64 |
| IOT | 200| 200 | 10.20.0.0/16 | fdb2:ae63:d45:d942::/64 | 2a01:e0a:2ea:d942::/64 |
| GUEST | 300| 300 | 10.30.0.0/16 | fdb2:ae63:d45:d943::/64 | 2a01:e0a:2ea:d943::/64 |
| DMZ | 400| 400 | 10.40.0.0/16 | fdb2:ae63:d45:d944::/64 | 2a01:e0a:2ea:d944::/64 |
| INTERNAL | 500| 500 | 10.50.0.0/16 | fdb2:ae63:d45:d945::/64 | 2a01:e0a:2ea:d945::/64 |
---
### **3. List of User Profiles**
| Name | Role | | Name | Role |
@@ -183,7 +207,7 @@ nixos-infra/
--- ---
### **3. User List** ### **4. User List**
| Name | Role | SSH Access | | Name | Role | SSH Access |
| --------| -----------------------| -----------| | --------| -----------------------| -----------|
| root | Superuser | ❌ | | root | Superuser | ❌ |
@@ -194,7 +218,7 @@ nixos-infra/
--- ---
### **4. User/Machine/Profile Mappings** ### **5. User/Machine/Profile Mappings**
| User | Machine | Applied Profiles | Role | | User | Machine | Applied Profiles | Role |
@@ -214,6 +238,43 @@ nixos-infra/
--- ---
## **🌐 Network Architecture**
The network topology and addressing are defined **declaratively** in `network/`, the single source of truth for:
- VLANs (`network/vlans.nix`)
- Subnet prefixes (`network/subnets.nix`)
- Host address assignments (`network/hosts.nix`)
### Prefix rules
| Type | Formula | Example (DMZ, effectiveId=400) |
|--------|-----------------------------------------------------------|--------------------------------|
| IPv4 | `10.<effectiveId>.0.0/16` — hosts in `10.<v>.128.0/17` | `10.40.0.0/16` |
| IPv6 ULA | `fdb2:ae63:d45:d94<N>::/64` where N = effectiveId/100 | `fdb2:ae63:d45:d944::/64` |
| IPv6 GUA | `2a01:e0a:2ea:d94<N>::/64` where N = effectiveId/100 | `2a01:e0a:2ea:d944::/64` |
> **ADMIN exception:** VLAN ID is 90 but treated as effective ID 100 for
> prefix computation. This avoids a risky production renumbering.
### Consumption
**From a NixOS configuration:**
```nix
let network = import ../../network { };
in {
networking.hostName = "dns01";
networking.useDHCP = true;
}
```
**From a shell script:**
```bash
nix eval --json -f network/default.nix hosts | jq '.dns01.ipv4'
# → "10.40.128.10"
```
---
## **🔄 Deployment Workflow** ## **🔄 Deployment Workflow**
### **For LXC containers (Proxmox)** ### **For LXC containers (Proxmox)**
@@ -276,6 +337,7 @@ nixos-infra/
| Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ | | Write the DNS module | Module for the DNS service (Bind). | ⬜ | ⭐⭐⭐ |
| Configure `agenix` | Encrypt the first secrets. | ⬜ | ⭐⭐ | | Configure `agenix` | Encrypt the first secrets. | ⬜ | ⭐⭐ |
| Document the process | `README.md` to explain deployment. | ⬜ | ⭐⭐ | | Document the process | `README.md` to explain deployment. | ⬜ | ⭐⭐ |
| DHCP service module | Kea or ISC DHCP consuming `network/hosts.nix` | ⬜ | ⭐⭐ |
| Automate with Ansible | Playbook to create multiple containers. | ⬜ | ⭐ | | Automate with Ansible | Playbook to create multiple containers. | ⬜ | ⭐ |
| Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ | | Integrate CI/CD | Test configurations before deployment. | ⬜ | ⭐ |
@@ -293,6 +355,10 @@ nixos-infra/
- **Security** : - **Security** :
- Disable root SSH access once deployment is complete. - Disable root SSH access once deployment is complete.
- Use SSH keys for authentication. - Use SSH keys for authentication.
- **Network** :
- IPv4 addresses are allocated from the upper half of each VLAN (`10.<v>.128.0/17`).
- Addresses are assigned via DHCP reservations — `network/hosts.nix` is the source of truth.
- See `network/README.md` for the complete architecture documentation.
- **Maintenance** : - **Maintenance** :
- Update `nixpkgs` regularly (`nix-channel --update`). - Update `nixpkgs` regularly (`nix-channel --update`).
- Document changes in the `CHANGELOG.md`. - Document changes in the `CHANGELOG.md`.
@@ -0,0 +1,19 @@
{ config, pkgs, lib, ... }:
{
imports = [
# Module for LXC containers
../../../modules/machine-types/lxc.nix
];
# Explicitly enable LXC machine type
lxc.enable = true;
# Host identity (IP address 10.40.128.10/16 assigned via DHCP reservation)
networking.hostName = "dns01";
networking.useDHCP = true;
# TODO: Add DNS service module import and configuration
# imports = [ ../../../modules/services/dns/default.nix ];
# services.dns.enable = true;
}
@@ -0,0 +1,19 @@
{ config, pkgs, lib, ... }:
{
imports = [
# Module for LXC containers
../../../modules/machine-types/lxc.nix
];
# Explicitly enable LXC machine type
lxc.enable = true;
# Host identity (IP address 10.40.128.11/16 assigned via DHCP reservation)
networking.hostName = "dns02";
networking.useDHCP = true;
# TODO: Add DNS service module import and configuration
# imports = [ ../../../modules/services/dns/default.nix ];
# services.dns.enable = true;
}
@@ -0,0 +1,20 @@
{ config, pkgs, lib, ... }:
{
imports = [
# Module for LXC containers
../../../modules/machine-types/lxc.nix
# Module for the git forge service
../../../modules/services/git-forge/default.nix
];
# Explicitly enable LXC machine type
lxc.enable = true;
# Host identity (IP address 10.40.128.20/16 assigned via DHCP reservation)
networking.hostName = "git01";
networking.useDHCP = true;
# TODO: Enable and configure the git forge service
# services.git-forge.enable = true;
}
@@ -0,0 +1,20 @@
{ config, pkgs, lib, ... }:
{
imports = [
# Module for LXC containers
../../../modules/machine-types/lxc.nix
# Module for password manager service
../../../modules/services/password-manager/default.nix
];
# Explicitly enable LXC machine type
lxc.enable = true;
# Host identity (IP address 10.40.128.30/16 assigned via DHCP reservation)
networking.hostName = "pass01";
networking.useDHCP = true;
# TODO: Enable and configure the password manager service
# services.password-manager.enable = true;
}
@@ -2,31 +2,25 @@
{ {
imports = [ imports = [
# Module pour les conteneurs LXC # Module for LXC containers
../../../modules/machine-types/lxc.nix ../../../modules/machine-types/lxc.nix
# Module pour le reverse proxy # Module for the reverse proxy
../../../modules/services/reverse-proxy/default.nix ../../../modules/services/reverse-proxy/default.nix
]; ];
# Configuration réseau (IPv4 + IPv6) # Host identity (IP address assigned via DHCP reservation)
networking.hostName = "rp01"; networking.hostName = "rp01";
networking.interfaces.eth0.ipv4.addresses = [ networking.useDHCP = true;
{ address = "10.40.0.199"; prefixLength = 24; }
];
# networking.interfaces.eth0.ipv6.addresses = [
# { address = "2001:db8::1"; prefixLength = 64; }
# ];
# Liste des services à exposer via le reverse proxy # Services to expose via the reverse proxy
services.reverse-proxy.publicServices = [ services.reverse-proxy.publicServices = [
{ host = "git"; internalHost = "git01"; port = 3000; } { host = "git"; internalHost = "git01"; port = 3000; }
{ host = "pass"; internalHost = "pass01"; port = 80; } { host = "pass"; internalHost = "pass01"; port = 80; }
# Ajoutez ici d'autres services (ex: dns01, etc.) # Add other services here (e.g. dns01, etc.)
]; ];
# Configuration spécifique à Caddy (optionnelle) # Caddy-specific configuration (optional)
services.caddy = { services.caddy = {
# Vous pouvez surcharger des paramètres ici si besoin email = "xavier@lagraula.fr"; # Email for Let's Encrypt
email = "xavier@lagraula.fr"; # Email pour Let's Encrypt
}; };
} }
+123
View File
@@ -0,0 +1,123 @@
# Network Architecture
This directory contains the centralised, declarative network topology data for
the infrastructure. It is the single source of truth for VLANs, subnets, and
host addresses, consumable both by NixOS configurations (via `import`) and by
external scripts (via `nix eval --json`).
## Files
| File | Purpose |
|------|---------|
| `vlans.nix` | VLAN definitions (ID, name, effective ID, description) |
| `subnets.nix` | IPv4 and IPv6 prefix allocations per VLAN |
| `hosts.nix` | Per-machine address assignments |
| `default.nix` | Aggregator — imports all three files |
## Consumption
### From a NixOS configuration
```nix
{ config, pkgs, lib, ... }:
let
network = import ../../network { };
in {
networking.hostName = "dns01";
networking.useDHCP = true;
}
```
### From a shell script
```bash
# Export all host data as JSON
nix eval --json -f nixos-infra/network/default.nix hosts
# Get a specific host's IPv4 address
nix eval -f nixos-infra/network/default.nix 'hosts.dns01.ipv4'
# Use with jq
nix eval --json -f nixos-infra/network/default.nix hosts | jq '.dns01'
```
## VLANs
| VLAN | ID | Effective ID | Description |
|------|----|--------------|-------------|
| INET | 1 | 1 | ISP uplink — untagged, out of project scope |
| ADMIN | 90 | **100** | Management / hypervisors |
| IOT | 200 | 200 | IoT devices |
| GUEST | 300 | 300 | Guest network |
| DMZ | 400 | 400 | Public-facing servers (LXC containers) |
| INTERNAL | 500 | 500 | Internal workstations |
> **ADMIN exception:** VLAN 90 is treated as effective ID 100 for prefix
> computation. This is a documented exception to avoid a risky production
> change. A future renumbering may bring `id` and `effectiveId` into line.
## Addressing Scheme
### IPv4
The formula is `10.<effectiveId>.0.0/16` per VLAN.
To avoid conflicts with the lower half (DHCP pools, infrastructure
services), **all static host addresses are allocated from the upper half**:
`10.<effectiveId>.128.0/17`.
The gateway (`.1`) is distributed by DHCPv4 and is not statically assigned.
### IPv6
IPv6 prefixes are derived from `effectiveId / 100`:
| Type | Formula | Example (DMZ, effectiveId=400) |
|------|---------|-------------------------------|
| ULA | `fdb2:ae63:d45:d94<N>::/64` | `fdb2:ae63:d45:d944::/64` |
| GUA | `2a01:e0a:2ea:d94<N>::/64` | `2a01:e0a:2ea:d944::/64` |
where `<N>` = `effectiveId / 100` (so 1 for ADMIN, 2 for IOT, …, 5 for
INTERNAL).
IPv6 addresses are formed by appending the host's 64-bit token to the
prefix, e.g. `fdb2:ae63:d45:d944::10` for dns01.
The gateway (`::1` in each subnet) is distributed via Router Advertisement.
### Host Address Allocation
IPv4 addresses are reserved via DHCP reservations. The `hosts.nix` file is
the source of truth for these reservations and is intended to drive DHCP
server configuration (Kea, ISC DHCP, or similar) in a future iteration.
IPv6 tokens are the last 64 bits of the host's address (expressed as `::XX`
shorthand) and are expected to be distributed via SLAAC with the corresponding
prefix.
## Key Design Decisions
1. **Why effectiveId?** The ADMIN VLAN has ID 90 but its IP prefixes are
computed as if ID were 100. Rather than fixing the VLAN ID in production,
the `effectiveId` field captures the exception explicitly and documents it.
2. **Why /16 per VLAN?** Each VLAN has a full `/16` IPv4 prefix, which is
larger than typical container/workstation subnets. This is intentional:
it simplifies VLAN-level routing and leaves room for future growth.
3. **Why DHCP and not static?** IPv4 addresses are distributed by DHCP, not
statically configured on each host. This centralises address management
and makes it easier to audit and change. The `hosts.nix` file is the
source of truth for the DHCP server's configuration.
4. **Why NO static IP in configuration.nix?** In the current state, LXC
containers have no static IP configuration at all — they rely entirely on
DHCP. This is intentional: the addressing plan lives centrally in
`network/hosts.nix` and the per-host `.nix` files only set `hostName` and
`useDHCP = true`. A future DHCP service module (Kea, etc.) will consume
`hosts.nix` to generate reservations.
5. **Why ULA + GUA for IPv6?** Both ULA (fd prefix) and GUA (2a01 prefix)
are defined for each VLAN. ULA provides stable internal addressing
independent of ISP changes; GUA provides global reachability for DMZ
services and outbound connectivity for workstations.
+14
View File
@@ -0,0 +1,14 @@
# Central network data source.
#
# Usage from a configuration.nix:
# network = import ../../network { };
# network.hosts.rp01.ipv4 → "10.40.128.199"
#
# Usage from a shell script (via `nix eval`):
# nix eval --json -f network/default.nix hosts
{
vlans = (import ./vlans.nix).vlans;
subnets = (import ./subnets.nix).subnets;
hosts = (import ./hosts.nix).hosts;
}
+87
View File
@@ -0,0 +1,87 @@
{
# Host-to-network assignments.
#
# Each entry has:
# vlan - Key referencing the VLAN in vlans.nix
# type - Host role (hypervisor, lxc, workstation)
# ipv4 - Static IPv4 address (reserved via DHCP reservation)
# ipv6Token - Last 64-bit suffix of the IPv6 address (::XX notation)
#
# IPv4 addresses are allocated from the 10.<v>.128.0/17 upper-half
# range to avoid conflicts with lower-half DHCP pools.
#
# IPv6 addresses are formed by appending the token to the VLAN's
# ULA or GUA prefix, e.g. fdb2:ae63:d45:d944::10 for dns01.
hosts = {
hyper01 = {
vlan = "admin";
type = "hypervisor";
ipv4 = "10.10.128.10";
ipv6Token = "::10";
};
hyper02 = {
vlan = "admin";
type = "hypervisor";
ipv4 = "10.10.128.11";
ipv6Token = "::11";
};
rp01 = {
vlan = "dmz";
type = "lxc";
ipv4 = "10.40.128.199";
ipv6Token = "::199";
};
dns01 = {
vlan = "dmz";
type = "lxc";
ipv4 = "10.40.128.10";
ipv6Token = "::10";
};
dns02 = {
vlan = "dmz";
type = "lxc";
ipv4 = "10.40.128.11";
ipv6Token = "::11";
};
git01 = {
vlan = "dmz";
type = "lxc";
ipv4 = "10.40.128.20";
ipv6Token = "::20";
};
pass01 = {
vlan = "dmz";
type = "lxc";
ipv4 = "10.40.128.30";
ipv6Token = "::30";
};
gaia = {
vlan = "internal";
type = "workstation";
ipv4 = "10.50.128.10";
ipv6Token = "::10";
};
"PC-FRIDA" = {
vlan = "internal";
type = "workstation";
ipv4 = "10.50.128.11";
ipv6Token = "::11";
};
sting = {
vlan = "internal";
type = "workstation";
ipv4 = "10.50.128.12";
ipv6Token = "::12";
};
};
}
+141
View File
@@ -0,0 +1,141 @@
{
# Subnet definitions per VLAN.
#
# Prefix rules:
# IPv4: 10.<effectiveId>.0.0/16 (hosts in the 10.<effectiveId>.128.0/17 range)
# IPv6 ULA: fdb2:ae63:d45:d94<effectiveId/100>::/64
# IPv6 GUA: 2a01:e0a:2ea:d94<effectiveId/100>::/64
#
# Gateways (.1 on each subnet) are distributed by DHCPv4 and Router
# Advertisement (SLAAC). They are listed in comments for documentation.
#
# Minimum host prefix is /16 for IPv4 (the whole VLAN). Host addresses
# are allocated from the upper half (10.<v>.128.0/17) to avoid conflicts
# with future lower-half allocations (DHCP pools, etc.).
#
# INET (VLAN 1) is the untagged ISP uplink. It is out of scope of this
# project and is listed for documentation only.
subnets = {
inet = {
vlan = "inet";
description = "ISP uplink out of scope";
# No prefixes defined: inet is outside this project's addressing plan.
};
admin = {
vlan = "admin";
description = "Management / hypervisors";
ipv4 = {
prefix = "10.10.0.0";
prefixLength = 16;
hostRange = "10.10.128.0/17";
# gateway = "10.10.128.1";
};
ipv6 = {
ula = {
prefix = "fdb2:ae63:d45:d941::";
prefixLength = 64;
# gateway = "fdb2:ae63:d45:d941::1";
};
gua = {
prefix = "2a01:e0a:2ea:d941::";
prefixLength = 64;
# gateway = "2a01:e0a:2ea:d941::1";
};
};
};
iot = {
vlan = "iot";
description = "IoT devices";
ipv4 = {
prefix = "10.20.0.0";
prefixLength = 16;
hostRange = "10.20.128.0/17";
# gateway = "10.20.128.1";
};
ipv6 = {
ula = {
prefix = "fdb2:ae63:d45:d942::";
prefixLength = 64;
# gateway = "fdb2:ae63:d45:d942::1";
};
gua = {
prefix = "2a01:e0a:2ea:d942::";
prefixLength = 64;
# gateway = "2a01:e0a:2ea:d942::1";
};
};
};
guest = {
vlan = "guest";
description = "Guest network";
ipv4 = {
prefix = "10.30.0.0";
prefixLength = 16;
hostRange = "10.30.128.0/17";
# gateway = "10.30.128.1";
};
ipv6 = {
ula = {
prefix = "fdb2:ae63:d45:d943::";
prefixLength = 64;
# gateway = "fdb2:ae63:d45:d943::1";
};
gua = {
prefix = "2a01:e0a:2ea:d943::";
prefixLength = 64;
# gateway = "2a01:e0a:2ea:d943::1";
};
};
};
dmz = {
vlan = "dmz";
description = "Public-facing servers (LXC containers)";
ipv4 = {
prefix = "10.40.0.0";
prefixLength = 16;
hostRange = "10.40.128.0/17";
# gateway = "10.40.128.1";
};
ipv6 = {
ula = {
prefix = "fdb2:ae63:d45:d944::";
prefixLength = 64;
# gateway = "fdb2:ae63:d45:d944::1";
};
gua = {
prefix = "2a01:e0a:2ea:d944::";
prefixLength = 64;
# gateway = "2a01:e0a:2ea:d944::1";
};
};
};
internal = {
vlan = "internal";
description = "Internal workstations and trusted devices";
ipv4 = {
prefix = "10.50.0.0";
prefixLength = 16;
hostRange = "10.50.128.0/17";
# gateway = "10.50.128.1";
};
ipv6 = {
ula = {
prefix = "fdb2:ae63:d45:d945::";
prefixLength = 64;
# gateway = "fdb2:ae63:d45:d945::1";
};
gua = {
prefix = "2a01:e0a:2ea:d945::";
prefixLength = 64;
# gateway = "2a01:e0a:2ea:d945::1";
};
};
};
};
}
+59
View File
@@ -0,0 +1,59 @@
{
# VLANs used in the infrastructure.
#
# Each VLAN entry has:
# id - The actual IEEE 802.1Q VLAN ID on the network equipment
# name - Short label
# effectiveId - The numeric value used to compute IPv4/IPv6 prefixes.
# This matches `id` for most VLANs, but can differ when
# the VLAN ID does not follow the mathematical scheme.
# e.g. ADMIN is VLAN 90 but prefixes are computed as if VLAN 100.
# description - Free-text purpose of the VLAN
#
# VLAN ID 1 (INET) is the untagged ISP uplink. It is listed here for
# documentation only and is out of scope of this project.
vlans = {
inet = {
id = 1;
name = "INET";
effectiveId = 1;
description = "ISP uplink untagged, out of project scope";
};
admin = {
id = 90;
name = "ADMIN";
effectiveId = 100; # Exception: treated as 100 for prefix computation
description = "Management / hypervisors";
};
iot = {
id = 200;
name = "IOT";
effectiveId = 200;
description = "IoT devices";
};
guest = {
id = 300;
name = "GUEST";
effectiveId = 300;
description = "Guest network";
};
dmz = {
id = 400;
name = "DMZ";
effectiveId = 400;
description = "Public-facing servers (LXC containers)";
};
internal = {
id = 500;
name = "INTERNAL";
effectiveId = 500;
description = "Internal workstations and trusted devices";
};
};
}