> ## Documentation Index
> Fetch the complete documentation index at: https://docs.niro.cx/llms.txt
> Use this file to discover all available pages before exploring further.

# Deploy an App

> Use the visual builder to deploy a containerized app to your cluster without writing YAML.

## Prerequisites

* A cluster connected to Niro (see [Connect a Cluster](/guides/connect-cluster))
* The apply capability enabled on the cluster (`NIRO_ENABLE_APPLY=1`)
* Optionally, a GitHub repo linked for GitOps (see [Set Up GitOps](/guides/gitops))

## 1. Open the builder

In the dashboard, click **Apps** in the sidebar, then click **Deploy app**.

Select the cluster you want to deploy to. If the cluster doesn't have the apply capability enabled, you'll see a prompt to enable it.

## 2. Configure the workload

The builder is organized into sections. Fill in the ones relevant to your app — you don't need to fill in everything.

### Workload (required)

| Field                     | Description                                                                    |
| ------------------------- | ------------------------------------------------------------------------------ |
| **Image**                 | Container image reference, e.g. `nginx:1.25` or `ghcr.io/my-org/my-app:v1.2.3` |
| **Name**                  | Name for the Kubernetes Deployment (and Service, if you add one)               |
| **Namespace**             | Target namespace. Type to create a new one.                                    |
| **Command / Args**        | Override the container entrypoint or arguments                                 |
| **Ports**                 | Container ports to expose                                                      |
| **Environment variables** | Key-value pairs injected as `env` entries                                      |
| **Resource requests**     | Minimum CPU/memory guaranteed to the container                                 |
| **Resource limits**       | Maximum CPU/memory the container can use                                       |
| **Liveness probe**        | Kubernetes liveness probe (HTTP, TCP, or exec)                                 |
| **Readiness probe**       | Kubernetes readiness probe                                                     |

<Tip>
  Set resource requests and limits to avoid [policy findings](/features/policies) and ensure predictable scheduling. A good starting point: `100m` CPU / `128Mi` memory requests; `500m` CPU / `512Mi` memory limits.
</Tip>

### Networking (optional)

Enable a Kubernetes **Service** to expose your app:

| Field            | Description                                                |
| ---------------- | ---------------------------------------------------------- |
| **Service type** | `ClusterIP` (internal only), `NodePort`, or `LoadBalancer` |
| **Port**         | Service port → container port mapping                      |

Enable an **Ingress** to expose the app via HTTP(S):

| Field        | Description                                                              |
| ------------ | ------------------------------------------------------------------------ |
| **Hostname** | Domain name to route (e.g. `myapp.example.com`)                          |
| **TLS**      | Enable TLS termination (requires cert-manager or a Traefik TLS resolver) |
| **Path**     | URL path prefix (defaults to `/`)                                        |

### Scaling (optional)

| Field                           | Description                                       |
| ------------------------------- | ------------------------------------------------- |
| **Replicas**                    | Number of pod replicas (default: 1)               |
| **Horizontal Pod Autoscaler**   | Scale automatically based on CPU or memory usage  |
| **Min replicas / Max replicas** | HPA bounds                                        |
| **Target CPU utilization**      | Percentage of requested CPU that triggers scaling |

### Storage (optional)

Add a **PersistentVolumeClaim** for stateful workloads:

| Field             | Description                                                   |
| ----------------- | ------------------------------------------------------------- |
| **Size**          | Storage size (e.g. `5Gi`)                                     |
| **Access mode**   | `ReadWriteOnce` (single node) or `ReadWriteMany` (multi-node) |
| **Mount path**    | Path inside the container where the volume is mounted         |
| **Storage class** | Leave empty to use the cluster default                        |

### Secrets (optional)

Reference Kubernetes Secrets or ConfigMaps as environment variables:

| Field            | Description                                                         |
| ---------------- | ------------------------------------------------------------------- |
| **envFrom**      | Inject all keys from a Secret or ConfigMap as environment variables |
| **secretKeyRef** | Inject a specific key from a Secret as a named environment variable |

Create or update those resources from the cluster **Config** panel before deploying the app. The app and the referenced Secret or ConfigMap must be in the same namespace.

To inject private registry credentials, use [Registry credentials](/guides/private-registries) instead — Niro adds `imagePullSecrets` automatically.

## 3. Review policy findings

As you fill in the form, Niro evaluates your configuration against [policy rules](/features/policies) in real time. Findings appear as inline warnings:

* **High** — should be fixed before deploying to production (e.g. privileged container, mutable `:latest` tag on a production cluster)
* **Medium** — best practice violations (e.g. missing resource limits)
* **Low / Info** — informational only

Findings are advisory — they never block deployment.

## 4. Deploy

Choose what to do with the generated manifests:

<Tabs>
  <Tab title="Apply directly">
    Click **Apply to cluster** to send the manifests to the cluster immediately. No Git commit is created.

    Niro shows the apply result within a few seconds — each Kubernetes object shows whether it was created, configured (updated), or unchanged.

    You can still commit the manifests to Git later from the deployment detail page.
  </Tab>

  <Tab title="Commit to Git">
    If your cluster has a [linked GitHub repo](/guides/gitops), click **Commit to repo** to:

    1. Create the manifest files in the linked repo folder
    2. Open a pull request
    3. Get AI-reviewed policy comments on the PR
    4. Apply automatically when the PR is merged (if auto-sync is enabled)

    You can choose to also apply immediately while the PR is open.
  </Tab>
</Tabs>

## 5. Monitor the deployment

After applying, Niro shows the deployment in the **Apps** list with its status:

* **Succeeded** — all objects applied cleanly
* **Partial** — some objects applied, some failed
* **Failed** — the apply command failed

Click the deployment to see per-object results, the apply history, and any policy findings on the current live state.

## Editing a deployment

Open the deployment detail page and click **Edit**. The builder reopens with the previously entered form values. Edit what you need and re-apply or commit a new PR.

## Private images

If your image requires authentication (Docker Hub private, GHCR, ECR, GCR, etc.), add your credentials in [Registries](/guides/private-registries) first. Niro will inject the appropriate `imagePullSecret` into the generated manifests automatically when you select that registry's image.

## Related

* [Visual Builder](/features/visual-builder) — full reference for all builder fields
* [Manage Secrets and ConfigMaps](/guides/secrets-configmaps) — create configuration resources for apps
* [Policies](/features/policies) — advisory standards checks run at build time
* [Private Registries](/guides/private-registries) — pull from private container registries
* [Set Up GitOps](/guides/gitops) — commit manifests to Git and auto-apply on merge
