Naming and Addressing #
How a site is addressed, how each thing on it gets an address, and how it gets a name.
The plan is fixed per site. How a thing gets an address and a name from that plan is deliberately boring for the substrate and deliberately different for tenants. This page sets out the plan, then the chain from declaration to address and name, where authority changes hands, and what each side is allowed to write.
The Site Address Plan #
Site Blocks #
Each site is assigned a /16 block from the 10.0.0.0/8 RFC1918 space:
| Site | Address Block |
|---|---|
| home | 10.10.0.0/16 |
| mobile | 10.20.0.0/16 |
The addressing pattern is: 10.{site_id}.{vlan_id}.0/24
- The second octet identifies the site
- The third octet matches the VLAN ID for that segment
- Each segment subnet is a /24 within the site’s /16
This creates a predictable, self-documenting address scheme where any IP immediately reveals which site and segment it belongs to.
Splitting the Site Block #
The pattern above describes substrate segments, where the third octet is a VLAN ID. Tenant
overlays are not VLANs, so they cannot be described by it. Each site’s /16 is therefore split,
per
ADR-0002:
| Block (mobile) | Purpose |
|---|---|
10.20.0.0/17 | Substrate segments β third octet = VLAN ID, as above |
10.20.128.0/18 | Tenant overlay subnets β 10.20.{128+n}.0/24 for tenant index n |
10.20.255.0/24 | Tenant fabric loopbacks / VTEP identity |
home mirrors this in 10.10.0.0/16. Keeping tenants inside the site block means there is still
exactly one aggregate per site to route β which matters in home dock mode, where home already
routes 10.20.0.0/16 to mobile and that route keeps covering tenants unchanged.
So the third octet also tells you which side of the line an address is on: below 128 is a
substrate segment, 128 and above is a tenant overlay.
Reserved VLAN Ranges #
| VLAN Range | Purpose |
|---|---|
| 10-40 | Core segment types (trusted, storage, platform, IoT, guest) |
| 50-59 | Tenant fabric transport (transit, underlay) β not a network per tenant |
| 60-69 | Reserved for future segment types |
| 70-79 | Experimental/lab segments |
| 99 | Management |
Gateway Convention #
Each subnet uses .1 as the gateway address:
10.10.30.1β home IoT segment gateway10.20.99.1β mobile management segment gateway
Host Addressing Ranges #
| Range | Purpose |
|---|---|
| .1 | Gateway (core router VLAN interface) |
| .2-.49 | Static infrastructure hosts |
| .50-.59 | Tenant-reserved addresses |
| .60-.69 | Reserved for future use |
| .70-.79 | Experimental/lab use β .79 is the transient image-build address (see
tenant hypervisors) |
| .100-.200 | DHCP dynamic pools (where applicable) |
Infrastructure hosts (routers, hypervisors, provisioners, switches, APs) receive static assignments in the low range. DHCP pools are used for segments with dynamic devices (trusted, IoT, guest).
WAN Operation Modes #
The mobile site operates in two WAN modes depending on physical location:
Travel Mode #
mobile operates behind dv02edg001p01 (travel router) with outbound NAT to upstream networks (hotel, tethered phone, etc.).
dv02edg001p01WAN: DHCP from upstreamdv02edg001p01LAN: 192.168.8.0/24 (unchanged, travel-router-local)- All mobile traffic NATs through
dv02edg001p01
Home Dock Mode #
When mobile is co-located with home, the mobile WAN connects to home’s trusted segment:
- mobile WAN IP: assigned from 10.10.10.0/24 (home trusted)
- home routes 10.20.0.0/16 to mobile’s WAN IP
- NAT is disabled on mobile’s WAN β traffic flows with clean source IPs
- Both sites can communicate with full visibility
This allows mobile devices to be reachable from home without double-NAT, while mobile retains its own addressing and can undock at any time.
How a Substrate Host Gets Its Address and Name #
Nothing on the substrate picks its own address, and nothing invents its own name. A single declared identity produces both:
graph LR
ID["Declared identity
(inventory)"] --> MAC["Hardware address"]
MAC --> RES["Address reservation"]
RES --> IP["Address"]
IP --> REC["Name record"]
REC --> NAME["service.site.deevnet.net"]
Every link is derived, not chosen:
| Link | Where it comes from |
|---|---|
| Identity β hardware address | Assigned from the estate’s own address namespace, derived from the host’s allocated identifier. Addresses on hardware we did not create are recorded as found, never rewritten. |
| Hardware address β address | A reservation on the address service, generated from inventory |
| Address β name | A record on the resolver, generated from the same inventory entry |
The consequence is that a host’s address is a fact about its declaration, not about the order it booted in. Rebuild it, and it comes back on the same address with the same name, because nothing along that chain was decided at runtime.
Reservations, Not Static Configuration #
Substrate hosts are addressed by reservation: they ask for an address, and the address service always gives them the same one because it recognises their hardware address. They are not configured with an address locally.
This looks like a detour β why not just configure the address on the host? β but it puts the addressing plan in one place that can be reviewed, and it means a host with a fresh operating system and no configuration at all still arrives at the right address. The declaration is authoritative; the host is disposable.
It also means the hardware address is load-bearing. A host whose hardware address does not match its declaration does not get its reserved address. It gets whatever the dynamic pool hands out, which is a working address that no name points at β a failure that looks like success until something tries to reach the host by name.
Segments Differ #
Not every segment is reservation-only. Segments carrying transient devices have dynamic pools; management and platform segments do not, because everything on them is declared. Where a pool and reservations coexist on one segment, the pool is positioned above the reserved range so the two cannot collide.
Tenants Address Themselves #
Tenant workloads do not use the substrate’s address service, and the reason is structural rather than preferential: a tenant’s network is an overlay owned by the tenant compute domain ( ADR-0001), and that overlay has no leasing service of its own.
So a tenant workload is given its address at creation time, from the tenant’s own code, derived from the tenant’s index ( ADR-0002). There is no reservation because there is nothing to reserve against.
| Substrate host | Tenant workload | |
|---|---|---|
| Address decided by | Reservation, from declared identity | The tenant’s own code, at creation |
| Address service involved | Yes | No |
| Survives a rebuild because | The reservation is derived from inventory | The address is derived from the tenant index |
Both are deterministic. They arrive there by different routes because they live on different networks with different capabilities, and pretending otherwise would mean adding a leasing service to the overlay purely for symmetry.
Two Naming Authorities #
Names split along the same seam as the tenant contract: the substrate names the things it runs, and a tenant names the things it runs.
graph TB
CLIENT["Any substrate client"] --> RESOLVER["Substrate resolver
site.deevnet.net"]
RESOLVER -->|"substrate names"| SUB["Answered directly
records generated from inventory"]
RESOLVER -->|"tenant zone"| AUTH["Tenant authoritative service"]
AUTH --> TEN["Answered from the tenant's zone
records written by the tenant"]
The substrate resolver answers for substrate names. Its records are generated from inventory by the same automation that generates the reservations, so the address and the name cannot disagree β they come from one declaration.
A tenant’s names live in a separate authoritative service. The substrate runs that service and creates each tenant’s zone, but it never writes a record into one. Records are tenant content ( ADR-0004).
This is the point of the arrangement. If tenant names lived in the substrate resolver, then either tenants would need to commit to a substrate repository to publish a name, or substrate reconciliation would be free to delete records it did not create. Separating the zone removes the conflict rather than managing it.
How a Query Reaches a Tenant Name #
This is the part worth being precise about, because the common shorthand is misleading.
A substrate client asks the substrate resolver for everything. When the name falls inside a tenant’s zone, the resolver forwards the query to the tenant authoritative service and returns its answer.
sequenceDiagram
participant C as Client
participant R as Substrate resolver
participant A as Tenant authoritative service
C->>R: api.tenant.site.deevnet.net?
R->>A: forwarded β this zone is yours
A->>R: answer from the tenant's zone
R->>C: answer
Forwarding Is Not Referral #
The resolver is configured with a rule of the form “for this zone, ask that server”. It is not following a delegation: no parent zone contains a referral to the tenant’s servers, and the resolver never asks the tenant zone which servers are authoritative for it.
That distinction has real consequences, and they are easy to miss:
- The tenant zone’s own apex records are never consulted on this path. A zone missing the records that name its own servers still resolves perfectly through the resolver, because nothing on this path ever looks at them. The defect is invisible from the client’s point of view β which is exactly how it went unnoticed until ADR-0005.
- Resolution depends on configuration, not on the DNS hierarchy. Anyone querying the tenant authoritative service directly gets the same answers; anyone querying the public hierarchy for these names gets nothing. These are internal names and that is intended.
- Anything that does validate the hierarchy will not be satisfied by this. A second authoritative server, a resolver that checks a child’s servers against its parent, or a genuine referral would all need the zone apex to be correct. Which is why it is maintained even though this path never reads it.
Calling it a delegation is fair as a description of ownership β the tenant owns the zone. It is inaccurate as a description of mechanism, and the difference is where the surprises live.
Two Write Paths #
The same split appears in how records get written.
| Substrate names | Tenant names | |
|---|---|---|
| Source of truth | Inventory | The tenant’s own IaC |
| Written by | Substrate automation, reconciling | The tenant, at deploy time |
| Transport | The resolver’s own configuration interface | Dynamic update, over the network |
| Authorisation | Access to the substrate repository | A credential scoped to that tenant’s zones |
| Blast radius of a mistake | The substrate zone | That tenant’s zone only |
The tenant’s credential is the part that makes the boundary real. It is issued per tenant and accepted only for that tenant’s zones, so a tenant writing outside its namespace is refused by the server rather than trusted not to try.
One qualification, recorded because the table above reads stronger than the truth: the credential is scoped to a zone, not to individual records within it. Everything inside a tenant’s own zone β including the apex records the substrate maintains β is writable by the tenant holding that credential. The namespace boundary is enforced; the boundary within a zone is a convention. See ADR-0005.
Reverse Names #
Reverse lookup follows the same shape. Each tenant gets a reverse zone alongside its forward zone, derived from the same tenant index, forwarded the same way, and populated β or not β by the tenant. Substrate reverse records are generated from inventory with everything else.
What This Arrangement Guarantees #
- A rebuilt host returns to its own address and name, because both derive from a declaration rather than from anything that happened at runtime.
- A rebuilt tenant restores its own names, with no substrate change, because the records were never substrate content.
- A rebuilt resolver loses no tenant names. Its share of the arrangement is one forwarding rule per tenant zone, regenerated from inventory; the records themselves were never in it.
- Neither side can quietly overwrite the other. They do not share a zone, so there is no reconciliation that could.
The cost is one more service to run and one more thing to be down. Tenant names depend on the authoritative service being up; substrate names do not, and continue to resolve if it is not.