# NodeWarden: a Bitwarden-compatible server that runs on Cloudflare Workers

> NodeWarden reimplements the Bitwarden server API on Workers, D1 and R2, so a personal vault can be self-hosted without a VPS. Here is what it covers, what it leaves out, and what to check before you point your clients at it.

**shuaiplus/nodewarden** — Bitwarden-compatible server running on Cloudflare Workers

- Repository: https://github.com/shuaiplus/nodewarden
- Website: https://nodewarden.app
- Stars: 3,814 · Forks: 4,312
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-09-10 · Updated: 2026-09-10 · Language: en
- Canonical page: https://hysenlabs.com/projects/shuaiplus-nodewarden

## What NodeWarden replaces, and for whom

NodeWarden is a Bitwarden-compatible server implemented in TypeScript and deployed to Cloudflare Workers. The problem it addresses is concrete: running the official Bitwarden server or Vaultwarden means operating a host, a database and a TLS endpoint. NodeWarden moves that to Cloudflare's edge, using D1 for the relational store and R2 or KV for attachments, while the Bitwarden clients on your devices keep talking to the same API they already speak. The README frames it as "Minimal Bitwarden-compatible server running on Cloudflare Workers" and states it is not affiliated with Bitwarden, with a request not to report NodeWarden issues upstream.

The audience is narrower than "self-hosters" in general. The feature table compares NodeWarden against Bitwarden Free and marks organizations, collections and roles as not implemented, and the same for SSO, SCIM and directory integration. So the target user is an individual or a small group sharing one vault through invite-code registration, not a company provisioning departments. The README also carries a disclaimer that the project is for learning and discussion purposes and tells users to back up their vault regularly. That sentence should be read as part of the product description, not as boilerplate.

## How the Worker, D1 and R2 fit together

The repository layout tells most of the architecture story. src/ holds the Worker entry point (package.json lists src/index.ts as main), webapp/ holds a Preact-based frontend built by Vite, shared/ holds code used by both, and migrations/ holds the D1 schema. Two Wrangler configurations exist: wrangler.toml for the default R2-backed deployment and wrangler.kv.toml for the KV variant. The deploy scripts differ accordingly, with deploy:kv running scripts/ensure-kv.cjs before wrangler deploy -c wrangler.kv.toml.

Data flow is the standard Bitwarden pattern with serverless substitutions. Clients authenticate against the Worker, which stores accounts and vault metadata in D1; the README says the Worker initializes the D1 schema on first request, so no manual SQL upload is needed. Attachments and Send files go to R2 by default, or to KV in the alternate mode. The README's storage table draws the trade-off: R2 requires a card on file but allows a 100 MB soft limit per attachment or Send file with a 10 GB free tier, while KV needs no card but caps a single file at 25 MiB (described as a Cloudflare limit) with a 1 GB free tier. Real-time push sync, attachments, Send, import and export, API keys, passkey login and TOTP are all listed as supported. The README notes TOTP includes steam:// support, which the comparison table marks as absent from Bitwarden Free.

The README also documents a fill-assist endpoint at POST /fill-assist and a set of extras that go beyond the free Bitwarden tier: an installable offline PWA, a cloud backup center doing scheduled WebDAV or S3 incrementals, device management with remove and trust controls, cross-device login approval, and equivalent-domain rules. Those are the reasons someone would pick this over a plain API shim.

## Deploying NodeWarden from a GitHub fork

The README offers two paths. The visual one forks the repository, connects the fork in Cloudflare Workers & Pages via Continue with GitHub, sets the build command to npm run build and the deploy command to npm run deploy (or npm run deploy:kv for KV mode), and opens the generated Workers URL. In that flow Cloudflare builds and deploys the code, and the README states that wrangler.toml or wrangler.kv.toml defines the binding names. Two configuration details are called out. First, if the site reports a missing JWT_SECRET, add it as a Secret in Workers settings, using a random string of at least 32 characters in production rather than an example value. Second, to hide the server-hosted Web Vault, add a text variable named HIDE_WEB_VAULT with the value 1; while enabled, server-hosted frontend pages and static assets return 404 Not Found, while login, sync, attachment, icon and notification endpoints stay available, and an already installed or cached PWA can keep using its local frontend. Deleting the variable or changing it to anything other than 1 restores the Web Vault.

The CLI path is shorter to type. The README gives this sequence:

```bash
git clone https://github.com/shuaiplus/NodeWarden.git
cd NodeWarden

npm install
npx wrangler login

# Default: R2 mode
npm run deploy

# Optional: KV mode
npm run deploy:kv

# Local development
npm run dev
npm run dev:kv
```

After npm run deploy finishes, the README says to open the generated Workers URL. The first request initializes the D1 schema, so the first sign of a binding problem is usually an error during that initial client sync rather than at deploy time.

## What the first request does, and how to update

After deployment, the first request to the Worker initializes the D1 schema, per the README. That is the moment to watch: if the bindings are wrong, the schema step has nothing to write to, and the failure surfaces as an error on the first client sync rather than at deploy time. The README does not document a rollback procedure, so a failed first request leaves you inspecting D1 directly.

Updates are deliberately low-ceremony. The README describes a manual path: open your fork on GitHub, and when the sync banner appears, click Sync fork then Update branch. There is no documented migration command for schema changes between versions, and the README does not describe how migrations/ entries are applied beyond the first-request initialization. That is the main operational unknown in the project's own documentation.

Client compatibility deserves a check before you commit. The README lists tested clients as Windows desktop, mobile app, browser extension and Linux desktop, and marks macOS desktop as "not fully verified yet". If your daily driver is a Mac, that warning is the first thing to resolve.

## Where NodeWarden is the wrong tool

The missing features are not edge cases for teams. Organizations, collections and roles are listed as not implemented, and so are SSO, SCIM and directory integration. A company that needs to grant a contractor access to one collection, or that provisions accounts from an identity provider, cannot use this. Invite-code registration is the documented multi-user mechanism, which is a shared-secret model rather than an administrative one.

There is a second boundary that is easy to overlook: the project's own disclaimer. The README states the project is for learning and discussion purposes only and asks users to back up their vault regularly. A password manager that tells you to keep backups is telling you its durability guarantees are yours to maintain. The cloud backup center (scheduled WebDAV or S3 incrementals) exists precisely because of that, and anyone adopting NodeWarden should treat configuring it as part of the install, not an optional extra.

Storage mode is a third constraint, not a preference. If you cannot attach a card to the Cloudflare account, you are on KV, and every attachment or Send file is capped at 25 MiB. That rules out storing large files in the vault.

## NodeWarden against Vaultwarden

The README credits Vaultwarden as the server implementation reference, and the comparison is the natural one because both speak the Bitwarden client protocol. The difference is where the server lives. Vaultwarden is a self-hosted server you run on a machine you control, which means you own the process, the database and the backups, and you can run it without a Cloudflare account. NodeWarden is a Worker: there is no long-running process to patch, scaling is Cloudflare's problem, and the free tiers of D1, R2 or KV absorb a personal vault's traffic.

The trade is control for operations. Vaultwarden's feature set covers organizations and the administrative surface that NodeWarden's table marks as absent; NodeWarden's table instead lists PWA offline support, a cloud backup center, device trust controls and cross-device login approval, several of which the comparison marks as missing from Bitwarden Free. If your requirement is a team vault with collections, the README's own table sends you elsewhere. If your requirement is a vault for yourself that survives without a VPS, the Workers model is the point of the project.

## Licence and the cost of staying current

package.json declares "license": "LGPL-3.0", and the README's badge and License section both say LGPL-3.0. The repository metadata does not carry a recognised SPDX identifier, so the package manifest and README are the sources to read; if you plan to redistribute a modified Worker or link it into a larger product, have someone qualified look at the LGPL obligations rather than assuming the badge settles it. This is a description of what the files say, not legal advice.

The upgrade cost is mostly Cloudflare's, not yours. The README's update path is a fork sync, and the deploy scripts (npm run deploy, npm run deploy:kv) are what push the new code. What you pay for is attention: releases arrive on their own schedule (v1.8.0 on 2026-07-17, v1.7.4 on 2026-07-12, v1.7.3 on 2026-07-06, according to the release list), and each one that touches migrations/ is a change to the schema your vault depends on. The last push to the repository was on 2026-09-06. Because the README documents no rollback and no explicit migration command, the practical cost of upgrading is having a working backup you can restore from, which is the same backup the disclaimer already asks you to keep.

## Conclusion

NodeWarden fits an individual or a small group who already pay for Cloudflare and want a Bitwarden-compatible vault without running a VPS. It is the wrong choice for anyone who needs organizations, collections, roles, SSO or SCIM, because the README lists those as not implemented. Before migrating, verify three things on your own deployment: that your target clients are on the tested list (the README marks macOS desktop as not fully verified), that you have set a random JWT_SECRET of at least 32 characters, and that the first request has created the D1 schema so sync against your existing vault data works.

## FAQ

### What is the NodeWarden server?

NodeWarden is a Bitwarden-compatible server written in TypeScript and deployed to Cloudflare Workers, with D1 for storage and R2 or KV for attachments and Send files. It is not affiliated with Bitwarden, and the README asks users not to report NodeWarden issues to the official Bitwarden team.

### How do I deploy NodeWarden to Cloudflare?

Fork the repository, connect the fork in Cloudflare Workers & Pages with Continue with GitHub, set the build command to npm run build and the deploy command to npm run deploy (or npm run deploy:kv for KV mode). The README also gives a CLI path using npm install, npx wrangler login and npm run deploy.

### Does NodeWarden support organizations and SSO?

No. The README's feature table lists organizations, collections and roles as not implemented, and the same for SSO, SCIM and directory integration. Multi-user access is handled through invite-code registration instead.

## Sources

- [Issues](https://github.com/shuaiplus/nodewarden/issues)
- [Project website](https://nodewarden.app)
- [README](https://github.com/shuaiplus/nodewarden/blob/main/README.md)
- [Releases](https://github.com/shuaiplus/nodewarden/releases)
- [shuaiplus/nodewarden on GitHub](https://github.com/shuaiplus/nodewarden)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/shuaiplus-nodewarden
