Skip to Content

drangler, in One Page

drangler is the command-line tool for a Drupflare site's whole life: stand one up, keep it healthy, develop a module against it, and move sites on or off. Every command takes --json and prints the same object its text is built from.

📦 Install

bun add -g @drupflare/drangler
# or
npm i -g @drupflare/drangler

Every release also ships a single-file binary for Linux and macOS on x64 and arm64, and Windows on x64, with a SHA256SUMS file beside it. drangler needs ssh and wrangler; drangler doctor checks both.

🚀 First Time

drangler runs on your own computer. Before the first deploy, install it with wrangler, sign in to Cloudflare, and let doctor check the setup:

npm i -g @drupflare/drangler wrangler
wrangler login     # opens a browser to approve access to your Cloudflare account
drangler doctor    # checks ssh, wrangler and the sign-in, and says how to fix what is missing

Commands that read an existing server (migrate, preview, doctor --source) connect over SSH with your usual keys. Commands that act on a deployed site take its address, and the owner token that site claim stored in your system keychain.

Every command accepts these flags:

FlagWhat it does
--dry-runprint what the command would do, and do none of it
--jsonprint the report as one JSON object, for scripts
--yes, -yconsent for anything that changes a live site; without it those refuse
--site <origin>the site to act on, such as https://my-site.example
--token <token>the owner token when it is not saved; DRUPFLARE_OWNER_TOKEN also works
--verbose, -vprint every command and request drangler makes
--quiet, -qhide progress; the report still prints

🎬 Common Jobs

Try Drupal on your laptop. One command clones the worker, downloads Drupal and the PHP interpreter, checks the result and serves it at http://localhost:8787. Run it again and it reuses the workspace.

drangler dev

Put it on Cloudflare. Deploy the same workspace, then claim the site to get the administrator password and the owner token. The token goes into your system keychain without asking, so later commands find it; --save also writes it to your user config.

drangler deploy
drangler site claim my-site.example --title "My Site" --save

Lost the owner token. It is shown once, at the claim. If you can write to the Cloudflare account the site is deployed on, you can get it back, and --store saves it to the keychain:

drangler recover-token my-site.example --store

Copy an existing site to see it running. preview reads your current server with read-only commands and brings up a working duplicate. The live site is not touched. Available from drangler 0.3; from 0.4 it finds the Drupal root itself, so the host is all it needs.

drangler preview --host [email protected]

Every choice it makes has a flag, a DRANGLER_PREVIEW_<NAME> variable and a prompt on a terminal, so a script answers it without flags and a person answers it by typing. A flag wins over a variable, and a question nobody can answer is refused rather than left waiting.

DRANGLER_PREVIEW_CONFIRM=old.example DRANGLER_PREVIEW_FOLLOW=mymodule=my-org/mymodule \
  drangler preview --host [email protected]

Credentials the database holds, such as payment keys, mail logins and OAuth secrets, are blanked in the duplicate and listed by name, so a copy cannot act as your live site. --carry-key <name> brings one back. --follow module=owner/repo keeps a module current from git, --check <path> compares more pages with the live site, and --deploy puts the copy on your Cloudflare account behind a Cloudflare Access login that only you can pass. The full list is in Migrate.

Keep an eye on it. status says what is deployed, health says whether it is serving. Both exit non-zero on a problem, so either can go in a monitor or a CI job.

drangler status my-site.example
drangler health my-site.example

Upgrade. Move the checkout to the latest release, deploy it, wait for the site to pick it up and run Drupal's database updates, in one step.

drangler site upgrade my-site.example

Get your data out. The whole database, as a file you own.

drangler migrate export --url my-site.example --out site.sql

🧰 Set Up and Run Locally

CommandWhat it does
doctorChecks the toolchain, the Cloudflare credential and the config
initConnects this machine to a site and records where it went
buildClones the worker and builds it into a deployable tree
validateEverything that has to hold before dev or deploy works
devBuilds if needed, checks, then runs Drupal on your machine

🚀 Deploy and Update

CommandWhat it does
deployBuilds if needed, checks, then deploys to your account
site claim <target>Mints the administrator password and the owner token
recover-token <target>Gets a lost owner token back; --store keeps it
update [worker]Moves a checkout to another version, and its worker
site upgrade <target>Deploys, waits for the database replay, runs the updates
site updb <target>Reads Drupal's update chain and drives one step of it

🩺 Operate a Site

CommandWhat it does
status <target>What is deployed: plan, version, claim state
health <target>Probes a site and reports which cache tier answered
heal <target>Reports the repair ladder and performs the repairs it can
reconcile <target>What a site still owes the shipped release, and drives it
sweep <target>How much of the site is cached, and what the scheduler decided
site invalidatePurges cached pages by tag, or retires them all at once
setup cloudflare <target>Whether a Cloudflare account grant is connected; --disconnect revokes it
setup mail <target>Sending-domain onboarding: what is set up, and takes the next step
setup identity <target>The OpenID Connect provider: read it, set it or clear it

🚚 Migrate

CommandWhat it does
previewSurveys, converts and brings up a working duplicate of a site
migrate surveyReads a server-hosted Drupal over SSH, read-only
migrate eligibilityCan this site move today, and what would have to change
migrate planScores a survey and orders the work, in either direction
migrate convertConverts a SQL dump between MySQL and SQLite
migrate installLands a converted database in a workspace, with a backup
migrate restorePuts a backup set back where it came from
migrate exportPulls a deployed site's database out
migrate deltaThe second pass of content that changed during a move
migrate cutoverThe checklist a person confirms while traffic switches
migrate filesWrites the managed files in a dump back onto a filesystem

🧩 Develop a Module

drangler modify puts a custom module or theme on a live site one revision at a time. Each revision is stored on the site itself, so sending a one-file change sends one file and a rollback sends nothing.

1. Link the project to a site. Run it inside the module's directory. It detects the project shape from the file it names, and writes drangler.json for the project and the owner token to your user config.

$ cd ~/work/events
$ drangler modify init --site https://my-site.example
detected      module-project (/work/events/events.info.yml)
package       events
mounts to     modules/custom/events
files         24
site          https://my-site.example (claimed)
owner token   set

2. Check it before anything leaves your machine. Every PHP file is linted with the PHP you name, and paths that would collide on the site are caught here.

$ drangler modify check --php php
package     events
mounts to   modules/custom/events
files       24 kept, 3 skipped
lint        24 of 24 ok (php 8.4.12)
paths       no collision inside this project

3. Upload. Only the files the site does not already hold are sent. The site then boots Drupal with the new code before making it live.

$ drangler modify upload --message "add the event listing"
package     events
plan        24 files, 2 not on the site, 22 already there
uploading   2 blob(s), 6.1 kB, 1 batch(es)
commit      rev 9f2c1ab4
verify      kernel booted

verify kernel booted is the line that matters. If the new code would stop Drupal from booting, the site restores the previous revision on its own and the command exits 1 naming the error.

4. Turn it on, the first time only:

drangler modify enable events

5. Undo if you need to. The last five revisions stay on the site.

drangler modify revisions        # newest first
drangler modify rollback --yes   # back to the one before
drangler modify activate 3d81ee07 --yes
CommandUse it to
modify statuscompare what is live on the site with what is on disk
modify difflist the files an upload would send; exits 3 if any
modify release --tagupload from a tagged commit, refusing uncommitted edits
modify listuploaded packages, and the git repositories the site follows
modify require <name>install contrib from drupal.org or Packagist
modify drop <rev>delete an old revision and the files only it used
modify devrun drangler dev with this project mounted, live-reloading

Contrib modules come from the registry rather than an upload: drangler modify require drupal/pathauto drupal/metatag --enable. Pin a version with --constraint, as in drangler modify require phpmailer/phpmailer --constraint v6.12.0.

☁️ Cloudflare Helpers

CommandWhat it does
cf whoamiWhich Cloudflare credential drangler would use
cf workersLists the account's workers against a saved list
cf versions <worker>The versions the platform still holds
cf rollback <worker> <v>Points a worker back at a version it already holds
cf secret <worker> …Lists, sets or removes a secret without printing it
secrets scan <paths…>Finds credentials in a dump or a tree, masked

⚙️ Configuration

CommandWhat it does
config whereWhich file supplied each setting
config check <file>Scores a wrangler config against known-bad setups
config levers <file>The optional features a config declares, and each state

Settings resolve from a flag, then an environment variable, then a drangler.json in the nearest parent directory, then your user config. The owner token never goes in drangler.json, which is committed. site claim stores it in the system keychain, and a machine with no keychain falls back to your user config with owner-only permissions.

Every command finds the owner token in this order: --token, then DRUPFLARE_OWNER_TOKEN, then the keychain, then the global config. A token already in the config is not copied into the keychain on first use; drangler recover-token --store is the explicit way to move one.

Recovering the Owner Token

recover-token proves you can write to the site's Cloudflare account instead of presenting the token. drangler writes a one-minute, single-use proof into the deployment's CONFIG_KV namespace through your own wrangler login, then presents it to the site's /recover-token route, which checks it, spends it and answers with the token. Recovery does not rotate the token, so anything else holding it keeps working.

  • It needs a wrangler login, or CLOUDFLARE_API_TOKEN, that can edit KV. --account picks the account when the login reaches several.
  • The namespace is --kv-namespace, else the CONFIG_KV binding in a wrangler.jsonc in the working directory, else the one account namespace with CONFIG_KV in its title.
  • A new proof can take up to a minute to reach the site. drangler retries with growing pauses, at most eight times, because the site refuses an address after 12 failed attempts in a minute.
  • --json puts the token in the ownerToken field.
  • It is not drangler recover, which reads the 30-day database recovery window.

🚦 Reading the Output

Every command prints a short two-column report on stdout. --json prints the same fields as one JSON object, and progress goes to stderr, so piping a command never mixes the two.

Exit CodeMeaning
0done
1the check could not run, such as a network failure
2the input was wrong, such as a missing flag
3it ran and found something: a blocker, a secret, a difference

health gives one verdict:

VerdictWhat it means
okthe site answered normally
warminga new site unpacking its database, or a page queued to render; wait
degradedan error status, or the site is shedding load on purpose to stay in its limits
unreachablenothing answered
not-drupflaresomething answered, and it is not a Drupflare site

Its tier line says what answered: EDGE is Cloudflare's cache in front of the site, HIT is the site's own stored copy, KV is a copy shared across locations, and RENDER means Drupal built the page for this request.

✍️ What Writes

build, migrate install, update and preview write to a local workspace; preview --deploy also creates a Cloudflare Access application and deploys the duplicate as a new worker, which needs a Cloudflare API token that can edit Access. site, heal, modify, reconcile --run and sweep --run change a live site, so each needs the owner token, and anything that changes what visitors see also needs --yes. recover-token writes one record to the site's CONFIG_KV namespace that expires in a minute, and needs your Cloudflare login instead of the token. Nothing in drangler deletes a file or a directory. The full reference is in the drangler README.