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.yml defines 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 mode for either of these two cases.
  • Only set mode: gitops when 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 name
  • services: the list of workloads NebuaCloud should generate resources for
  • image: the container image for each service
  • ports: the ports exposed by the service when needed
  • environment: optional environment variables
  • volumes: 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:

  1. Pick a stack name.
  2. Add one service for each containerized component such as web, api, worker, or redis.
  3. Set the image for each service.
  4. Add ports when the service should be reachable inside the cluster.
  5. Add environment for runtime configuration.
  6. Add volumes when 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

  1. Create a Stack using Stack Mode, Manifest Mode, or GitOps Mode.
  2. NebuaCloud compiles or resolves the input into a deployment repository path.
  3. NebuaCloud creates or updates the backing stack deployment.
  4. NebuaCloud keeps the generated path synchronized with the target cluster.
  5. 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 apply for stack payloads.

API Reference

Swagger API Docs

Use Swagger UI for an interactive view of the Application Stacks API:

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/redeploy after fixing the GitOps source.

Stack Deployment Fails

  • Check GET /v1/stacks/:id/events for the deployment error.
  • Check GET /v1/stacks/:id/resources to 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.yml at repository root for application build/runtime settings only.

Profile picture

Written with love by Nebuacloud, Private Cloud Infrastructure Automation Platform.

This site uses cookies to improve the user's experience.