YAML File Mode
Reis supports declarative infrastructure management through YAML files. Define your resources in YAML, commit them to version control, and apply them with reis apply -f for repeatable, auditable deployments.
Prerequisites
Before applying resources, you must set an organisation context. Reis needs to know which organisation to apply resources to:
# Set your default organisation (interactive)
reis org:switch
# Or pass it explicitly on each apply
reis apply -f infrastructure.yml --org 550e8400-e29b-41d4-a716-446655440000
See Authentication for details on setting up credentials and your default organisation.
File format
Every YAML resource document uses a flat format — all fields are top-level alongside kind:
kind: <resource-type>
project: <project-handle> # required for project-scoped resources
handle: <resource-handle>
name: <display-name>
# resource-specific fields at the top level
Supported kinds
| Kind | Description |
container | Container deployment |
memcached | Memcached instance |
registry | Private registry credential |
secret | Encrypted secret |
project | Project |
Multi-document files
Combine multiple resources in a single file using the YAML document separator ---:
kind: secret
project: my-project
handle: db-password
name: Database Password
value: s3cret-value-here
---
kind: registry
project: my-project
handle: ghcr
name: GitHub Registry
server: ghcr.io
username: myuser
password: my-token
---
kind: container
project: my-project
handle: web-api
name: Web API
image: ghcr.io/myorg/api:v1.0.0
registry: ghcr
regions:
- falkenstein-1
- virginia-1
workload:
cpu: "500"
memory: "512"
port: "8080"
healthcheck: /healthz
env:
NODE_ENV: production
LOG_LEVEL: info
secrets:
DB_PASSWORD: db-password
scaling:
replicas: "2"
max_replicas: "8"
autoscalingtargetcpu: "70"
Resources are applied in the order they appear in the file. Define secrets and registries before containers that reference them.
Container fields
kind: container
project: my-project
handle: web-api
name: Web API
image: ghcr.io/myorg/api:v1.0.0
registry: my-registry # registry handle (for private images)
regions:
- falkenstein-1
- virginia-1
workload:
cpu: "500" # min CPU in millicores
memory: "512" # min memory in MB
port: "8080"
healthcheck: /healthz
bootstraptime: 30 # bootstrap time in seconds
env: # environment variables as key-value pairs
NODE_ENV: production
LOG_LEVEL: info
secrets: # env-var-name -> secret-handle
DB_PASSWORD: db-password
API_KEY: api-key
scaling:
replicas: "2"
max_replicas: "8"
autoscalingtargetcpu: "70" # percentage
autoscalingtargetmemory: "80" # percentage
storage:
ephemeral_storage_gb: 3 # 3 GB free, max 10 GB
persistent_volumes: # each replica gets its own copy
- name: data
mount_path: /data
size_gb: 10
observability:
prometheus_port: "9090"
prometheus_path: /metrics # default /metrics
Group structure
Container fields are organised into groups that mirror the console form accordions:
| Group | What it controls |
| (top level) | name, handle, image, project, registry, regions, type — identity and routing |
workload | CPU/memory, port, health check, env vars, secrets |
scaling | Manual replicas, autoscaling caps and targets |
storage | Ephemeral storage size, persistent volumes |
networking | Hostnames, DNS, external networking, www redirect |
observability | Prometheus scraping |
security | Basic auth, rate limiting, IP allow/deny lists |
proxy_cache | Kong proxy cache + managed memcached settings |
schedule | Cron expression, timezone, retry limits (cronjob only) |
Friendly field aliases
Reis maps friendly names to API fields automatically. The path is the group + the friendly name; the same friendly name can be reused under different groups (e.g. cpu under workload is CPU request; under quotas.request on a project YAML it's the namespace quota).
| YAML path | API field |
workload.port | containerport |
workload.cpu | mincpu |
workload.memory | minmemory |
workload.healthcheck | healthcheckpath |
workload.env | newenvvar |
workload.secrets | secretsenvvar |
regions | activeregions |
scaling.replicas | autoscalingminreplicas |
scaling.max_replicas | autoscalingmaxreplicas |
storage.ephemeral_storage_gb | ephemeralstoragegb |
storage.persistent_volumes | persistentvolumes |
observability.prometheus_port | prometheusport |
observability.prometheus_path | prometheuspath |
Memcached fields
kind: memcached
project: my-project
handle: session-cache
name: Session Cache
regions:
- falkenstein-1
tuning:
memory: 256 # memory per node in MB
max_connections: 1024
threads: 4
max_item_size_mb: 1
topology:
nodes: 2
mode: cluster
Memcached field mapping
| YAML path | API field |
tuning.memory | memorymb |
tuning.max_connections | maxconnections |
tuning.max_item_size_mb | maxitemsizemb |
regions | activeregions |
Registry fields
kind: registry
project: my-project
handle: ghcr
name: GitHub Registry
server: ghcr.io
username: myuser
password: ghp_xxxxxxxxxxxx
Secret fields
kind: secret
project: my-project
handle: db-password
name: Database Password
value: s3cret-value-here
Project fields
kind: project
handle: my-project
name: My Project
regions:
- falkenstein-1
- virginia-1
Project quotas (read-only display)
When you reis get an existing project, you'll also see a quotas: block showing the namespace quotas the platform has applied. These values are display-only — Reis silently ignores any edits you make under quotas: when you re-apply the file, so you can round-trip without manual cleanup.
kind: project
handle: my-project
name: My Project
regions: [falkenstein-1, virginia-1]
quotas: # read-only — set by the platform
request:
cpu: 1000m
memory: 1G
limit:
cpu: 2000m
memory: 2G
Create-or-update semantics
When you run reis apply -f, Reis looks up each resource by its handle:
- If the resource does not exist, it is created
- If the resource already exists, it is updated with the values from the YAML file
This makes reis apply idempotent — running it multiple times with the same file produces the same result.
Dry run
Validate a YAML file without making any changes:
reis apply -f infrastructure.yml --dry-run
Dry run does not require authentication. It parses the file, validates the structure, and shows what resources would be created or updated.
Exporting resources
Export any existing resource to YAML format:
# Export to stdout
reis export container web-api --project my-project
# Export to file
reis export container web-api --project my-project --file web-api.yml
The exported YAML uses the same format that reis apply expects, so you can export, modify, and re-apply.
Tips
- Order matters in multi-document files. Define secrets and registries before the containers that reference them.
- Use handles, not UUIDs. Handles are immutable in Bahriya and are the primary identifier in YAML files.
- Environment variables can be specified as a YAML map (
KEY: value). Reis converts them to the API format automatically.
- Commit your YAML files to version control for an audit trail of infrastructure changes.
- Use dry run to validate changes before applying them, especially in CI/CD pipelines.