Instalacja serwera Vaultwarden bez użycia Dockera - Michał Sternadel Instalacja serwera Vaultwarden bez użycia Dockera

Światło: Zapal | Zgaś

Instalacja serwera Vaultwarden bez użycia Dockera

Dodano: 24.01.2026, 11:14:07

Niektórzy z administratorów sceptycznie patrzą na konteneryzację, pomimo faktu, że jest z nami na prawdę bardzo długo. Czasem wynika to z braku wiedzy, czasem z braku możliwości i chęci utrzymywania całego technologicznego zaplecza dla jednego czy też dwóch kontenerów, a czasem - minimalizacji narzutu kolejnych warstw i optymalizacji prędkości działania. W poniższym opisie przedstawię jak zainstalować serwer Vaultwarden bezpośrednio na systemie Linux z pominięciem kompilacji oprogramowania. Plik binarny jak również pliki aplikacji webowej zostaną pobrane i wypakowane z dostępnego obrazu Dockera, udostępnianego publicznie.

Założenia:

  • Urządzenie z systemem Linux, z procesorem o architekturze AMD64 lub ARM64 (Tutaj Raspberry Pi 4 z systemem Debian 13)
  • Baza danych - dowolna, obsługiwana przez Vaultwarden, tutaj będzie to SQLite, ale nic nie stoi na przeszkodzie, aby wcześniej zainstalować sobie MariaDB.
  • Adres usługi to https://vaultwarden.home.arpa:8443
  • Udostępnienie aplikacji Web-Vault
  • Samopodpisany certyfikat x509 w celu uruchomienia Vaultwarden po SSL na porcie 8443
  • Użytkownik, który może tworzyć organizacje: [email protected]
  • Domeny, na które można wykonywać rejestrację użytkowników: localhost, home.arpa

Instalacja paczek potrzebnych do działania

apt-get update && apt-get -y install curl git wget ssl-cert

Utworzenie użytkownika, na którym będzie działała usługa

adduser --system --shell /usr/sbin/nologin --comment "Vaultwarden User" --create-home --home /usr/lib/vaultwarden/ vaultwarden
adduser vaultwarden ssl-cert

Utworzenie katalogu z konfiguracją

mkdir -p /etc/vaultwarden/ && chown vaultwarden:vaultwarden /etc/vaultwarden && chmod 0750 /etc/vaultwarden

Utworzenie katalogu na dane oraz dla plików tymczasowych

mkdir -p /usr/lib/vaultwarden/data/ && chown vaultwarden:vaultwarden /usr/lib/vaultwarden/data && chmod 0750 /usr/lib/vaultwarden/data
mkdir -p /usr/lib/vaultwarden/data/tmp && chown vaultwarden:vaultwarden /usr/lib/vaultwarden/data/tmp && chmod 0750 /usr/lib/vaultwarden/data/tmp

Utworzenie katalogu dla logów

mkdir -p /var/log/vaultwarden && chown vaultwarden:vaultwarden /var/log/vaultwarden && chmod 0751 /var/log/vaultwarden

Konfiguracja rotacji logów

cat < /etc/logrotate/vaultwarden
/var/log/vaultwarden/vaultwarden.log {
        su vaultwarden vaultwarden
        rotate 60
        daily
        missingok
        copytruncate
        notifempty
        compress
        sharedscripts
        postrotate
                invoke-rc.d rsyslog rotate >/dev/null 2>&1 || true
        endscript
}
EOF

Wypakowanie plików z obrazu Dockera

W celu wypakowania plików niezbędnych do uruchomienia usługi można ręcznie pobrać każdą z warstw dostępnych w manifeście dla obrazu vaultwarden/server lub też skorzystać z przygotowanego skryptu powłoki (instalujac uprzednio jq apt-get install jq -y):

#!/usr/bin/env bash
DEST_WEB="/usr/lib/vaultwarden"
DEST_BIN="/usr/bin"
VAULTWARDEN_USER="vaultwarden"
VAULTWARDEN_GROUP="vaultwarden"
IMAGE="vaultwarden/server"
TAG="latest"
case "$(uname -m)" in
  x86_64)  ARCH="amd64" ;;
  aarch64) ARCH="arm64" ;;
  *) echo "Unsupported architecture, exiting..."; exit 1 ;;
esac
TARGET_DIR="web-vault"
TARGET_BIN="vaultwarden"

mkdir -p "$DEST_WEB"

echo "[*] Getting registry token..."
TOKEN=$(curl -s \
  "https://auth.docker.io/token?service=registry.docker.io&scope=repository:${IMAGE}:pull" \
  | jq -r '.token')

echo "[*] Fetching manifest list..."
MANIFEST_LIST=$(curl -s \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
  "https://registry-1.docker.io/v2/${IMAGE}/manifests/${TAG}")

echo "[*] Selecting manifest for $ARCH..."
MANIFEST_DIGEST=$(echo "$MANIFEST_LIST" \
  | jq -r ".manifests[] | select(.platform.architecture == \"$ARCH\") | .digest")

if [[ -z "$MANIFEST_DIGEST" ]]; then
    echo "Error: no manifest for architecture '$ARCH'"
    exit 1
fi

echo "[*] Using manifest: $MANIFEST_DIGEST"

echo "[*] Fetching image manifest..."
MANIFEST=$(curl -s \
  -H "Authorization: Bearer ${TOKEN}" \
  -H "Accept: application/vnd.docker.distribution.manifest.v2+json" \
  "https://registry-1.docker.io/v2/${IMAGE}/manifests/${MANIFEST_DIGEST}")

echo "[*] Downloading layers..."
rm -f layer_*.tar
i=0
for DIGEST in $(echo "$MANIFEST" | jq -r '.layers[].digest'); do
  i=$((i+1))
  FILE="layer_${i}.tar"
  echo "    - downloading $FILE ($DIGEST)"
  curl -s -L \
    -H "Authorization: Bearer ${TOKEN}" \
    "https://registry-1.docker.io/v2/${IMAGE}/blobs/${DIGEST}" \
    -o "$FILE"
done

echo "[*] Searching for '$TARGET_DIR' and '$TARGET_BIN' in layers..."
FOUND_DIR=0
FOUND_BIN=

for LAYER in layer_*.tar; do
    if [[ "$FOUND_DIR" -eq 0 ]]; then
        if tar -tf "$LAYER" | grep "${TARGET_DIR}/index.html"; then
            echo "[*] Found '$TARGET_DIR' in $LAYER — extracting to $DEST_WEB"
            tar -xf "$LAYER" -C "$DEST_WEB" "$TARGET_DIR"
            FOUND_DIR=1
        fi
    fi
    if [[ "$FOUND_BIN" -eq 0 ]]; then
        if tar -tf "$LAYER" | grep "${TARGET_BIN}"; then
            echo "[*] Found '$TARGET_BIN' in $LAYER — extracting to $DEST_BIN"
            tar -xf "$LAYER" -C "$DEST_BIN" "$TARGET_BIN"
            FOUND_BIN=1
        fi
    fi
    if [[ "$FOUND_DIR" -eq 1 && "$FOUND_BIN" -eq 1 ]]; then
        break
    fi
done

rm -f layer_*.tar

if [[ "$FOUND_DIR" -eq 0 || "$FOUND_BIN" -eq 0 ]]; then
    echo "Error: Could not find one or both targets ('$TARGET_DIR' and '$TARGET_BIN') in the image layers."
    exit 1
fi
echo "[*] Change permissions..."
chown $VAULTWARDEN_USER:$VAULTWARDEN_GROUP $DEST_WEB/$TARGET_DIR -R
chown $VAULTWARDEN_USER:$VAULTWARDEN_GROUP $DEST_BIN/$TARGET_BIN
echo "[+] Done!"
echo "→ Extracted files are in: $DEST_WEB and $DEST_BIN"
echo "  - Web Vault: $DEST_WEB/$TARGET_DIR"
echo "  - Binary: $DEST_BIN/$TARGET_BIN"
Po zapisaniu skryptu pod nazwą "/root/dedocker-vaultwarden.sh" oraz po włączeniu bitu wykonywania i  uruchomieniu go, na konsoli powinny pojawić się stosowne komunikaty:
# ./dedocker-vaultwarden.sh 
[*] Getting registry token...
[*] Fetching manifest list...
[*] Selecting manifest for arm64...
[*] Using manifest: sha256:a24a108a90f6380a8f990308831025b038ee8df5d5be7f4c04922441ac7d6ff0
[*] Fetching image manifest...
[*] Downloading layers...
    - downloading layer_1.tar (sha256:2ae15a20160209c6fd6cff4886e4ba2e666fa5bedd7b54a2c0097ea6646f0273)
    - downloading layer_2.tar (sha256:45431c76674b0df695a222114e087abf9d53d313517bc2b072f06913e8c89dcd)
    - downloading layer_3.tar (sha256:7c614f5e5b12d769ab1c7209670d560dfa11dad61b1b47e205d239ba64a8b0e6)
    - downloading layer_4.tar (sha256:6043b4e5998fa5bb92ed2956636c3718d33dea6c277cdd7510d2f6814db914a7)
    - downloading layer_5.tar (sha256:389eb04f03834ad4fa7d5b2fa18ae377990943fffd16b96397bfae35dfa6a6ba)
[*] Searching for 'web-vault' and 'vaultwarden' in layers...
web-vault/index.html
[*] Found 'web-vault' in layer_4.tar — extracting to /usr/lib/vaultwarden
vaultwarden
[*] Found 'vaultwarden' in layer_5.tar — extracting to /usr/bin
[*] Change permissions...
[+] Done!
→ Extracted files are in: /usr/lib/vaultwarden nad /usr/bin
  - Web Vault: /usr/lib/vaultwarden/web-vault
  - Binary: /usr/bin/vaultwarden
W katalogu /usr/bin/ powinien pojawić się plik vaultwarden, a w katalogu /usr/lib/vaultwarden/ katalog web-vault/. Sprawdźmy, czy program działa poprawnie:
cd /usr/lib/vaultwarden
/usr/bin/vaultwarden --version
Vaultwarden 1.35.2
Web-Vault 2025.12.1+build.3

Następnie możemy przystąpić do generowania certyfikatu SSL oraz konfiguracji usługi.

Generowanie klucza oraz certyfikatu

apt-get install -y openssl
openssl genrsa -out /etc/ssl/private/self-vaultwarden.home.arpa.key 4096
chgrp ssl-cert /etc/ssl/private/self-vaultwarden.home.arpa.key
chmod 0640 /etc/ssl/private/self-vaultwarden.home.arpa.key
openssl req -x509 -new \
  -key /etc/ssl/private/self-vaultwarden.home.arpa.key \
  -sha256 \
  -days 825 \
  -out /etc/ssl/certs/self-vaultwarden.home.arpa.crt \
  -subj "/CN=vaultwarden.home.arpa" \
  -addext "subjectAltName=DNS:vaultwarden.home.arpa"
chgrp ssl-cert /etc/ssl/certs/self-vaultwarden.home.arpa.crt 
chmod 0644 /etc/ssl/certs/self-vaultwarden.home.arpa.crt 

Vaultwarden wymaga klucza rsa do podpisywania tokenów, zaproszeń dla użytkowników czy też danych w bazie danych. Należy zatem wygenerować go:

openssl genrsa -out /etc/vaultwarden/rsa_key.pem 4096
chown vaultwarden:vaultwarden /etc/vaultwarden/rsa_key.pem
chmod 0600 /etc/vaultwarden/rsa_key.pem

Skonfigurujmy teraz Vaultwarden, według założeń:

cat <> /etc/vaultwarden/vaultwarden.conf
DATA_FOLDER=/usr/lib/vaultwarden/data
RSA_KEY_FILENAME=/etc/vaultwarden/rsa_key
WEB_VAULT_FOLDER=/usr/lib/vaultwarden/web-vault/
WEB_VAULT_ENABLED=true
DATABASE_URL=/usr/lib/vaultwarden/data/db.sqlite3
WEBSOCKET_ENABLED=false
WEBSOCKET_ADDRESS=0.0.0.0
WEBSOCKET_PORT=3012
PUSH_ENABLED=False
PUSH_INSTALLATION_ID=CHANGEME
PUSH_INSTALLATION_KEY=CHANGEME
DOMAIN=https://vaultwarden.home.arpa:8443
SENDS_ALLOWED=False
SIGNUPS_ALLOWED=True
SIGNUPS_VERIFY=False
SIGNUPS_DOMAINS_WHITELIST=localhost,home.arpa
[email protected]
INVITATIONS_ALLOWED=False
INVITATION_ORG_NAME=Snakeoil
EMAIL_CHANGE_ALLOWED=False
LOF_FILE=/var/log/vaultwarden/vaultwarden.log
LOG_LEVEL=error
ROCKET_ADDRESS=0.0.0.0
ROCKET_PORT=8443
ROCKET_TLS={certs="/etc/ssl/certs/self-vaultwarden.home.arpa.crt",key="/etc/ssl/private/self-vaultwarden.home.arpa.key"}
EOF
chown vaultwarden:vaultwarden /etc/vaultwarden/vaultwarden.conf
chmod 0640 /etc/vaultwarden/vaultwarden.conf

Pozostała tylko instalacja usługi oraz jej uruchomienie. W tym celu należy utworzyć jednostkę systemd w /etc/systemd/system/vaultwarden.service:

cat <> /etc/systemd/system/vaultwarden.service
[Unit]
Description=Vaultwarden server
After=network.target auditd.service

[Service]
RestartSec=5s
Type=simple
User=vaultwarden
Group=vaultwarden
EnvironmentFile=/etc/vaultwarden/vaultwarden.conf
WorkingDirectory=/usr/lib/vaultwarden
ExecStart=/usr/bin/vaultwarden
Restart=always
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
NoNewPrivileges=true
ProtectSystem=strict
ReadOnlyPaths=/usr/lib/vaultwarden/web-vault/ /etc/vaultwarden
ReadWritePaths=/usr/lib/vaultwarden/data/ /var/log/vaultwarden/
LimitNOFILE=1048576
LimitNPROC=64

[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now vaultwarden.service

Sprawdzenie poprawności działania usługi

# ss -plnat |grep 8443
LISTEN 0      4096         0.0.0.0:8443       0.0.0.0:*     users:(("vaultwarden",pid=3147,fd=24))  

# systemctl status vaultvarden.service
● vaultwarden.service - Vaultwarden server
     Loaded: loaded (/etc/systemd/system/vaultwarden.service; enabled; preset: enabled)
     Active: active (running) since Sat 2026-01-24 10:50:33 CET; 1min 21s ago
 Invocation: ba3204b2476940c9b3d82cbbf64d2e35
   Main PID: 3147 (vaultwarden)
      Tasks: 13 (limit: 8749)
        CPU: 195ms
     CGroup: /system.slice/vaultwarden.service
             └─3147 /usr/bin/vaultwarden

Jan 24 10:50:33 r4pie vaultwarden[3147]: | This is an *unofficial* Bitwarden implementation, DO NOT use the   |
Jan 24 10:50:33 r4pie vaultwarden[3147]: | official channels to report bugs/features, regardless of client.   |
Jan 24 10:50:33 r4pie vaultwarden[3147]: | Send usage/configuration questions or feature requests to:         |
Jan 24 10:50:33 r4pie vaultwarden[3147]: |   https://github.com/dani-garcia/vaultwarden/discussions or        |
Jan 24 10:50:33 r4pie vaultwarden[3147]: |   https://vaultwarden.discourse.group/                             |
Jan 24 10:50:33 r4pie vaultwarden[3147]: | Report suspected bugs/issues in the software itself at:            |
Jan 24 10:50:33 r4pie vaultwarden[3147]: |   https://github.com/dani-garcia/vaultwarden/issues/new            |
Jan 24 10:50:33 r4pie vaultwarden[3147]: \--------------------------------------------------------------------/

Można już z powodzeniem utworzyć konta użytkowników i korzystać do woli. Podobny efekt, z tym, że automatycznie, można uzyskać wykonując polecenia:

sudo apt-get install -y ansible git
cat < /tmp/localhost_vars.yml
linux_vaultwarden_domain: vaultwarden.home.arpa
linux_vaultwarden_signups_domains_whitelist:
  - localhost
  - home.arpa
linux_vaultwarden_org_creation_users:
  - [email protected]
EOF
ansible-pull \
  -U https://github.com/michalsternadel/linux_vaultwarden.git \
  -e @/tmp/localhost_vars.yml \
  local.yml

Zalecam skonfigurować Vaultwarden tak, aby słuchał jedynie na hoście lokalnym oraz wykorzystać reverse-proxy do udostępniania usługi z odpowiadnią terminacją SSL. Przy dużych wdrożeniach również rozsądniej byłoby zamiast SQLite użyć silnika MariaDB.


Dodaj komentarz

Szybki kontakt:

Pozostaw zółtą karteczkę-wlepkę pod adresem:
Kraków, ul. Pawia 3 z id: #776AFFDA# oraz wiadomością. Jak nie zginie -- odczytam.

Ostatnie fotografie


Paproć
Paproć

Grzyb
Grzyb

  Więcej...