regions.yaml
Per-environment region file at resources/<env>/regions.yaml. It is the single authority for
which regions an environment deploys into and for all provider config — credentials plus each
region's realization. The keys under regions: are the deploy set; there is no separate selector.
Schema
regions: # required — one entry per region this env deploys into
us-east-1: # the abstract region name
slug: use1 # required — short code used in names, DNS, URNs
dns: # optional — this region's DNS authority (records are created on it)
provider: cloudflare # provider that owns the zone (credentials in providers.cloudflare)
zone: abc123 # zone id every derived record is created in
providers: # required — this region's provider config
hetzner: # credentials + this region's realization, in one block
apiToken: ${HCLOUD_TOKEN}
location: ash
network_zone: us-east
serverTypes: {SMALL: cx23, MEDIUM: cx33, LARGE: cx43}
images: {ubuntu-24.04: ubuntu-24.04}
cloudflare:
apiToken: ${CLOUDFLARE_API_TOKEN}
global: # optional — region-less slot (no slug)
placementRegion: us-east-1 # required when global: is present — must match a key under regions:
providers: # provider config for resources/<env>/global/
hetzner:
apiToken: ${HCLOUD_TOKEN}
location: ash
network_zone: us-east
serverTypes: {SMALL: cx23, MEDIUM: cx33, LARGE: cx43}
images: {ubuntu-24.04: ubuntu-24.04}
Fields
regions
A map from abstract region name (e.g. us-east-1) to that region's entry. The set of keys is exactly
the set of regions the environment deploys into: the single shared resource set under
resources/<env>/ is instantiated into every region listed here. Each resource's provider: must be
declared in every region's providers block, since the same set deploys into all of them.
Each entry has:
slug— the short location code the region maps to (e.g.us-east-1→use1). Slugs appear in display names, DNS names, and resource URNs. See Environments & Regions.providers— everything each provider needs for this region, one block per provider: credentials plus, for providers that place resources into regions (e.g. Hetzner), the region's realization directly in the block. A realization is the complete concretization of the region on that provider — for Hetzner:location,network_zone,serverTypes(size name → server-type SKU) andimages(canonical image → provider image id). Realizations are fully explicit per region: there are no built-in defaults and no inheritance, so each region's block is the whole truth (use YAML anchors to de-duplicate across regions). Credentials are typically${ENV_VAR}references supplied from the environment.
Resources select which provider handles them via their own provider: field — configuring a provider
here does not, by itself, route any resource to it. A resource's provider: must be declared in its
region's providers block.
dns
An optional per-region block naming the single DNS authority every derived record for that region
is created on. inforge does not have a hand-authored DNS resource: it derives the host (<compute>.vm),
service (<service>.svc) and vanity records automatically and creates them here (see DNS).
provider— the provider that owns the zone (e.g.cloudflare). Its credentials stay in the matchingprovidersblock (providers.cloudflare.apiToken); the authority carries only the selector and the zone.zone— the zone id records are created in (for Cloudflare, the zone id).
Different regions may declare different authorities. When a region omits dns, inforge creates no DNS
records for it.
global
An optional, region-less slot for resources that should exist once per environment rather than in
every region. Resources under resources/<env>/global/ realize against it with region-less names
(wardnet-<env>-<type>-<name>). When omitted, the environment has no global resources.
The global: block requires a placementRegion field naming one of the abstract regions
declared under regions: (e.g. us-east-1). It is validated now and will be used to select the
provider credentials and realization for global-slice resources. It does not affect resource names —
no slug is inserted into global cloud names. Omitting placementRegion when a global: block is
present is a validation error.
The global slice's DNS authority is the placement region's (dns: on that region), but its
providers come from global.providers — the two halves are read from different blocks. So
global.providers must itself carry the authority's provider block (e.g. cloudflare), or the
global DNS provider would be registered with an empty credential and every global record would fail
at apply. inforge validate enforces it; regions.yaml commonly reuses the region's block with a
YAML anchor:
regions:
us-east-1:
slug: use1
dns: &dns
provider: cloudflare
zone: ${CLOUDFLARE_ZONE_ID}
providers: &providers
hetzner: { apiToken: ${HCLOUD_TOKEN}, location: ash, network_zone: us-east }
cloudflare: { apiToken: ${CLOUDFLARE_API_TOKEN} }
global:
placementRegion: us-east-1
providers: *providers
regions.yaml replaces the built-in region table entirely. There is no default fallback: an
environment with no regions.yaml (or an empty regions: map) deploys nothing.
Example
regions:
eu-central-1:
slug: euc1
dns:
provider: cloudflare
zone: abcdef123456
providers:
hetzner:
apiToken: ${HCLOUD_TOKEN}
location: nbg1
network_zone: eu-central
serverTypes: {SMALL: cx23, MEDIUM: cx33, LARGE: cx43}
images: {ubuntu-24.04: ubuntu-24.04}
cloudflare:
apiToken: ${CLOUDFLARE_API_TOKEN}
global:
placementRegion: eu-central-1
providers:
hetzner:
apiToken: ${HCLOUD_TOKEN}
location: nbg1
network_zone: eu-central
serverTypes: {SMALL: cx23, MEDIUM: cx33, LARGE: cx43}
images: {ubuntu-24.04: ubuntu-24.04}