Network Configuration
Defines named network topologies with subnets and peering references. YAML files declare address
spaces, subnet CIDRs, and network peering intent — validated by strata (including CIDR overlap
detection) and built into networks.auto.tfvars.json for Terraform consumption.
When to Use
Use the network kind when you want to:
Define address spaces and named subnets as code alongside your infrastructure
Catch CIDR overlap and containment errors before Terraform ever runs
Give resources a validated subnet reference (
spoke_app/frontend) instead of hardcoded CIDRsSupport per-environment CIDR flexibility via variable or secret references
Out of scope: Route tables, NSG rules (use the firewall kind), provider-specific subnet properties (delegations, service endpoints), and peering configuration (routes, gateways). Strata models the topology intent — Terraform handles provider-specific implementation.
Schema
apiVersion: strata.huybrechts.xyz/v1
kind: network
meta:
name: <resource_name> # Required: ^[a-z][a-z0-9_]*$
annotations:
description: <description>
labels:
version: "<version>"
spec:
references: # Optional: declare keys used by var/secret CIDRs
variables:
- <var_key> # Resolved from environment variables at build time
secrets:
- <secret_key> # Injected as TF_VAR_<key> at deploy time
networks:
- name: <network_name> # Required: unique within spec
description: <text> # Optional
address_space:
- value: <cidr> # one of: literal CIDR notation
var: <key> # one of: variable key from spec.references.variables
secret: <key> # one of: secret key from spec.references.secrets
subnets:
- name: <subnet_name> # Required: unique within network
description: <text> # Optional
cidr:
value: <cidr> # one of: literal CIDR
var: <key> # one of: variable key
secret: <key> # one of: secret key
peerings: # Optional
- name: <peering_name> # Required: unique within network
target: <network> # Required: name of target network in this spec
Top-level Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
object |
No |
Variable and secret key declarations. Required when any CIDR uses |
|
array |
Yes |
One or more network definitions. At least one required. |
spec.references Fields
Declares the variable and secret keys that CIDRs in this file may reference. Required when
any address space or subnet CIDR uses var: or secret:.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
list of strings |
No |
Keys resolved from environment variables at build time. |
|
list of strings |
No |
Keys injected as |
Network Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Network name — unique within |
|
string |
No |
Human-readable description of the network’s purpose. |
|
array |
Yes |
One or more CIDR ranges for this network. Each entry is a |
|
array |
Yes |
At least one subnet required per network. |
|
array |
No |
Peering references to other networks in the same spec. |
CidrSource Fields
A CIDR value with three mutually exclusive source types. Used for both address_space entries
and subnet cidr values.
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
one of |
Literal CIDR notation (e.g. |
|
string |
one of |
Variable key from |
|
string |
one of |
Secret key from |
Exactly one of
value,var, orsecretmust be set per CIDR source.
Subnet Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Subnet name — unique within the parent network. |
|
string |
No |
Human-readable description of the subnet’s purpose. |
|
CidrSource |
Yes |
Single CIDR for this subnet. Same value/var/secret union. |
Peering Fields
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Peering name — unique within the parent network. |
|
string |
Yes |
Name of the target network. Must exist in |
v1 scope: Peerings are lightweight
(name, target)references only — no routing config, gateway settings, or direction. Strata declares the intent to peer; Terraform implements it.
Examples
Haven (simple flat network)
A home lab with a single network and three subnets — about 12 lines of spec:
apiVersion: strata.huybrechts.xyz/v1
kind: network
meta:
name: haven_network
annotations:
description: "Home lab flat network"
spec:
networks:
- name: home_lab
address_space:
- value: "10.0.0.0/16"
subnets:
- name: default
cidr:
value: "10.0.0.0/24"
- name: services
cidr:
value: "10.0.1.0/24"
- name: management
cidr:
value: "10.0.2.0/24"
Enterprise (multi-network with peerings and variable CIDRs)
A hub-and-spoke topology where address spaces vary by environment. The hub uses literal CIDRs
for well-known subnets; spoke address spaces are injected from environment variables so dev
gets 10.1.0.0/16 while prod gets 10.100.0.0/16:
apiVersion: strata.huybrechts.xyz/v1
kind: network
meta:
name: contoso_networking
annotations:
description: "Contoso enterprise network topology"
labels:
region: westeurope
spec:
references:
variables:
- hub_address_space
- spoke_app_address_space
- spoke_data_address_space
secrets: []
networks:
- name: hub_vnet
address_space:
- var: hub_address_space
subnets:
- name: gateway
cidr:
value: "10.0.0.0/27"
description: "VPN/ExpressRoute gateway subnet"
- name: firewall
cidr:
value: "10.0.0.32/26"
description: "Azure Firewall subnet"
- name: bastion
cidr:
value: "10.0.0.128/26"
description: "Azure Bastion subnet"
- name: management
cidr:
value: "10.0.1.0/24"
- name: spoke_app
address_space:
- var: spoke_app_address_space
subnets:
- name: frontend
cidr:
value: "10.1.0.0/24"
- name: backend
cidr:
value: "10.1.1.0/24"
- name: integration
cidr:
value: "10.1.2.0/24"
peerings:
- name: to_hub
target: hub_vnet
- name: spoke_data
address_space:
- var: spoke_data_address_space
subnets:
- name: database
cidr:
value: "10.2.0.0/24"
- name: analytics
cidr:
value: "10.2.1.0/24"
peerings:
- name: to_hub
target: hub_vnet
CIDR Overlap Detection
The core value of the network kind is catching CIDR misconfigurations before Terraform runs.
Strata performs three levels of overlap validation:
Subnet-to-subnet overlap
Subnets within the same network must not overlap each other. For example, 10.0.0.0/24 and
10.0.0.128/25 overlap — strata rejects this at validation time.
Subnet containment
Every subnet CIDR must fit within its parent network’s address space. A subnet of 10.1.0.0/24
in a network with address space 10.0.0.0/16 fails validation — the subnet is outside the
network boundary.
Cross-network overlap
When two networks have overlapping address spaces:
Peered networks — hard error. Azure, AWS, and GCP all reject peered networks with overlapping CIDRs. Strata catches this before
terraform planwastes time.Non-peered networks — warning. Overlapping address spaces in isolated networks may be intentional (e.g., dev and staging reusing
10.0.0.0/16in separate environments).
Variable and secret CIDRs
When a CIDR uses var: or secret:, overlap checks are deferred. At parse time, strata
validates syntax only. At build time, after variable injection resolves CIDRs to literal values,
the service re-validates the merged result. This matches how DNS handles var-sourced record
values.
Cross-Kind References
Resources in the workspace reference subnets using a qualified <network_name>/<subnet_name>
format on the subnet field:
# workspace.yaml
spec:
resources:
- name: app_server
file: "@infra/resources/vm-app.yaml"
subnet: "spoke_app/frontend"
firewalls:
- app_firewall
The qualified format avoids ambiguity in multi-network setups — two networks could both have
a subnet named default. During validation, strata checks that every resource.subnet
reference resolves to a declared <network>/<subnet> in the loaded network definitions.
Variable and Secret CIDRs
CIDRs support three mutually exclusive value sources. Choose based on how environment-specific and sensitive the address space is.
Source |
Use when |
Build behaviour |
|---|---|---|
|
The CIDR is the same in every environment |
Written literally to |
|
The CIDR varies by environment but is not sensitive |
Resolved from |
|
The CIDR is sensitive (e.g., enterprise topology is classified) |
Not written to |
var: — build-time variable resolution
When a CIDR uses var: <key>, strata resolves <key> from the spec.variables section of
your active environment.yaml at strata build run and writes the resolved value into
networks.auto.tfvars.json. Declare the key in both places:
spec.references.variablesin the network YAML filespec.variablesin the matchingenvironment.yaml
secret: — deploy-time injection
When a CIDR uses secret: <key>, the value is emitted as null in networks.auto.tfvars.json
and the key is registered in tf_required_secrets.json. The value is never stored on disk by
strata. Ensure it is available as TF_VAR_<key> when Terraform runs.
Declare the key in both places:
spec.references.secretsin the network YAML filespec.secretsin the matchingenvironment.yaml
Linking to a Workspace
Reference one or more network definition files from your workspace YAML using spec.networks:
# workspace.yaml
spec:
networks:
- name: hub_networking
file: "@infra/networks/hub.yaml"
- name: spoke_networking
file: "@infra/networks/spokes.yaml"
Field |
Type |
Required |
Description |
|---|---|---|---|
|
string |
Yes |
Unique name. Used as the outer key in |
|
string |
Yes |
Path to the network YAML file. Supports |
Names must be unique across all networks entries in the workspace.
Build Output
Running strata build run generates networks.auto.tfvars.json in the build directory:
build/<deployment>/
networks.auto.tfvars.json ← consumed by your Terraform networking module
firewalls.auto.tfvars.json
dns.auto.tfvars.json
platform.json
...
The file serialises networks, subnets, and peerings as a JSON variable file. Subnets and
peerings are keyed by name — designed for Terraform for_each iteration. Your Terraform
module reads it via a variable "networks" { ... } declaration and *.auto.tfvars.json
auto-load.
Validation Rules
Rule |
Enforcement |
|---|---|
|
Pydantic / model load |
Exactly one of |
Model validator |
Literal |
Model validator |
Network names must be unique within |
Model validator |
Subnet names must be unique within each network (V4) |
Model validator |
Peering |
Model validator |
No self-peering — peering target must not equal the network’s own name (V6) |
Model validator |
Peering names must be unique within each network (V7) |
Model validator |
|
Model validator |
Subnets within a network must not overlap each other (V9) |
Model validator |
Subnets must fit within their network’s address space (V10) |
Model validator |
Cross-network address space overlap: warning (non-peered) or error (peered) (V11) |
Model validator |
Resource |
Dynamic validation |
All |
Build-time |
Merge Behaviour
When multiple network files are referenced in a workspace, strata merges them into a single topology before validation:
Element |
Strategy |
|---|---|
Network names |
Merge by name — last-wins for metadata and address space |
Subnets within network |
Merge by |
Peerings |
Merge by |
Meta (annotations) |
Shallow merge — last-wins per key |
References |
Union — all declared variables and secrets accumulated |
Post-merge validation: After merging, strata re-runs CIDR overlap detection on the combined result. Two files may each be valid independently but create overlaps when combined.
Template
Create a new network configuration file from the built-in template:
strata new network my-networks --path config/networks/
Best Practices
Use literal CIDRs for well-known subnets (gateway, firewall, bastion) that never change across environments. Reserve
var:for address spaces that differ per environment.One file per topology — group hub and spoke networks together when they form a logical unit. Split only when different teams own different network segments.
Name subnets by purpose (
frontend,database,management), not by CIDR range.Comment subnets with their intended workload using the
descriptionfield or YAML inline comments.Naming: Lowercase with underscores (
haven_network,contoso_networking).