inforge.yaml
The inforge.yaml file at the repo root is the project-level configuration. Every
inforge command reads it (unless --config overrides the path).
Full schema
name: my-infra # required — Pulumi project name (alphanumeric + hyphens)
backend:
type: file # required — one of: file, git-branch, s3, r2
url: file://.pulumi # used for "file" and "s3" types
branch: pulumi-state # used for "git-branch" type
providers: # optional — project-level provider defaults
compute: hetzner # default provider for all Compute resources
database:
postgresql: self-hosted # default provider for postgresql database-clusters
backups: # optional — self-hosted Postgres backup destination
bucket: wardnet-backups # a dedicated R2 bucket (distinct from state + artifacts)
Fields
name
The Pulumi project name. Must be unique per backend. Alphanumeric characters and hyphens only.
backend
Controls where Pulumi state is stored.
type: file
State stored in a local directory. Recommended for getting started.
backend:
type: file
url: file://.pulumi # relative path from repo root
type: git-branch
State stored on a dedicated git branch. inforge fetches the branch before apply and commits+pushes after a successful apply. Keeps state history out of the main branch.
backend:
type: git-branch
branch: pulumi-state # remote branch name (created if it doesn't exist)
type: s3
State stored in an S3-compatible bucket. Uses standard AWS credentials or environment variables.
backend:
type: s3
url: s3://my-bucket/inforge-state
Requires AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_REGION env vars,
or an IAM role.
type: r2
State stored in Cloudflare R2 (S3-compatible). inforge translates r2:// to the
correct S3-compatible endpoint automatically.
backend:
type: r2
url: r2://my-r2-bucket
Requires CLOUDFLARE_ACCOUNT_ID environment variable. R2 credentials are provided via
AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (R2 API token).
providers
An optional project-level block that sets default provider names for each resource class. Resources
that omit their provider: field inherit from here; an explicit provider: on a resource always
takes precedence.
providers:
compute: hetzner
database:
postgresql: self-hosted
compute— default provider name for all Compute resources. Network resources inherit this same default (there is no separatenetworkkey).database.<engine>— default provider for database-clusters of that engine. When unset it defaults toself-hosted— inforge installs and runs the engine on a compute host you provision (ADR-0036).
When providers: is omitted every Compute and Network resource must declare provider:
explicitly. Secrets need no provider configuration at all: inforge resolves a service's
vault:/ref:/grant values at deploy time and age-encrypts them directly to the target host's own
SSH key, delivering them over the same SSH connection inforge already uses to provision the host.
backups
The destination for self-hosted PostgreSQL backups (ADR-0036). Optional — only cluster hosts running a database with backups enabled read it.
backups:
bucket: wardnet-backups # a dedicated Cloudflare R2 bucket name
bucket— the R2 bucket name per-databasepg_dumparchives are uploaded to. It is authored flat (a bare bucket name, not anr2://URL or a path — inforge rejects a value containing:or/); the R2 endpoint is derived fromCLOUDFLARE_ACCOUNT_ID, exactly like the state/artifacts stores. Objects are keyed<env>/<region>/<cluster>/<database>/<timestamp>.dump.gz, so one bucket serves every environment and region (the region segment keeps a regional cluster's per-region backups apart).
The backups bucket must be distinct from both the state bucket and the artifacts bucket — inforge rejects the config otherwise. Backups hold sensitive full data with their own retention lifecycle, so they never colocate with Pulumi state or release tarballs.
Backups need a backup-scoped R2 credential delivered to each cluster host — the two reserved
secrets backups/r2_access_key_id and backups/r2_secret_access_key (see
inforge secret --reserved and
Database — Backups). A backups.bucket set with no credential fails
the deploy; a database with backups enabled and no backups.bucket configured also fails (set the
bucket, or opt the database out with backup.enabled: false).
Minimal example
name: my-infra
backend:
type: file
url: file://.pulumi