# KeeWeb: a KeePass client you can host yourself

> A browser and desktop password manager that opens kdbx files and ships as a single HTML file, a service worker and a set of Docker images for people who want to self-host.

**keeweb/keeweb** — Free cross-platform password manager compatible with KeePass

- Repository: https://github.com/keeweb/keeweb
- Website: https://keeweb.info
- Stars: 13,020 · Forks: 1,166
- Language: HTML
- License: NOASSERTION
- Published: 2026-10-07 · Updated: 2026-10-07 · Language: en
- Canonical page: https://hysenlabs.com/projects/keeweb-keeweb

## Three ways to run the same client

KeeWeb opens `kdbx` files, the format used by KeePass and KeePassXC, and either creates a new vault or works on one you already have. What varies is where the client runs.

The hosted web app at app.keeweb.info is the hosted demo, and beta.keeweb.info runs the beta channel. The desktop build comes from the GitHub releases and supports Linux, Windows and macOS. And the self-hosted route is the one that distinguishes the project: KeeWeb itself is a single HTML file combined with a service worker, which is optionally there for offline access. You can download the distribution files straight from the repository's `gh-pages` branch as a zip archive.

That last point deserves emphasis, because it is unusual. There is no server component to write and no database to provision. What you host is static files, so anything that serves an HTML file can serve KeeWeb, and the service worker is what makes it work with no network connection once it has been loaded.

Where the vault lives is your decision as well. The README lays out the options: a local file, or one of Dropbox, Google Drive or Microsoft OneDrive. The earlier v1.18.7 release notes show how actively that area is developed, adding Microsoft Teams as a storage provider and the option to override the tenant in OneDrive.

## Self-hosting with Docker

Pre-built images are published to both Docker Hub and GitHub Container Registry, and the tag set covers versioned, architecture-specific and development builds. For a single container, the README gives this directly.

```shell
docker run -d --restart=unless-stopped -p 443:443 --name keeweb -v ${PWD}/keeweb:/config ghcr.io/keeweb/keeweb:latest
```

The shape of that command is the deployment. Port 443 is published because the app is expected to sit behind TLS, the container restarts unless you stop it, and the single volume mount at `/config` is where the state lives. If you self-host this, that volume is the thing you back up.

The compose file adds three environment variables that matter for a containerised deployment.

```yml
services:
    keeweb:
        container_name: keeweb
        image: ghcr.io/keeweb/keeweb:latest       # Github image
      # image: keeweb/keeweb:latest               # Dockerhub image
        restart: unless-stopped
        volumes:
            - ./keeweb:/config
        environment:
            - PUID=1000
            - PGID=1000
            - TZ=Etc/UTC
```

`PUID` and `PGID` set the user and group the process runs as, which determines whether the files it writes into `/config` are readable by the host account that owns the directory. `TZ` sets the container's timezone. Set them to match your host and you avoid the ownership problems that come with writing into a bind mount as root.

The README also documents an optional Traefik integration with label-based discovery and both dynamic and static configuration, including an entry point variant for Cloudflare users, and an Authentik integration for putting the app behind an authentication provider. Both are marked optional, which is the right framing: the container works alone, and the reverse-proxy sections are for people who already run those stacks.

## What the dependency list says about the security posture

The manifest lists `argon2-browser` at 1.15.4, which is the key derivation KeePass databases use and the single most important dependency in the list. Key stretching is what makes a stolen vault expensive, and having a dedicated, pinned implementation rather than a home-grown one is the correct call for a password manager.

`dompurify` handles HTML sanitisation, which matters in an application that renders user-controlled content such as notes and custom fields. Also present are `electron-notarize` and `electron-osx-sign`, so the macOS build is signed and notarised rather than shipping as an unsigned binary.

Two dependencies come as tarballs fetched from GitHub releases rather than from the registry: `@keeweb/keeweb-native-messaging-host` at 0.3.5 and `@keeweb/keeweb-native-modules` at 0.11.6. These are the pieces that let the desktop build talk to the outside, and pinning them to a release asset means a build cannot silently pull a newer version of a security-relevant component. The host package is the bridge for browser integration; the native modules package is the bridge for hardware access. Treat both as part of the trust surface.

One entry deserves a second look: `electron-evil-feature-patcher`. The name is blunt, and its purpose is to re-enable renderer features Electron disabled for security reasons, which a password manager with a web UI needs in order to function. That is a deliberate trade and a good example of a dependency you should understand rather than accept on sight.

## The Electron version and the release gap

The manifest pins `electron` at `^13.6.9`, which resolves within the 13 line. Electron 13 is a long way behind current releases, and for an application that handles decrypted credentials in a renderer process, the gap between your Electron version and the security patches published since is the first thing to weigh. The caret means a fresh install resolves to the newest 13.x available, not to anything newer, so updating means changing this line deliberately.

The rest of the toolchain is older in a consistent way: Babel 7 with a `preset-env`, Grunt as the build entry point, ESLint 7 with the `standard` config, and webpack-era loaders including `babel-loader`, `css-loader` and `base64-loader`. There is also `mise.toml` and `.nvmrc` in the tree, which suggests the toolchain versions are pinned on disk, and `electron-builder` handles packaging. This is a conventional pre-Babel-to-Vite front-end stack that has been maintained rather than rewritten.

The release history has a gap worth naming rather than smoothing over. v1.18.9 was published 2026-05-08 and contains a single change, a release preparation pull request. v1.18.8 came nine days earlier on 2026-04-30 and is substantive: a CI fix for Puppeteer arguments, a verify workflow, legacy support for `npm run dev`, and the Electron 13 bump itself. Before that, v1.18.7 dates from 2021-07-18 and its notes list feature changes such as Microsoft Teams storage, OneDrive tenant override, disabling automatic installation of KeePassXC-Browser, and a fix for a visible crash on socket write error.

Read together, that says a long-dormant project resumed in 2026 rather than a project that never stops. The maintainers are active now, the last push to the default branch was 2026-05-08, and the project carries 12,996 stars, 1,158 forks and 441 open issues, an issue backlog consistent with a large installed base returning to a repository that had gone quiet. The default branch is still named `master`, and there is a `SECURITY.md` and a `DEPS-LICENSE` file in the tree.

## Conclusion

KeeWeb's idea is narrow and worth stating plainly: take the KeePass file format seriously enough that you can bring your own vault, then give people three ways to run it, in the browser, as a desktop application, or on a server they control. The single-file self-hosting story is the part most password managers cannot offer at all, and the Docker images with PUID, PGID, TZ and a config volume make it a five-minute job rather than a weekend.

Two things to weigh before you adopt it. The Electron dependency sits at 13, which is well behind current releases, and the recent release history has a shape you should notice rather than gloss over: v1.18.7 dates from 2021 and v1.18.8 from 2026, so the project came back to life after a long quiet stretch. That is good news for the code and a reason to read issues before committing. The licence file is present in the repository, though GitHub's licence detection returns nothing for it, so read the file rather than the badge. If your requirement is an offline-capable web app that reads an existing kdbx vault and syncs it through Dropbox, Drive or OneDrive, this fits. If it is a bleeding-edge passkey manager, it is not where to start.

## FAQ

### How do I open a .kdbx file?

Open it in KeeWeb. The application exists to work with `kdbx` files created by other applications such as KeePass and KeePassXC, so you point it at an existing vault rather than importing and converting. After opening, the file is stored wherever you choose: a local file, Dropbox, Google Drive or Microsoft OneDrive.

### Can I self-host KeeWeb?

Yes, and the deployment is small. KeeWeb is a single HTML file plus an optional service worker for offline access, downloadable from the repository's gh-pages branch. Pre-built Docker images exist on Docker Hub and GitHub Container Registry, and the compose file needs only a config volume and three variables: PUID, PGID and TZ.

### What are the Docker environment variables for?

`PUID` and `PGID` set the user and group the container runs as, which decides whether files written into the `/config` bind mount are readable by the host account that owns the directory. `TZ` sets the container timezone. Matching them to your host avoids ownership problems with bind-mounted volumes.

### Is KeeWeb still maintained?

Yes, though the history has a gap worth knowing about. Releases v1.18.8 and v1.18.9 came in April and May 2026, including an Electron bump and a new CI verify workflow, after v1.18.7 which dates from July 2021. The default branch was last pushed 2026-05-08, and the repository carries 441 open issues.

### Why should I care about the Electron version?

Because the manifest pins `electron` at `^13.6.9`, so installs resolve within the 13 line rather than tracking current releases. For an application that handles decrypted credentials in a renderer process, how far behind your embedded Chromium is matters. Moving to a newer Electron means changing that line deliberately and testing the build, not waiting for an update.

## Sources

- [Issues](https://github.com/keeweb/keeweb/issues)
- [keeweb/keeweb on GitHub](https://github.com/keeweb/keeweb)
- [Project website](https://keeweb.info)
- [README](https://github.com/keeweb/keeweb/blob/master/README.md)
- [Releases](https://github.com/keeweb/keeweb/releases)

---

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