Stacks
Create and manage application stacks in PodWarden
Overview
Stacks are templates that describe how to run a containerized workload. Each stack specifies the container image, resource requirements, environment variables, volumes, ports, and deployment configuration. Stacks are reusable — create one stack and deploy it to multiple clusters.
Creating a Stack
Navigate to Apps & Stacks in the sidebar and click Create.
Basic Fields
| Field | Required | Description |
|---|---|---|
name | Yes | Display name for the workload |
kind | Yes | Workload type: deployment (long-running), job (batch), or daemonset (per-node) |
image_name | Yes | Container image name (e.g. ollama/ollama, postgres) |
image_tag | No | Image tag (defaults to fleet-level setting from Settings → Registry) |
registry_url | No | Override the default registry for this workload |
registry_credentials | No | Registry auth credentials (for private registries) |
command | No | Container command override (overrides the image's CMD) |
host_network | No | Use host networking (hostNetwork: true). For UDP multicast, IPTV, or direct network access |
dns_policy | No | Kubernetes dnsPolicy for pods. Default: ClusterFirst. Use Default for Docker-in-Docker workloads (see Networking) |
Resource Requests
| Field | Description | Examples |
|---|---|---|
cpu_request | CPU cores or millicores | 500m, 1, 2, 4 |
memory_request | RAM allocation | 512Mi, 2Gi, 8Gi |
gpu_count | Number of NVIDIA GPUs | 0, 1, 2 |
vram_request | GPU VRAM requirement | 8Gi, 24Gi |
concurrent_jobs | Max concurrent instances (for job kind) | 1, 4 |
PodWarden converts these into Kubernetes resource requests. GPU workloads use nvidia.com/gpu resource limits.
Environment Variables
Stacks support two types of environment variables:
Static Environment Variables (env)
Fixed key-value pairs embedded directly in the definition. These are set at definition time and applied as-is to every deployment.
[
{ "name": "OLLAMA_HOST", "value": "0.0.0.0" },
{ "name": "LOG_LEVEL", "value": "info" }
]Use static env vars for values that are the same across all deployments — host bindings, log levels, feature flags with known values.
Configurable Environment Variables (env_schema)
Schema-defined variables that document available configuration. Each entry has a name, optional default value, a required flag, and a description.
[
{
"name": "OLLAMA_MODELS",
"required": false,
"default_value": "/models",
"description": "Path where Ollama stores downloaded models"
},
{
"name": "OLLAMA_NUM_PARALLEL",
"required": false,
"default_value": "1",
"description": "Number of parallel model requests"
}
]env_schema serves as documentation and configuration guidance. When deploying from the Hub catalog, configurable variables help operators understand what can be tuned.
| Schema Field | Description |
|---|---|
name | Variable name (e.g. OLLAMA_MODELS) |
required | Whether the variable must be set |
default_value | Default value if not overridden |
description | Human-readable explanation |
generate | Auto-generation strategy for secrets (optional). When set, the Hub's one-click installer generates a random value using openssl rand. Strategies: password (18-byte alphanumeric), hex16, hex32, hex64 (hex strings), base64 (32-byte base64), uuid. |
Example with generate:
[
{
"name": "DB_PASSWORD",
"required": true,
"description": "Database password",
"generate": "password"
},
{
"name": "SECRET_KEY_BASE",
"required": true,
"description": "Rails session encryption key",
"generate": "hex64"
}
]Variables with generate hints show an "Auto-generate secrets" toggle in the Hub catalog's install modal. The .env.example file in the download bundle includes # generate:<strategy> markers that the install script reads to produce random values.
Secret References (secret_refs)
References to secrets stored in PodWarden's encrypted secret store. At deploy time, PodWarden injects these as environment variables from Kubernetes secrets.
Ports
Define which container ports to expose:
[
{ "containerPort": 11434, "protocol": "TCP" },
{ "containerPort": 8080, "protocol": "TCP" }
]Exposed ports are included in the generated Kubernetes Service manifest.
Config Files (config_schema)
Stacks can declare mountable config files — configuration files that operators can edit per deployment. Each config slot specifies a file name, mount path, file type, and optional default content. At deploy time, PodWarden creates a Kubernetes ConfigMap for each slot and mounts it into the container.
See the Config Files guide for details on defining config slots, editing content per assignment, and examples.
Volume Mounts
Attach persistent storage to the container. See the Storage guide for all volume types (emptyDir, hostPath, PVC, NFS, S3, configMap, secret).
Scheduling
| Field | Description |
|---|---|
node_selector | Kubernetes node selector labels (JSON object, e.g. {"gpu": "a100"}) |
tolerations | Kubernetes tolerations for tainted nodes |
required_network_types | Network types the target cluster must support (see Networking) |
Network Requirements
The Required connectivity field declares what network types the target cluster must support for this workload. Options: public, mesh, lan.
Before deployment, PodWarden runs a pre-flight check comparing the workload's required network types against the cluster's available networks. See Networking for details.
Security Context
The Security context section controls container-level security settings. These map directly to the Kubernetes pod securityContext.
| Field | Description | Example |
|---|---|---|
| Privileged | Run the container with elevated privileges (full host device access) | Required for VPN tunnels, network tools |
| Capabilities Add | Linux capabilities to add to the container | NET_ADMIN, SYS_PTRACE |
| Capabilities Drop | Linux capabilities to remove from the container | ALL (then add back only what's needed) |
Common capability combinations:
| Use Case | Capabilities |
|---|---|
| VPN / mesh networking (Nebula, WireGuard) | NET_ADMIN (creates tun/tap interfaces) |
| Network debugging (tcpdump, ping) | NET_RAW |
| Full device access (USB passthrough) | Privileged mode |
| Hardened container | Drop ALL, add only what's needed |
The security context is stored as a JSON object:
{
"privileged": true,
"capabilities": {
"add": ["NET_ADMIN"],
"drop": ["ALL"]
}
}Health Probes
Health probes let Kubernetes monitor your container and restart it if it becomes unhealthy. PodWarden supports three probe types:
| Probe | Purpose |
|---|---|
| Liveness | Detects stuck containers. If the probe fails, Kubernetes restarts the container. |
| Readiness | Detects containers not ready to serve traffic. Failing containers are removed from the Service. |
| Startup | Gives slow-starting containers time to initialize before liveness checks begin. |
Each probe can use one of three methods:
| Method | When to use | Example |
|---|---|---|
| exec | Run a command inside the container | ["pg_isready", "-U", "postgres"] |
| httpGet | HTTP GET to a path and port | {"path": "/health", "port": 8080} |
| tcpSocket | Check if a TCP port is open | {"port": 5432} |
Probes are configured as a JSON object:
{
"liveness": {
"httpGet": { "path": "/health", "port": 8080 },
"periodSeconds": 30,
"timeoutSeconds": 5,
"failureThreshold": 3
},
"readiness": {
"tcpSocket": { "port": 8080 },
"periodSeconds": 10
}
}Probes are optional. If not set, Kubernetes assumes the container is healthy as long as the main process is running.
Stack Types
Every stack is one of two types:
- Single Service — A single container deployed as one Kubernetes Deployment. This is the default when you create a stack manually or import a single-image template from Hub.
- Compose Stack — A multi-service template imported from a
docker-compose.ymlfile. Each service becomes a separate Kubernetes Deployment.
Compose Stacks
PodWarden supports importing docker-compose.yml files as stacks. A Compose Stack is a multi-service template where each service becomes a separate Kubernetes Deployment.
How compose stacks work
- Import a
docker-compose.ymlfrom the Apps & Stacks page (or from Hub) - PodWarden parses the compose file and creates a single stack marked as a compose stack
- When deployed, PodWarden creates a parent assignment plus child assignments for each service
- Each service is translated to Kubernetes resources (Deployment + Service + PVCs)
Compose-to-Kubernetes translation
| Compose | Kubernetes |
|---|---|
Each service | Deployment + ClusterIP Service |
ports | containerPort + Service ports |
volumes (bind mount /host:/ctr) | hostPath volume |
volumes (named vol:/ctr) | PVC |
environment | Container env |
healthcheck | livenessProbe + readinessProbe |
cap_add | securityContext.capabilities.add |
privileged: true | securityContext.privileged |
network_mode: host | hostNetwork: true |
command / entrypoint | Container command / args |
deploy.resources.limits | resources.limits |
deploy.resources.reservations | resources.requests |
depends_on | No equivalent (services use DNS discovery) |
The x-podwarden extension
Compose templates can include an x-podwarden block with PodWarden-specific metadata:
services:
app:
image: myapp:latest
ports:
- "8080:8080"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 30s
timeout: 5s
x-podwarden:
name: My Application
description: "Full-stack application with health monitoring"
required_network_types: [public]
form_fields:
- name: APP_SECRET
label: Application Secret
required: true
description: "Secret key for session encryption"
- name: LOG_LEVEL
label: Log Level
default: "info"The form_fields in x-podwarden map to env_schema entries, making variables configurable per deployment.
Variable substitution
Compose templates use {{VAR_NAME}} placeholders (double braces) in the compose source and config templates. At deploy time, PodWarden substitutes these with values from the assignment's environment variables. The double-brace syntax avoids collision with shell $VAR syntax in scripts.
Pre-deploy scripts
Compose templates can include scripts that run on the target host before deployment:
x-podwarden:
scripts:
pre_deploy:
- name: setup-certs
run_on: host
content: |
#!/bin/bash
mkdir -p /etc/myapp/certs
# Generate certificates...Pre-deploy scripts execute via SSH on the target host with sudo privileges. They run before any Kubernetes resources are created and fail the deployment if they exit with a non-zero status.
Importing a compose file
- Go to Apps & Stacks and click Import from Compose
- Paste the
docker-compose.ymlcontent (with optionalx-podwardenblock) - PodWarden parses the compose file and creates a stack
- The definition is marked as a Compose Stack with the parsed services listed
Editing Stacks
Click any stack to open the edit form. All fields are editable. Changes apply to future deployments — already-running workloads are not affected until you redeploy.
Deploying Stacks
Stacks are deployed to clusters via Deployments:
- Go to Deployments and click Create
- Select a Stack (the template)
- Select a Cluster (the target)
- Optionally override the namespace
- Click Deploy to generate the Kubernetes manifest and apply it
PodWarden generates a complete Kubernetes manifest (Deployment/Job/DaemonSet + Service + PVCs) and applies it via kubectl. Deployment status is tracked in real-time.
See the Deployment guide for details on assignments, undeploying, logs, and rollbacks.
Importing from PodWarden Hub
Connect to PodWarden Hub to browse and import curated stacks.
How to Import
- Go to Apps & Stacks and click Import from Hub
- Browse templates by category, search by name, or filter by tags
- Click Import on any template
- PodWarden creates a local stack with all fields copied:
- Image, registry, resources (CPU, memory, GPU, VRAM)
- Environment variables (static and configurable)
- Ports, volumes, node selectors, tolerations, network requirements
- The imported definition tracks its Hub origin (
hub_template_slugandhub_template_version)
After import, the definition is independent — customize any field before deploying.
Checking for Updates
Imported definitions show a Hub badge. PodWarden can check if newer versions are available by comparing your local hub_template_version against the current version on Hub.
Hub Connection Required
To use the import feature, configure your Hub connection under Settings → Hub. See Connecting to Hub for setup instructions.
Stack Fields Reference
| Field | Type | Description |
|---|---|---|
name | string | Display name |
kind | string | deployment, job, or daemonset |
image_name | string | Container image name |
image_tag | string | Image tag |
registry_url | string | Override registry URL |
registry_credentials | string | Registry auth credentials |
command | string | Container command override |
cpu_request | string | CPU request (e.g. 500m, 2) |
memory_request | string | Memory request (e.g. 512Mi, 8Gi) |
gpu_count | integer | Number of GPUs |
vram_request | string | VRAM requirement |
concurrent_jobs | integer | Max concurrent instances |
env | JSON array | Static environment variables |
env_schema | JSON array | Configurable environment variable schema (name, required, default_value, description, generate) |
config_schema | JSON array | Mountable config file definitions (see Config Files) |
secret_refs | JSON | Secret references |
ports | JSON array | Container port mappings |
volume_mounts | JSON array | Volume mount configurations |
node_selector | JSON object | Kubernetes node selector |
tolerations | JSON | Kubernetes tolerations |
required_network_types | text[] | Required network types (public, mesh, lan) |
host_network | boolean | Use host networking (binds to node's network stack) |
dns_policy | string | Kubernetes dnsPolicy for pods (ClusterFirst, Default, None, ClusterFirstWithHostNet) |
security_context | JSON | Container security context (capabilities, privileged) |
probes | JSON | Health probes (liveness, readiness, startup) |
is_compose_stack | boolean | Whether this is a compose stack (multi-service template) |
compose_source | text | Raw docker-compose.yml source (compose stacks only) |
compose_services | JSON | Extracted service list for compose stacks |
hub_template_slug | string | Hub template slug (if imported) |
hub_template_version | string | Hub template version (if imported) |
hub_imported_at | timestamp | When the template was imported from Hub |