doc/administration/secrets_manager/_index.md
{{< details >}}
{{< /details >}}
{{< history >}}
{{< /history >}}
The GitLab Secrets Manager uses OpenBao, an open-source secrets management solution. OpenBao provides secure storage, access control, and lifecycle management for secrets used in your GitLab instance.
GitLab CI/CD jobs using secrets from the GitLab Secrets Manager must use GitLab Runner 18.6 or later.
OpenBao integrates with GitLab as an optional component that runs in parallel to existing GitLab services.
flowchart TB
SecretStore[Secret store]
PostgreSQL[PostgreSQL]
LB[Load balancer]
OpenBao[OpenBao active node]
Rails-- Write secrets and permissions -->LB
Runner-- Get pipeline secrets -->LB
LB-->OpenBao
OpenBao-- Get unseal key -->SecretStore
OpenBao-- Store -->PostgreSQL
OpenBao runs with a single active node that handles all requests, and optionally multiple standby nodes that take over if the active node fails.
Prerequisites:
To install OpenBao, use the OpenBao Helm chart for Kubernetes deployments.
After installation, verify that OpenBao is working by following the GitLab Secrets Manager user documentation to test secret operations.
OpenBao resource requirements depend on your GitLab instance size and secret usage patterns.
Monitor your deployment and adjust resources as needed based on actual usage patterns.
OpenBao CPU usage is primarily driven by:
Recommended number of CPU cores:
| Deployment Size | Fetch frequency | CPU Cores |
|---|---|---|
| Small | Less than 100 ops/sec | 1 core |
| Medium | 100 to 200 ops/sec | 1-2 cores |
| Large | More than 200 ops/sec | 2+ cores |
For example, testing a deployment with 100,000 secrets corresponded to 139 fetch operations per second. This assumes each secret is fetched by a CI/CD job approximately every 12 minutes, and OpenBao makes full use of its memory cache.
OpenBao memory usage primarily depends on the number of projects where GitLab Secrets Manager is enabled. You should allocate at least 1 GB of memory per 200 projects, plus a safety margin of 1 GB.
Recommended memory allocation:
| Deployment Size | Number of Projects | Memory |
|---|---|---|
| Small | Less than 200 | 2 GB |
| Medium | 400 to 800 | 5 GB |
| Large | More than 1,000 | 6+ GB |
Storage requirements for the PostgreSQL database depends primarily on the number of secrets. It takes about 13 KB to store a single version of a secret and the corresponding metadata.
Usage example:
OpenBao data is stored in PostgreSQL and should be included in your regular GitLab backup procedures.
For detailed backup and restore procedures specific to OpenBao, see the OpenBao backup documentation.
For production deployments, consider:
OpenBao provides health check endpoints for monitoring:
openbao.example.com/v1/sys/health: Returns the health status of OpenBaoopenbao.example.com/v1/sys/seal-status: Returns the seal statusYou can integrate these endpoints with your monitoring system.
If you experience slow secret operations:
OpenBao supports Geo deployments. OpenBao is deployed on both the primary and secondary Geo sites, but only the primary site runs an active OpenBao node.
On the primary site, OpenBao runs as an active node connected to a writable PostgreSQL database. On the secondary site, OpenBao runs in standby mode, connected to a PostgreSQL read replica.
PostgreSQL streaming replication carries all OpenBao data (secrets, policies, authentication configuration) from the primary to the secondary site automatically.
Both GitLab instances (primary and secondary) connect to the primary OpenBao URL. The secondary OpenBao deployment remains in standby, and is promoted to active when the secondary PostgreSQL database becomes writable during a Geo failover.
On the secondary site, OpenBao logs failed to acquire lock and
cannot execute INSERT in a read-only transaction errors. These errors are expected. OpenBao cannot
acquire the HA leader lock on a read-only database.
Prerequisites:
The secondary OpenBao must use the same unseal key as the primary to decrypt replicated data.
Copy the gitlab-openbao-unseal Kubernetes secret from the primary cluster to the secondary
cluster:
kubectl --namespace gitlab get secret gitlab-openbao-unseal -o yaml
Apply the exported secret to the secondary cluster. For more information, see Back up the secrets.
If you plan to update the DNS record of the primary domain to point to the secondary site during failover,
you might want to configure OpenBao accordingly ahead of time.
Configure the Helm chart and set the url and jwt_audience to the primary OpenBao URL:
global:
openbao:
enabled: true
url: https://openbao.<primary-domain>
jwt_audience: https://openbao.<primary-domain>
For more information on chart configuration options, see Geo configuration.
Deploy the GitLab Helm chart on the secondary site. OpenBao pods start and remain in standby mode. This is expected.
On the secondary cluster, check that OpenBao pods are running:
kubectl --namespace gitlab get pods -l app=openbao
All pods should be in Running state. Secondary pods do not have the openbao-active: "true"
label. This is expected.
Confirm that the active service has no endpoints on the secondary cluster:
kubectl --namespace gitlab get endpoints gitlab-openbao-active
Zero endpoints on the secondary is expected.
Test the Secrets Manager by running a CI pipeline that uses a Secrets Manager variable on the secondary site.
When working with the Secrets Manager, you might encounter the following issues.
| Symptom | Cause | Resolution |
|---|---|---|
cipher: message authentication failed or unknown key ID in secondary OpenBao logs | Unseal key mismatch between primary and secondary | Copy gitlab-openbao-unseal from the primary cluster to the secondary cluster and restart OpenBao pods. |
failed to acquire lock in secondary OpenBao logs | OpenBao standby on read-only database | Expected behavior. No action required. |
cannot execute INSERT in a read-only transaction in secondary OpenBao logs | OpenBao attempting leader election on read replica | Expected behavior. No action required. |
| JWT authentication fails after Geo failover | jwt_audience does not match boundAudiences in OpenBao | Set jwt_audience to the primary OpenBao URL on both sites. |