Skip to main content
Every guest gets a 6-digit identity number, every network is a trust-ordered tier, and the two are wired together: a guest’s VMID announces which tier it belongs to, and that tier is its VLAN. Identity and placement stop being two facts to keep in sync — they become one fact, encoded once.
Most homelabs hand out VM IDs in arrival order — 100, 101, 102 — and pick a VLAN per service by hand. That works until it doesn’t: nothing about ID 137 tells you what it is or where it lives, and the mapping between guests and networks lives only in someone’s head. This model replaces both ad-hoc schemes with a single positional convention. The VMID encodes the guest’s role; the role’s tier number, times ten, is the VLAN it runs on. Sort the guests numerically and they fall into trust order for free. The page below is the high-level design rationale. The exhaustive, digit-by-digit allocation tables are intentionally not here — that detailed spec is maintained in the private infrastructure docs.

The VMID positional scheme

A VMID is six digits, each position carrying meaning. Read left to right, the digits go from coarsest grouping to finest:
[Tier][Sub-tier][Crit][Instance][OS][Env]
   │      │        │      │       │    │
   │      │        │      │       │    └─ environment (0 prod · 1 stg · 2 test · 3 dev · 4 sbx)
   │      │        │      │       └────── OS family (4 = LXC, the common case)
   │      │        │      └────────────── instance number within the group
   │      │        └───────────────────── criticality, rolling 0–9 (lower = more critical)
   │      └────────────────────────────── sub-tier (0 user-facing, 1 mgmt, 2 download)
   └───────────────────────────────────── trust tier (1–9)
Because the most significant digit is the tier and the next is the sub-tier, a plain numeric sort groups guests by tier, then sub-tier, then criticality — no tags, no naming convention to enforce, just arithmetic.
PositionMeaningNotes
TierTrust tier, 19Most-trusted (1) to least-trusted (9). Equals VLAN ÷ 10.
Sub-tierRole within the tier0 user-facing, 1 management (present in every tier), 2 download/ingest
CriticalityRolling 09Lower is more critical; 0 restore-first, 5 the default middle, 9 expendable
InstanceInstance counterDistinguishes siblings within the same group
OSOS family1 macOS · 2 Windows · 3 Docker · 4 LXC (most guests) · 5 Debian · 6 Ubuntu · 7 Fedora · 9 RHEL
EnvEnvironment0 prod · 1 staging · 2 test · 3 dev · 4 sandbox
A worked example — Plex, the media library’s user-facing service — decodes as 703040: tier 7 (media) · sub-tier 0 (user-facing) · criticality 3 (more critical than the default 5) · instance 0 · OS 4 (LXC) · env 0 (prod). Its tier digit is 7, so it lives on VLAN 70. Identity read off, network derived — same number.

Trust-ordered tiers map to VLANs

There are nine tiers, ordered from most-trusted core infrastructure down to untrusted and guest devices. Each tier’s VLAN tag is simply the tier number times ten, so the tier you read off a VMID is the network the guest belongs on.
TierVLAN tagNameWhat lives here
110Core servicesFoundational infrastructure everything else depends on
220StorageNAS, block/object storage, backup targets
330Data / pipeline / computeData movement, batch, general compute
440Observability & securityMonitoring, logging, security tooling
550AI / MLInference, training, model-serving workloads
660ApplicationsGeneral self-hosted application services
770MediaMedia library and its supporting services
880Home & IoTHome automation and IoT devices
990Untrusted / surveillance / guestCameras, guest access, anything least-trusted
Three special-purpose VLANs sit outside the tier numbering:
VLAN tagNamePurpose
1DefaultNative / fallback network
5ManagementInfrastructure management, including BMC / out-of-band
53DNSDedicated DNS network (named for port 53)
CIDR pattern, not the real subnet. Each VLAN’s subnet follows the pattern 192.168.<vlan-tag>.0/24 — the VLAN tag drops straight into the third octet. The real subnets are secret and injected at runtime, never committed; the pattern above is a placeholder shape, not a live address. UniFi zones group one or more VLANs by trust posture rather than mapping one zone per VLAN. The current zones are Management, Default, and IoT-Untrusted, with a DMZ zone planned for future externally-reachable workloads.

DHCP and DNS-first addressing

Guests do not carry hardcoded IP addresses. Each guest gets its address by DHCP and is referenced everywhere by name — {hostname}.{subdomain} — with DNS owning the actual IP. Infrastructure-as-code carries hostnames, not octets, so a guest can move, re-IP, or be rebuilt without rewriting any references to it. The one requirement that makes this work: every guest must have a defined hostname. A guest without a name has nothing for DNS to resolve, so the hostname is non-negotiable — it is the primary key.
ConcernDNS-first answer
What owns the IP?DNS — the address is a DHCP lease, resolved by name
What does IaC reference?{hostname}.{subdomain} — never a raw IP
When are static IPs used?The exception only: core network gear and servers that must be reachable before DNS is up
What must every guest have?A hostname — the requirement the whole model rests on

Deterministic MACs pin the reservations

“DHCP-first” does not mean “random address.” A guest can still get a stable address — the trick is to make the MAC deterministic and let a DHCP reservation do the pinning:
  1. The guest is declared dhcp: true; its identity is its FQDN, never an octet.
  2. Its MAC is derived from the hostname: the locally-administered prefix 02: followed by digits of the hostname’s MD5 digest. Same hostname → same MAC, on every rebuild, with no MAC ever stored by hand.
  3. A DHCP reservation in the network controller maps that MAC to a reserved host octet, so the lease the guest receives is always the same address.
  4. The DNS A record points at the reserved address — and only the DNS record holds it.
The derived {mac, reserved_ip} pair flows from the provisioning layer to the configuration layer through the IaC inventory contract, so no downstream repo ever hand-types either value. Rebuild the guest from scratch and it comes back with the same MAC, the same lease, and the same name — identity fully reconstructed from the hostname alone. Migration to this model is incremental, not a flag day. New guests adopt the convention immediately; existing guests move over as windows allow.

Target state, rolled out in phases

This is a design, and parts of it are still being realized. The honest status:
  • The tier ↔ VLAN renumber and re-homing of existing hosts onto their correct tiers are target-state. They are rolled out in phases as maintenance windows open, not all at once.
  • DHCP + DNS-first addressing is being adopted incrementally alongside the renumber.
Treat the tables above as the destination. The detailed, per-guest allocation and the live rollout state are maintained in the private infrastructure docs.

What this connects to

tofu-unifi

Networks, VLANs, zones, and firewall rules as code — where the tier-to-VLAN mapping is enforced.

tofu-proxmox

VMs and LXC containers — where VMIDs are assigned and guests are placed on their tier’s VLAN.

Infrastructure overview

How provisioning, configuration, and placement fit together across the homelab.

Scrubbed values

Why subnets here are patterns, not real addresses — the public-repo scrubbing rules.