Lightweight & distributed / self-hosted / v0.7.5

A lightweight, distributed secret manager.

Run it in your own cloud — AWS, GCP, a VPS, Kubernetes, anywhere that runs a container. It brings its own database and its own accounts, so there is no identity provider to wire up and nothing to reach out to.

docker pull ghcr.io/clement880101/secret-manager
<10 MBsingle binary, no runtime
Zero setupown accounts, own database
N replicasno state in process memory
Apache 2.0self-host the whole thing
01

A real session

secretmgr
$ docker run -d -p 8000:8000 -v secretmgr-data:/data \
    ghcr.io/clement880101/secret-manager:latest
No API tokens existed, so one was created for user 'admin'.
    smt_sGQr0f3dFBP39sUNBm2jpwZ6tnZyFms-dLPcIUp6SwE

$ secretmgr register alice
Choose a password:
Registered and logged in as alice

$ secretmgr create db-pw hunter2
Stored secret `db-pw`.

$ secretmgr share db-pw bob
Granted access to `db-pw` for bob.

$ secretmgr list
db-pw

$ secretmgr get db-pw
hunter2
02

Run it in your cloud

One stateless container on port 8000, configured entirely through environment variables. It does not terminate TLS — whatever you put in front of it already does, which is what lets it run anywhere.

What you need

A container runtime. That is the whole list. No database to provision, no identity provider, no certificate, no config file, no accounts created in advance. Then, depending on what you are doing:

Anything you would missSECRET_ENCRYPTION_KEY, or values are stored unencrypted
Clients on other machinesBACKEND_URL, and TLS in front of it
Not publicly signup-ableALLOW_REGISTRATION=false
More than one replicaDB_URL at Postgres, and a fixed BOOTSTRAP_TOKEN
A specific listen portPORT — honoured on Cloud Run and similar
OPTION 01

Docker

That is the whole setup. It brings its own database and issues its own tokens. Published for amd64 and arm64.

docker run -d -p 8000:8000 \ -v secretmgr-data:/data \ ghcr.io/clement880101/secret-manager:latest

For anything real, add SECRET_ENCRYPTION_KEY to encrypt values at rest and BACKEND_URL for the address clients reach.

OPTION 02

Compose

The API and a Postgres with a persistent volume, together.

git clone https://github.com/clement880101/secret-manager cd secret-manager/deploy cp .env.example .env # fill it in docker compose up -d

Anywhere else

Fly.io, Render, Railway, Cloud Run, Azure Container Apps and Kubernetes all build from the same Dockerfile, and terminate TLS for you.

Full deployment guide →

Pick a database

SQLite is bundled and is the default, written to the /data volume. Nothing external needed for a single instance.

Point DB_URL at Postgres for more than one replica — the driver ships in the image too. A database inside the app container would give each replica its own copy.

Scale past one replica

Login state lives in the database, not in process memory, so a login can start on one instance and finish on another.

Rate-limit counters are shared too, so the limit is the limit rather than the limit multiplied by however many instances are running.

Encrypt at rest

Set SECRET_ENCRYPTION_KEY and values are encrypted before they reach the database. Keep the key — losing it makes existing values unreadable.

docker run --rm \ ghcr.io/clement880101/secret-manager:latest \ python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
03

Then get the CLI

Once your server is up, this is how people talk to it. A self-contained executable under 10 MB — no Python, no dependencies. Set BACKEND_URL to your deployment: there is no default, so it can never send your secrets somewhere you did not choose.

Then make it runnable

Downloads arrive without the executable bit. Rename it, mark it executable, put it on your PATH:

chmod +x secretmgr-* && sudo mv secretmgr-* /usr/local/bin/secretmgr

Check it: secretmgr ping → API healthy.

On macOS, the first run

These builds are not code-signed, so Gatekeeper refuses them until you say otherwise. Clear the quarantine flag:

xattr -d com.apple.quarantine /usr/local/bin/secretmgr

Or open it once from Finder with right-click → Open.

Verify what you downloaded

Every release ships a SHA256SUMS file built alongside the binaries.

shasum -a 256 -c SHA256SUMS --ignore-missing

All release assets →

04

How it works

STEP 01

Sign yourself up

secretmgr register creates an account on that deployment. No invitation and no external account. Close sign-ups with ALLOW_REGISTRATION=false on anything facing the open internet.

STEP 02

Store a key and value

Secrets are scoped to you. Keys are unique per account, so a second create on the same key is refused rather than silently overwriting.

STEP 03

Share with a teammate

Grant read access by whatever name you issued their token under. They see it in their own list; only you can delete or re-share it.

05

Commands

secretmgr register NAMECreate an account on this deployment and log in.
secretmgr login NAMELog in with your password.
secretmgr login --token TLog in with a token the server issued.
secretmgr passwdChange your password.
secretmgr revoke TOKENRevoke a token, after losing a machine.
secretmgr token USERIssue a token for someone else.
secretmgr whoamiShow who you are and how the deployment authenticates.
secretmgr logoutRemove the stored token from this machine.
secretmgr create KEY VALUEStore a new secret you own.
secretmgr update KEY VALUEReplace a value, keeping who it is shared with. Deleting and recreating would drop the shares.
secretmgr listList everything visible to you — what you own, plus what others have shared with you.
secretmgr share KEY USERGive a teammate read access. They must already have an account.
secretmgr delete KEYDelete a secret you own.
secretmgr pingCheck that the backend is reachable.
secretmgr versionPrint the CLI version.
06

Before you trust it with anything

Before you put real secrets in it

  • Set SECRET_ENCRYPTION_KEY and back it up. Without it values are stored unencrypted; lose it and they are unreadable, permanently.
  • Put TLS in front. The service speaks plain HTTP by design so it fits any platform. The CLI warns when it is talking cleartext to a remote host.
  • A stolen token still grants access to everything that account can read — one key at a time now, rather than in a single request, and every read is recorded.
  • Authentication is rate limited; the rest of the API is not. Failed logins are blocked per username and per address, but a valid token can be replayed as fast as the service answers.
  • The audit trail is per-account. You can see your own activity; there is no administrator view across all users, and events are pruned after 90 days by default.
  • No account recovery. A forgotten password needs an administrator to issue a token.
  • Released binaries are unsigned. Verify the published SHA-256 checksums.
07

Questions

Do I need a GitHub account, or any identity provider?

No. The service has its own accounts and issues its own tokens. Nothing is registered anywhere else, and it makes no outbound network calls.

Does it need a separate database?

Not to start. The container bundles SQLite and a volume is the whole setup. Point DB_URL at Postgres when you want more than one replica, because SQLite cannot back concurrent writers.

Can it run more than one replica behind a load balancer?

Yes. Replicas hold no state in process memory, so no session affinity is needed. Give them one Postgres and a shared BOOTSTRAP_TOKEN, then scale to any number.

How are secrets stored?

Encrypted at rest with Fernet (AES-128-CBC and HMAC-SHA256) under the key in SECRET_ENCRYPTION_KEY. Without that variable values are stored in plaintext, so set it before storing anything real.

How do I rotate the encryption key?

Put the old key in SECRET_ENCRYPTION_KEYS_RETIRED and the new one in SECRET_ENCRYPTION_KEY, then run rotate_keys. It re-encrypts everything and reports how many secrets are still on the old key; only drop the retired key once that reaches zero.

What does it cost?

Nothing. It is open source under Apache 2.0, and it runs on your own infrastructure, so there is no account, quota or vendor involved.

How is this different from Vault or AWS Secrets Manager?

It is deliberately much smaller. There is no identity provider to wire up, no policy language, no cloud account and no agent — a container and a CLI binary under 10 MB. That is the trade: far less to run and far less to learn, and far fewer features.