# How to self-host Vaultwarden with Docker Compose

> Deploy Vaultwarden, the lightweight Bitwarden-compatible server, with Docker Compose: HTTPS setup, Argon2 admin token, signups, backups and safe upgrades.

## Key facts

| Fact | Value |
|---|---|
| App | Vaultwarden (https://appsgit.com/apps/vaultwarden) |
| Difficulty | beginner |
| Time | about 15 minutes |
| Requirements | 1 vCPU / 512 MB RAM; Docker + Docker Compose v2; A domain name with HTTPS (required by Bitwarden clients) |
| Last updated | 2026-10-06 |

## What is Vaultwarden?

Vaultwarden is an alternative server for the Bitwarden password manager, written in Rust and designed to run on very small machines. It is open source under the GPL-3.0 license and works with the official Bitwarden browser extensions, desktop apps and mobile apps. It is not affiliated with Bitwarden, Inc.

## Requirements

- Any Linux server: 1 vCPU and 512 MB of RAM is plenty for a family or small team.
- Docker Engine and Docker Compose v2.
- A domain name and HTTPS. The web vault uses browser crypto APIs that only work in a secure context, so plain HTTP does not work except on `localhost`.

## Step 1: Prepare the server

This guide assumes Ubuntu 24.04 with Docker installed. If not, follow the [Docker Engine install guide](https://docs.docker.com/engine/install/ubuntu/). Create a folder:

```bash
mkdir -p ~/vaultwarden && cd ~/vaultwarden
```

Before writing the Compose file, generate a hashed admin token. Vaultwarden supports Argon2 hashes for `ADMIN_TOKEN`, so the plain password is never stored on disk:

```bash
docker run --rm -it vaultwarden/server:latest /vaultwarden hash
```

Enter a strong admin password twice. The command prints a string starting with `$argon2id$`. Keep the password in your password manager. You will type it on the `/admin` page.

## Step 2: Create the Docker Compose file

Save this as `docker-compose.yml`:

```yaml
services:
  vaultwarden:
    image: vaultwarden/server:1.37.4
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      DOMAIN: "https://vault.example.com"
      SIGNUPS_ALLOWED: "true"
      INVITATIONS_ALLOWED: "true"
      SHOW_PASSWORD_HINT: "false"
      ADMIN_TOKEN: "CHANGE_ME"
      LOG_FILE: "/data/vaultwarden.log"
      TZ: "Europe/London"
    volumes:
      - ./vw-data:/data
    ports:
      - "127.0.0.1:8080:80"
```

Replace `CHANGE_ME` with the Argon2 string from Step 1. Docker Compose treats `$` as the start of a variable, so double every dollar sign in the hash (`$argon2id$v=19$...` becomes `$$argon2id$$v=19$$...`). If you prefer to keep it out of the Compose file, put `ADMIN_TOKEN='...'` in a `.env` file with single quotes and reference it as `${ADMIN_TOKEN}`. `DOMAIN` must match the exact public URL, including `https://`, or attachments, WebAuthn and email links will break.

The port is bound to `127.0.0.1` on purpose: Vaultwarden should only be reached through the HTTPS proxy.

## Step 3: Start and open the app

```bash
docker compose up -d
docker compose logs -f vaultwarden
```

Vaultwarden starts in a second or two. Complete Step 4, then open `https://vault.example.com` and click "Create account". This account is a normal user. The admin panel is separate, at `https://vault.example.com/admin`, and uses the admin password you hashed.

Once your own account and your family or team accounts exist, set `SIGNUPS_ALLOWED: "false"` and run `docker compose up -d` again. New users can then join only by invitation from an organization or the admin panel. Configure SMTP in the admin panel so invitations and two-step login emails work.

## Step 4: Put it behind HTTPS

With [Caddy](https://caddyserver.com/docs/) on the host:

```caddyfile
vault.example.com {
    encode zstd gzip
    reverse_proxy 127.0.0.1:8080 {
        header_up X-Real-IP {remote_host}
    }
}
```

Caddy obtains the certificate automatically. Since version 1.29, Vaultwarden serves WebSocket notifications on the same port, so no extra route for port 3012 is needed. With Nginx Proxy Manager, point a proxy host at port 8080, request a Let's Encrypt certificate, and enable "Websockets Support".

## Backups and upgrades

Everything lives in `./vw-data`: the SQLite database `db.sqlite3`, `attachments/`, `sends/`, `config.json` (settings saved from the admin panel) and `rsa_key*` files. For a consistent database copy while the container runs, use the built-in backup command:

```bash
docker compose exec vaultwarden /vaultwarden backup
```

Then copy the whole `vw-data` folder off-site with restic, Borg or rclone, encrypted. Test a restore at least once.

Upgrade with:

```bash
docker compose pull && docker compose up -d
```

If you pinned a version, change the tag first after reading the release notes.

## Troubleshooting

- **Web vault shows a blank page or crypto error:** you are on plain HTTP. Use your HTTPS domain.
- **Admin page says the token is invalid:** the `$` signs in the Argon2 hash were not doubled in the Compose file, so Compose mangled the value. Check with `docker compose config`.
- **Settings in `docker-compose.yml` are ignored:** values saved in the admin panel go into `config.json` and override environment variables. Change them in the panel or delete the key from `config.json`.
- **Mobile app cannot log in:** make sure the self-hosted server URL in the app exactly matches `DOMAIN`.

## Next steps

Enable two-step login for every account, set up an organization for shared passwords, add fail2ban rules against the Vaultwarden log, and schedule automatic encrypted backups.

## FAQ

### What port does Vaultwarden use?

Inside the container Vaultwarden listens on port 80. You normally map it to a local port such as 8080 and put an HTTPS reverse proxy in front, because Bitwarden clients and the web vault require HTTPS.

### Is Vaultwarden free?

Yes. Vaultwarden is free and open source under the GPL-3.0 license, and it unlocks Bitwarden features such as organizations and TOTP storage without a paid plan.

### Is Vaultwarden safe to use?

Vaultwarden stores only end-to-end encrypted vault data, so the server never sees your master password. Your real risk is server hygiene: use HTTPS, disable open signups, hash the admin token and keep backups.

### Vaultwarden vs Bitwarden: what is the difference?

Vaultwarden is an unofficial, community-written server that implements the Bitwarden API in Rust. It uses a fraction of the resources of the official Bitwarden server and works with the official Bitwarden apps and browser extensions.

### How do I hash the Vaultwarden ADMIN_TOKEN?

Run docker run --rm -it vaultwarden/server /vaultwarden hash, enter a password, and paste the resulting Argon2 PHC string into ADMIN_TOKEN. In a Compose file, escape every dollar sign as a double dollar sign.

Prefer not to do it yourself? [appsgit installation help](https://appsgit.com/services/install) installs it on your server for a fixed quote.

---

Canonical page: https://appsgit.com/guides/vaultwarden
Source: appsgit (https://appsgit.com), the app store for github. Data from the GitHub API, refreshed nightly.
Machine access: JSON API https://appsgit.com/api/v1/apps (OpenAPI: https://appsgit.com/openapi.json), MCP server https://mcp.appsgit.com/mcp, full index https://appsgit.com/llms-full.txt.
