> For the complete documentation index, see [llms.txt](https://docs.credebl.id/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.credebl.id/docs/getting-started/local-deployment/platform/openbao.md).

# OpenBao Secret Storage (Optional)

The CREDEBL Platform can source the credentials used by its email and file-storage integrations from an [OpenBao](https://openbao.org) server instead of plain environment variables. OpenBao is a HashiCorp Vault-compatible secrets engine that provides a central, access-controlled store for your API keys and credentials.

{% hint style="info" %}
OpenBao secret storage is **optional** and **disabled by default**. The Platform continues to work with credentials supplied directly through the `.env` file as described in the [Platform](/docs/getting-started/local-deployment/platform.md) guide.
{% endhint %}

When enabled, the following credentials can be stored in OpenBao and fetched by the Platform at runtime:

| Credential                                                       | Stored in OpenBao                 | Used for                                  |
| ---------------------------------------------------------------- | --------------------------------- | ----------------------------------------- |
| `RESEND_API_KEY`                                                 | `secret/credebl_resend_api_key`   | Sending emails through Resend             |
| `SENDGRID_API_KEY`                                               | `secret/credebl_sendgrid_api_key` | Sending emails through SendGrid           |
| `SMTP_HOST`, `SMTP_PORT`, `SMTP_USER`, `SMTP_PASS`               | `secret/credebl_smtp_config`      | Sending emails through SMTP               |
| `AWS_ACCESS_KEY`, `AWS_SECRET_KEY`                               | `secret/credebl_aws_keys`         | Internal S3 file storage                  |
| `AWS_PUBLIC_ACCESS_KEY`, `AWS_PUBLIC_SECRET_KEY`                 | `secret/credebl_aws_keys`         | Public (logo/URL) S3 storage              |
| `AWS_S3_STOREOBJECT_ACCESS_KEY`, `AWS_S3_STOREOBJECT_SECRET_KEY` | `secret/credebl_aws_keys`         | Connection URL / shortened URL S3 storage |

The Platform loads these in two ways:

1. **Startup injection** — every microservice fetches its secrets once during bootstrap and injects them into the process environment before it starts listening.
2. **Runtime lookup with caching** — email and S3 clients fetch their own credential sets on demand, cached per secret path for 10 minutes, so credentials can be rotated without restarting the service.

## Step 1: Run the OpenBao server

OpenBao is provided as a Docker service in the platform repository.

```bash
docker compose -f docker-compose.openbao.yml up -d
```

This starts an OpenBao server on `http://127.0.0.1:8200` with file-backed storage persisted on a named Docker volume, so data survives container restarts. Server settings live in `config.hcl`.

## Step 2: Provision the server

OpenBao starts sealed and uninitialized. Run the one-shot provisioning script from the root of the platform repository:

```bash
./openbao-init.sh
```

The script is idempotent and safe to re-run. It:

* Initializes and unseals the server.
* Enables the KV v2 secrets engine at `secret/`.
* Enables the AppRole auth method.
* Creates a `credebl` role scoped to the `credebl_*` secret paths.
* Stores the secret values found in the matching environment variables.
* Prints the values to add to your `.env` file:

```
BAO_URL=http://127.0.0.1:8200
BAO_SECRET_PATH=secret/data/credebl_resend_api_key
BAO_ROLE_ID=<generated>
BAO_SECRET_ID=<generated>
```

{% hint style="danger" %}
The script also prints `BAO_UNSEAL_KEY` and `BAO_ROOT_TOKEN`. These are shown **only on the first run** — save them securely, as they are required to unseal the server or log in later. Do not commit them to the repository.
{% endhint %}

On later runs, pass `BAO_ROOT_TOKEN` (and `BAO_SECRET_ID` to re-print it) so the script can connect to the already-initialized server:

```bash
BAO_ROOT_TOKEN=<root-token> ./openbao-init.sh
```

## Step 3: Configure the Platform

Add the following to your `.env` file, replacing `<role-id>` and `<secret-id>` with the values printed by `openbao-init.sh`:

```sh
# Enable OpenBao secret storage
ENABLE_BAO=true

# Secret provider: only 'openbao' is supported today
SECRETS_PROVIDER=openbao

# OpenBao server URL (docker-compose.openbao.yml maps 8200)
BAO_URL=http://127.0.0.1:8200

# Default KV v2 path fetched at boot and injected into the process environment
BAO_SECRET_PATH=secret/data/credebl_resend_api_key

# AppRole credentials generated by ./openbao-init.sh
BAO_ROLE_ID=<role-id>
BAO_SECRET_ID=<secret-id>
```

{% hint style="info" %}
These variables are already present (with placeholder values) in the `.env.demo` file at the root of the platform repository.
{% endhint %}

## How secrets are stored

The `openbao-init.sh` script writes each credential set only when the matching environment variable is set (non-empty). For example, to store a Resend API key and SMTP settings:

```bash
RESEND_API_KEY=your-resend-key \
SMTP_HOST=smtp.example.com \
SMTP_PORT=587 \
SMTP_USER=user \
SMTP_PASS=password \
./openbao-init.sh
```

If none of the variables for a given path are set, that path is skipped.

## Disabling OpenBao

To return to plain environment variables, set `ENABLE_BAO` to anything other than `true` (or remove it) and restart the services. The Platform then falls back to the credentials provided directly in the `.env` file.
