Skip to main content

Stacks

A stack is one YAML file that describes a group of containers you want to run together, for example a web app and its database. You hand the file to Clouduler once. From then on the cluster keeps those containers running, puts them on nodes that can run them, and moves them if a node fails.

If you know Docker Compose, a stack file looks familiar on purpose: it is a subset of Compose v3 with an x-clouduler block for Clouduler-only features such as proxy routes and drive-backed volumes. Every field is listed in the stack spec reference.

How it works​

  1. Deploy stores the YAML in the cluster and bumps the stack's revision. Config and secret files the stack references are bundled with it.
  2. The scheduler turns each service into one or more instances (named STACK.SERVICE.INDEX, for example vaultwarden.app.0) and picks a node for each. See Placement.
  3. The node's daemon creates the container and keeps it running. If the node dies, the instance is placed somewhere else. See Failover.

You can deploy from the web UI or the CLI. Both do the same thing; the difference is how much they check first (see validation).

Deploy a stack​

Open Stacks. If you have none yet, the page shows an empty state with a Deploy stack button (admins only).

/stacks
The empty Stacks page on a new cluster.
  1. Click Deploy stack (or go to /stacks/new).
  2. Type the Stack name. Lowercase letters, numbers and dashes are safe.
  3. Type or paste your YAML into the Spec editor, or use Load from file. The editor autocompletes keys and your cluster's real network, drive and node names.
  4. Watch the panels fill in as you type:
    • Validation shows Spec is valid or a list of problems to fix.
    • What it needs lists the networks, drives, configs and secrets the spec uses.
    • Bundled files appears if the spec references configs or secrets with file:. Load each file or type its content here.
    • Where it can run shows, per service, which nodes can host it.
  5. Click Deploy NAME. The button stays disabled until the spec is valid. You land on the stack page.

If a step fails you see a red Not deployed banner: The deploy failed while STEP: MESSAGE.

/stacks
A cluster with three stacks running.

A minimal stack:

vaultwarden.yaml
networks:
lan: {}

services:
app:
image: vaultwarden/server:1.32.0
restart: always
networks: [lan]
volumes:
- fast/vaultwarden:/data # drive/volume:/container/path
x-clouduler:
proxy:
- host: vault # becomes vault.<domain of the lan network>
network: lan
port: 80

Validation is the same in the UI and the CLI​

The web UI, the HTTP API, the MCP tools and clouduler stack deploy all run the syntax checks and then the cluster checks. A typo like fats/vaultwarden:/data is refused with a message such as drive fats is not defined in cluster.yaml, both by Validate and on Deploy, before anything is stored.

Look at a running stack​

Click a stack in Stacks to open its page. The header shows the revision, number of services and nodes, and when it was deployed.

/stacks/vaultwarden
The stack page. Tabs: Containers, Placement, Spec, Settings.
  • Containers: each instance with its state and node, plus recent log lines.
  • Placement: why each node can or cannot run each service.
  • Spec: the stored YAML and Changes since last deploy.
  • Settings: configs and secrets the stack uses, the update webhook, and Remove stack.

Update (redeploy)​

Changing a stack means deploying a new revision of the same name. Clouduler stores the previous spec so you can see what changed.

Open the stack and click Redeploy NAME (admins). The Deploy page opens pre-filled with the running spec and the name field disabled. Edit, check Changes to deploy, then click Deploy NAME. The revision goes up by one.

An identical redeploy still bumps the revision. To pull newer container images without changing the spec, use the Updates page or clouduler update; see Updates.

Stop, start, restart​

The UI controls individual containers. Open the Containers tab, or click an instance to open /instances/vaultwarden.app.0, and use the Restart, Stop and Start buttons there (each label includes the instance id, for example Restart vaultwarden.app.0). Stopping asks for confirmation and the container stays stopped until you start it again.

/instances/vaultwarden.app.0
One instance: state, logs and actions.

The stack page (tabs Containers, Placement, Spec, Settings) has no stack-wide stop or start button. To stop every instance at once, use clouduler stack stop NAME on the CLI.

Remove​

Open the stack, go to Settings, find the Remove stack panel and click Remove NAME. You must type the stack name to confirm. It stops every container of the stack and deletes the stack.

Removing a stack keeps its volumes on the drives, but it also deletes the stack's configs and secrets that no other stack uses. The remove dialog does not mention volumes; it asks you to type the stack name.

Logs​

The Containers tab of a stack shows recent lines for each instance. For the full stream open the instance and go to its logs section (/instances/NAME#logs).

Exec and shell​

Running a command inside a container is a CLI feature: the web UI does not offer a shell.

clouduler exec vaultwarden.app.0 # tries bash, falls back to sh
clouduler exec vaultwarden.app.0 -- ls -la /data # use -- before a command with flags
clouduler exec -u 1000:1000 vaultwarden.app.0 -- id

It works from any machine that holds the cluster key, wherever the container runs. To debug connectivity, clouduler capture vaultwarden.app.0 -- port 80 runs tcpdump on the right node. See the CLI reference.

Health​

A stack is healthy when every instance runs as asked. Clouduler looks at the container state, the Docker healthcheck from your spec (healthcheck:), and the proxy's active check for routed services.

  • In the UI, open the stack page. A failing instance shows a tag such as Restart 3 of 5 or a placement problem,.
  • On the CLI, clouduler stack unhealthy lists instances that are restarting, exited when they should run, failing a health check, stopped by stack stop, or waiting for placement. Add --placement for the reason (the reason= part of the line below only appears with that flag) and --logs 10 for the last lines. stack stop, start, restart and logs on a stack with no running instances fail with stack NAME has no running instances.
vaultwarden 1 unhealthy instance(s)
vaultwarden.app.0 state=pending_placement health=none reason=...

If a service has depends_on, its instance waits until each dependency has an instance running somewhere. A healthcheck block without test: is silently ignored.

Placement basics​

Every instance runs on one node. The scheduler picks a node that can hold everything the service needs: the drives it mounts, the networks it uses, any ports it exposes, and any pin or constraint you wrote. If no node qualifies, the instance waits as pending_placement and the Placement tab says why for each node. The full list of reasons is on the Placement page.

Quirks and gotchas​