Support Environment Variables/Secrets in `wrangler versions upload`
Describe the solution
Problem Statement
Currently, there's no practical way to upload Worker code and environment variables/secrets together in a single atomic operation with wrangler versions upload. This creates challenges for complex deployment scenarios, particularly when coordinating multiple Workers.
Current Limitations
1. --var Flag Issues:
- Requires complex scripting to extract variables from
.envfiles - Variables are stored as plain text, not as encrypted secrets
- Not suitable for sensitive data (API keys, tokens, etc.)
2. wrangler secret bulk Separation:
- Creates a separate version for secrets vs code
- Makes atomic deployments and rollbacks more complex
- Doesn't align with versioning workflow for coordinated deployments
Use Case: Atomic Multi-Worker Deployment
We deploy API and frontend Workers together using this workflow:
# Phase 1: Upload both workers (code only)
wrangler versions upload --name api-worker
wrangler versions upload --name frontend-worker
# Phase 2: Deploy both versions atomically
wrangler versions deploy <api-version-id>@100% --name api-worker
wrangler versions deploy <frontend-version-id>@100% --name frontend-worker
Problem: Environment variables using secrets must be managed separately, breaking atomicity and complicating rollbacks.
Current Workaround
We've implemented complex TypeScript scripts that:
- Parse
.envfiles - Extract key-value pairs
- Pass them via multiple
--vararguments - Hide sensitive values in logs
// Example of current complexity
const envVars = parseEnvFile('.env.production')
const args = ['versions', 'upload', '--var']
envVars.forEach(({ key, value }) => {
args.push(`${key}:${value}`) // Plain text, not encrypted
})
Proposed Solution
Option A: Environment File Support
wrangler versions upload --env-file .env.production
wrangler versions upload --env-file .env.staging --env staging
Option B: Secrets File Support
wrangler versions upload --secrets-file .secrets.production
Option C: Mixed Approach
wrangler versions upload --env-file .env.production --secrets-file .secrets.production
Benefits
- 🔒 Security: Secrets stored encrypted, not as plain text
- ⚡ Simplicity: No complex scripting required
- 🎯 Atomicity: Code + environment in single version
- 🔄 Rollbacks: Single version contains everything
- 📦 Consistency: Aligns with existing
.envecosystem
Alternative Considerations
If file-based approach isn't feasible, consider:
-
Bulk secret upload with version targeting:
wrangler secret bulk --target-version <version-id> .secrets.env -
Environment inheritance:
wrangler versions upload --inherit-env production
Related Issues
This would greatly improve developer experience for:
- Multi-service deployments
- Environment parity
- CI/CD pipelines
- Blue-green deployments
Workaround Impact
Current workarounds require significant custom tooling and don't provide the security or atomicity that Cloudflare's versioning system otherwise enables.
Would love to hear the team's thoughts on this! Happy to provide more details about our use case or help test any proposed solutions. 🙏
+1
hitting the same problem would definitely go for for Option C if possible
+1
It would be great to have atomic deploy.
Because right now I'm using a workaround:
"scripts": {
"cf-typegen": "wrangler types",
"check-types": "tsc --noEmit",
"versions-secret-bulk": "wrangler versions secret bulk .dev.vars",
"deploy": "pnpm run cf-typegen && pnpm run check-types && pnpm run versions-secret-bulk && wrangler deploy"
}
Are you aware of the wrangler versions secret command?
https://developers.cloudflare.com/workers/wrangler/commands/#secret-put-1
@petebacondarwin as stated in the very first comment, it is about doing it atomically: code + secrets + env variables. the way it is now does not make an atomic version for all of these hence has the overhead of keeping multiple related versions
Ah right, I was confused because the comment doesn't mention wrangler versions secret only wrangler secret which is not designed to support the version upload flow.
One thing to note is that non-secret vars should be stored in the Wrangler config file (e.g. wrangler.jsonc) and are already uploaded alongside the Worker code when doing a wrangler versions upload.
I think we should indeed support effectively combining wrangler versions upload and wrangler versions secret bulk into a single command. This may need an update to the backend API to have a single entry-point. Otherwise, if we only do this in Wrangler, then the two API calls will still result in two items in your version history.
I personally currently still use wrangler.jsonc for all env vars (secret or not) which is not a good practice but for this exact reason because now I can run a CI pipeline and get reverted to any previous version with a single command and atomically.
OK - talked to the backend API team. It looks like we already have the pieces in place to do a bulk upload of secrets alongside a version upload.
Adding this to our backlog to implement when we have capacity.
If anyone wanted to have a crack at this the code in
https://github.com/cloudflare/workers-sdk/blob/436e254d8ef876c661a636be9367c23e3174f3d6/packages/wrangler/src/versions/secrets/bulk.ts#L44
and
https://github.com/cloudflare/workers-sdk/blob/436e254d8ef876c661a636be9367c23e3174f3d6/packages/wrangler/src/versions/secrets/index.ts#L98
would need to be combined into the code in
https://github.com/cloudflare/workers-sdk/blob/436e254d8ef876c661a636be9367c23e3174f3d6/packages/wrangler/src/versions/upload.ts#L361
in other words, the vars property passed to versionsUpload() should include the secrets parsed from the bulk secrets file where the type is either inherit or secret_text.
Would love to see this being possible without necessarily using an intermediary file, allowing something like wrangler deploy --secrets $(fetch-and-spit-out-secrets)