Team Vault Setup
You are the team lead. You want to initialize a vault that, from the very first secret, is encrypted for every member of your team. Each secret store call should produce ciphertext that any teammate can decrypt with their own GPG key, no follow-up secret share needed.
Prerequisites
Section titled “Prerequisites”- dotsecenv installed
- Your own GPG key (run
dotsecenv identity createif you do not have one) - The GPG public key fingerprint of every team member who needs access on day one
-
Collect public keys from every team member
Each teammate exports their public key:
Terminal window # Each teammate runs:gpg --armor --export them@example.com > them.ascThey send you
them.ascover a channel you trust. Public keys are safe to share publicly — the encryption only requires their public key, never their private key. -
Verify each fingerprint out-of-band
Import and inspect each key:
Terminal window gpg --import alice.ascgpg --fingerprint alice@example.com# Read the 40-character fingerprint aloud and confirm with Alice.Repeat for every teammate. Make a list of the verified fingerprints.
-
Initialize your config and vault
Terminal window dotsecenv init config --login YOUR_FINGERPRINTdotsecenv init vaultinit configstores your fingerprint as the default identity.init vaultcreates a fresh vault file at the XDG data path and writes its location into your config. Seedotsecenv initfor path overrides. -
Add every teammate’s identity to the vault
The team-lead pattern is a shell loop over your verified fingerprints:
Terminal window TEAM_FPS=("ABC123DEF456...ALICE""789ABC012DEF...BOB""FED654CBA321...CAROL")for fp in "${TEAM_FPS[@]}"; dogpg --fingerprint "$fp" >/dev/null || { echo "Missing key: $fp"; exit 1; }dotsecenv identity add "$fp"doneEach
identity addwrites a signed identity entry to the vault. The pre-flightgpg --fingerprintcall fails fast if a public key is missing from your keyring before any vault changes happen. -
Store your first secret
Terminal window echo "super-secret-db-password" | dotsecenv secret store DATABASE_PASSWORDThe
storecommand encrypts the value with a fresh AES-256-GCM session key, then encrypts that session key once for each registered identity. Every teammate is inavailable_tofrom the very first version — no follow-upsecret shareneeded. -
Verify the access list
Terminal window dotsecenv vault describeYou should see every team member listed under
Identities, andDATABASE_PASSWORDlisted underSecrets. The JSON form shows the per-secret access list explicitly:Terminal window dotsecenv vault describe --json | jq '.[].secrets'# [# {# "key": "DATABASE_PASSWORD",# "available_to": ["ALICE_FP", "BOB_FP", "CAROL_FP", "YOUR_FP"]# }# ] -
Confirm the GPG environment is healthy
Terminal window dotsecenv vault doctordoctorchecks that gpg-agent is reachable, the vault format is current, and the vault is not fragmented. A green run here means the workflow will Just Work for teammates with the same GPG hygiene. -
Commit the vault to version control
The vault file is encrypted — committing it to a private repo is the standard distribution mechanism.
Terminal window git add path/to/vaultgit commit -m "Initialize team vault with N members"git pushEach teammate now follows Team Onboarding on their machine: pull the vault,
dotsecenv login, andsecret get DATABASE_PASSWORDto confirm access.
Expected Result
Section titled “Expected Result”After this tutorial:
- One vault file holds one signed identity entry per team member plus one signed value entry for
DATABASE_PASSWORD. - Every team member can decrypt every future
secret storewrite into this vault. - New team members join via Team Onboarding or Share a Secret, without re-initializing the vault.
Variations
Section titled “Variations”Multiple vaults (e.g., dev and prod)
Section titled “Multiple vaults (e.g., dev and prod)”Run init vault once per environment, then add identities with --all:
dotsecenv init vault -v ~/.config/dotsecenv/vault-devdotsecenv init vault -v ~/.config/dotsecenv/vault-prodfor fp in "${TEAM_FPS[@]}"; do dotsecenv identity add "$fp" --alldone--all adds the identity to every configured vault in one call.
Different access lists per environment
Section titled “Different access lists per environment”If only some teammates should access prod, register only their fingerprints in the prod vault:
PROD_FPS=("YOUR_FP" "ALICE_FP") # smaller subsetfor fp in "${PROD_FPS[@]}"; do dotsecenv identity add "$fp" -v ~/.config/dotsecenv/vault-proddoneCI-only identities
Section titled “CI-only identities”Generate a dedicated CI key and register its fingerprint as a team member. See GitHub Action integration for the full CI pattern.
Troubleshooting
Section titled “Troubleshooting”gpg: error reading key: No public key
You ran identity add against a fingerprint whose public key you have not imported. Re-import that teammate’s .asc and verify with gpg --fingerprint FP.
secret store fails with access denied
The latest value of an existing secret was encrypted to a fingerprint set you no longer hold. This typically means a teammate stored a value before adding you back. Either ask them to share the secret with your fingerprint, or rotate the value at its source and secret store again.
Teammate cannot decrypt after pulling the vault
Check the access list with dotsecenv vault describe --json and confirm their fingerprint appears in available_to. If not, run dotsecenv secret share SECRET THEIR_FP --all and push again.
Next Steps
Section titled “Next Steps”- Team Onboarding — what each teammate runs on their machine
- Share a Secret — extend access to a new member after the initial setup
- Audit Trail — query who added what, and when
- Revoke Access — remove a member when they leave