Skip to content

Stack template

Create a custom stack by writing a YAML template or by forking a stack provided by Wodby. The format is a deliberately limited deployment schema inspired by Docker Compose and Kubernetes; arbitrary fields from either format are not accepted.

Managed-stack features

Managed stacks and their forks can contain implementation catalog data and upgrade behavior that cannot be expressed in a custom template.

Top-level sections

Name Required Description
services yes Named container services.
variables no Reusable literal or generated values.
volumes no Named persistent host-path volumes.
service_types no Display names for service categories referenced by a service's type.
metadata no Stack metadata retained with the template.

Names of services and volumes can contain lowercase letters, numbers, and hyphens. Variable names can contain lowercase letters, numbers, and underscores.

Service reference

Name Type Description
image string Required container image reference.
image_pull string Always or IfNotPresent; defaults to the runtime policy used by Wodby.
entrypoint string or string array Replaces the image entrypoint.
command string or string array Arguments passed to the entrypoint, replacing the image command.
working_dir string Container working directory.
environment map Environment variable names and string or numeric values.
volumes string array Host or named-volume mounts. Add :ro for a read-only mount.
memory integer or string Memory request and optional limit in MB.
cpu integer or string CPU request and optional limit in millicores.
ports string array Internal and public port mappings.
check_ready map Readiness probe used to decide when the service can receive traffic.
check_alive map Liveness probe used to decide when a container should be restarted.
deployment map Replica, update-strategy, and deployment-source settings.
security_context map Container privilege and user settings.
annotations map Annotations applied to the rendered workload.
metadata map String or numeric service metadata.
title string Human-readable service title.
type string Service category, optionally declared under service_types.
enabled boolean Whether the service is initially enabled; defaults to true.
required boolean Prevents the service from being disabled when true; defaults to false.
scale integer Legacy replica field. Prefer deployment.replicas.
privileged boolean Legacy privilege field. Prefer security_context.privileged.

Memory

Specify a request alone or a request and limit separated by a colon:

memory: 128       # request 128 MB
memory: 512:1024  # request 512 MB, limit 1024 MB

The limit cannot be lower than the request. A request reserves scheduling capacity; it is not a measurement of current use. Exceeding the memory limit can terminate the container with an out-of-memory error. Infrastructure 7 does not use swap.

CPU

CPU values use millicores, where 1000 is one core. The minimum request is 100:

cpu: 1000      # request 1 core
cpu: 650       # request 0.65 core
cpu: 200:250   # request 0.2 core, limit 0.25 core

The limit cannot be lower than the request. Kubernetes throttles a container that reaches its CPU limit; it does not terminate the container merely for using its full CPU allowance.

Ports

Port entries use:

[PUBLIC_PORT::][SERVICE_PORT:]CONTAINER_PORT[/tcp|udp]

TCP is used when the protocol is omitted.

ports:
  - "8080"               # service and container port 8080
  - "80:8080"            # service port 80 to container port 8080
  - "edge::80:8080"      # publish HTTP through Edge
  - "auto::8080"         # allocate a stable node port
  - "32223::80:8080"     # use an explicit unmanaged node port
  - "32767::5353/udp"    # explicit UDP node port

auto allocates a port from Wodby's managed range, 31222–32222. An explicit node port must be in the separate unmanaged range, 32223–32767. Open the selected port in any external firewall. edge publishes the service through the Wodby edge proxy; the first Edge-published service receives a technical domain.

Readiness and liveness checks

Both check_ready and check_alive accept exactly one action: exec or http.

check_ready:
  exec:
    command: ["/bin/sh", "-c", "test -f /tmp/ready"]
  initial_delay_seconds: 5
  period_seconds: 10
  timeout_seconds: 2
  failure_threshold: 3
  success_threshold: 1

For an HTTP probe:

check_alive:
  http:
    path: /health
    port: 8080
    scheme: HTTP
    headers:
      X-Health-Check: wodby
  initial_delay_seconds: 10
  period_seconds: 20

HTTP path and port are required. host, scheme, and headers are optional. Probe timing fields use seconds; periods, thresholds, and timeouts must be positive, while the initial delay can be zero.

Deployment

Name Type Description
strategy string rolling_update (default) or recreate.
replicas integer Desired replicas, including explicit zero; defaults to one.
min_ready_seconds integer Time a new replica must remain ready before becoming available.
progress_deadline_seconds integer Maximum time for a deployment to make progress.
max_surge integer Replicas allowed above the desired count during a rolling update.
max_unavailable integer Replicas allowed to be unavailable during a rolling update.
type string ci for CI-built code or git for direct Git deployment.

Use recreate for stateful services such as databases and search engines. Rolling updates can run old and new replicas simultaneously and therefore require storage and application behavior designed for concurrent replicas.

A service with deployment.type: ci starts with zero replicas until its first CI build is deployed. See Code deployment.

Security context

Name Type Description
privileged boolean Gives the container host-equivalent privileges. Avoid unless required.
capabilities.add string array Linux capabilities to add.
capabilities.drop string array Linux capabilities to remove.
read_only_root_filesystem boolean Mounts the container root filesystem read-only.
run_as_non_root boolean Rejects an image that would run as UID 0.
run_as_user integer UID used to run the container process.

Example:

security_context:
  run_as_non_root: true
  run_as_user: 1000
  read_only_root_filesystem: true
  capabilities:
    drop: ["ALL"]

Volumes

Define a host-path volume once and mount it into one or more services:

volumes:
  application-data:
    path: ./data

services:
  application:
    image: example/application:1
    volumes:
      - "application-data:/var/lib/application"
      - "./configuration:/etc/application:ro"

A relative host path is resolved beneath the instance data directory, /srv/wodby/instances/INSTANCE_UUID. The mount suffix :ro makes that service mount read-only.

Custom-template global volumes are currently materialized as host paths. Mount external storage such as NFS on the server first and reference its host path; do not rely on a template-level NFS driver.

Mounted host directories are commonly created as root. Make sure the image's runtime UID can read or write them as needed, preferably through an idempotent entrypoint permission check rather than running the main process as root.

Variables and generated values

Variables can be literal values or generated once when Wodby creates the stack revision:

variables:
  db_user: application
  db_password: auto:password:64
  application_key: auto:openssl_rand:32:base64
  hex_key: auto:openssl_rand:32:hex

auto:password:LENGTH creates a password of the requested length. auto:openssl_rand:LENGTH:ENCODING creates random bytes encoded as base64 or hex; the default length is 32 bytes and the default encoding is base64.

Reference a variable with Mustache syntax:

services:
  application:
    image: example/application:1
    environment:
      DB_USER: "{{db_user}}"
      DB_PASSWORD: "{{db_password}}"
      APP_KEY: "base64:{{application_key}}"

The older %db_password form remains supported for compatibility, but new templates should use {{db_password}}. Write %% when a literal percent sign would otherwise be interpreted as a legacy variable token.

Environment entries that still reference generated password material are protected by Wodby. See Protected and generated values.

Complete example

service_types:
  database: Database
  web: Web

variables:
  db_password: auto:password:64

volumes:
  database-data:
    path: ./database

services:
  database:
    title: Database
    type: database
    image: mariadb:11
    required: true
    environment:
      MARIADB_ROOT_PASSWORD: "{{db_password}}"
    volumes:
      - "database-data:/var/lib/mysql"
    deployment:
      strategy: recreate
    check_ready:
      exec:
        command: ["healthcheck.sh", "--connect"]

  web:
    title: Web
    type: web
    image: example/web:1
    ports:
      - "edge::80:8080"
    environment:
      DB_PASSWORD: "{{db_password}}"
    memory: "256:512"
    cpu: "200:500"
    deployment:
      strategy: rolling_update
      replicas: 1