آموزش نصب Vaultwarden روی VPS با Docker
راهنمای کامل خودمیزبانی مدیریت رمز عبور Vaultwarden روی سرور مجازی. یاد بگیرید چگونه با Docker و تنظیمات امنیتی شامل HTTPS و Fail2ban، سرویس خود را با 100 مگابایت رم اجرا کنید.
آنچه میسازید
یک مدیریتکننده رمز عبور که مالکیت کامل آن با شماست: Vaultwarden که در یک کانتینر کوچک پشت یک reverse proxy اجرا میشود؛ پروکسیای که HTTPS را مدیریت (terminate) میکند. اپلیکیشنهای رسمی Bitwarden روی گوشی، لپتاپ و مرورگر شما به این سرور متصل میشوند. Vaultwarden پیادهسازی مجدد API سرور Bitwarden با زبان Rust است و از همان پروتکلی استفاده میکند که bitwarden.com به کار میبرد. بنابراین، تمام کلاینتهای رسمی بدون نیاز به تغییر با آن کار میکنند، اما به جای پشته (stack) چند کانتینری رسمی، تنها به حدود 100 MB رم نیاز دارد.
نصب آن در واقع شامل دوازده خط کد در Compose است. سه موردی که واقعاً اهمیت دارند و در صورت عدم رعایت باعث خرابی میشوند، عبارتند از: TLS باید پیش از بارگذاری web vault وجود داشته باشد، ثبتنام عمومی باید بلافاصله پس از ایجاد حساب کاربری خودتان بسته شود، و از volume دادهها باید نسخه پشتیبان تهیه شده و بازیابی آن تست شود؛ زیرا همان یک دایرکتوری، تمام رمزهای عبور شما را در خود جای داده است.
پیشنیازها و نکات مهم
- یک سرور مجازی (VPS) با Docker Engine و افزونه Compose، روی یک سیستمعامل تازه Ubuntu 24.04 KVM با دسترسی root یا sudo. مقدار 512 MB رم واقعاً کافی است؛ 1 GB رم شرایط راحتی را فراهم میکند. این یکی از سبکترین سرویسهایی است که میتوانید اجرا کنید و در صدر فهرست سرویسهای مناسب برای self-hosting قرار دارد. با این حال، منابع سرور را بر اساس سایر سرویسهای همنشین تنظیم کنید: قرار دادن یک کتابخانه عکس self-hosted مانند PhotoPrism یا Immich روی همان VPS، حداقل رم مورد نیاز را به چند گیگابایت افزایش میدهد، در حالی که Vaultwarden تأثیر ناچیزی بر مصرف رم دارد. همین محاسبات برای رابطهای کاربری رسانهای که بعداً اضافه میکنید نیز صادق است، چرا که تبدیل کتابخانه Jellyfin به یک فروشگاه کرایه فیلم دهه 90 به معنای یک کانتینر همیشه روشن دیگر به همراه فضای مورد نیاز برای transcoding در همان بودجه منابع است.
- یک دامنه با رکورد A (و AAAA اگر IPv6 دارید) که
vault.example.comبه VPS اشاره میکند. گواهی TLS برای همین نام دقیق صادر میشود، بنابراین DNS باید پیش از شروع کار، آدرس را به درستی resolve کند. - پورتهای 80 و 443 باید برای اینترنت باز باشند و توسط reverse proxy شما مدیریت شوند؛ هرگز نباید Vaultwarden مستقیماً به این پورتها متصل باشد. پورت 80 فقط برای چالش گواهی ACME و تغییر مسیر (redirect) از HTTP به HTTPS استفاده میشود.
- مهمترین نکته از همان ابتدا: کلاینتهای Bitwarden از برقراری ارتباط با سروری که HTTPS نیست، خودداری میکنند. هیچ گزینهای برای "ابتدا تست با http" وجود ندارد؛ این مسیر به دلیلی که در ادامه توضیح داده میشود، کار نمیکند.
چرا Vaultwarden و نه پشته رسمی Bitwarden
کلاینتهای یکسان، با کسری از وزن. نسخه رسمی و self-hosted نرمافزار Bitwarden بهصورت مجموعهای از کانتینرها (شامل MSSQL، Nginx، Identity، Api، Admin و موارد دیگر) عرضه میشود و به حدود 2 GB رم نیاز دارد. در مقابل، Vaultwarden یک فایل اجرایی واحد است که بهصورت پیشفرض دادهها را در یک دیتابیس SQLite ذخیره میکند و در حالت idle تنها چند ده مگابایت رم مصرف میکند. برای یک نفر، یک خانواده یا یک تیم کوچک، این انتخاب منطقی است؛ همچنین به دلیل پیادهسازی دقیق API نرمافزار Bitwarden، دادههای شما بین این سرویس و bitwarden.com کاملاً قابل انتقال (portable) باقی میمانند.
آنچه در این مسیر از دست میدهید، بخش بزرگی از قابلیتهای سازمانی (enterprise) است: خبری از SCIM provisioning نیست (هرچند قابلیت آزمایشی OpenID Connect SSO از نسخه 1.35.0 اضافه شده است) و از آنجا که شما مسئول عملیات هستید، وظیفه بهروزرسانی (patching)، مدیریت HTTPS و تهیه نسخه پشتیبان بر عهده خودتان است. این راهنما دقیقاً به همین سه وظیفه میپردازد.
چرا HTTPS اختیاری نیست
وبولت Bitwarden و افزونههای مرورگر، کلیدهای رمزنگاری شما را در مرورگر با استفاده از Web Crypto API (window.crypto.subtle) مشتق میکنند. مرورگرها crypto.subtle را فقط در یک بستر امن، یعنی HTTPS یا حالت خاص http://localhost، در دسترس قرار میدهند. روی http://vault.example.com ساده، این قابلیت undefined است؛ بنابراین به محض اینکه برنامه بخواهد کلیدی را مشتق کند، با خطا مواجه میشود و کنسول پیام زیر را نمایش میدهد:
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')صفحه متوقف میشود یا یک خطای عمومی رمزنگاری نشان میدهد و هیچ ورود به سیستمی انجام نمیشود. کلاینتهای دسکتاپ، موبایل و مرورگر، بررسیهای خود را روی URL میزبانیشده توسط کاربر انجام میدهند و در برابر یک endpoint با پروتکل http (یا غیرقابل دسترس)، با پیام زیر از اتصال امتناع میکنند:
This is not a recognized Bitwarden server. You may need to check with your provider or update your server.هر دو مورد دلیل یکسانی دارند: نبود HTTPS معتبر. بنابراین ما ابتدا TLS را راهاندازی میکنیم و هرگز ولت را روی http باز نمیکنیم، حتی برای یک نگاه سریع.
گام 1، DNS و reverse proxy (ابتدا TLS)
رکورد را به سمت VPS خود هدایت کنید و مطمئن شوید که به آدرس صحیح resolve میشود:
dig +short vault.example.comخروجی این دستور باید IP سرور VPS شما باشد. اگر خروجی خالی است یا آدرس اشتباهی را نشان میدهد، تنظیمات DNS را اصلاح کنید و منتظر بمانید تا TTL منقضی شود؛ صدور گواهی برای دامنهای که resolve نمیشود، با شکست مواجه خواهد شد.
برای بخش HTTPS front end، این راهنما از Traefik استفاده میکند که گواهیهای Let's Encrypt را بهطور خودکار صادر و تمدید کرده و مستقیماً در Compose جای میگیرد. اگر هنوز آن را اجرا نکردهاید، ابتدا راهنمای راهاندازی Traefik reverse proxy و TLS خودکار را دنبال کنید؛ این کار یک شبکه Docker خارجی (proxy در ادامه) و یک ACME resolver (letsencrypt) ایجاد میکند که سرویس Vaultwarden به آن متصل میشود. استفاده از nginx ساده با گواهی دستی نیز از سمت Vaultwarden دقیقاً به همین شکل عمل میکند.
آیا nginx و Certbot را به Traefik ترجیح میدهید؟ Vaultwarden را روی 127.0.0.1:8080 قرار دهید (ports: ["127.0.0.1:8080:80"] را به سرویس اضافه کرده و برچسبهای Traefik را حذف کنید)، سپس یک گواهی صادر کرده و آن را proxy کنید. بخش مربوط به گواهی در صدور گواهیهای Let's Encrypt با Certbot و nginx پوشش داده شده است. نکته حیاتی اضافی، ارتقای WebSocket در مسیر notifications است:
server {
listen 443 ssl;
server_name vault.example.com;
client_max_body_size 525M;
location / {
proxy_pass http://127.0.0.1:8080;
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;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}به خط X-Real-IP توجه کنید؛ این همان چیزی است که به Fail2ban اجازه میدهد بعداً مهاجم واقعی را به جای 127.0.0.1 مشاهده کند. تمام موارد دیگر در این راهنما، فارغ از اینکه Traefik یا nginx در مقابل قرار گرفته باشد، یکسان است.
گام 2، فایل Compose
ابتدا دایرکتوری پروژه را ایجاد کنید. این راهنما از /opt/vaultwarden استفاده میکند که باعث میشود نام پروژه Compose و در نتیجه volume دادهها یعنی vaultwarden_vw-data، قابل پیشبینی باشد؛ مراحل Fail2ban و پشتیبانگیری در ادامه، به همین نام دقیق وابسته هستند.
sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwardenیک .env برای secret مدیریت و فایل Compose در آن دایرکتوری ایجاد کنید.
# .env
ADMIN_TOKEN=paste-a-strong-token-hereآن توکن را با openssl rand -base64 48 تولید کرده و در فایل قرار دهید. (یک فرم هششده قویتر در مرحله بعد بررسی میشود؛ یک رشته تصادفی طولانی برای شروع کافی است.)
# docker-compose.yml
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
environment:
DOMAIN: "https://vault.example.com"
SIGNUPS_ALLOWED: "true" # closed in Step 4, keep true just to register
ADMIN_TOKEN: "${ADMIN_TOKEN}"
IP_HEADER: "X-Forwarded-For" # X-Real-IP if your proxy sends that instead
LOG_FILE: "/data/vaultwarden.log"
LOG_LEVEL: "warn"
volumes:
- vw-data:/data
networks:
- proxy
labels:
- "traefik.enable=true"
- "traefik.http.routers.vw.rule=Host(`vault.example.com`)"
- "traefik.http.routers.vw.entrypoints=websecure"
- "traefik.http.routers.vw.tls.certresolver=letsencrypt"
- "traefik.http.services.vw.loadbalancer.server.port=80"
volumes:
vw-data:
networks:
proxy:
external: trueدو نکته در مورد این فایل، کل طراحی را در بر میگیرد. هیچ mapping برای ports: وجود ندارد، بنابراین Vaultwarden فقط از طریق Traefik و TLS آن در دسترس است؛ انتشار پورت آن روی host همان روشی است که باعث میشود کاربران بهطور تصادفی vault را از طریق http ارائه دهند. و DOMAIN باید آدرس کامل و عمومی HTTPS باشد: این مقدار در لینکهای پیوست، WebAuthn 2FA و endpoint اعلانها گنجانده میشود، بنابراین یک مقدار اشتباه یا http باعث از کار افتادن آنها میشود، حتی اگر سایت بارگذاری شود. تگ latest یک استثنای عمدی نسبت به قانون معمولِ هرگز-latest است؛ Vaultwarden نسخههای پایدار خود را به عنوان یک image واحد و در حال تغییر (rolling) عرضه میکند و :testing کانال جداگانه برای نسخههای پیشانتشار (pre-release) است، بنابراین بهصورت آگاهانه بهروزرسانی کنید و پیش از pull کردن، یادداشتهای انتشار را مرور کنید. البته این استثنا محدود است: اکثر کانتینرهای با عمر طولانی بهتر است به یک تگ دقیق متصل (pin) شوند، که همان چیزی است که یک agent همیشه روشن که روی همان VPS میزبانی میشود را در طول rebootها و pullها قابل پیشبینی نگه میدارد.
سرویس را بالا بیاورید و لاگ را مشاهده کنید:
docker compose up -d
docker compose logs -f vaultwardenیک شروع صحیح با خطی مانند Rocket has launched from http://0.0.0.0:80 پایان مییابد. چند ثانیه به Traefik فرصت دهید تا گواهی را دریافت کند، سپس https://vault.example.com را بارگذاری کنید؛ باید web vault مربوط به Bitwarden را با یک قفل معتبر و بدون هشدار گواهی مشاهده کنید.
گام 3، یک ADMIN_TOKEN قوی و تلهی $$
ADMIN_TOKEN از /admin محافظت میکند؛ پنلی که میتواند تمام کاربران و تنظیمات نمونهٔ شما را بخواند، بنابراین با آن مانند رمز عبور root رفتار کنید. دو روش برای این کار وجود دارد.
روش ساده، همان رشتهٔ تصادفی است که قبلاً با openssl rand -base64 48 تولید کردهاید. از آنجا که base64 هرگز شامل $ نمیشود، بدون نیاز به escaping مستقیماً در .env قرار میگیرد.
روش امنتر، استفاده از هش Argon2 PHC است تا متن سادهٔ توکن هرگز روی دیسک ذخیره نشود. یک هش با استفاده از همان image تولید کنید:
docker run --rm -it vaultwarden/server /vaultwarden hash --preset owaspاین دستور دو بار از شما ورودی میگیرد و رشتهای که با $argon2id$v=19$... شروع میشود را چاپ میکند. این همان تلهای است که وقت بسیاری از کاربران را میگیرد: Docker Compose کاراکتر $ را به عنوان متغیر در نظر میگیرد، بنابراین هنگام کپی کردن هش در فایل Compose، باید تمام $ها را به $$ تبدیل کنید. آن را مستقیماً زیر environment: قرار دهید، نه از طریق .env، و آن را داخل کوتیشن قرار ندهید:
environment:
ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$c29tZXNhbHQ$$RdescudvJCsgt3ub+b+dWRWJTmaaJObGاگر علامتهای $ را به صورت تکی باقی بگذارید، Compose هشدار The "argon2id" variable is not set را نمایش داده و توکن را خالی میکند، در نتیجه /admin رمز عبور صحیح شما را رد خواهد کرد. دستور docker compose up -d را اجرا کنید و متن سادهای که در زمان درخواست وارد کردهاید را در مدیریت رمز عبور خود نگه دارید.
گام 4، ثبتنام حساب کاربری و سپس بستن دسترسی
با استفاده از SIGNUPS_ALLOWED: "true"، فایل https://vault.example.com را باز کنید، روی Create account کلیک کنید و با ایمیل و یک رمز عبور اصلی (master password) قوی ثبتنام کنید. این رمز عبور اصلی هرگز قابل بازیابی نیست و امکان بازنشانی (reset) وجود ندارد، بنابراین ابتدا آن را در جای امن و پایداری ذخیره کنید.
اکنون دسترسی را ببندید. فایل Compose را ویرایش کنید تا ثبتنام غیرفعال شود:
SIGNUPS_ALLOWED: "false"تغییرات را با docker compose up -d اعمال کنید. این یک اقدام امنیتی است که نباید به تعویق بیفتد. اگر ثبتنام باز بماند، هر کسی که URL را پیدا کند (و خزندههای وب حتماً آن را پیدا میکنند) میتواند در سرور شما یک حساب کاربری بسازد. آنها نمیتوانند به vault شما دسترسی داشته باشند، اما منابع سرور را مصرف کرده و نمونهٔ خصوصی شما را به یک سرویس عمومی تبدیل میکنند. نشانهٔ باز ماندن ثبتنام این است که /admin حسابهایی را فهرست میکند که شما هرگز ایجاد نکردهاید.
برای افزودن اعضای خانواده یا همکاران در آینده بدون بازگشایی ثبتنام عمومی، از دکمهٔ Invite User در /admin استفاده کنید؛ این مسیر نیازمند پیکربندی SMTP است تا دعوتشونده بتواند لینک خود را دریافت کند.
گام 5، دسترسی به /admin
به https://vault.example.com/admin بروید و توکن مدیریت متنی (رشته تصادفی یا رمز عبوری که هش کردهاید، نه خودِ هش) را وارد کنید. در این بخش میتوانید کاربران را لیست کنید، تنظیمات را تغییر دهید، ایمیل تست بفرستید و از پایگاه داده نسخه پشتیبان تهیه کنید.
اگر صفحه خطای 404 Not Found را برمیگرداند، به این معنی است که ADMIN_TOKEN خالی یا تنظیمنشده است؛ این موضوع پنل را بهطور کامل غیرفعال میکند که اگر نیازی به آن ندارید، انتخاب معتبری است. اگر صفحه بارگذاری میشود اما توکن شما را رد میکند، به تلهٔ escaping در $$ در لیست خطاهای زیر مراجعه کنید. توکن را فراموش کردهاید؟ هیچ گزینه بازیابی وجود ندارد؛ فایل .env یا فایل Compose را ویرایش کنید، یک توکن جدید قرار دهید و docker compose up -d را اجرا کنید.
گام 6، اتصال کلاینتهای Bitwarden
تمام کلاینتهای رسمی میتوانند به یک سرور self-hosted متصل شوند؛ بنابراین کلاینت دسکتاپ، موبایل یا مرورگر Bitwarden را از فروشگاههای استاندارد نصب کنید. شما به هیچ نسخهٔ خاصی از Vaultwarden نیاز ندارید.
پیش از ورود، روی آیکون چرخدنده در صفحهٔ ورود کلیک کنید (که با عنوان Self-hosted یا Region → Self-hosted مشخص شده است)، مقدار Server URL را روی https://vault.example.com تنظیم کرده و ذخیره کنید. سپس با ایمیل و رمز عبور اصلی (master password) که ثبت کردهاید وارد شوید؛ کلاینت باید بلافاصله متصل شده و پیشنهاد پر کردن و ذخیرهٔ اطلاعات کاربری را ارائه دهد.
اگر کلاینت خطای This is not a recognized Bitwarden server. You may need to check with your provider or update your server. را نشان داد، یعنی آدرس URL اشتباه است، از پروتکل http استفاده شده یا گواهی امنیتی معتبر نیست. ابتدا بررسی کنید که https://vault.example.com در مرورگر بدون مشکل بارگذاری میشود. تأخیر در بهروزرسانی سایر دستگاهها مربوط به WebSocket push است که در ادامه به آن پرداخته میشود.
گام 7، ایجاد یک jail در Fail2ban برای endpoint ورود
Vaultwarden تمام تلاشهای ناموفق برای ورود را در فایلی که توسط LOG_FILE تعیین شده ثبت میکند؛ این دقیقاً همان چیزی است که برای مقابله با حملات brute-force نیاز داریم. اگر در حال حاضر از Fail2ban استفاده نمیکنید، مراحل نصب و تنظیمات پایه آن در راهنمای ایمنسازی SSH با Fail2ban آمده است؛ در اینجا یک jail اختصاصی برای vault اضافه میکنیم.
ابتدا مسیر volume نامگذاریشده را روی میزبان پیدا کنید تا Fail2ban بتواند لاگ را بخواند:
docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}'این دستور خروجی مشابه /var/lib/docker/volumes/vaultwarden_vw-data/_data چاپ میکند؛ فایل لاگ در مسیر vaultwarden.log قرار دارد. فیلتر را ایجاد کنید:
# /etc/fail2ban/filter.d/vaultwarden.conf
[Definition]
failregex = ^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =و سپس jail را بسازید:
# /etc/fail2ban/jail.d/vaultwarden.local
[vaultwarden]
enabled = true
filter = vaultwarden
logpath = /var/lib/docker/volumes/vaultwarden_vw-data/_data/vaultwarden.log
banaction = iptables-allports
chain = DOCKER-USER
maxretry = 5
findtime = 600
bantime = 3600با دستور sudo systemctl restart fail2ban تنظیمات را بارگذاری مجدد کرده و با sudo fail2ban-client status vaultwarden وضعیت را بررسی کنید.
سه نکته در Docker تعیین میکند که آیا این محافظت کارآمد است یا خیر. اول، اگر لاگها در هر تلاش ناموفق، آدرس IP: 127.0.0.1 یا آدرس proxy شما را نشان میدهند، یعنی Vaultwarden در حال مسدود کردن proxy است؛ مقدار IP_HEADER را روی هِدری تنظیم کنید که proxy شما واقعاً ارسال میکند (X-Forwarded-For برای Traefik، X-Real-IP برای بلوک nginx در بالا، و CF-Connecting-IP اگر پشت Cloudflare هستید). دوم، زنجیره (chain) مناسب در iptables به proxy شما بستگی دارد: اگر Traefik به عنوان یک container با پورتهای منتشرشده اجرا میشود، ترافیک از مسیر FORWARD در Docker عبور میکند، بنابراین ban باید طبق دستور بالا در DOCKER-USER قرار گیرد؛ اما اگر گزینه host-nginx را از گام 1 انتخاب کردهاید، اتصالات در زنجیره INPUT روی میزبان خاتمه مییابند و ban در DOCKER-USER آنها را نمیبیند؛ در این صورت خط chain = DOCKER-USER را حذف کنید تا Fail2ban از زنجیره پیشفرض INPUT استفاده کند. سوم، به جای پیشفرضِ مبتنی بر پورت، از banaction = iptables-allports استفاده کنید؛ این jail هیچ پورتی را تعریف نمیکند و یک ban برای تمام پورتها در DOCKER-USER، مهاجم را بهطور کامل از تمامی سرویسهای منتشرشده روی سرور مسدود میکند.
گام 8، پشتیبانگیری از vault و سپس بازیابی واقعی آن
volume vw-data همان مدیریت رمز عبور شماست. این volume شامل db.sqlite3 (تمام ورودیها)، دایرکتوریهای attachments/ و sends/، فایلهای rsa_key.* که نشستهای ورود را امضا میکنند و config.json از پنل مدیریت است. پشتیبانی که هر یک از این موارد را نادیده بگیرد، در زمان نیاز کارایی نخواهد داشت.
کپی کردن db.sqlite3 در حالی که Vaultwarden در حال نوشتن است، ممکن است منجر به ثبت یک فایل ناقص و خراب شود؛ بنابراین یک snapshot سرد بگیرید، زمان از دسترس خارج شدن سرویس تنها چند ثانیه است:
#!/usr/bin/env bash
set -euo pipefail
STAMP=$(date +%F)
DEST=/root/vw-backups
VOL=$(docker volume inspect vaultwarden_vw-data --format '{{ .Mountpoint }}')
mkdir -p "$DEST"
docker compose -f /opt/vaultwarden/docker-compose.yml stop vaultwarden
tar czf "$DEST/vw-$STAMP.tgz" -C "$VOL" .
docker compose -f /opt/vaultwarden/docker-compose.yml start vaultwardenاین دستور را هر شب از طریق cron اجرا کنید و .tgz را به خارج از سرور منتقل کنید؛ پشتیبانی که فقط روی همان سروری باشد که از آن محافظت میکنید، پشتیبان محسوب نمیشود. روش تمیز برای انتقال آن یک پشتیبانگیری شبانه با restic به سرور دیگر یا فضای ذخیرهسازی ابری است که آرشیو را رمزنگاری کرده و snapshotهای تکراری را برای شما deduplicate میکند. دکمه Backup Database در پنل مدیریت، یک snapshot سریع و کاربردی فقط از فایل SQLite است، اما فایلهای پیوست و کلیدها را شامل نمیشود.
اکنون مراسمی که یک پشتیبان واقعی را از یک پشتیبان احتمالی متمایز میکند انجام دهید؛ آن را یک بار بازیابی کنید و ثابت کنید که کار میکند:
mkdir -p /tmp/vw-restore
tar xzf /root/vw-backups/vw-2026-07-15.tgz -C /tmp/vw-restore
docker run --rm -p 127.0.0.1:8888:80 -v /tmp/vw-restore:/data vaultwarden/serverاز لپتاپ خود، با استفاده از ssh -L 8888:127.0.0.1:8888 you@your-vps یک تونل به آن بزنید و http://localhost:8888 را باز کنید. از آنجا که localhost یک بستر امن است، crypto.subtle در دسترس بوده و vault در اینجا روی http ساده رمزگشایی میشود؛ این تنها موردی است که چنین اجازهای دارد. با رمز عبور اصلی خود وارد شوید و تأیید کنید که ورودیهای شما موجود هستند: اگر چنین است، دیتابیس، کلیدهای RSA و رمز عبور اصلی شما همگی بهدرستی کار میکنند و میتوانید در عرض چند دقیقه سیستم را روی یک VPS جدید بازسازی کنید. container را با Ctrl-C متوقف کرده و /tmp/vw-restore را حذف کنید. این عادت استفاده از تونل را برای هر رابط کاربری مدیریتی دیگری روی سرور که نباید در معرض اینترنت باشد حفظ کنید؛ این همان روشی است که برای دسترسی به یک اسکنر امنیتی open-kritt خودمیزبان روی پورت 5173 نیز استفاده خواهید کرد.
حالتهای شکست، همراه با پیامهایی که مشاهده خواهید کرد
Cannot read properties of undefined (reading 'importKey') در کنسول مرورگر. والت از طریق http بارگذاری شده است، بنابراین crypto.subtle تعریفنشده است؛ فقط از طریق https:// به آن دسترسی پیدا کنید و تغییر مسیر HTTP به HTTPS را در پروکسی اضافه کنید.
This is not a recognized Bitwarden server... در یک کلاینت. آدرس Server URL از نوع http است، اشتباه تایپ شده یا گواهی مورد اعتماد نیست؛ تأیید کنید که https://vault.example.com یک قفل معتبر نشان میدهد، سپس آن را مجدداً در تنظیمات self-hosted کلاینت وارد کنید.
/admin رمز عبور صحیح را رد میکند. هش Argon2 کاراکترهای escape خود را از دست داده است، هر $ در فایل Compose باید $$ باشد، یا اینکه شما به جای متن اصلی (plaintext)، خودِ هش را وارد کردهاید.
همگامسازی کند بین دستگاهها؛ کنسول WebSocket connection to 'wss://vault.example.com/notifications/hub' failed را نشان میدهد. پروکسی هدرهای Upgrade/Connection را فوروارد نمیکند؛ Traefik این کار را بهصورت خودکار انجام میدهد، اما nginx به دو خط upgrade از مرحله 1 نیاز دارد. والت همچنان کار میکند، فقط همگامسازی هنگام باز کردن برنامه انجام میشود. پورت اختصاصی قدیمی 3012 از نسخه v1.31.0 حذف شده است، بنابراین نیازی به مسیر WebSocket جداگانه نیست.
Fail2ban گزارش مسدودسازی میدهد اما مهاجم همچنان متصل میشود. این ابزار در حال مسدود کردن 127.0.0.1 است زیرا IP_HEADER اشتباه است، یا مسدودسازی در زنجیره iptables اشتباه قرار دارد؛ chain = DOCKER-USER و banaction = iptables-allports را تنظیم کنید.
ارتقا
ایمیج جدید را دریافت کرده و کانتینر را دوباره ایجاد کنید؛ volume نامگذاریشده و تمام دادههای شما باقی میمانند:
docker compose pull
docker compose up -dنرمافزار Vaultwarden نسخههای جدید را بهطور مکرر منتشر میکند. بهجای ثابت نگهداشتن نسخه (pinning)، یادداشتهای انتشار پروژه را دنبال کنید، زیرا برخی نسخهها شامل نکات مربوط به مهاجرت دادهها هستند. پیش از هر ارتقای عمده، یک نسخه پشتیبان جدید تهیه کنید؛ در صورت بروز مشکل، میتوانید با بازگردانی فایل tarball به یک volume جدید، به نسخه قبل بازگردید.
FAQ
آیا Vaultwarden همان Bitwarden است؟
این یک سرور مستقل و سازگار است، نه سرور رسمی. Vaultwarden پیادهسازی مجدد API سرور Bitwarden با زبان Rust است؛ بنابراین تمام کلاینتهای رسمی دسکتاپ، موبایل، مرورگر و CLI با آن کار میکنند، در حالی که منابع بسیار کمتری نسبت به پشتهٔ رسمی مصرف میکند. فرمت vault یکسان است، بنابراین میتوانید با export و import کردن، دادهها را در هر دو جهت جابهجا کنید.
آیا واقعاً به HTTPS نیاز دارم یا میتوانم آن را روی شبکه محلی (LAN) با http اجرا کنم؟
شما برای هر چیزی بهجز یک تست localhost به HTTPS نیاز دارید. وبولت و افزونههای Bitwarden از Web Crypto API مرورگر استفاده میکنند که فقط در بستر امن در دسترس است؛ بنابراین روی http ساده، کلاینت خطای Cannot read properties of undefined میدهد و هرگز وارد نمیشود. تنها آدرس http که کار میکند http://localhost است، به همین دلیل است که تست بازیابی در مرحله 8 از یک تونل SSH استفاده میکند.
چگونه از ثبتنام غریبهها در سرورم جلوگیری کنم؟
بلافاصله پس از ایجاد حساب کاربری خود، مقدار SIGNUPS_ALLOWED: "false" را در فایل Compose تنظیم کرده و دستور docker compose up -d را اجرا کنید. از آن پس، افراد جدید را از طریق دکمه Invite User در /admin اضافه کنید که نیازمند پیکربندی SMTP است تا آنها لینک دعوت را دریافت کنند. گهگاه لیست کاربران مدیر را بررسی کنید تا مطمئن شوید حساب غیرمنتظرهای ایجاد نشده است.
چگونه از vault مربوط به Vaultwarden نسخه پشتیبان تهیه کنم؟
کانتینر را برای مدت کوتاهی متوقف کنید و کل volume مربوط به vw-data، شامل db.sqlite3، attachments/، sends/، config.json و فایلهای rsa_key.* را آرشیو کنید، سپس آرشیو را از سرور خارج کنید؛ ایدهآل این است که این کار را با یک cron شبانه انجام دهید. کپی کردن فایل زنده SQLite در حین اجرای سرور، ریسک خرابی snapshot را به همراه دارد، بنابراین پشتیبانگیری را در حالت سرد (cold) انجام دهید. مهمتر از همه، یک بار آن را در یک کانتینر موقت بازیابی کنید و وارد شوید تا مطمئن شوید پشتیبان واقعی است و پیش از نیاز به آن، از صحت آن اطمینان داشته باشید.
آیا میزبانی شخصی رمزهای عبور واقعاً امن است؟
بله، اگر سه موردی که در این راهنما پوشش داده شده است را انجام دهید: HTTPS واقعی، بستن ثبتنامها به همراه یک توکن مدیریتی قوی، و پشتیبانگیری تستشده. vault شما در سمت کلاینت با رمز عبور اصلی (master password) رمزنگاری میشود، بنابراین حتی سرور هم هرگز رمزهای عبور شما را به صورت متن ساده نمیبیند و یک db.sqlite3 سرقتشده بدون آن رمز عبور بیفایده است. معامله این است که وصلهکردن و پشتیبانگیری اکنون بر عهده شماست، به همین دلیل است که Fail2ban و آیین بازیابی در اینجا اختیاری نیستند. هنگامی که این موارد برقرار شدند، نگاهی دقیقتر به نقاطی که یک vault میزبانیشده میتواند مورد حمله قرار گیرد گام بعدی مفید است، زیرا با رمزنگاری ورودیها در کلاینت، آنچه برای دفاع باقی میماند، توکن مدیریتی و آرشیو پشتیبان است.