> ## 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.

# SeaweedFS

> Deploy SeaweedFS on Control Plane using the Template Catalog. A single all-in-one node providing S3-compatible object storage with SigV4 authentication, persistent volume storage, startup bucket creation, and an admin UI — the in-org storage target for any template that speaks S3. Covers the two prerequisite credential secrets.

## Overview

SeaweedFS is a distributed object store with an S3-compatible API. This template deploys a single all-in-one node — master, volume server, filer, S3 gateway, and admin UI in one process — with persistent storage, startup bucket creation, and SigV4-authenticated S3 on port `8333`.

Its main use is as an in-org storage target: any workload or template that accepts an S3-compatible endpoint and a static access key pair can point at it without leaving your organization. Backing up [postgres-highly-available](/template-catalog/templates/postgres-highly-available) into SeaweedFS, and restoring from it, was verified end to end with no changes on the consumer side. See [Using SeaweedFS as an S3 backend](#using-seaweedfs-as-an-s3-backend).

Both sets of credentials — the S3 keys and the admin UI login — come from secrets you create **before** installing. Nothing sensitive passes through Helm values, and as of `1.1.0` the template creates no secret of its own at all.

<Warning>
  **Upgrading an install created with `1.0.0` is a breaking change.** `adminUI.username` and `adminUI.password` no longer exist, and an upgrade that still sets either one stops with an error naming its replacement — even when `adminUI.enabled` is `false`. See [Upgrading From 1.0.0](#upgrading-from-1-0-0). The S3 half is unchanged: `s3.credentialsSecretName` worked exactly this way in `1.0.0` and needs no edit.
</Warning>

### Architecture

* **All-in-one node** — A single `stateful` workload running `weed mini`, which starts the master, volume server, filer, S3 gateway, and admin UI in one process. The S3 API is served on port `8333`; the admin UI on port `23646`.
* **One disk for everything** — Object data, filer metadata (leveldb), and master metadata all live on one persistent volume set mounted at `/data`.
* **Authenticated by default** — S3 credentials come from a dictionary secret you create before installing. SeaweedFS serves S3 with *no authentication at all* when credentials are absent, so the chart refuses to render without one.
* **The admin login is a prerequisite too** — The admin UI's `username` and `password` come from a second dictionary secret you create. The template creates no secrets, so no credential ever lands in the Helm release.
* **Private by default** — External access is off (`publicAccess.enabled: false`); the S3 API is reachable only from inside the GVC until you turn it on. The admin UI is never publicly routed.

### What Gets Created

* **Stateful SeaweedFS Workload** — One replica serving the S3 API on port `8333`, plus the admin UI on port `23646` when enabled.
* **Volume Set** — Persistent storage at `/data` for objects and all metadata, with optional autoscaling. A final snapshot is retained for 7 days when the volume set is deleted.
* **Identity & Policy** — An identity bound to the workload with `reveal` on exactly the secrets it mounts: your S3 credentials secret, plus your admin credentials secret when the admin UI is enabled. Nothing else, and no cloud access at all.

<Note>
  This template creates **no secrets**. Both credentials live in secrets you own, which means uninstalling the release never destroys them — verified on a real uninstall, where both survived with their contents intact.
</Note>

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

## Prerequisites

**Two secrets must exist before you install.** They are deliberately separate: the S3 keys are handed to every client application, while the admin login reaches the bucket browser and maintenance tools. Secrets are org-level, so no GVC flag is involved.

<Steps>
  <Step title="Create the S3 credentials secret">
    A [dictionary secret](/guides/create-secret/dictionary) holding exactly the keys `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. These are the credentials every S3 client uses, and SeaweedFS serves S3 with *no authentication at all* without them:

    ```bash theme={null}
    cpln secret create-dictionary --name my-seaweedfs-s3-credentials \
      --entry AWS_ACCESS_KEY_ID="$(openssl rand -hex 10)" \
      --entry AWS_SECRET_ACCESS_KEY="$(openssl rand -hex 24)"
    ```

    Set `s3.credentialsSecretName` to the name you used.
  </Step>

  <Step title="Create the admin UI credentials secret">
    A [dictionary secret](/guides/create-secret/dictionary) holding exactly the keys `username` and `password`, guarding the admin login form. Required whenever `adminUI.enabled` is `true`, which is the default:

    ```bash theme={null}
    cpln secret create-dictionary --name my-seaweedfs-admin-credentials \
      --entry username=admin \
      --entry password="$(openssl rand -hex 24)"
    ```

    Set `adminUI.credentialsSecretName` to the name you used.
  </Step>

  <Step title="Read either secret back later">
    `-o yaml` is required; without it the command prints the secret's metadata table rather than its contents:

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

<Note>
  **The S3 half is unchanged from `1.0.0`.** `s3.credentialsSecretName` was already a prerequisite secret, so anything already backing up into SeaweedFS — [postgres-highly-available](/template-catalog/templates/postgres-highly-available), [thanos](/template-catalog/templates/thanos), [mimir](/template-catalog/templates/mimir) — needs no change whatsoever.
</Note>

<Warning>
  **A missing prerequisite secret wedges the install rather than failing it.** `cpln helm install` still exits 0 and reports success, all four resources are created, and the workload then never starts — it sits at zero replicas. Because the container never ran, `cpln logs` returns **zero lines**, which reads as a broken platform rather than a missing prerequisite.

  The only diagnostic is `status.versions[].message`, which names the missing secret:

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

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

  It is **`get-deployments`** — plain `cpln workload get` has no `versions` key at all. Creating the missing secret clears the wedge on its own, but slowly: recovery was measured at **7 minutes 15 seconds** here, inside the 5.5–8.5 minute range seen across the catalog. A forced redeployment shortcuts it to roughly 90 seconds.
</Warning>

## Installation

Install the template using your preferred method:

<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>

The node reaches `ready` about **52 seconds** after install, with the master, volume server, filer, S3 gateway, and admin UI all up in the one process.

## Upgrading From 1.0.0

Version `1.1.0` moved the admin UI login out of Helm values. `1.0.0` shipped a working username and password as values, used exactly as written, guarding the bucket browser and maintenance tools — a published default sitting in the release for the life of the install.

|                      | `1.0.0`                                          | `1.1.0`                                                                                         |
| -------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------- |
| Admin UI login       | `adminUI.username` and `adminUI.password` values | `adminUI.credentialsSecretName` — a dictionary secret you create with `username` and `password` |
| Chart-created secret | Held the admin credentials                       | None; the template creates no secrets at all                                                    |
| S3 credentials       | `s3.credentialsSecretName` prerequisite secret   | Unchanged                                                                                       |

<Warning>
  **A `helm upgrade` that still carries either removed key is rejected before anything is applied**, and the guard deliberately fires **even when `adminUI.enabled` is `false`** — otherwise a stale `password:` in your values would be silently accepted while you believed a credential was still in force. A real `cpln helm upgrade` carrying the old keys failed at render, created no Helm revision, and left the running release healthy and untouched:

  ```text theme={null}
  adminUI.username and adminUI.password were removed in seaweedfs 1.1.0 — the admin UI login form is
  now guarded by a REQUIRED prerequisite dictionary secret. Create one holding the keys 'username' and
  'password', then set adminUI.credentialsSecretName to its name.
  ```

  Leaving `adminUI.credentialsSecretName` empty while the UI is enabled is refused the same way. With `adminUI.enabled: false` an empty name renders fine — the feature is simply off, with no admin port, no credential environment, and no admin secret in the policy.
</Warning>

To upgrade an existing install:

<Steps>
  <Step title="Create the admin credentials secret">
    Follow [Prerequisites](#prerequisites). Put your existing username and password into it if you want current logins to keep working; otherwise choose new ones — the shipped `1.0.0` default was public.
  </Step>

  <Step title="Drop the removed keys from your values">
    Remove `adminUI.username` and `adminUI.password`, and set `adminUI.credentialsSecretName` instead. Leave `s3.credentialsSecretName` exactly as it is.
  </Step>

  <Step title="Upgrade">
    The single replica restarts and the store is briefly unavailable — see the outage window in [Important Notes](#important-notes). Stored objects on the volume set are untouched.
  </Step>
</Steps>

## Configuration

The default `values.yaml` for this template:

```yaml theme={null}
# Official upstream image. Runs `weed mini` — the image's own default command —
# which starts the master, volume server, filer, S3 gateway and admin UI in one
# process. Pin a concrete released tag; never latest.
image: chrislusf/seaweedfs:4.40

resources:
  minCpu: 250m
  maxCpu: 1000m
  minMemory: 512Mi
  maxMemory: 2Gi # raise for stores holding tens of millions of objects (in-memory volume index)

# Storage: objects + filer metadata + master metadata, all at /data
volumeset:
  capacity: 20 # initial capacity in GiB (minimum is 10)
  autoscaling:
    enabled: false # set to true to grow the volume automatically as it fills
    maxCapacity: 200 # maximum capacity in GiB when autoscaling is enabled
    minFreePercentage: 10 # minimum free percentage that triggers scaling
    scalingFactor: 1.2 # how much to grow the volume when scaling is triggered

# S3 API (port 8333)
s3:
  # PREREQUISITE dictionary secret — MUST EXIST BEFORE INSTALL, or the deployment
  # waits on it forever and looks broken. These are the S3 credentials every client
  # uses; SeaweedFS serves S3 with NO authentication if they are absent.
  credentialsSecretName: my-seaweedfs-s3-credentials
  # Buckets created at startup if they do not already exist, e.g. [backups, uploads].
  # Most backup tools require the bucket to exist before they run.
  buckets: []

# Admin UI (port 23646, reachable inside the GVC only)
adminUI:
  enabled: true # cluster status, bucket browser, user and maintenance management
  # REQUIRED PREREQUISITE SECRET when adminUI.enabled is true — CREATE IT BEFORE
  # YOU INSTALL. A `dictionary` secret holding exactly two keys, `username` and
  # `password`, guarding the admin login form. If it does not exist at install
  # time the deployment WEDGES silently — `cpln logs` returns nothing at all.
  credentialsSecretName: my-seaweedfs-admin-credentials

publicAccess:
  enabled: false # true = S3 API on the auto *.cpln.app HTTPS endpoint (path-style addressing)
internalAccess: # internal firewall scope
  type: same-gvc # options: none, same-gvc, same-org, workload-list
  workloads: [] # only used when type is workload-list
```

### Image and Resources

* `image` — The official upstream image. `weed mini` is the image's own default command; the template pins every port explicitly because mini's port layout can change between releases.
* `resources.minCpu` / `resources.maxCpu` / `resources.minMemory` / `resources.maxMemory` — CPU and memory for the container. The defaults run a typical store comfortably; raise `maxMemory` for stores holding tens of millions of objects, since the volume index is held in memory.

### Storage

* `volumeset.capacity` — Initial volume size in GiB (minimum 10). This one volume holds object data, filer metadata, and master metadata.
* `volumeset.autoscaling.enabled` — Automatically expand the volume as it fills. When enabled:
  * `maxCapacity` — Maximum volume size in GiB. Must be greater than or equal to `volumeset.capacity`.
  * `minFreePercentage` — Trigger a scale-up when free space drops below this percentage.
  * `scalingFactor` — Multiply the current capacity by this factor when scaling up.

Data survives restarts, redeployments, and `helm upgrade` under the same release name. Uninstalling deletes the volume set — and every stored object with it — keeping a final snapshot for 7 days.

<Note>
  SeaweedFS derives its volume file size from the disk capacity at startup, so growing the volume set takes effect on the next restart. This is harmless: SeaweedFS simply creates more volume files.
</Note>

### S3 API

* `s3.credentialsSecretName` — Name of the prerequisite dictionary secret holding `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. Required; the chart fails to render if it is empty.
* `s3.buckets` — Buckets created at startup if they do not already exist, for example `[backups, uploads]`. Names must be lowercase letters, digits, dots, and hyphens, 3–63 characters, starting with a letter or digit. Buckets are only ever created, never deleted — removing a name from this list leaves the bucket in place. You can also create buckets at runtime through the admin UI or with `aws s3 mb`.

Rotating the credentials secret and redeploying genuinely rotates the keys: the S3 identity is rebuilt from the environment on every boot rather than stored on disk. The old access key is rejected with `InvalidAccessKeyId` once the new replica is serving; stored objects are untouched.

### Admin UI

* `adminUI.enabled` — Cluster status, bucket browser, user, and maintenance management on port `23646`. Reachable from inside the GVC only.
* `adminUI.credentialsSecretName` — Name of the prerequisite dictionary secret holding the `username` and `password` that guard the login form. Required whenever the admin UI is enabled; the chart fails to render if it is empty.

Setting `adminUI.enabled: false` removes the port and the credential references, and narrows the policy to the S3 credentials secret alone. The admin routes then return `404`.

Reach the UI from your laptop with a tunnel — it is never publicly routed, and the tunnel works even when the workload is closed to both the internet and the GVC:

```bash theme={null}
cpln port-forward RELEASE_NAME-seaweedfs 23646:23646 --gvc GVC_NAME
```

Then open `http://localhost:23646` and log in with the two values from your admin secret. Authentication is genuinely enforced against that secret: an unauthenticated request redirects to `/login`, the protected API returns `401`, and a wrong username or password is refused with `Invalid credentials`.

<Note>
  Upstream `weed mini` still starts the admin component in-process when the UI is disabled — only its routes are unregistered. Because the port is not declared on the workload and no credentials are injected, nothing is reachable from outside the container.
</Note>

### Access

* `publicAccess.enabled` — `false` by default. When set to `true`, the S3 API is served over HTTPS on the automatically assigned `*.cpln.app` canonical endpoint, using path-style addressing. Only port `8333` is exposed this way; the admin UI is never publicly routed.

<Note>
  **Port 23646 is not reachable from outside, even with `publicAccess.enabled: true`.** The workload declares `8333` first, so the canonical endpoint binds to the S3 gateway and there is no public route to the admin port at all. Requesting `/login` on the public endpoint returns S3 XML that parses the path as a bucket name — `<BucketName>login</BucketName>` — which proves the request reached the S3 gateway rather than the admin server.
</Note>

* `internalAccess.type` — Internal firewall scope of the workload:

| Type            | Description                                                                                                          |
| --------------- | -------------------------------------------------------------------------------------------------------------------- |
| `none`          | No internal access.                                                                                                  |
| `same-gvc`      | Allow access from all workloads in the same GVC (default).                                                           |
| `same-org`      | Allow access from all workloads in the same organization, including other GVCs.                                      |
| `workload-list` | Allow access only from workloads listed in `internalAccess.workloads`, e.g. `//gvc/GVC_NAME/workload/WORKLOAD_NAME`. |

<Note>
  **Firewall changes take a minute or two to take effect.** Turning `publicAccess.enabled` on was measured at **132 seconds** end to end, stepping through `403` (closed) and `503` (routing not yet up) before serving `200`. A client that cached a negative DNS answer can lag an allow by another 30 seconds or so. Re-test before concluding a knob is broken.
</Note>

## Using SeaweedFS as an S3 Backend

Any client that speaks S3 works, subject to three rules:

* **Path-style addressing is required** (`http://host:8333/bucket/key`). Virtual-host style (`bucket.host`) is not served.
* **Any region value works.** The region is read from the client's signature scope and never compared against a server-side value, so a consumer hardcoded to `us-east-1` is fine as-is.
* **The bucket must already exist** for most backup tools. Create it with `s3.buckets`, through the admin UI, or with `aws s3 mb`.

### Verifying from inside the GVC

```bash theme={null}
aws configure set default.s3.addressing_style path
aws --endpoint-url http://RELEASE_NAME-seaweedfs:8333 s3 ls
aws --endpoint-url http://RELEASE_NAME-seaweedfs:8333 s3 cp ./file s3://BUCKET/file
```

### Catalog templates

Endpoint and credentials for the common catalog consumers. `accessKey` / `secretKey` (or `accessSecret`) are the two values you put in the prerequisite secret.

| Consumer template                                                                                                                                                                          | Values to set                                                                                                                                                                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [postgres-highly-available](/template-catalog/templates/postgres-highly-available), [timescaledb-highly-available](/template-catalog/templates/timescaledb-highly-available)               | `backup.provider: minio`, `backup.minio.endpoint: http://RELEASE_NAME-seaweedfs:8333`, plus `backup.minio.bucket`, `backup.minio.accessKey`, `backup.minio.secretKey`, `backup.minio.prefix`                                                                                 |
| [thanos](/template-catalog/templates/thanos), [mimir](/template-catalog/templates/mimir)                                                                                                   | `storage.type: minio`, `storage.minio.endpoint: RELEASE_NAME-seaweedfs.GVC_NAME.cpln.local:8333` (host:port, no scheme), `storage.minio.insecure: true`, `storage.minio.region: us-east-1`, plus `bucket`, `accessKey`, `accessSecret`                                       |
| [prometheus](/template-catalog/templates/prometheus)                                                                                                                                       | Same fields, nested one level deeper: `thanos.objectStorage.enabled: true`, `thanos.objectStorage.type: minio`, then `thanos.objectStorage.minio.*`                                                                                                                          |
| [sftpgo](/template-catalog/templates/sftpgo)                                                                                                                                               | `storage.type: minio`, `storage.minio.endpoint: http://RELEASE_NAME-seaweedfs:8333`, plus `bucket`, `region`, `accessKey`, `accessSecret`                                                                                                                                    |
| [docmost](/template-catalog/templates/docmost)                                                                                                                                             | `storage.type: s3`, `storage.s3.endpoint: http://RELEASE_NAME-seaweedfs:8333`, `storage.s3.forcePathStyle: true`, `storage.s3.bucket`, `storage.s3.region: us-east-1`, and `storage.s3.auth.secretName` pointing at a **separate** dictionary secret — see the warning below |
| [n8n](/template-catalog/templates/n8n), [metabase](/template-catalog/templates/metabase), [keycloak](/template-catalog/templates/keycloak), [unleash](/template-catalog/templates/unleash) | Backups of their bundled database: `postgresHA.backup.provider: minio` (or `postgres.backup.provider: minio` in single-instance mode) with the matching `…backup.minio.endpoint`, `bucket`, `accessKey`, `secretKey`, `prefix`                                               |

<Warning>
  **Docmost needs a second secret with different key names.** Its static-key secret must contain `AWS_S3_ACCESS_KEY_ID` and `AWS_S3_SECRET_ACCESS_KEY` — the same two values as this template's secret, under different keys. Point `storage.s3.auth.secretName` at that secret, not at `s3.credentialsSecretName`.
</Warning>

Templates whose object-storage support is limited to named providers — [ghost](/template-catalog/templates/ghost) and [clickhouse](/template-catalog/templates/clickhouse), which offer only `aws`/`gcp` and similar — cannot point at an arbitrary S3 endpoint, so they cannot use this template as their storage target.

## Connecting

| Target                        | Address                                                   | Notes                                                                                                                                                                                                                     |
| ----------------------------- | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| S3 API, same GVC              | `http://RELEASE_NAME-seaweedfs:8333`                      | Short name; resolves from any workload in the same GVC.                                                                                                                                                                   |
| S3 API, same GVC (FQDN)       | `http://RELEASE_NAME-seaweedfs.GVC_NAME.cpln.local:8333`  | Same host, fully qualified.                                                                                                                                                                                               |
| S3 API, host:port form        | `RELEASE_NAME-seaweedfs.GVC_NAME.cpln.local:8333`         | For clients that take a bare host:port, such as Thanos and Mimir. Pair with `insecure: true`.                                                                                                                             |
| S3 API, public *(if enabled)* | `https://<canonical>.cpln.app`                            | Port 443, no port suffix. Requires `publicAccess.enabled: true`.                                                                                                                                                          |
| Admin UI                      | `http://RELEASE_NAME-seaweedfs.GVC_NAME.cpln.local:23646` | Inside the GVC only, never publicly routed. From a laptop, tunnel with `cpln port-forward RELEASE_NAME-seaweedfs 23646:23646 --gvc GVC_NAME`. Log in with the `username` / `password` from your admin credentials secret. |
| Health check                  | `GET /healthz` on port `8333`                             | Unauthenticated by design.                                                                                                                                                                                                |

Same-GVC clients use plain `http://` over the mesh's mTLS; external clients use `https://`, with TLS terminated at the platform edge. The canonical hostname appears under `status.canonicalEndpoint` in `cpln workload get RELEASE_NAME-seaweedfs --gvc GVC_NAME -o yaml`.

Requests without a valid signature are rejected: unsigned requests get `403`, and a wrong secret key gets `SignatureDoesNotMatch`.

## Important Notes

* **Create both prerequisite secrets before installing.** A missing one wedges the deployment with no log output at all; [Prerequisites](#prerequisites) gives the one command that diagnoses it.
* **The template creates no secrets** — both credentials are yours, so `helm uninstall` leaves them in place.
* **Install to ready takes about 52 seconds** on the shipped defaults.
* **The template deploys a single replica by design.** `weed mini` runs one master, one filer, and one volume server in a single process, so raising the replica count would create separate, divergent object stores. Multi-node clustering is a planned follow-up.
* **A redeploy or upgrade is a full S3 outage.** Measured at **337 failed requests over an 80.8 second gap** (at roughly 5 requests/second), with the store serving again about 128 seconds after the redeploy was triggered. Almost all of that is platform teardown and reschedule — SeaweedFS itself boots in about 1.5 seconds. Schedule upgrades accordingly, and expect the same window whenever the platform reschedules the replica.
* **Clients must use path-style addressing**; virtual-host style is not served.
* **Only the S3 API is publicly routable.** `publicAccess` exposes port `8333` alone — reach the admin UI from inside the GVC or through `cpln port-forward`.
* **Rotating the credentials secret and redeploying rotates the keys**, leaving stored data untouched. Update every consumer at the same time.
* **Data survives restarts and upgrades; uninstall deletes the volume set** and every stored object, keeping a final snapshot for 7 days.
* **Uninstall does not delete either credentials secret** — both are your resources, created outside the release, and they stay until you remove them.

## External References

<CardGroup cols={2}>
  <Card title="SeaweedFS on GitHub" icon="github" href="https://github.com/seaweedfs/seaweedfs">
    Source, releases, and issue tracker
  </Card>

  <Card title="Quick Start with weed mini" icon="rocket" href="https://github.com/seaweedfs/seaweedfs/wiki/Quick-Start-with-weed-mini">
    The all-in-one mode this template runs
  </Card>

  <Card title="Amazon S3 API Support" icon="cloud" href="https://github.com/seaweedfs/seaweedfs/wiki/Amazon-S3-API">
    Which S3 operations SeaweedFS implements
  </Card>

  <Card title="S3 Credentials" icon="key" href="https://github.com/seaweedfs/seaweedfs/wiki/S3-Credentials">
    How SeaweedFS resolves S3 identities and access keys
  </Card>

  <Card title="Admin UI" icon="gauge" href="https://github.com/seaweedfs/seaweedfs/wiki/Admin-UI">
    Cluster status, bucket browser, and maintenance
  </Card>

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