Application YAML (v3)
The canonical Application format used by edgible stack deploy. One YAML document describes one application; multiple documents in a single file are separated by ---.
The schema is enforced by the control plane and the agent. Unknown keys are rejected.
Top level
Section titled “Top level”apiVersion: v3kind: Applicationmetadata: { ... }spec: { ... }| Field | Required | Type | Notes |
|---|---|---|---|
apiVersion | yes | v3 | The only supported value today. |
kind | yes | Application | The only supported value today. |
metadata | yes | object | See Metadata. |
spec | yes | object | See Spec. |
Metadata
Section titled “Metadata”metadata: name: my-app organization: <org-id> labels: env: production annotations: owner: platform-team dependsOn: [other-app-name]| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Unique within the organization. Lowercase alphanumeric with hyphens, 1–63 chars. |
organization | yes | string | Your organization ID. Find with edgible config list. |
labels | no | map | Free-form key/value strings. Used by placement.deviceSelector.labels. |
annotations | no | map | Free-form key/value strings. Not interpreted by the platform. |
dependsOn | no | string[] | Names of other applications that must be deployed before this one. |
spec: placement: { ... } workloads: [ ... ] storage: [ ... ] # optional access: [ ... ] # optional but typical cloud: { ... } # optional, only valid when placement.strategy is cloud or automaticspec.workloads is the only required field. At least one workload must be declared.
spec.placement
Section titled “spec.placement”Where the application runs. Three strategies, with different required fields.
# Run on a specific device you ownplacement: strategy: serving-device deviceSelector: deviceName: my-first migrationPolicy: manual# Run on Edgible-managed cloud infrastructureplacement: strategy: cloud region: us-east-1# Let the platform pick (cloud or device based on capabilities)placement: strategy: automatic| Field | Required | Type | Notes |
|---|---|---|---|
strategy | yes | enum | serving-device, cloud, or automatic. |
deviceSelector | required for serving-device | object | See below. |
region | required for cloud | string | Edgible cloud region (e.g., us-east-1). |
migrationPolicy | no | enum | manual (default), allowed, or automatic. Governs whether the application can be moved between devices. See Migrate between devices. |
placement.deviceSelector
Section titled “placement.deviceSelector”At least one selector field is required.
| Field | Type | Notes |
|---|---|---|
deviceName | string | Pin to a device by name. |
deviceId | string | Pin to a device by ID. |
labels | map | Match devices that carry these labels. |
region | string | Match devices in this region. |
capabilities | string[] | Match devices that report these capabilities (e.g., gpu, kvm). |
spec.workloads[]
Section titled “spec.workloads[]”A list of one or more workloads. Common fields apply to every type:
workloads: - name: api type: compose | docker | managed-process | vm | pre-existing ports: [ ... ] storage: [ ... ] # optional env: { ... } # optional envFrom: [ ... ] # optional healthChecks: [ ... ] # optional resources: { ... } # optional restartPolicy: always # optional dependsOn: [ ... ] # optional, names of other workloads| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Unique within the application. |
type | yes | enum | One of compose, docker, managed-process, vm, pre-existing. |
ports | usually | array | Ports the workload listens on. Required if access[] references this workload. |
storage | no | array | Volumes from spec.storage[] to mount. |
env | no | map | String-to-string environment variables. |
envFrom | no | array | Environment from secret references. See envFrom. |
healthChecks | no | array | See Health checks. |
resources | no | object | CPU/memory requests and limits. See Resources. |
restartPolicy | no | enum | always, on-failure, or never. |
dependsOn | no | string[] | Names of other workloads in this application that must start first. |
type: compose
Section titled “type: compose”- name: api type: compose composeFile: ./api.compose.yml projectName: api # optional| Field | Required | Type | Notes |
|---|---|---|---|
composeFile | yes | string | Path to a Docker Compose file relative to the application YAML, OR base64:<encoded yaml> (the agent decodes it before invoking compose). |
projectName | no | string | Override the compose project name. Defaults to the workload name. |
type: docker
Section titled “type: docker”A single image, no compose file.
- name: redis type: docker image: redis:7-alpine command: ["redis-server"] args: ["--appendonly", "yes"]| Field | Required | Type | Notes |
|---|---|---|---|
image | yes | string | A pullable image reference. |
command | no | string[] | Override the image’s ENTRYPOINT. |
args | no | string[] | Override the image’s CMD. |
type: managed-process
Section titled “type: managed-process”A long-running native process supervised by the agent.
- name: worker type: managed-process command: "./bin/worker --queue jobs" workingDir: /opt/app logFile: /var/log/edgible/worker.log| Field | Required | Type | Notes |
|---|---|---|---|
command | yes | string | Command line. The agent splits on whitespace; no shell expansion. |
workingDir | no | string | CWD for the process. Defaults to the agent’s working directory. |
logFile | no | string | Where stdout/stderr are written. |
type: vm
Section titled “type: vm”A virtual machine. The disk can be declared inline (legacy) or via a storage[] mount (recommended; required for migration).
# Recommended: storage-backed disk- name: legacy type: vm vmBackend: qemu memory: 2048 cpus: 2 storage: - { name: vm-disk, mountPath: /disk }# Legacy: inline disk image path on the host- name: legacy type: vm vmBackend: qemu diskImage: /var/lib/edgible/vms/legacy.qcow2 memory: 2048 cpus: 2| Field | Required | Type | Notes |
|---|---|---|---|
vmBackend | yes | enum | qemu, wsl, or firecracker. |
memory | yes | number | MiB. |
cpus | yes | number | Virtual CPUs. |
diskImage | one of | string | Host path to a disk image. Mutually exclusive with a storage[] disk. |
storage[] | one of | array | A storage mount referencing spec.storage[]. The first mount is the disk. |
vmArch | no | enum | x86_64 or aarch64. |
sshPort | no | number | SSH port to expose to the agent. |
sshPublicKey | no | string | Public key to inject. |
vmExtraArgs | no | string[] | Extra args passed to the backend. |
type: pre-existing
Section titled “type: pre-existing”Tells Edgible to forward to a process or service that’s already running on the device — useful for adopting an existing service without changing how it runs.
- name: legacy-svc type: pre-existing hostPort: 8080 hostAddress: 127.0.0.1 # optional, defaults to localhost| Field | Required | Type | Notes |
|---|---|---|---|
hostPort | no | number | A port already listening on the device. Required unless the workload only declares ports[] for access targeting. |
hostAddress | no | string | Address the existing service listens on. Defaults to 127.0.0.1. |
spec.workloads[].ports[]
Section titled “spec.workloads[].ports[]”ports: - { name: http, containerPort: 8080, protocol: tcp } - { name: dns, containerPort: 53, protocol: udp }| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Used by access entries and health checks to reference this port. |
containerPort | yes | number | The port number the workload listens on. |
protocol | no | enum | tcp (default) or udp. |
spec.workloads[].storage[]
Section titled “spec.workloads[].storage[]”Mounts a volume declared in spec.storage[].
storage: - { name: pgdata, mountPath: /var/lib/postgresql/data } - { name: cache, mountPath: /tmp/cache, readOnly: false }| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Must match a spec.storage[].name. |
mountPath | yes | string | Absolute path inside the workload. |
readOnly | no | bool | Mount read-only. |
Health checks
Section titled “Health checks”healthChecks: - { type: http, port: http, path: /healthz, intervalSeconds: 10 } - { type: tcp, port: db, intervalSeconds: 30 } - { type: exec, command: ["pg_isready"], intervalSeconds: 60 }| Field | Required | Type | Notes |
|---|---|---|---|
type | yes | enum | http, tcp, or exec. |
port | http/tcp | string | Port name from ports[]. |
path | http | string | URL path to GET. |
command | exec | string[] | Command to run inside the workload. |
intervalSeconds | no | number | How often to probe. |
timeoutSeconds | no | number | Probe timeout. |
failureThreshold | no | number | Consecutive failures before the workload is marked unhealthy. |
Resources
Section titled “Resources”resources: requests: cpu: "500m" memory: 512Mi limits: cpu: "2" memory: 2Gi| Field | Type | Notes |
|---|---|---|
requests.cpu / limits.cpu | string | Cores or millicores (e.g., 2, 500m). |
requests.memory / limits.memory | string | Size string (e.g., 512Mi, 2Gi). |
Honored by compose, docker, and vm workloads where the backend supports it.
envFrom
Section titled “envFrom”Inject environment variables from a secret stored in the platform.
envFrom: - name: DATABASE_URL secretRef: { secret: prod-db, key: url } - name: API_TOKEN secretRef: { secret: prod-api } # whole secret as the value| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Env var name to set inside the workload. |
secretRef.secret | yes | string | Secret identifier in the platform. |
secretRef.key | no | string | Field within the secret. |
spec.storage[]
Section titled “spec.storage[]”Application-level storage volumes. Each entry is a logical volume that one or more workloads can mount.
storage: - name: pgdata type: persistent size: 20Gi mobility: movable backup: enabled: true scheduleCron: "0 3 * * *" retainCount: 7 encryption: enabled: true keyRef: { secret: storage-key }| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Referenced by workloads[].storage[].name. |
type | yes | enum | persistent or ephemeral. |
size | required for persistent | string | Size like 20Gi, 500Mi. |
driver | no | string | Storage driver hint. Most users leave unset. |
mobility | no | enum | immovable (default), movable, replicated, or cloud-only. See below. |
backup | no | object | { enabled, scheduleCron, retainCount }. |
encryption | no | object | { enabled, keyRef }. |
Mobility values:
immovable— bound to the device it was created on; cannot migrate.movable— the volume can be quiesced, snapshotted, transferred, and restored on another device. Required for Migrate between devices.replicated— the volume is kept consistent on more than one device.cloud-only— only valid withplacement.strategy: cloudorautomatic. Rejected onserving-device.
spec.access[]
Section titled “spec.access[]”Public-facing entry points. Each entry exposes a workload port through Edgible’s edge.
access: # HTTPS with a generated edgible.app hostname - name: public type: https target: { workload: web, port: http } hostname: { generated: true } tls: { managedBy: edgible } publish: true policies: auth: { mode: none }
# HTTPS with one or more custom domains - name: api type: https target: { workload: api, port: http } hostname: { custom: api.example.com } tls: { managedBy: edgible } policies: auth: { mode: api-key } ipRules: allow: ["10.0.0.0/8", "192.168.0.0/16"] rateLimit: requestsPerMinute: 600 burst: 100
# Raw TCP - name: postgres type: tcp target: { workload: db, port: pg } listenPort: 5432
# Raw UDP - name: dns type: udp target: { workload: dns, port: dns } listenPort: 53| Field | Required | Type | Notes |
|---|---|---|---|
name | yes | string | Unique within the application. |
type | yes | enum | https, tcp, or udp. |
target.workload | yes | string | A name from spec.workloads[]. |
target.port | yes | string | A port name from that workload. |
hostname | https only | object | { generated: true } OR { custom: <fqdn> } OR { custom: [<fqdn>, ...] }. |
tls | https only | object | { managedBy: edgible } (default) or { managedBy: passthrough }. |
listenPort | tcp/udp only | number | Public port the platform listens on. |
publish | no | bool | Defaults to true. If false, the route is configured but not exposed publicly. |
policies | no | object | See Policies. |
Policies
Section titled “Policies”Available on every access type, with tcp/udp supporting only ipRules and rateLimit.
| Field | Type | Notes |
|---|---|---|
auth.mode | enum | none, edgible-login, api-key, or short-code. See Authentication modes. |
auth.allowedOrganizations | string[] | When mode: edgible-login, restrict to specific orgs. |
apiKey.required | bool | Force an API key in addition to the primary auth.mode. |
shortCode.required | bool | Force a short code in addition to the primary auth.mode. |
ipRules.allow | string[] | CIDR allow-list. |
ipRules.deny | string[] | CIDR deny-list. |
rateLimit.requestsPerMinute | number | Per-source request budget. |
rateLimit.burst | number | Allowed burst above the steady rate. |
waf.enabled | bool | Enable web-application firewall. |
waf.mode | enum | enforce or log-only. |
spec.cloud
Section titled “spec.cloud”Cloud-specific behavior. Only valid when placement.strategy is cloud or automatic. Rejected on serving-device.
cloud: sleep: enabled: true idleAfter: 5m wake: sync minActive: 1 classes: compute: standard storage: ssd isolation: dedicated| Field | Type | Notes |
|---|---|---|
sleep.enabled | bool | Suspend the workload after it goes idle. |
sleep.idleAfter | duration | How long to wait before sleeping (30s, 5m, 1h). |
sleep.wake | enum | sync (block the request while waking) or async (return immediately, wake in background). |
minActive | number | Minimum active instances. 0 allows full sleep. |
classes.compute / .storage / .isolation | string | Class hints to the cloud scheduler. |
See Cloud sleep and wake for tuning guidance.
Multi-document files
Section titled “Multi-document files”You can put several Applications in one file, separated by ---:
apiVersion: v3kind: Applicationmetadata: name: db organization: <org-id>spec: { ... }---apiVersion: v3kind: Applicationmetadata: name: api organization: <org-id> dependsOn: [db]spec: { ... }edgible stack deploy -f all.yml deploys both, in dependsOn order. See Stack with dependencies for the full pattern.