Documentation
Application Stacks
Deploy reusable runtime infrastructure manifests to Kubernetes clusters with NebuaCloud Application Stacks
Application Stacks let you deploy runtime infrastructure resources to your Kubernetes clusters from NebuaCloud without exposing internal deployment tooling to the user.
Every deployed stack is compiled into a Git-based deployment path and reconciled through the NebuaCloud deployment system. NebuaCloud never applies stack resources directly to the cluster.
Use a Stack when you want to manage runtime resources such as Deployments, Services, ConfigMaps, Ingress objects, Jobs, StatefulSets, CRDs, and related Kubernetes manifests as one deployable unit while keeping NebuaCloud as the single deployment control surface.
Stack vs nebuacloud.yml
NebuaCloud uses two different deployment concepts and they are intentionally separate.
nebuacloud.ymldefines how NebuaCloud should build and run an application from a repository.- Application Stack defines runtime infrastructure manifests that NebuaCloud should apply to a target Kubernetes cluster.
These can coexist in the same repository.
/nebuacloud.yml
/stacks/production.yml
/stacks/staging.yml
What A Stack Can Include
- Deployments
- Services
- ConfigMaps
- Secrets generated by NebuaCloud during deployment
- Ingress resources
- StatefulSets
- Jobs and CronJobs
- CRDs and cluster-scoped resources
Deployment Modes
| Mode | User input | NebuaCloud internal result | | --- | --- | --- | | Compose Mode | Docker Compose YAML | generated Kubernetes manifests + generated deployment path + generated stack deployment | | Legacy Stack Mode | simplified Nebua stack spec | generated Kubernetes manifests + generated deployment path + generated stack deployment | | Manifest Mode | raw Kubernetes manifests | manifests stored in deployment path + generated stack deployment | | GitOps Mode | existing Git repository path | generated stack deployment only |
Compose Mode
Compose Mode is the preferred beginner-friendly input for Application Stacks because it uses a familiar standard instead of a NebuaCloud-specific schema.
name: my-app
services:
api:
image: node:20
ports:
- "3000:3000"
redis:
image: redis:7
ports:
- "6379:6379"
NebuaCloud converts supported Docker Compose services into Kubernetes Deployments, Services, Secrets, and storage resources, then reconciles them through the NebuaCloud deployment system.
Legacy Stack Mode
Legacy Stack Mode is still accepted for backward compatibility, but Compose and raw Kubernetes manifests should be preferred for new stacks.
name: my-app
services:
api:
image: node:20
port: 3000
redis:
image: redis
NebuaCloud can generate Deployments, Services, ConfigMaps, Secrets, Ingress resources, HPAs, and NetworkPolicies from this simplified legacy spec.
Manifest Mode
Manifest Mode accepts raw Kubernetes YAML, but NebuaCloud still stores the resulting manifest set in the deployment repository and deploys it through the NebuaCloud deployment system only.
User Input Examples
Application Stacks accept Compose YAML or raw Kubernetes YAML in the manifest field.
What To Post To The Stack API
For both of the inline input styles below, send the YAML in the same manifest field when calling POST /v1/stacks.
- If your YAML is a Docker Compose file, NebuaCloud detects Compose Mode automatically.
- If your YAML is raw Kubernetes manifests, NebuaCloud detects Manifest Mode automatically.
- Legacy Nebua stack specs are still detected, but Compose is the recommended standard for new usage.
- You usually do not need to set
modefor either of these two cases. - Only set
mode: gitopswhen you are not sending inline YAML and want NebuaCloud to deploy from an existing repository path.
The basic request shape is:
{
"name": "my-stack",
"clusterId": 42,
"namespace": "apps",
"manifest": "...yaml content here..."
}
Using NebuaCloud Labs
If you are deploying into a NebuaCloud Labs workspace, create the stack against the NebuaCloud shared cluster record and your assigned namespace.
Use the numeric shared cluster id shown in the dashboard cluster selector or the cluster context panel as clusterId. Use your workspace namespace as namespace. NebuaCloud resolves the Labs deployment target internally and keeps the deployment path reconciled through the deployment system.
{
"name": "labs-stack",
"clusterId": 42,
"namespace": "your-workspace-namespace",
"manifest": "name: shared-demo\nservices:\n web:\n image: nginx:1.27\n ports:\n - \"80:80\"\n"
}
Do not use the host cluster kubeconfig or a Labs runtime API server address in the stack request. The stack API only needs the shared NebuaCloud clusterId, namespace, and stack input.
Docker Compose
Use this mode when you want to submit a standard Docker Compose document and let NebuaCloud translate it into GitOps-managed Kubernetes resources.
NebuaCloud supports common Compose service fields such as image, command, ports, environment, volumes, and depends_on. For Application Stacks, Compose services must still resolve to deployable container images.
How To Create A Compose Stack
Start with these basic parts:
name: the application or stack nameservices: the list of workloads NebuaCloud should generate resources forimage: the container image for each serviceports: the ports exposed by the service when neededenvironment: optional environment variablesvolumes: optional service storage definitions
Minimal example:
name: my-app
services:
web:
image: nginx:1.27
ports:
- "80:80"
You can build up the spec service by service. A good workflow is:
- Pick a stack name.
- Add one service for each containerized component such as
web,api,worker, orredis. - Set the
imagefor each service. - Add
portswhen the service should be reachable inside the cluster. - Add
environmentfor runtime configuration. - Add
volumeswhen the service needs mounted storage.
Example with a frontend and API:
name: customer-portal
services:
frontend:
image: ghcr.io/example/customer-portal-frontend:2026.05.23
ports:
- "3000:3000"
environment:
NODE_ENV: production
API_BASE_URL: https://api.example.com
api:
image: ghcr.io/example/customer-portal-api:2026.05.23
ports:
- "8080:8080"
environment:
NODE_ENV: production
DATABASE_URL: postgres://user:pass@postgres:5432/app
Use Docker Compose when:
- you want a standard authoring format instead of a NebuaCloud-specific schema
- you are deploying common app patterns such as web, API, cache, or worker services
- you want NebuaCloud to generate the Kubernetes resources for you
Use raw Kubernetes manifests instead when you need exact control over resource fields or advanced Kubernetes features.
name: storefront
services:
web:
image: ghcr.io/example/storefront-web:2026.05.23
ports:
- "3000:3000"
environment:
NODE_ENV: production
API_BASE_URL: https://api.example.com
redis:
image: redis:7
ports:
- "6379:6379"
Typical use cases:
- simple web apps
- internal tools
- teams that want fewer Kubernetes details in the input file
Example API request:
{
"name": "storefront-stack",
"clusterId": 42,
"namespace": "apps",
"manifest": "name: storefront\n\nservices:\n web:\n image: ghcr.io/example/storefront-web:2026.05.23\n ports:\n - \"3000:3000\"\n environment:\n NODE_ENV: production\n API_BASE_URL: https://api.example.com\n\n redis:\n image: redis:7\n ports:\n - \"6379:6379\"\n"
}
Legacy Nebua Stack Spec
If you already have the older Nebua stack format in existing workflows, NebuaCloud still accepts it. New examples and new integrations should prefer Docker Compose instead.
Raw Kubernetes Manifests
Use this mode when you already know the exact Kubernetes resources you want NebuaCloud to deploy.
apiVersion: apps/v1
kind: Deployment
metadata:
name: storefront-web
spec:
replicas: 2
selector:
matchLabels:
app: storefront-web
template:
metadata:
labels:
app: storefront-web
spec:
containers:
- name: web
image: ghcr.io/example/storefront-web:2026.05.23
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
---
apiVersion: v1
kind: Service
metadata:
name: storefront-web
spec:
selector:
app: storefront-web
ports:
- port: 80
targetPort: 3000
Typical use cases:
- existing Kubernetes workloads
- custom controllers or advanced resource settings
- teams migrating current manifests into NebuaCloud
Example API request:
{
"name": "storefront-manifests",
"clusterId": 42,
"namespace": "apps",
"manifest": "apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: storefront-web\nspec:\n replicas: 2\n selector:\n matchLabels:\n app: storefront-web\n template:\n metadata:\n labels:\n app: storefront-web\n spec:\n containers:\n - name: web\n image: ghcr.io/example/storefront-web:2026.05.23\n ports:\n - containerPort: 3000\n env:\n - name: NODE_ENV\n value: production\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: storefront-web\nspec:\n selector:\n app: storefront-web\n ports:\n - port: 80\n targetPort: 3000\n"
}
GitOps Mode
GitOps Mode points to an existing repository path. NebuaCloud only creates the deployment record and leaves the manifests in the repository you specify.
Core Workflow
- Create a Stack using Stack Mode, Manifest Mode, or GitOps Mode.
- NebuaCloud compiles or resolves the input into a deployment repository path.
- NebuaCloud creates or updates the backing stack deployment.
- NebuaCloud keeps the generated path synchronized with the target cluster.
- Review resources, events, and revision history.
Security Model
Stack APIs require a NebuaCloud bearer token.
- Required scopes:
stacks:create,stacks:update,stacks:delete,stacks:deploy,stacks:read - Token expiration is enforced through JWT expiry.
- Token revocation is enforced against the stored user API key record.
- Free plans cannot deploy Application Stacks.
- Standard and Business plans can deploy stacks.
Entitlements And Limits
- Free: not allowed
- Growth: 25 stack deployments per month, 256 KB manifest limit, 100 rendered resources per stack
- Business: unlimited stack deployments, 1 MB manifest limit, 250 rendered resources per stack
Deployment Ownership
Application Stacks always deploy through the NebuaCloud deployment system.
- NebuaCloud generates or resolves a deployment repository path.
- NebuaCloud generates or updates the backing stack deployment.
- The deployment system performs the actual synchronization to the cluster.
- NebuaCloud never runs direct
kubectl applyfor stack payloads.
API Reference
Swagger API Docs
Use Swagger UI for an interactive view of the Application Stacks API:
- Production: https://api.nebuacloud.com/swagger
- Local development: http://localhost:5000/swagger
In production, Swagger is restricted to Application Stacks endpoints only.
Create Stack
POST /v1/stacks
JSON requests are still supported, but for longer manifests it is usually better to keep the YAML in a file and load it into the request.
curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "marketing-stack",
"description": "Landing page runtime resources",
"clusterId": 42,
"namespace": "marketing",
"manifest": "apiVersion: v1\nkind: ConfigMap\nmetadata:\n name: marketing-config\ndata:\n APP_NAME: ${STACK_NAME}\n",
"variables": {
"IMAGE_TAG": "2026-05-23"
},
"dryRun": false
}'
Create Stack From A YAML File With jq --rawfile
This keeps the manifest in a normal multi-line file and lets jq place the file contents into the JSON manifest field.
jq -n --rawfile manifest stack.yaml '{
name: "marketing-stack",
description: "Landing page runtime resources",
clusterId: 42,
namespace: "marketing",
manifest: $manifest,
variables: {
IMAGE_TAG: "2026-05-23"
},
dryRun: false
}' | curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-H "Content-Type: application/json" \
-d @-
Create Stack With multipart/form-data
The stack API also accepts a manifest file upload under the field name manifestFile. This can be a Kubernetes manifest file or a Docker Compose file.
curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-F "name=marketing-stack" \
-F "description=Landing page runtime resources" \
-F "clusterId=42" \
-F "namespace=marketing" \
-F "dryRun=false" \
-F 'variables={"IMAGE_TAG":"2026-05-23"}' \
-F "manifestFile=@docker-compose.yml;type=text/yaml"
Create Stack With Docker Compose
curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "compose-stack",
"clusterId": 42,
"namespace": "apps",
"manifest": "name: my-app\nservices:\n api:\n image: node:20\n ports:\n - \"3000:3000\"\n redis:\n image: redis:7\n ports:\n - \"6379:6379\"\n"
}'
Create Stack In Legacy Stack Mode
You can also send the older simplified stack definition in the same manifest field. NebuaCloud still detects this legacy Stack Mode automatically when the document is not Compose and not a Kubernetes resource.
curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "beginner-stack",
"clusterId": 42,
"namespace": "apps",
"manifest": "name: my-app\nservices:\n api:\n image: node:20\n port: 3000\n redis:\n image: redis\n"
}'
Create Stack In GitOps Mode
curl -X POST https://api.nebuacloud.com/v1/stacks \
-H "Authorization: Bearer $NEBUA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "existing-gitops-stack",
"clusterId": 42,
"namespace": "production",
"mode": "gitops",
"repositorySource": {
"repoUrl": "https://github.com/example/gitops.git",
"targetRevision": "main",
"path": "clusters/cluster-a/namespaces/production/stacks/my-app"
}
}'
Update Stack
PUT /v1/stacks/:id
Delete Stack
DELETE /v1/stacks/:id
Get Stack
GET /v1/stacks/:id
List Stacks
GET /v1/stacks
Redeploy Stack
POST /v1/stacks/:id/redeploy
Stack Events
GET /v1/stacks/:id/events
Stack Resources
GET /v1/stacks/:id/resources
Stack History
GET /v1/stacks/:id/history
OpenAPI Snippet
openapi: 3.0.3
paths:
/v1/stacks:
post:
security:
- bearerAuth: []
summary: Create an Application Stack
requestBody:
content:
application/json: {}
multipart/form-data: {}
/v1/stacks/{id}:
get:
summary: Get a Stack
put:
summary: Update a Stack
delete:
summary: Delete a Stack
/v1/stacks/{id}/redeploy:
post:
summary: Redeploy a Stack
/v1/stacks/{id}/events:
get:
summary: List Stack events
/v1/stacks/{id}/resources:
get:
summary: List Stack resources
/v1/stacks/{id}/history:
get:
summary: List Stack revisions
Troubleshooting
Stack Does Not Sync
- Confirm the generated or referenced deployment path exists in the repository NebuaCloud watches.
- Confirm the deployment points to the expected repository URL, revision, and path.
- Retry
POST /v1/stacks/:id/redeployafter fixing the GitOps source.
Stack Deployment Fails
- Check
GET /v1/stacks/:id/eventsfor the deployment error. - Check
GET /v1/stacks/:id/resourcesto see which resources drifted or are missing. - Verify the current plan still has available stack deployment quota.
Repo Uses Both Application Stacks And nebuacloud.yml
- Keep stack manifests under a dedicated folder such as
stacks/. - Keep
nebuacloud.ymlat repository root for application build/runtime settings only.