In short
- Vault has been under the BSL 1.1 since version 1.15 and IBM has owned HashiCorp since February 2025. OpenBao is the MPL-2.0 fork, now at 2.7.2.
- For a team of under ten: your cloud's own secret store or Infisical, SOPS with age for config kept in Git, and OIDC instead of long-lived cloud keys in CI.
- When a secret leaks, revoke it first. Rewriting Git history comes last and never removes copies in forks, clones or cached views.
On this page
- What a secrets tool has to do
- HashiCorp Vault
- OpenBao
- Infisical
- Doppler
- Cloud-native stores
- 1Password for developers
- SOPS with age
- Comparison
- OIDC: remove the long-lived CI secrets first
- Kubernetes: three ways to deliver secrets
- Secret scanning and push protection
- Leaked-secret response runbook
- What I’d pick for a team of under ten
- Checklist
This is for small engineering teams deciding where secrets should live, how they reach applications and CI jobs, and how they get rotated. It covers HashiCorp Vault, OpenBao, Infisical, Doppler, AWS Secrets Manager and Parameter Store, Azure Key Vault, Google Secret Manager, 1Password for developers, and SOPS with age. Then it covers the practices that matter more than the tool: OIDC federation in CI, Kubernetes delivery, secret scanning, and what to do when a secret leaks.
Prices, free tiers, licences and versions were checked against vendor pages on 13 November 2026. They change often, so check again before you commit.
What a secrets tool has to do
Four jobs, and most tools do only some of them well:
- Store values encrypted, with access control per application and environment.
- Inject them at runtime, never into a repository, an image or a hand-copied CI variable.
- Rotate them. Static secrets change on a schedule. Dynamic secrets are created on request with a lease and revoked when it ends.
- Audit who read what, and when. After an incident this is the first question, and many setups cannot answer it.
Secrets handling and incident response are part of my day-to-day work, and the gap is rarely the tool. It is usually a long-lived key that nobody owns.
HashiCorp Vault
Licence. On 10 August 2023 HashiCorp moved future releases from MPL 2.0 to the Business Source License 1.1. Vault’s LICENSE file applies it to “Vault Version 1.15.0 or later”, with each release converting to MPL 2.0 four years after publication. Production use is allowed unless you offer Vault to third parties, hosted or embedded, to compete with IBM’s paid versions, and internal use is explicitly not a competitive offering.
Ownership and versions. IBM completed its acquisition of HashiCorp on 27 February 2025, and the licence file now reads “(c) 2024 IBM Corp.” Vault 2.0 reached general availability on 14 April 2026. Community Edition 2.2.2 was announced on 12 November 2026.
Hosted options. HCP Vault Secrets stopped being sold on 30 June 2025 and reached end of life on 1 July 2026, when its applications were deleted. IBM pointed customers to HCP Vault Dedicated or Vault Community. IBM’s pay-as-you-go table lists IBM Vault Dedicated at $0.61644 an hour for an extra-small Development cluster (about $450 for a 730-hour month), $1.57799 an hour for a small Essentials cluster, and $72.92 a month per client on Essentials and Standard. IBM calls these prices indicative. I found no free tier, only a $500 trial credit across HashiCorp Cloud Platform.
Dynamic secrets and rotation. This is Vault’s strength. The database secrets engine creates a unique username and password per request, with a lease and a default_ttl and max_ttl per role. Static roles rotate an existing database user’s password, every 24 hours by default.
Audit. “When you initialize a new Vault cluster, auditing is disabled.” Enable a file, syslog or socket audit device on day one. Most string values are written as HMAC-SHA256 hashes, not plaintext.
CI. HashiCorp’s vault-action supports method: jwt with the GitHub OIDC token, so a workflow needs id-token: write and no stored Vault token.
OpenBao
OpenBao is the community fork of Vault’s last MPL release, licensed MPL-2.0 and run as a Linux Foundation project under OpenSSF, where it is listed as a Sandbox project. The latest release is v2.7.2, published on 26 October 2026. The CLI is bao instead of vault.
Its docs say the API “should be compatible with Vault to the extent that existing clients should not even register a difference.” The in-place migration guide was only tested against Vault 1.14.1, and newer Vault versions are “untested and unsupported”. Moving from Vault 1.15 or later means a planned migration, not a binary swap.
Dynamic PostgreSQL credentials, from OpenBao’s docs:
bao secrets enable database
bao write database/config/my-postgresql-database \
plugin_name="postgresql-database-plugin" \
allowed_roles="my-role" \
connection_url="postgresql://{{username}}:{{password}}@localhost:5432/database-name" \
username="openbaouser" \
password="openbaopass"
bao write -force database/rotate-root/my-postgresql-database
bao write database/roles/my-role \
db_name="my-postgresql-database" \
creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
default_ttl="1h" \
max_ttl="24h"
bao read database/creds/my-role
rotate-root changes the bootstrap password so only OpenBao knows it. With Vault, swap bao for vault. Either way, someone must own unsealing, upgrades, backups and high availability.
Infisical
Infisical is open core: the repository is MIT, “with the exception of the ee directories”, which need a licence. You can use Infisical Cloud or self-host the core for free.
Secrets management is priced per identity a month:
- Free: $0, 5 identities, unlimited projects, 3 environments, 10 secret syncs. No rotation, no dynamic secrets, no audit log retention.
- Pro: $20 billed annually or $23 monthly. Rotation for “public databases only”, 30 days of audit logs, SAML SSO, versioning and point-in-time recovery.
- Advanced: $40 annually or $46 monthly. Full rotation, dynamic secrets, 90 days of audit logs.
- Enterprise: custom, adds approval workflows. Supported self-hosting, including air-gapped, is an Enterprise item.
Dynamic secrets need Advanced, self-hosted included. The GitHub Action (v1.0.18 is the latest release) authenticates with OIDC:
permissions:
id-token: write
contents: read
steps:
- uses: Infisical/secrets-[email protected]
with:
method: "oidc"
identity-id: "24be0d94-b43a-41c4-812c-1e8654d9ce1e"
domain: "https://app.infisical.com"
env-slug: "prod"
project-slug: "my-project"
Doppler
Doppler is SaaS only. The Developer plan is free for 3 users, then $8 a month per additional user, with 10 projects, 4 environments, 50 service tokens and 3 days of activity logs. Team is $21 per user a month, with 90 days of activity logs, automatic secret rotation, SAML SSO and identity-based authentication. Enterprise is custom and is the only plan listing dynamic secrets. The pricing page says “AI agents and non-human identities ride free.”
The CLI injects secrets as environment variables:
doppler setup
doppler run -- npm start
In CI, service account identities replace static tokens with OIDC: “Identities allow a service account to authenticate to Doppler via OIDC without using a static API token.” That needs Team or Enterprise.
Cloud-native stores
If everything runs in one cloud, its own store is usually the right default: no extra vendor, and IAM and audit trails you already have.
AWS Secrets Manager and Parameter Store
Secrets Manager costs $0.40 per secret a month and $0.05 per 10,000 API calls; new versions created by rotation are free. Managed rotation covers most managed secrets and partner-held credentials without a Lambda function; everything else rotates through a Lambda function you supply. CloudTrail records every Secrets Manager API call, with 90 days of event history unless you create a trail.
Parameter Store standard parameters cost nothing extra: up to 10,000 per account and Region, 4 KB each. Advanced parameters are $0.05 each a month, 8 KB, up to 100,000, with expiry and notification policies. With standard throughput, API calls on standard parameters are free; higher throughput costs $0.05 per 10,000 interactions. AWS’s own advice: for credentials that need “automatic rotation, cross-account access, or fine-grained audit logging”, use Secrets Manager.
Azure Key Vault
The pricing page renders its prices in the browser, so I took them from Microsoft’s Retail Prices API (East US, USD). Standard and Premium both charge $0.03 per 10,000 operations. A certificate renewal is $3, an automated key rotation is $1, and a Premium HSM-protected RSA 2048-bit key is $1 a month. Managed HSM Standard B1 is $3.20 an hour. I found no per-secret storage meter.
Secret rotation is something you build. Thirty days before a secret expires, Key Vault publishes a SecretNearExpiry event to Event Grid, and your Azure Function generates the new value and updates the target service. Microsoft’s tutorial says a managed identity is the best way to authenticate, so no secret exists at all. Logging has to be enabled; then AuditEvent records arrive within 10 minutes.
Google Secret Manager
Each active secret version costs $0.000082192 an hour per location, which is $0.06 a month in Google’s worked example. Access is $0.03 per 10,000 operations and rotation notifications are $0.05 each. The always-free tier, per billing account each month, covers 6 active versions, 10,000 access operations and 3 rotation notifications. Management operations are free, and automatic replication bills as one location.
Like Azure, rotation is a schedule plus a Pub/Sub message: “You must configure a Pub/Sub subscriber to receive and act on the SECRET_ROTATE messages.” For audit, AccessSecretVersion is a Data Access log, and “Data Access audit logs are disabled by default for all services except some BigQuery services.” Switch them on for Secret Manager, or you will not know who read a secret.
1Password for developers
1Password Business is $8.99 per user a month billed annually; Teams Starter Pack is $24.95 a month for up to 10 members. Both list the developer tools.
Service accounts are the machine identity: up to 100, scoped to chosen vaults. Teams allows 1,000 reads and 100 writes an hour per token and 5,000 a day per account; Business allows 10,000, 1,000 and 50,000.
- name: Load secret
id: load_secrets
uses: 1password/load-secrets-action@v5
env:
OP_SERVICE_ACCOUNT_TOKEN: ${{ secrets.OP_SERVICE_ACCOUNT_TOKEN }}
DB_PASSWORD: op://app-cicd/postgres/password
That still stores one long-lived token in GitHub. 1Password’s Credential Broker, in public preview, uses the CI platform’s OIDC identity instead. I found no automatic rotation or dynamic secrets in the service account docs.
SOPS with age
SOPS encrypts the values in YAML, JSON, ENV, INI and binary files and leaves the keys readable, so diffs still make sense. It is MPL-2.0, a CNCF Sandbox project since 2023, and at v3.13.3 (23 July 2026). It encrypts with AWS KMS, GCP KMS, Azure Key Vault, HuaweiCloud KMS, age and PGP, and its docs recommend age over PGP. age is BSD-3-Clause, at v1.3.2.
age-keygen -o key.txt
# Public key: age1... (store key.txt in a password manager, never in Git)
# .sops.yaml at the repository root; the first matching rule wins
creation_rules:
- path_regex: secrets/prod/.*\.yaml$
encrypted_regex: "^(data|stringData|password|token)$"
age: "age1qe5lxzzeppw5k79vxn3872272sgy224g2nzqlzy3uljs84say3yqgvd0sw"
sops edit secrets/prod/app.yaml
sops exec-env secrets/prod/app.yaml './run-migrations'
On Linux, SOPS reads the private key from ~/.config/sops/age/keys.txt or SOPS_AGE_KEY_FILE. exec-env passes decrypted values to one child process without writing them to disk. There is no rotation and no access log beyond Git history. When someone leaves, remove their recipient with sops updatekeys and still rotate every secret they could read.
Comparison
| Tool | Model | Licence | Entry price (13 Nov 2026) | Dynamic secrets | Rotation | Audit log | CI/CD |
|---|---|---|---|---|---|---|---|
| Vault | Self-hosted or IBM Vault Dedicated | BSL 1.1 | Free self-hosted; Dedicated from $0.61644/hour | Yes | Yes | Off until enabled | vault-action with OIDC |
| OpenBao | Self-hosted | MPL-2.0 | Free | Yes | Yes | Off until enabled, as in Vault | JWT/OIDC auth, Vault-compatible API |
| Infisical | SaaS or self-hosted | MIT core, ee licensed |
Free for 5 identities; Pro $20/identity/month | Advanced plan | Pro (public DBs), Advanced | 30 days on Pro | Action with OIDC |
| Doppler | SaaS | Proprietary | Free for 3 users; Team $21/user/month | Enterprise | Team | 3 days free, 90 on Team | OIDC on Team |
| AWS Secrets Manager | Managed | Proprietary | $0.40/secret/month | No | Managed or Lambda | CloudTrail | OIDC to IAM role |
| AWS Parameter Store | Managed | Proprietary | Standard tier free | No | No | Not verified here | OIDC to IAM role |
| Azure Key Vault | Managed | Proprietary | $0.03/10,000 operations | No | Event Grid plus your function | Off until enabled | azure/login with OIDC |
| Google Secret Manager | Managed | Proprietary | 6 versions free, then $0.06/version/month | No | Pub/Sub plus your code | Data Access logs, off by default | google-github-actions/auth |
| 1Password | SaaS | Proprietary | Business $8.99/user/month | No | Not found | Not verified here | Service account token |
| SOPS with age | Files in Git | MPL-2.0, BSD-3-Clause | Free | No | Manual | Git history | Decrypt key in CI |
OIDC: remove the long-lived CI secrets first
The change with the biggest payoff is not choosing a vault. It is deleting the AWS_SECRET_ACCESS_KEY in your CI settings. With OIDC, GitHub’s docs say “your cloud provider issues a short-lived access token that is only valid for a single job, and then automatically expires,” and you no longer “duplicate your cloud credentials as long-lived GitHub secrets.”
On AWS, trust GitHub’s OIDC provider and restrict the subject claim to one repository and one environment:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789012:oidc-provider/token.actions.githubusercontent.com"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"token.actions.githubusercontent.com:aud": "sts.amazonaws.com",
"token.actions.githubusercontent.com:sub": "repo:my-org/my-app:environment:production"
}
}
}
]
}
permissions:
id-token: write
contents: read
jobs:
deploy:
runs-on: ubuntu-latest
environment: production
steps:
- uses: aws-actions/configure-aws-[email protected]
with:
role-to-assume: arn:aws:iam::123456789012:role/github-deploy
aws-region: me-central-1
Azure uses azure/login@v3 with client-id, tenant-id and subscription-id, which are identifiers, not credentials. Google Cloud uses google-github-actions/auth@v3 with a workload_identity_provider, and its README says “Workload Identity Federation is recommended over Service Account Keys.” Pin these Actions to commit SHAs, as covered in dependency scanning tools compared. GitLab and Jenkins setups are compared in CI/CD tools compared.
Kubernetes: three ways to deliver secrets
External Secrets Operator (Apache-2.0) syncs values from an external store into ordinary Kubernetes Secrets. Its provider list includes AWS Secrets Manager and Parameter Store, Vault, OpenBao, Azure Key Vault, Google Cloud Secret Manager, Infisical, Doppler and 1Password.
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: app-db
spec:
refreshInterval: "1h"
secretStoreRef:
name: aws-store
kind: ClusterSecretStore
target:
name: app-db
data:
- secretKey: password
remoteRef:
key: prod/app/db
property: password
Sealed Secrets (Apache-2.0, v0.41.2, now at bitnami/sealed-secrets) encrypts a Secret with the controller’s public key so it can sit in Git: kubeseal -f mysecret.json -w mysealedsecret.json. Sealing keys renew every 30 days, which the README says is not rotation of the secrets themselves. Back up the sealing keys, or a rebuilt cluster cannot decrypt anything.
Secrets Store CSI Driver (Apache-2.0, v1.6.2) mounts secrets as files from AWS, Azure, GCP, Vault, OpenBao and others. Syncing to Kubernetes Secrets and auto rotation are alpha, and the project warns they “are not stable”.
For most small teams, ESO plus a cloud store is simplest. Pick Sealed Secrets or SOPS when Git must be the only source of truth.
Secret scanning and push protection
Prevention is cheaper than rotation.
GitHub. Push protection for users is on by default and stops you pushing secrets to public repositories. Secret scanning, push protection, provider patterns and provider notification are free on public repositories. Repository push protection on private repositories needs GitHub Secret Protection at $19 per active committer a month. Anyone with write access can bypass with a reason, and each bypass creates an alert and an audit log event.
gitleaks (MIT, v8.30.1) runs locally, in pre-commit and in CI:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.30.1
hooks:
- id: gitleaks
gitleaks git scans history and gitleaks dir scans files. gitleaks-action@v3 needs a free GITLEAKS_LICENSE for organisation accounts. The README now says gitleaks is feature complete with security patches only, and its author is moving to Betterleaks (MIT), which has not yet shipped a stable v2.
TruffleHog (AGPL-3.0, v3.99.9) tests found credentials against the provider’s API and labels them verified, unverified or unknown, which makes it the better tool for sweeping old history:
trufflehog git file://. --results=verified
trufflehog github --org=my-org --results=verified
Run gitleaks or GitHub push protection before code lands, and TruffleHog on a schedule across every repository.
Leaked-secret response runbook
When a secret reaches a repository, a log, a ticket or a chat:
- Revoke or rotate it now. GitHub’s own guidance makes this the first step. Assume it was copied the moment it was pushed.
- Check what it could reach. Read the audit trail for that credential: CloudTrail, Key Vault
AuditEvent, Secret Manager Data Access logs if you enabled them, or Vault’s audit device. Look for use from unfamiliar IP addresses since the leak. - Rotate its neighbours. Anything stored in the same CI variables,
.envfile or vault path is suspect. - Fix the source. Move the value into the secrets manager, or replace it with OIDC so no static credential exists.
- Purge history only after that, and know the limits. GitHub recommends
git-filter-repo2.47 or later with--sensitive-data-removal, for examplegit-filter-repo --sensitive-data-removal --replace-text ../passwords.txt. Rewriting changes every later commit hash. Copies survive in clones and forks, in cached views reachable by SHA, and in pull requests that reference the commits. GitHub Support can remove cached views and pull request references; nobody can clean other people’s clones. - Add a guard so the same pattern is blocked next time: push protection, a custom pattern or a pre-commit rule.
For the wider launch checklist around this, see launching a vibe-coded app securely.
What I’d pick for a team of under ten
All on one cloud. Use that cloud’s store and OIDC from CI. On AWS, Secrets Manager for credentials that rotate (30 secrets is $12 a month plus API calls) and standard Parameter Store for plain configuration. On Google Cloud, the free tier covers a small project. On Azure, Key Vault plus managed identities, so most services need no secret at all.
Several clouds, or many SaaS keys and developers who need local .env values. Infisical Cloud: Free covers 5 identities, and Pro adds audit retention and SSO. Doppler’s free Developer plan suits three people, but a 3-day activity log is too short for incident work.
GitOps repositories. SOPS with age, or with your cloud KMS so access follows IAM, plus External Secrets Operator for runtime values.
Vault or OpenBao only when you need dynamic database credentials or PKI across environments and someone owns a highly available cluster. With HCP Vault Secrets gone and Vault Dedicated starting around $450 a month, self-hosted OpenBao is the open-source route, though Vault’s BSL licence permits internal use.
Already on 1Password Business. Service accounts are fine for a few third-party keys in CI. Watch the rate limits.
Checklist
- One secrets store per environment, with an owner.
- No long-lived cloud keys in CI: OIDC to AWS, Azure and Google Cloud, with
subrestricted to repository and environment. - Audit logging switched on and retained: Vault audit device, Key Vault logging, Google Data Access logs.
- Rotation scheduled for every static credential that cannot be replaced by OIDC or dynamic secrets.
- Kubernetes secrets delivered by External Secrets Operator, Sealed Secrets or the CSI driver, never committed as plain manifests.
- Push protection on, gitleaks in pre-commit and CI, TruffleHog scheduled across all repositories.
- Every third-party Action pinned to a commit SHA.
- A written leak runbook: revoke, check the audit trail, rotate neighbours, fix the source, then purge history.
Sources
- hashicorp/vault LICENSE (GitHub) github.com
- HashiCorp adopts Business Source License (HashiCorp) hashicorp.com
- IBM Completes Acquisition of HashiCorp (IBM Newsroom) newsroom.ibm.com
- Vault release notes 2.x (HashiCorp Developer) developer.hashicorp.com
- Vault 2.2.2, 1.21.14, and 1.19.25 released (HashiCorp Discuss) discuss.hashicorp.com
- HCP Vault Secrets End Of Life (IBM Support) ibm.com
- HashiCorp pricing (IBM) ibm.com
- Database secrets engine (HashiCorp Developer) developer.hashicorp.com
- Audit devices (HashiCorp Developer) developer.hashicorp.com
- hashicorp/vault-action (GitHub) github.com
- OpenBao (OpenBao) openbao.org
- openbao/openbao releases (GitHub) github.com
- In-place migration from Vault CE (OpenBao docs) openbao.org
- PostgreSQL database secrets engine (OpenBao docs) openbao.org
- Infisical pricing (Infisical) infisical.com
- Infisical/infisical (GitHub) github.com
- Dynamic secrets overview (Infisical docs) infisical.com
- Infisical/secrets-action (GitHub) github.com
- Doppler pricing (Doppler) doppler.com
- Service account identities (Doppler docs) docs.doppler.com
- Doppler CLI (Doppler docs) docs.doppler.com
- AWS Secrets Manager pricing (AWS) aws.amazon.com
- Rotate AWS Secrets Manager secrets (AWS docs) docs.aws.amazon.com
- Log AWS Secrets Manager events with AWS CloudTrail (AWS docs) docs.aws.amazon.com
- AWS Systems Manager pricing (AWS) aws.amazon.com
- Choosing parameter tiers in Parameter Store (AWS docs) docs.aws.amazon.com
- Assigning parameter policies in Parameter Store (AWS docs) docs.aws.amazon.com
- Azure Key Vault pricing (Microsoft) azure.microsoft.com
- Azure Retail Prices API, Key Vault meters (Microsoft) prices.azure.com
- Rotation tutorial for resources with one set of authentication credentials (Microsoft Learn) learn.microsoft.com
- Azure Key Vault logging (Microsoft Learn) learn.microsoft.com
- Secret Manager pricing (Google Cloud) cloud.google.com
- About rotation schedules (Google Cloud docs) docs.cloud.google.com
- Secret Manager audit logging (Google Cloud docs) docs.cloud.google.com
- Enable Data Access audit logs (Google Cloud docs) docs.cloud.google.com
- 1Password business pricing (1Password) 1password.com
- Service accounts (1Password Developer) 1password.dev
- Service account rate limits (1Password Developer) 1password.dev
- Load secrets from 1Password into GitHub Actions (1Password Developer) 1password.dev
- 1Password/load-secrets-action (GitHub) github.com
- SOPS documentation (SOPS) getsops.io
- Encrypting using age (SOPS docs) getsops.io
- Using .sops.yaml conf (SOPS docs) getsops.io
- SOPS reference (SOPS docs) getsops.io
- SOPS advanced usage (SOPS docs) getsops.io
- getsops/sops releases (GitHub) github.com
- FiloSottile/age (GitHub) github.com
- Configuring OpenID Connect in Amazon Web Services (GitHub Docs) docs.github.com
- OpenID Connect (GitHub Docs) docs.github.com
- aws-actions/configure-aws-credentials (GitHub) github.com
- Azure/login (GitHub) github.com
- google-github-actions/auth (GitHub) github.com
- External Secrets Operator (External Secrets) external-secrets.io
- ExternalSecret API (External Secrets docs) external-secrets.io
- bitnami/sealed-secrets (GitHub) github.com
- Secrets Store CSI Driver (Kubernetes SIGs) secrets-store-csi-driver.sigs.k8s.io
- About push protection (GitHub Docs) docs.github.com
- GitHub Security plans and pricing (GitHub) github.com
- gitleaks/gitleaks (GitHub) github.com
- gitleaks/gitleaks-action (GitHub) github.com
- betterleaks/betterleaks (GitHub) github.com
- trufflesecurity/trufflehog (GitHub) github.com
- Removing sensitive data from a repository (GitHub Docs) docs.github.com