Everything About This Secrets Manager Screamed 'Too Good to Be True.' So I Tested That.
I've been on a bit of a "install random dev tools and see if they actually hold up" kick lately, and this time I pointed it at Dopbase. It's a secrets manager that claims to be a server, admin UI, REST API, and CLI all packed into one binary. No sponsorship, nobody paid me for this, I just grabbed it, installed it clean, and tried to break it. Here's what happened. What I actually did, for context: installed it from a clean machine, read the install script before running it, bootstrapped the server, created a multi-environment project (development / staging / production ) with six realistic secrets, rotated a key in production only, cut a CI token and used it non-interactively, tried every export format, ran an import --dry-run , took a backup, and killed the server mid-command just to see what would break. Everything below is copy-pasted straight from the terminal, not paraphrased from docs. The problem it's solving Every team eventually reinvents the same bad system for secrets. A .env file gets copied around Slack, a secrets.example.env sits three keys out of date, and there's always one person who "just has the prod values somewhere." It's fine until it isn't. Someone commits .env by accident, or the one person with the values goes on vacation right when staging breaks. The usual fix is Vault, Doppler, or Infisical. They all work, but they all mean setting up another service, another auth flow, and for the hosted ones, another subscription. For a two-person side project or a small team that just wants secrets to stop living in Slack DMs, that's a lot of infrastructure to adopt for what's basically a glorified key-value store. Dopbase's pitch is simple: one binary. Server, admin UI, REST API, and CLI client all in a single executable. No Postgres to provision, no Docker Compose file with six services in it. I wanted to see if that claim actually holds up, so I installed it clean and ran it end to end. Dopbase Open-source, self-hosted secrets management in a single file. One binary contains the server, Admin UI, REST API, and command-line client Quick start | CLI reference | Demo | Why Dopbase | How it works | Documentation | Security | Contributing | Code of conduct The Admin UI ships inside the Dopbase executable, so there is no separate frontend to deploy. Dopbase keeps application secrets organized by project and environment on infrastructure you control. Runtime data stays separate from the executable: its SQLite database, configuration, and master key live under ~/.dopbase by default. Quick start Install the latest release on macOS or Linux, then start a local server: curl -fsSL https://dopbase.com/install.sh | sh dopbase server start Open http://localhost:8840 to finish setup in the Admin UI. The quick-start guide covers sign-in, importing a .env file, and running an application with its secrets. Native release archives are available for macOS and Linux… Installing it curl -fsSL https://dopbase.com/install.sh | sh Before running any install script off the internet, I actually read it first. Worth doing for anything that pipes into sh . It turned out to be a plain POSIX script: it detects your OS and arch, downloads the matching release archive from GitHub, verifies it against a checksums.txt with sha256sum or shasum , and only then extracts and installs. No curl | sudo bash nonsense, no silent background daemon getting installed behind your back. It just drops a single dopbase binary into ~/.local/bin . That's the whole thing. Downloading Dopbase 0.1.8 for darwin/arm64... Installed Dopbase 0.1.8 to /Users/varshit.hegde/.local/bin/dopbase Starting the server is one command: dopbase server up Dopbase Secure, Simple and Private Version 0.1.8 Public URL: http://localhost:8840 Admin UI: http://localhost:8840 API: http://localhost:8840/api/v1 Dopbase setup token (shown once): setup_tViW7FWwlm_n7qSXjjqOM_sOy9dTN5_UyYe3ZL7sDYE That setup token gets printed once, to your terminal, on first boot. Not emailed, not defaulted to admin/admin . You paste it into the Admin UI (or hit the setup URL it prints) to create the first admin account. It's a small thing, but it's the kind of small thing that tells you someone thought about the "what if this box is internet-facing for thirty seconds during setup" case. Actually using it This is usually where I bail on a "secrets manager" tool, because half of them want you to define a whole dopbase.yaml before you're even allowed to set a single value. Dopbase doesn't make you do that. I set up a fake project, acmeshop , a shop backend with a Postgres URL, a Stripe key, a JWT secret, a Redis URL, an email API key, and a Sentry DSN, all from one plain .env file: dopbase init acmeshop/development --from .env Initialized acmeshop/development. Project ID: prj_01M3K47BT6X81BNE54KASXEPE1 Environment ID: env_751368 Secrets: 6 One command, and all six secrets got imported and encrypted server-side. Listing them back doesn't show values by default: $ dopbase secret list acmeshop/development KEY VERSION UPDATED DATABASE_URL 1 2026-09-28 04:26 UTC JWT_SECRET 1 2026-09-28 04:26 UTC REDIS_URL 1 2026-09-28 04:26 UTC RESEND_API_KEY 1 2026-09-28 04:26 UTC SENTRY_DSN 1 2026-09-28 04:26 UTC STRIPE_SECRET_KEY 1 2026-09-28 04:26 UTC You have to explicitly ask to see a value, and it re-prompts for your password before it'll actually show it: $ dopbase secret get acmeshop/development STRIPE_SECRET_KEY --reveal Password confirmation required. ? Password: ******** sk_test_51ABCDEF1234567890 Same story for export . Dumping secrets to a .env file or stdout requires a fresh password confirmation every single time, even if you're already logged in. That's a deliberate bit of friction and honestly I liked it. Most tools let a valid session token do anything a human can do. This one draws a line between "read metadata" and "see plaintext," and makes you prove you're still you before it lets you cross it. Multiple environments, and secrets that actually drift A real app is never just one environment. So I cloned development into staging and production : dopbase env clone acmeshop/development staging --yes dopbase env clone acmeshop/development production --yes $ dopbase env list acmeshop PROJECT ENVIRONMENT ID UPDATED acmeshop development env_751368 2026-09-28 04:26 UTC acmeshop production env_555699 2026-09-28 04:26 UTC acmeshop staging env_021195 2026-09-28 04:26 UTC 3 environment(s) Then I rotated the Stripe key in production only, the way you'd do after an actual key leak or just a routine rotation: $ printf 'sk_live_51PRODROTATEDKEY9876543210\n' | dopbase secret set acmeshop/production STRIPE_SECRET_KEY --stdin Saved STRIPE_SECRET_KEY in acmeshop/production. Version: 2 $ dopbase secret list acmeshop/production KEY VERSION UPDATED ... STRIPE_SECRET_KEY 2 2026-09-28 04:26 UTC $ dopbase secret list acmeshop/development KEY VERSION UPDATED ... STRIPE_SECRET_KEY 1 2026-09-28 04:26 UTC Production shows version 2, development is still stuck on version 1. That's exactly what I want to see when I'm trying to answer "did staging actually get the new key or not" in the middle of an incident. Running an app with secrets injected, with no .env file ever touching disk, works exactly the way you'd want dotenv to work: dopbase run acmeshop/development -- node server.js Under the hood it fetches the environment and injects everything as env vars into the child process only. The values never get printed to your terminal. A CI token, and proving it actually pulls the right values The realistic version of "run this in a pipeline" isn't your own logged-in session, it's a scoped token that a GitHub Actions job uses. I created one for production with a 30-day expiry: $ dopbase token create acmeshop/production --name github-actions-deploy --expires-in 720h Created token github-actions-deploy for acmeshop/production. ID: tok_01M3K47KD1YGBTGRMCBBQFEHVM Expires: 2026-10-28T04:26:38Z Token: dbs_D2YjuFlzupYWXYouQSoyIPt0TAZk0D4XVcUiOgnluTY Warning: Store this token now. Dopbase will not show it again. That's the only time the raw token gets shown, same "shown once" pattern as the setup token. Then I used it exactly like a CI runner would, with no interactive login at all: $ DOPBASE_TOKEN="dbs_D2YjuFlzupYWXYouQSoyIPt0TAZk0D4XVcUiOgnluTY" dopbase run acmeshop/production -- env | grep STRIPE STRIPE_SECRET_KEY=sk_live_51PRODROTATEDKEY9876543210 That's the rotated production key coming back, not the original dev value. So a deploy pipeline holding this token genuinely can't accidentally ship a stale or wrong-environment secret. Every export needs a live human, and you can't script around it I tried to export secrets non-interactively (piping a password, setting an env var, anything I could think of) just to see if there was some backdoor around the password prompt. There isn't: $ dopbase export acmeshop/development --output out.yaml --format yaml --force Error: interactive password confirmation is required for plaintext secret access That error shows up even with --force , even with stdin piped, even inside a script. The only way to get plaintext out via export is a real terminal with an actual human typing a password into a masked prompt: $ dopbase export acmeshop/development --output out.yaml --format yaml --force Exported 6 secret(s) to out.yaml. $ cat out.yaml DATABASE_URL: postgres://app_user:pass@localhost:5432/acmeshop JWT_SECRET: super-secret-jwt-signing-key-123 REDIS_URL: redis://localhost:6379 RESEND_API_KEY: re_123456789_abcdefghijklmnop SENTRY_DSN: https://examplekey@o123456.ingest.sentry.io/123456 STRIPE_SECRET_KEY: sk_test_51ABCDEF1234567890 I ran the same check against every supported format (dotenv , json , yaml , toml , and docker ) and they all produced clean, correctly shaped output, all gated behind the same live password prompt. This is a genuine design choice, not an oversight. export is for a human sitting at a keyboard. run and CI tokens are what you reach for when you want automation. If your mental model going
Comments
No comments yet. Start the discussion.