> ## Documentation Index
> Fetch the complete documentation index at: https://controlplanecorporation-majid-docs-content-expansion.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# MongoDB

> Deploy MongoDB on Control Plane using the Template Catalog. Covers the prerequisite credentials secret, volumes, internal and external access, scheduled S3 and GCS backups, and upgrading from template version 1.3.2.

## Overview

MongoDB is a document-oriented NoSQL database designed for flexible, schema-free data storage at scale. This template deploys a single-replica MongoDB instance with persistent storage and optional external access via a direct load balancer.

Database credentials are **not** template values. MongoDB reads its username, password and database name from a dictionary secret you create before installing, so no password passes through Helm or lands in the release.

<Warning>
  **Template version 1.4.0 is a breaking security change.** `config.username` and `config.password` were removed, and an install or upgrade that still sets either one now fails at render instead of silently falling back to a published default password. If you are running 1.3.2 or earlier, read [Upgrading From 1.3.2 or Earlier](#upgrading-from-1-3-2-or-earlier) before you touch the release.
</Warning>

<Note>
  MongoDB on Control Plane operates as a single-replica deployment. Do not scale up the replica count, as this would result in multiple isolated instances rather than a replicated cluster.
</Note>

### What Gets Created

* **Stateful MongoDB Workload** — A single-replica MongoDB container with configurable resources.
* **Volume Set** — Persistent storage for MongoDB data, with optional autoscaling.
* **Backup Config Secret** *(optional)* — A dictionary secret holding the backup bucket and region. Non-sensitive, and created only when `backup.enabled: true`.
* **Identity & Policy** — An identity bound to the workload, and a policy granting it `reveal` on exactly the credentials secret you created — plus the backup config secret and Cloud Account binding when backup is enabled.
* **Backup Cron Workload** *(optional)* — A scheduled `mongodump` backup job that writes compressed archives to AWS S3 or GCS.

The template creates **no credential secret of its own.** The username, password and database name live only in the prerequisite secret described below.

<Note>
  This template does not create a GVC. You must deploy it into an existing GVC.
</Note>

## Upgrading From 1.3.2 or Earlier

Template versions up to 1.3.2 took the database credentials as plain Helm values, shipped working defaults for them, and wrote those credentials into a chart-owned secret named after the release. Version 1.4.0 removes all of that.

|                          | 1.3.2 and earlier                                                      | 1.4.0                                                           |
| ------------------------ | ---------------------------------------------------------------------- | --------------------------------------------------------------- |
| Database credentials     | `config.username`, `config.password`, `config.database` values         | `config.credentialsSecretName` → a dictionary secret you create |
| Where the password lives | Chart-created secret `RELEASE_NAME-mongo-config`, and the Helm release | Only the secret you create                                      |

<Warning>
  **Carrying the old values forward stops the upgrade.** The removed keys are rejected at render, so `cpln helm upgrade` fails and your existing release is left untouched and running, rather than quietly restarting against a different password:

  ```text theme={null}
  Error: execution error at (mongodb/templates/identity.yaml:1:4): mongodb: config.username and
  config.password were REMOVED — they are now a `dictionary` secret you create, named by
  config.credentialsSecretName, holding the keys `username`, `password` and `database`. Delete
  them from your values. See Prerequisites in the README.
  ```
</Warning>

<Steps>
  <Step title="Read the credentials the database already uses">
    Credentials are written into the data directory the first time the volume is initialized, so an existing database keeps whatever it was created with. Recover them from your current values file, or from the secret the old version created — do this **before** upgrading:

    ```bash theme={null}
    cpln secret reveal RELEASE_NAME-mongo-config -o yaml
    ```

    Pass `-o yaml`. A bare `cpln secret reveal` prints only a summary table, not the values.
  </Step>

  <Step title="Create the prerequisite secret with those same values">
    Follow [Prerequisites](#prerequisites), using the existing username, password and database name. Different values here do not change the database — they just leave the workload unable to authenticate.
  </Step>

  <Step title="Remove the old keys from your values">
    Delete `config.username`, `config.password` and `config.database`, and set `config.credentialsSecretName` to your secret's name.
  </Step>

  <Step title="Upgrade, then rotate the password">
    After the upgrade succeeds, change any password that came from a 1.3.2 default — those defaults were published in the public template repository, so treat them as compromised. Rotate inside MongoDB, then update the secret to match:

    ```javascript theme={null}
    db.changeUserPassword("myuser", "NEW-STRONG-PASSWORD")
    ```
  </Step>
</Steps>

<Warning>
  **`RELEASE_NAME-mongo-config` no longer holds credentials.** It is now created only when `backup.enabled: true`, and holds nothing but the bucket and region. Anything outside this release that read the username or password from it by name — another workload's environment, a policy, or a parent chart bundling MongoDB as a subchart — must be pointed at the secret you create instead. A reference to a key that no longer exists does not fail loudly; it wedges the referring workload silently.
</Warning>

## Prerequisites

**One secret must exist before you install.** It holds the credentials your applications put in their connection strings. The values never pass through Helm, so they do not land in the release. Secrets are org-level, so no GVC flag is involved.

<Steps>
  <Step title="Create the database credentials secret">
    A [dictionary secret](/guides/create-secret/dictionary) holding exactly three keys — `username`, `password` and `database`. MongoDB creates that user and that database on first boot:

    ```bash theme={null}
    cpln secret create-dictionary --name my-mongodb-credentials \
      --entry username=myuser \
      --entry password='YOUR-STRONG-PASSWORD' \
      --entry database=mydb
    ```

    Set `config.credentialsSecretName` to the name you used. Secret names are org-wide, so give each release its own.
  </Step>

  <Step title="Read the secret back later">
    Pass `-o yaml`. A bare `cpln secret reveal` prints only a summary table, not the values:

    ```bash theme={null}
    cpln secret reveal my-mongodb-credentials -o yaml
    ```
  </Step>
</Steps>

<Warning>
  **Create the secret before installing, or the deployment wedges silently.** The template refuses to render when `config.credentialsSecretName` is blank, but a name pointing at a secret that does not exist installs "successfully" and then never starts. The container never runs, so `cpln logs` returns **zero lines** — there is nothing to log, and every summary surface just looks like a slow deploy. The one place the reason appears is `status.versions[].message`:

  ```bash theme={null}
  cpln workload get-deployments RELEASE_NAME-mongo --gvc GVC_NAME -o yaml
  ```

  ```text theme={null}
  The secret my-mongodb-credentials no longer exists. Workload updates are paused until the
  secret is added or the reference to the secret removed.
  ```

  Use `get-deployments` — plain `cpln workload get` has no `versions` key and will show you nothing. Creating the missing secret repairs it on its own with no further action, in roughly **5.5 to 10.5 minutes** measured across five templates, or run `cpln workload force-redeployment RELEASE_NAME-mongo --gvc GVC_NAME` to clear it in about 90 seconds.
</Warning>

Backups need a bucket, and a Control Plane Cloud Account, before they can be enabled — see [AWS S3](#aws-s3) or [GCS](#gcs). Nothing else is required.

## Installation

Create the [prerequisite secret](#prerequisites) first, then install by whichever method you prefer:

<CardGroup cols={2}>
  <Card title="UI" href="/template-catalog/install-manage/ui" icon="laptop">
    Browse, install, and manage templates visually
  </Card>

  <Card title="CLI" href="/template-catalog/install-manage/cli" icon="terminal">
    Manage templates from your terminal
  </Card>

  <Card title="Terraform" href="/template-catalog/install-manage/terraform" icon={<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128"><g fill-rule="evenodd"><path d="M77.941 44.5v36.836L46.324 62.918V26.082zm0 0" fill="#5c4ee5"/><path d="M81.41 81.336l31.633-18.418V26.082L81.41 44.5zm0 0" fill="#4040b2"/><path d="M11.242 42.36L42.86 60.776V23.941L11.242 5.523zm0 0M77.941 85.375L46.324 66.957v36.82l31.617 18.418zm0 0" fill="#5c4ee5"/></g></svg>}>
    Declare templates in your Terraform configurations
  </Card>

  <Card
    title="Pulumi"
    href="/template-catalog/install-manage/pulumi"
    icon={<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" id="Pulumi-Icon--Streamline-Svg-Logos" height="24" width="24">
    <desc>
        Pulumi Icon Streamline Icon: https://streamlinehq.com
    </desc>
    <path fill="#f26e7e" d="M4.683025 13.3318c0.869125 -0.5018 0.870575 -2.1264 0.003225 -3.62865s-2.27504 -2.313275 -3.1441725 -1.811475C0.672945 8.3935 0.6715 10.0181 1.53885 11.52035c0.86735 1.502275 2.27505 2.313275 3.144175 1.81145Zm0.0052 3.2167c0.86735 1.502275 0.865925 3.126875 -0.003225 3.628675 -0.86915 0.5018 -2.2768275 -0.309225 -3.144175 -1.81145 -0.8673525 -1.50225 -0.8659075 -3.126875 0.003225 -3.628675 0.8691325 -0.5018 2.276825 0.309225 3.144175 1.81145Zm5.922875 3.4243c0.86735 1.50225 0.8659 3.126775 -0.003225 3.62875 -0.869125 0.501775 -2.27685 -0.309325 -3.1442 -1.81155 -0.867325 -1.50225 -0.865875 -3.12685 0.00325 -3.628675 0.869125 -0.5018 2.276825 0.309225 3.144175 1.811475Zm-0.001925 -6.845275c0.86735 1.50225 0.8659 3.12685 -0.003225 3.628675 -0.869125 0.5018 -2.276825 -0.309225 -3.144175 -1.811475 -0.86735 -1.50225 -0.8659 -3.12685 0.003225 -3.62865 0.869125 -0.501825 2.276825 0.3092 3.144175 1.81145Z" stroke-width="0.25"></path>
    <path fill="#8a3391" d="M22.45775 11.524125c0.86725 -1.502225 0.865925 -3.12685 -0.003225 -3.62865 -0.869125 -0.501825 -2.276825 0.3092 -3.144175 1.811475 -0.86735 1.50225 -0.8659 3.126825 0.003225 3.62865 0.869125 0.501825 2.276825 -0.3092 3.144175 -1.811475Zm0.000175 3.2151c0.869075 0.5018 0.870625 2.1264 0.003225 3.62865 -0.86735 1.50225 -2.27505 2.313275 -3.144175 1.81145 -0.869125 -0.5018 -0.870575 -2.126425 -0.003225 -3.62865 0.86735 -1.50225 2.27505 -2.313275 3.144175 -1.81145ZM16.536225 18.157875c0.86915 0.501825 0.8706 2.126425 0.00325 3.628675 -0.86735 1.502125 -2.275075 2.313225 -3.1442 1.81145 -0.869125 -0.50175 -0.870575 -2.126425 -0.003225 -3.62865 0.867375 -1.502275 2.27505 -2.3133 3.144175 -1.811475Zm-0.003325 -6.843775c0.869125 0.5018 0.870575 2.126425 0.003225 3.628675s-2.27505 2.313275 -3.1442 1.811475c-0.869125 -0.501825 -0.870575 -2.126425 -0.003225 -3.628675 0.86735 -1.502275 2.27505 -2.313275 3.1442 -1.811475Z" stroke-width="0.25"></path>
    <path fill="#f7bf2a" d="M15.138225 2.06721c0 1.003615 -1.40625 1.817215 -3.14095 1.817215 -1.7347 0 -3.14095 -0.8136 -3.14095 -1.817215C8.856325 1.06359 10.262575 0.25 11.997275 0.25c1.7347 0 3.14095 0.81359 3.14095 1.81721ZM9.2166 5.482375c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172s1.40625 -1.817225 3.14095 -1.817225c1.7347 0 3.14095 0.8136 3.14095 1.817225Zm8.71005 1.8172c1.7347 0 3.14095 -0.813575 3.14095 -1.8172s-1.40625 -1.817225 -3.14095 -1.817225c-1.7347 0 -3.14095 0.8136 -3.14095 1.817225s1.40625 1.8172 3.14095 1.8172Zm-2.788425 1.605625c0 1.003625 -1.40625 1.8172 -3.14095 1.8172 -1.7347 0 -3.14095 -0.813575 -3.14095 -1.8172 0 -1.0036 1.40625 -1.8172 3.14095 -1.8172 1.7347 0 3.14095 0.8136 3.14095 1.8172Z" stroke-width="0.25"></path>
    </svg>}
  >
    Declare templates in your Pulumi programs
  </Card>
</CardGroup>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
image: mongo:8.2.3

resources:
  minCpu: 200m
  minMemory: 256Mi
  maxCpu: 500m
  maxMemory: 512Mi

config:
  # REQUIRED PREREQUISITE SECRET — CREATE IT BEFORE YOU INSTALL.
  # A `dictionary` secret holding exactly three keys: `username`, `password`
  # and `database`. If it does not exist at install time the deployment
  # WEDGES silently — `cpln logs` returns nothing at all. See Prerequisites
  # for the exact `cpln secret create-dictionary` command.
  credentialsSecretName: my-mongodb-credentials

volumeset:
  capacity: 10 # initial capacity in GiB (minimum is 10)
  autoscaling:
    enabled: false # Set to true to enable autoscaling
    maxCapacity: 100 # Maximum capacity in GiB when autoscaling is enabled
    minFreePercentage: 10 # Minimum free percentage to trigger scaling when autoscaling is enabled
    scalingFactor: 1.2 # Scaling factor to determine how much to scale up when autoscaling is triggered

internalAccess: # Sets the internal firewall scope
  type: same-gvc # options: none, same-gvc, same-org, workload-list
  workloads:  # Note: can only be used if type is same-gvc or workload-list
    #- //gvc/GVC_NAME/workload/WORKLOAD_NAME

directLoadBalancer:
  enabled: false

backup:
  enabled: false
  image: ghcr.io/controlplane-com/backup-images/mongo-backup:8.0
  schedule: "0 2 * * *"   # daily at 2am UTC

  resources:
    cpu: 100m
    memory: 128Mi

  provider: aws # Options: aws or gcp

  aws:
    bucket: my-backup-bucket
    region: us-east-1
    cloudAccountName: my-backup-cloudaccount
    policyName: my-backup-policy
    prefix: mongodb/backups

  gcp:
    bucket: my-backup-bucket
    cloudAccountName: my-backup-cloudaccount
    prefix: mongodb/backups
```

### Credentials

* `config.credentialsSecretName` — Name of the dictionary secret holding `username`, `password` and `database`. MongoDB creates that root user and that initial database on first boot, and these are the credentials your applications put in their connection strings.

The secret must exist before installing — see [Prerequisites](#prerequisites). The workload reads it through `cpln://secret/...` references, so the values appear in neither the Helm release nor the stored workload spec.

<Note>
  The credentials are applied only on first startup, when the data directory is empty. Changing the secret afterwards does **not** change the running database — it only changes what the workload presents when it authenticates, which will then fail. To rotate on an existing instance, change it inside MongoDB with `db.changeUserPassword()` first, then update the secret to match.
</Note>

### Resources

* `resources.minCpu` / `resources.minMemory` — Minimum CPU and memory guaranteed to the workload.
* `resources.maxCpu` / `resources.maxMemory` — Maximum CPU and memory the workload can use.

### Storage

* `volumeset.capacity` — Initial volume size in GiB (minimum 10).
* `volumeset.autoscaling.enabled` — Automatically expand the volume as it fills. When enabled:
  * `maxCapacity` — Maximum volume size in GiB.
  * `minFreePercentage` — Trigger a scale-up when free space drops below this percentage.
  * `scalingFactor` — Multiply the current capacity by this factor when scaling up.

### Internal Access

* `internalAccess.type` — Controls which workloads can connect to MongoDB on port `27017`:

| Type            | Description                                                     |
| --------------- | --------------------------------------------------------------- |
| `none`          | No internal access allowed                                      |
| `same-gvc`      | Allow access from all workloads in the same GVC                 |
| `same-org`      | Allow access from all workloads in the same organization        |
| `workload-list` | Allow access only from specific workloads listed in `workloads` |

### Direct Load Balancer

* `directLoadBalancer.enabled` — When `true`, exposes MongoDB externally on port `27017` via a dedicated load balancer IP.

### Connecting to MongoDB

Once deployed, connect to MongoDB from within the same GVC using:

```text theme={null}
RELEASE_NAME-mongo.GVC_NAME.cpln.local:27017
```

## Backup

Backup is disabled by default. When enabled, a cron workload runs `mongodump` on the configured schedule and uploads compressed archives to AWS S3 or GCS. The backup image is compatible with all MongoDB versions.

* `backup.enabled` — Enable scheduled backups.
* `backup.schedule` — Cron expression for backup frequency (default: daily at 2am UTC).
* `backup.provider` — `aws` or `gcp`.
* `backup.resources.cpu` / `backup.resources.memory` — Resources for the backup cron container.

### AWS S3

Before enabling backup with `provider: aws`, complete the following in your AWS account:

1. Create an S3 bucket. Set `backup.aws.bucket` to its name and `backup.aws.region` to its region.
2. If you do not have a Cloud Account set up, refer to the docs to [Create a Cloud Account](/guides/create-cloud-account). Set `backup.aws.cloudAccountName` to its name.
3. Create an IAM policy with the following JSON, replacing `YOUR_BUCKET_NAME`:

<Warning>
  **Version 1.4.1 narrows AWS backup permissions.** This version removes `aws::ReadOnlyAccess` from the backup identity. That AWS managed policy granted read access to **every bucket in your AWS account** and contains no write actions at all, so it was never carrying the backup itself — but it *was* silently supplying any read action your own bucket-scoped policy happened to omit.

  **Update your IAM policy to the full action list below before upgrading.** If it already matches, no action is needed. The identity now carries `cpln-connector` and your bucket-scoped policy only, which is strictly narrower than before. Nothing else changes.
</Warning>

```json theme={null}
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject",
                "s3:ListBucket",
                "s3:GetObjectVersion",
                "s3:DeleteObjectVersion",
                "s3:GetBucketLocation",
                "s3:AbortMultipartUpload",
                "s3:ListBucketMultipartUploads",
                "s3:ListMultipartUploadParts"
            ],
            "Resource": [
                "arn:aws:s3:::YOUR_BUCKET_NAME",
                "arn:aws:s3:::YOUR_BUCKET_NAME/*"
            ]
        }
    ]
}
```

4. Set `backup.aws.policyName` to the name of the policy created in step 3.
5. Set `backup.aws.prefix` to the folder path where backups will be stored.

### GCS

Before enabling backup with `provider: gcp`, complete the following in your GCP account:

1. Create a GCS bucket. Set `backup.gcp.bucket` to its name.
2. If you do not have a Cloud Account set up, refer to the docs to [Create a Cloud Account](/guides/create-cloud-account). Set `backup.gcp.cloudAccountName` to its name.
3. Add the **Storage Admin** role to the GCP service account associated with the Cloud Account.
4. Set `backup.gcp.prefix` to the folder path where backups will be stored.

## Restoring a Backup

Run the following from a client with access to the backup bucket. For GCS, replace `aws s3 cp s3://...` with `gsutil cp gs://...`. `USERNAME` is the `username` entry from your credentials secret.

```sh theme={null}
aws s3 cp s3://BUCKET_NAME/PREFIX/BACKUP_FILE.gz - \
  | gunzip \
  | mongorestore \
      --host=RELEASE_NAME-mongo.GVC_NAME.cpln.local \
      --port=27017 \
      --username=USERNAME \
      --archive
```

## External References

<CardGroup cols={2}>
  <Card title="MongoDB Documentation" icon="book" href="https://www.mongodb.com/docs/">
    Official MongoDB documentation
  </Card>

  <Card title="Backup Image Source" icon="github" href="https://github.com/controlplane-com/backup-images/tree/main/mongo-backup">
    Source code for the MongoDB backup container image
  </Card>

  <Card title="MongoDB Template" icon="github" href="https://github.com/controlplane-com/templates/tree/main/mongodb">
    View the source files, default values, and chart definition
  </Card>
</CardGroup>
