Skip to content

Stack with dependencies

A stack is a single YAML file containing multiple kind: Application documents separated by ---, with metadata.dependsOn declaring the order. edgible stack deploy resolves the graph and applies each application in order.

Use this when you have separate applications that need to be deployed together — for example, a database, an API, and a web frontend, where the API must be up before the frontend can start.

This shape (multiple applications, joined by metadata.dependsOn):

metadata:
name: api
dependsOn: [db]

versus this shape (one application with multiple workloads, joined by workload-level dependsOn):

workloads:
- name: db
type: compose
composeFile: ./db.yml
- name: api
type: compose
composeFile: ./api.yml
dependsOn: [db]

Choose multi-workload when the pieces are tightly coupled — they always deploy together, share a lifecycle, and live on the same device. Choose a stack when the pieces are loosely coupled — different teams own them, they can be updated independently, and they may live on different devices.

Save as stack.yml:

stack.yml
apiVersion: v3
kind: Application
metadata:
name: stack-db
organization: <your-org-id>
spec:
placement:
strategy: serving-device
deviceSelector: { deviceName: my-server }
workloads:
- name: db
type: compose
composeFile: ./docker-compose-db.yml
ports:
- { name: pg, containerPort: 5432, protocol: tcp }
access:
- name: pg
type: tcp
target: { workload: db, port: pg }
listenPort: 5432
publish: false
---
apiVersion: v3
kind: Application
metadata:
name: stack-api
organization: <your-org-id>
dependsOn: [stack-db]
spec:
placement:
strategy: serving-device
deviceSelector: { deviceName: my-server }
workloads:
- name: api
type: compose
composeFile: ./docker-compose-api.yml
ports:
- { name: http, containerPort: 8080, protocol: tcp }
access:
- name: api
type: https
target: { workload: api, port: http }
hostname: { custom: api.example.com }
tls: { managedBy: edgible }
policies: { auth: { modes: [api-key] } }
---
apiVersion: v3
kind: Application
metadata:
name: stack-web
organization: <your-org-id>
dependsOn: [stack-api]
spec:
placement:
strategy: serving-device
deviceSelector: { deviceName: my-server }
workloads:
- name: web
type: compose
composeFile: ./docker-compose-web.yml
ports:
- { name: http, containerPort: 3000, protocol: tcp }
access:
- name: web
type: https
target: { workload: web, port: http }
hostname: { custom: app.example.com }
tls: { managedBy: edgible }
policies: { auth: { modes: [edgible-login] } }

The db application has a tcp access entry with publish: false — it’s reachable from other workloads in the same device pool over the WireGuard mesh, but not from the public internet.

Terminal window
edgible stack deploy -f stack.yml

The CLI:

  1. Reads every kind: Application document in the file.
  2. Builds a topological order from metadata.dependsOn.
  3. Applies them in order: stack-dbstack-apistack-web.
  4. Waits for each to reach ready before moving to the next.

If the graph contains a cycle, validation rejects the file before any deploy.

Terminal window
edgible stack status -f stack.yml

Shows status across all applications in the file as a single view.

Terminal window
edgible stack diff -f stack.yml

Prints the real plan of what applying the file would do — + create, ~ update (with the exact path: from → to changes), = in sync, and ! orphaned — plus a Plan: summary. This is the same output as stack deploy --dry-run. Orphaned applications are those live in your org but not declared in this file (they may belong to another stack or an imperative application create); they are shown so you notice them, and a deploy never touches them — removal is always the explicit stack teardown or application delete. See the stack reference for the full plan format.

Terminal window
edgible stack validate -f stack.yml

Checks the file against the schema and the dependency graph without contacting the control plane.

Terminal window
edgible stack teardown -f stack.yml

Removes every application in the file in reverse-dependency order: stack-webstack-apistack-db. Storage attached to any application is released as that application is removed.

Nothing forces every application in a stack to run on the same device. The same file can pin the database to one serving device and the API to another:

metadata: { name: stack-db, ... }
spec:
placement: { strategy: serving-device, deviceSelector: { deviceName: data-box } }
...
---
metadata:
name: stack-api
dependsOn: [stack-db]
spec:
placement: { strategy: serving-device, deviceSelector: { deviceName: web-box } }
...

Useful for keeping data on a dedicated box while running the public-facing tier on another device you own.