Team Member Offboarding
When a team member leaves, you need to revoke their access and rotate any secrets they had visibility into. envctl makes this process explicit and auditable.
Why Rotation Matters
Removing someone from a project revokes their ability to receive future updates, but they still have copies of the secrets they previously had access to. These copies exist on their local machine, potentially in backups, or in their memory.
For true security, you must:
- Revoke access — Stop them from receiving new secrets
- Rotate secrets — Change the values of secrets they had access to
- Update CI bundles — Re-export encrypted bundles with new secrets
Removal alone is not enough
Simply removing a team member does not invalidate the secrets they've already seen. Always rotate secrets after removing someone, especially for production environments.
Step 1: Review Their Access
Before removing someone, understand what they had access to:
$ envctl project access bob
Access for bob in myproject:
Environment Role Since
----------- ---- -----
dev member 2024-01-10
staging member 2024-01-10
prod reader 2024-02-15
This shows which environments Bob could access and their role in each. Roles determine what they could do:
- reader — Can view secrets but not modify them
- member — Can view and modify secrets
- admin — Can manage members and environments
All roles can see secret values, so all environments they had access to need rotation.
Step 2: Remove from Project
Remove the team member from the project. After removal, envctl will prompt you to rotate secrets:
$ envctl project remove bob
Remove 'bob' from project? [y/N] y
Member 'bob' removed.
'bob' had access to: dev, staging, prod
SECURITY: The removed member may have copied secret values.
You should set NEW values for sensitive secrets (API keys, passwords, etc.)
Rotate secrets for these environments? [Y/n] y
Rotating secrets for myproject/prod...
# Opens $EDITOR - update secrets with NEW values, save and close
Updated: DATABASE_URL, API_KEY, STRIPE_SECRET
Rotating secrets for myproject/staging...
# Opens $EDITOR again for staging
Updated: DATABASE_URL, API_KEY
Rotating secrets for myproject/dev...
# Opens $EDITOR again for dev
Updated: DATABASE_URL
Done. Updated secrets will be synced to team members when the daemon is running.
This does several things:
- Removes their membership from the project chain
- Prevents them from receiving new sync messages
- Revokes their ability to decrypt future secrets
- Prompts to rotate secrets in each environment they had access to
Editor-based rotation
When you choose to rotate secrets, envctl opens your $EDITOR for each environment. The file shows all current secrets with helpful comments explaining what needs to be done. Update any sensitive values (API keys, passwords, tokens) with NEW values from your service providers, then save and close.
Use --silent to skip all prompts (useful for scripts, but remember to rotate secrets separately):
$ envctl project remove bob --silent
Member 'bob' removed.
Step 3: Identify Secrets to Rotate
envctl tracks who has seen which secrets. View the secrets Bob had access to:
$ envctl env var list -e dev
Variables in myproject/dev:
DATABASE_URL = postgres://... (set by alice, 2024-01-10)
API_KEY = sk_dev_... (set by bob, 2024-02-01)
STRIPE_KEY = pk_test_... (set by alice, 2024-01-15)
All secrets in environments Bob had access to should be considered compromised and rotated.
Check the Audit Log
For a detailed view of what Bob accessed:
$ envctl log --search bob --since 90d
2024-03-01 14:20 bob Pulled secrets (dev: 3, staging: 3, prod: 2)
2024-02-28 09:15 bob Set API_KEY in dev
2024-02-15 11:30 alice Granted bob reader access to prod
2024-02-01 10:00 bob Set API_KEY in dev
2024-01-10 09:00 alice Added bob to project
Step 4: Rotate Affected Secrets
If you used the integrated rotation prompt in Step 2, you've already rotated secrets in the editor. This section covers what you need to do at the service level and how to rotate manually if needed.
What "Rotation" Really Means
Rotating a secret involves two steps:
- Generate new credentials at the actual service (database, API provider, etc.)
- Update the secret in envctl with the new value
Simply changing the value in envctl isn't enough—you need to create a genuinely new credential at the source.
Example: Rotating Database Credentials
- Create a new database user or password in your database
- Update the secret in envctl (in the editor, or manually):
$ envctl env var set -e prod DATABASE_URL=postgres://newuser:newpass@host/db ✓ Set DATABASE_URL in prod - Deploy your application with the new credentials
- Delete the old database user or password
Example: Rotating API Keys
- Generate a new API key from the service provider
- Update the secret (in the editor, or manually):
$ envctl env var set -e prod API_KEY=sk_live_new_key_here ✓ Set API_KEY in prod - Revoke the old API key from the service provider
Rotate in order of sensitivity
The integrated rotation prompt handles environments in the order the member had access, but if you're doing it manually, start with production secrets, then staging, then development.
Manual Rotation (Alternative)
If you skipped the rotation prompt or need to rotate additional secrets later, use the editor command:
# Edit secrets in an environment
$ envctl env edit -e prod
# Opens $EDITOR with all secrets - make changes, save and close
# Or set individual secrets
$ envctl env var set -e prod DATABASE_URL=postgres://newuser:newpass@host/db
$ envctl env var set -e prod API_KEY=sk_prod_new_key
Step 5: Update CI Bundles
If you use envctl for CI/CD, re-export your encrypted bundles with the new secrets:
$ envctl ci export -e prod -o .envctl/prod.enc
Exported 8 variables to .envctl/prod.enc
$ envctl ci export -e staging -o .envctl/staging.enc
Exported 6 variables to .envctl/staging.enc
$ git add .envctl/*.enc
$ git commit -m "Rotate secrets after team change"
$ git push
Your CI pipelines will automatically use the new secrets on the next run.
Step 6: Verify Removal
Confirm the team member has been removed:
$ envctl project members
Members of myproject:
Name Role Environments Joined
---- ---- ------------ ------
alice admin dev, staging, prod 2024-01-05
charlie member dev, staging 2024-01-20
2 members total
Bob no longer appears in the member list.
Verify in the Audit Log
$ envctl project log | head
2024-03-01 16:00 alice Removed bob (reason: Left company)
2024-03-01 16:05 alice Set DATABASE_URL in prod
2024-03-01 16:05 alice Set API_KEY in prod
...
Notify Remaining Team
After rotating secrets, remaining team members need to sync:
$ envctl pull
✓ Pulled 6 updates from alice
prod: 3 variables changed
staging: 2 variables changed
dev: 1 variable changed
If using the relay, syncing happens automatically. For P2P-only setups, team members may need to be online at the same time or manually pull updates.
Team members should also update their local .env files:
$ envctl env use dev
✓ .env written (3 secrets)
Best Practices
Create an Offboarding Checklist
For your organization, maintain a checklist of secrets that need rotation when someone leaves. Group them by service:
- Database — DATABASE_URL, REDIS_URL
- Payment — STRIPE_SECRET, STRIPE_WEBHOOK_SECRET
- Email — SENDGRID_API_KEY, SMTP_PASSWORD
- Cloud — AWS_SECRET_ACCESS_KEY, GCP_SERVICE_ACCOUNT
- Third-party APIs — TWILIO_AUTH_TOKEN, GITHUB_TOKEN
Use Environment-Based Access Control
Limit who has access to production:
# Grant dev/staging access to new developers
$ envctl project grant alice --env dev,staging
# Only grant prod access when needed
$ envctl project grant alice --env prod
This minimizes the rotation scope when someone leaves—if they only had dev access, you only need to rotate dev secrets.
Schedule Regular Rotation
Don't wait for offboarding to rotate secrets. Consider:
- Rotating production secrets quarterly
- Rotating after any security incident
- Rotating when contractors complete projects
Document in the Audit Log
Use descriptive reasons when removing members:
$ envctl project remove bob --reason "Contract ended 2024-03-01"
This creates a permanent record in the project chain that's visible to all admins.
Emergency Removal
If you suspect a security incident or need to remove someone immediately:
- Remove immediately:
$ envctl project remove compromised-user --reason "Security incident" - Rotate production secrets first:
$ envctl env var set -e prod CRITICAL_SECRET=new_value - Re-export CI bundles:
$ envctl ci export -e prod -o .envctl/prod.enc && git add .envctl/prod.enc && git commit -m "Emergency rotation" && git push - Deploy with new secrets
- Rotate remaining environments
- Review audit logs for suspicious activity
Related
- Team Onboarding — How to add new team members
- Security Best Practices — General security recommendations
- Multiple Environments — Managing access per environment
- Command Reference: project remove