The Way to Your Own Cloud (Part 10) – The own password safe Vaultwarden

Passwords are the key to our digital lives – and often the biggest weak point.

If you store them unencrypted in your browser or with large cloud providers, you risk losing control over them entirely.

Vaultwarden is a lightweight, resource-efficient open-source alternative to Bitwarden.

It runs entirely on your own server, stores all data encrypted, and offers apps for desktop, browser, and smartphone.

Setup

First, create a working directory for Vaultwarden:

sudo mkdir -p /opt/vaultwarden

cd /opt/vaultwarden

Vaultwarden uses SQLite as its default database.

Now create the file /opt/vaultwarden/docker-compose.yaml with the following content (adjust domain and port as needed):

services:
  vaultwarden:
    image: localhost:5000/vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=false    # No open registrations
      - ADMIN_TOKEN=<VERY-STRONG-TOKEN>     # For the admin panel
      - DOMAIN=https://<CLOUD-DOMAIN>:<RANDOM-PORT>
      - WEB_VAULT_ENABLED=true    # best is to set this to "false" after setup
    volumes:
      - ./data:/data
    ports:
      - "8989:80"

Pull the Docker image from the official hub into your local registry:

docker pull vaultwarden/server:latest

docker tag vaultwarden/server:latest localhost:5000/vaultwarden/server:latest

docker push localhost:5000/vaultwarden/server:latest

Then start Vaultwarden:

docker compose up -d

To securely access it from the outside, choose a free port:

echo $(shuf -i 1024-65535 -n 1)

Then create the NGINX configuration file /etc/nginx/sites-available/vaultwarden:

server {
    listen <RANDOM-PORT> ssl;
    server_name <CLOUD-DOMAIN>;

    ssl_certificate /etc/letsencrypt/live/<CLOUD-DOMAIN>/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/<CLOUD-DOMAIN>/privkey.pem;

    client_max_body_size 128M;

    location / {
        proxy_pass http://localhost:8989;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /notifications/hub {
        proxy_pass http://localhost:8989;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/

sudo systemctl restart nginx

Open the firewall for the selected port:

sudo ufw allow <RANDOM-PORT>

sudo ufw reload

You can now use the admin token to access the administration interface:

https://<CLOUD-DOMAIN>:<RANDOM-PORT>/admin

Apps

Vaultwarden does not develop its own apps but is 100% compatible with the official Bitwarden clients.

You can find them at: https://kloubi-l.ink/download-bitwarden

Conclusion

With Vaultwarden, you take back full control of your passwords.

Combined with the official apps, you can access them from any device without your credentials ever leaving your own system.

Quick & Dirty

DOMAIN='cloud.example.com'
PORT=$(shuf -i 1024-65535 -n 1)
ADMIN_TOKEN='SET_YOUR_STRONG_TOKEN'

# Create directory
sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwarden

# Create docker-compose.yaml
cat <<EOF > docker-compose.yaml
services:
  vaultwarden:
    image: localhost:5000/vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      - WEBSOCKET_ENABLED=true
      - SIGNUPS_ALLOWED=false
      - ADMIN_TOKEN=$ADMIN_TOKEN
      - DOMAIN=https://$DOMAIN:$PORT
      - WEB_VAULT_ENABLED=true
    volumes:
      - ./data:/data
    ports:
      - "8989:80"
EOF

# Pull image into local registry
docker pull vaultwarden/server:latest
docker tag vaultwarden/server:latest localhost:5000/vaultwarden/server:latest
docker push localhost:5000/vaultwarden/server:latest

# Start service
docker compose up -d

# Create NGINX config
sudo tee /etc/nginx/sites-available/vaultwarden >/dev/null <<EONGX
server {
    listen $PORT ssl;
    server_name $DOMAIN;

    ssl_certificate /etc/letsencrypt/live/$DOMAIN/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/$DOMAIN/privkey.pem;

    client_max_body_size 128M;

    location / {
        proxy_pass http://localhost:8989;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /notifications/hub {
        proxy_pass http://localhost:8989;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}
EONGX

# Enable & restart NGINX
sudo ln -sf /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/
sudo systemctl restart nginx

# Adjust firewall
sudo ufw allow $PORT
sudo ufw reload

echo "Vaultwarden is running at: https://$DOMAIN:$PORT"