Overview
An app is a program that runs all the time: a website, an API, a worker. You give EnclaveStack a container image, or a Git repository with a Dockerfile, and it keeps the app running, restarts it when it stops and deploys every change without taking it down.
Apps get settings as environment variables, secrets decrypted at start, private names other resources reach them by, and, with a domain, a web address with HTTPS.
When to use it
- A website or API to put online.
- A worker that reads from a queue.
- Several copies of a service behind one name.
- Code in a Git repository you want built and run on push of a button.
How it works
- Docker Engine
- Each copy of an app is a container on the machine’s Docker Engine, driven through its API.
- Revisions
- Every deploy is a numbered revision (es-app-<name>-r<N>); revisions share the app’s private name.
- Health probes
- HTTP, TCP or command checks run before a new revision takes traffic.
- Builds from Git
- A shallow clone (go-git) built through the engine’s build API, tagged per revision.
- Caddy edge
- Domains reach the app through the edge proxy, which follows the app’s replicas.
You describe the app; the control plane stores it and the reconciler makes it real. Each change becomes a new revision: its containers start next to the serving ones, health checks must pass, then traffic switches, the old revision drains and stops.
A revision is 1 – 10 replicas. All of them answer to the app’s private name (<name>.app.internal), so other resources and the edge spread requests across them. Publishing binds one host port on this machine instead.
Secrets named in the app are decrypted from the store at deploy time and handed to the containers as environment variables; they never appear in the API, events or logs.
Architecture
- Visitor to Edge (Caddy): HTTPS
- Edge (Caddy) to Revision r1: proxy
- Other resources to Private name: by name
- Private name to Revision r1
- Revision r1 to Volume: mount
- Secrets to Revision r2: env
Flows
Deploying a change
- You change the image, a setting or press Redeploy.
- The reconciler starts revision N+1 next to the serving one, with the same name and mounts.
- Each new replica must pass its health check; if it never does, it is discarded and revision N keeps serving.
- Traffic switches to N+1; revision N drains for a few seconds, then stops.
A request from the internet
- The visitor’s browser connects to the edge on port 443 with the domain’s certificate.
- The edge proxies to the app’s private name, which answers with every healthy replica.
- The app answers through the edge.
Building from Git
- The control plane clones the branch, tag or commit you chose.
- The engine builds the Dockerfile from the build context.
- The image is tagged for the revision and deployed as above; the build log is kept on the app.
Set it up
In the console
- Open Apps and choose New app.
- Give it a name, an image (or a Git repository) and the port it listens on.
- Turn on Publish to reach it from this computer, or add a domain later.
- Choose Create and watch Pull, Start, Health and Switch.
With the CLI
enclave app create web --image nginx:1.27-alpine --port 80 --publish --waitWith OpenTofu
resource "enclave_app" "web" {
name = "web"
image = "nginx:1.27-alpine"
port = 80
publish = true
}Settings reference
Every setting and output of the OpenTofu resource; the console and the CLI use the same names in their own words. Generated from platform 4d30582.
| Name | Type | Use | What it does |
|---|---|---|---|
name | text | required | Name of the app: 3–40 lowercase letters, digits or hyphens, starting with a letter. Changing it replaces the app. |
command | list of text | optional | Replaces the image's command. |
env | map of text | optional | Plain environment variables. |
health_check | list of objects | optional | When a new revision may take traffic. Unset: tcp on the port, or 5 s running without restarts. |
image | text | optional | Container image, e.g. nginx:1.27-alpine. Exactly one of image or source. |
machine | text | optional | The machine to run on (default: EnclaveStack chooses, and this reads back its choice). Changing it moves the resource, with its data, in place; apply waits for the move. |
machine_labels | map of text | optional | Labels the machine must have, when machine isn't set (key=value, all must match). |
memory_mib | number | optional | Memory limit in MiB (64–16384). |
network | text | optional | Network to place it in (default: the default network). Changes in place. |
port | number | optional | Port the app listens on. |
project | text | optional | The project to create it in. Defaults to the provider's project (ENCLAVE_PROJECT, else default). Changing it replaces the resource. |
publish | true or false | optional | Publish the port on the host (requires port). |
replicas | number | optional | Containers per revision (1–10); a published app runs one. |
secret_env | map of text | optional | Environment variables taken from secrets: variable name → secret name. |
source | list of objects | optional | Build the app from a Git repository and its Dockerfile (BuildKit). Exactly one of image or source. A redeploy builds the ref's latest commit. |
strategy | text | optional | rolling: a new revision takes traffic only once healthy; recreate: stop, then start. Published apps always recreate. |
subnet | text | optional | Subnet of the network (default: its first). |
volumes | list of objects | optional | Filesystem volumes mounted into every container; a change deploys a new revision. |
built_commit | text | output | The commit the serving revision was built from (source apps). |
host | text | output | Host to reach a published app from this machine. |
host_port | number | output | Port to reach a published app from this machine. |
id | text | output | Resource ID. |
internal_host | text | output | Host other apps use on the EnclaveStack network. |
internal_port | number | output | Port other apps use on the EnclaveStack network. |
private_dns | text | output | Name the app answers to inside its network: <name>.app.internal. |
private_ip | text | output | The serving revision's address in its network. |
serving_revision | number | output | The revision receiving traffic. |
Limits and security
Good to know
- 1 – 10 replicas per app; a published app runs one.
- Memory is reserved per replica (256 MiB unless you choose).
- Build arguments are not for secrets; use secret environment variables.
Security
- Never privileged, never on the host network, never with host folders mounted.
- Secrets reach the app only as environment variables at start.
- A firewall can limit who may connect to it.