At DMNO we love Cloudflare. This very site is hosted on it! That’s why we’re excited to make it easier and safer to manage config and secrets in all of your Cloudflare projects.
This platform integration exposes premade schemas and underlying types to interact with env vars related to Cloudflare, as well as a special cli wrapper around wrangler
that helps deal with config. Aside from all the usual benefits of DMNO - validation, type-safety, sync with backends like 1Password, sharing config across a monorepo - our Cloudflare integration has a few extra tricks up its sleeve:
- configure
wrangler
using DMNO, injecting built-in env vars, and special new ones that are passed in via flags - inject config into Cloudflare Workers - during both local dev and deployment
- enable DMNO security features in workers - leak prevention, log redaction
- handle both static and dynamic config
- add type-safety to your config, without needing to run
wrangler types
- access your config anywhere, not just within route handlers
Setup
Configuring wrangler
using DMNO
Many facets of the wrangler
CLI, including authentication, can be set using system environment variables. By default, if you have a .env
file in your repo, wrangler
will automatically use it. But, this suffers from all the usual headaches of using a .env
file. Instead, DMNO provides a premade vendor schema and associated types so you can inject validated settings into wrangler
without resorting to a gitignored .env
file. Instead, you can pull your sensitive Cloudflare API keys from any DMNO plugin, like 1Password or an encrypted vault, share values across a monorepo, or compose your config however you see fit.
Because wrangler
is configured using a mix of wrangler.toml
, env vars, CLI flags, and has no concept of plugins, we also provide a wrapper CLI, called dwrangler
, that handles everything automatically.
For example, if you wanted to pull your Cloudflare credentials from 1Password, configure dev options, and inject your config, your .dmno/config.mts
might look like this:
To take advantage of this new config, you swap usage of wrangler
to dwrangler
, whether calling it directly or in your package.json
scripts.
Cloudflare Workers
Dealing with config in Cloudflare Workers is a bit different than other JS/TS environments. Instead of relying on a global process.env
, config is passed in as bindings to route handlers. These values can be either vars (not-sensitive, plaintext) or secrets (sensitive, encrypted), and can be set in a variety of ways for local development and for deployments:
wrangler --var
CLI option - sets vars during local dev, also sets non-sensitive vars duringwrangler deploy
wrangler.toml
in a[vars]
section - sets vars, can also be varied per environment (e.g.,[staging.vars]
).dev.vars
file - set sensitive secrets during local development onlywrangler secret
- command to set secrets remotely, also seewrangler versions secret
to handle versioned deploys with secrets
Additionally, if not relying on a custom build, wrangler
internally uses esbuild, and you can do build-time replacements, which can also be used for configuration purposes:
wrangler.toml
in a[define]
section - static vars, can also be varied per environment (e.g.,[staging.define]
)wrangler --define
CLI option - does static replacements during the build, both locally and during deploys
Navigating all of this can be tricky, so we built this integration to make it as easy as possible. Define your DMNO config, and we take care of the rest, giving you a unified way to access your configuration, regardless of if it is static or dynamic, and sensitive or not.
Injection via inline mode
While it is not very Cloudflare-y, our preferred way to inject DMNO config is by inlining the entire resolved config during the build/deploy process. While it may feel a little odd, config changes always trigger a new deployment anyway.
Doing it this way has a few important benefits:
- validated and coerced config, with additional metadata, and it is directly a part of a specific version of your worker
- all config can now be accessed everywhere, just like
process.env
, not just within request handlers - type-safety and IntelliSense on your config, without re-running
wrangler types
- enables DMNO’s security features to prevent secrets from leaking over http responses, requests to other servers, and redact secrets from logs
To set this up, we must import the DMNO globals injector at the top of your main worker entrypoint. This version is specifically made to be compatible with Cloudflare’s edge runtime, and will look for data injected by dwrangler
at build time.
Injection via secrets mode
If you want to continue to use Cloudflare’s built-in secrets functionality, you can instead use the secrets injection mode. In this mode, static config items will still be replaced at build time, dynamic config items will be set as Cloudflare secrets and you will continue to read them from the env
binding injected into your route handlers.
To enable this mode, you must set the WRANGLER_INJECT_MODE
in your config to secrets
:
Pros:
- secrets are no longer bundled into your code
- existing calls to
env.SOME_KEY
will continue to work
Cons:
- we cannot activate DMNO’s security features - sensitive secrets can appear in logs, and easily be leaked
- you still cannot access config outside of route handlers
- secrets will always be injected as strings
- less reliable types
To make things a bit more convenient, we do replace references to DMNO_CONFIG.SOME_VAR
to env.SOME_VAR
, which means you get automatic type-safety and IntelliSense, and you never have to think about whether a config item is static or dynamic.
While it should all feel seamless, running dwrangler deploy
in this mode calls multiple commands to do a 3-part deployment:
- build and upload a new versioned deploy, without activating it
- upload resolved config as encrypted secrets, creating another version with secrets attached
- activate the new version with correct secrets attached
Which mode should you use?
We think for most users the inline mode is the better choice, but both options have their merits. Here is a comparison table to help:
Inline mode | Secrets mode |
---|---|
👍 Static config injected at build time, accessible anywhere | < same |
✨ Dynamic config acessible outside route handlers! | 😪 Dynamic config only accessible within route handlers must use env naming convention |
🔐 Log redaction, leak detection! | 😢 No DMNO security features |
🙊 Bundled worker code is accessible within the Cloudflare UI | 🙈 Cloudflare secrets are never visible within the Cloudflare UI |
🛠️ Additional installation code | 🛠️ More complex deployment |
Using dwrangler
with the Workers Builds git integration
Cloudflare’s new Workers Builds (beta) allows you to connect your worker to a git repo, and it will run the CI process within Cloudflare, similar to how it works for Pages.
While this is great, it’s not much different than running your CI anywhere else, and the same issues of injecting config into your running worker are present.
To use dmno
within Workers Builds, just swap your deploy command from wrangler
to dwrangler
, just like if you were running it anywhere else. There is also a section for setting “Build variables and secrets” where you can populate any additional config needed during the build. If you are using DMNO to fetch sensitive config from somehwere else, this is how you would pass in that secret-zero, for example, a service account token for 1Password.
Cloudflare Pages
Cloudflare pages allows you to host static sites and provides a little sugar on top of Cloudflare Workers for attached functions. Unfortunately, Wrangler’s Pages functionality does not allow the same level of configuration of the underlying ESBuild process. However, it may not matter because, in practice, most users are likely using an existing framework and already have their own build process. In this case, you can rely on our drop-in integrations to inject your DMNO config.
Regardless, you could still use DMNO to resolve your config and upload secrets to Cloudflare, but without a custom build, you would have to rely on env
rather than DMNO_CONFIG
, and you would not get all the benefits of DMNO.
Please reach out if you need help setting things up, or have a use case that is not supported.
Cloudflare Pages env vars
The Cloudflare Pages environment injects a few environment variables into its build environment that provide information about the current build. This module exposes a pre-made config schema object which you can use in your own schema. You can use the pickFromSchemaObject
utility to pick only the env var keys that you need from the full list. For example:
Other workflows
If you have a totally custom setup, that does not fit with the above workflows, you can still use dwrangler
to manage Cloudflare auth, and push resolved config to Cloudflare however you want.
Note that wrangler
has several bulk secret related methods, and they all take JSON from stdin.
For example: dwrangler secrets:bulk < dmno resolve --format json