SSD Nodes Learn Hosting plans →
নির্দেশিকা Matt Connorদ্বারা Matt Connor

VPS-এ Vaultwarden দিয়ে নিজের পাসওয়ার্ড ম্যানেজার তৈরি

Docker ব্যবহার করে VPS-এ Vaultwarden সেটআপ করার পূর্ণ নির্দেশিকা। HTTPS কনফিগারেশন, ADMIN_TOKEN সেটআপ এবং Fail2ban দিয়ে সার্ভার সুরক্ষিত রাখার নিয়মগুলো এখানে বিস্তারিত দেওয়া হলো।

আপনি যা তৈরি করছেন

আপনার নিজস্ব একটি পাসওয়ার্ড ম্যানেজার: একটি ছোট কন্টেইনারে চলমান Vaultwarden, যা HTTPS টার্মিনেট করে এমন একটি reverse proxy-এর পেছনে থাকবে। আপনার ফোন, ল্যাপটপ এবং ব্রাউজারে থাকা অফিসিয়াল Bitwarden অ্যাপগুলো এই সার্ভারের দিকে নির্দেশ করা থাকবে। Vaultwarden মূলত Rust-এ Bitwarden সার্ভার API-এর একটি পুনঃবাস্তবায়ন এবং এটি bitwarden.com-এর মতোই একই প্রোটোকল ব্যবহার করে। তাই অফিসিয়াল ক্লায়েন্টগুলো কোনো পরিবর্তন ছাড়াই এর সাথে কাজ করে, যদি আপনি সার্ভারটি আপ-টু-ডেট রাখেন (নতুন ক্লায়েন্ট রিলিজের জন্য মাঝে মাঝে Vaultwarden-এর নতুন রিলিজের প্রয়োজন হয়: 2026.8.0 এবং তার পরবর্তী ক্লায়েন্টগুলোর জন্য 1.37.2 সংস্করণটি আবশ্যক)। তবে এটি অফিসিয়াল মাল্টি-কন্টেইনার স্ট্যাকের পরিবর্তে মাত্র 100 MB RAM-এ চলতে সক্ষম।

ইনস্টলেশন প্রক্রিয়াটি মূলত বারো লাইনের একটি Compose ফাইল। যে তিনটি বিষয় সবচেয়ে গুরুত্বপূর্ণ এবং যা প্রায়ই সমস্যা তৈরি করে তা হলো: ওয়েব ভল্ট লোড করার আগেই TLS কনফিগার করতে হবে, আপনার নিজের অ্যাকাউন্ট তৈরি হওয়ার সাথে সাথেই পাবলিক সাইনআপ বন্ধ করতে হবে, এবং ডেটা ভলিউমটির নিয়মিত ব্যাকআপ নিতে হবে ও তা পুনরুদ্ধার করে পরীক্ষা করতে হবে, কারণ ওই একটি ডিরেক্টরিতেই আপনার সমস্ত পাসওয়ার্ড সংরক্ষিত থাকে।

পূর্বশর্ত এবং কিছু গুরুত্বপূর্ণ সতর্কতা

  • একটি নতুন Ubuntu 24.04 KVM সার্ভারে Docker Engine এবং Compose plugin ইনস্টল করা থাকতে হবে, যেখানে আপনার root বা sudo অ্যাক্সেস আছে। 512 MB RAM-ই যথেষ্ট; 1 GB হলে আরও ভালো। এটি অত্যন্ত হালকা একটি সার্ভিস, যা সেলফ-হোস্টিংয়ের যোগ্য সার্ভিসগুলোর তালিকার একদম উপরের দিকে থাকে। তবে সার্ভারে অন্য কী কী চলছে তার ওপর ভিত্তি করে RAM-এর পরিমাণ নির্ধারণ করুন: PhotoPrism বা Immich-এর মতো ফটো লাইব্রেরি একই VPS-এ চালালে RAM-এর চাহিদা কয়েক GB পর্যন্ত বাড়তে পারে, যেখানে Vaultwarden-এর জন্য খুব সামান্যই RAM প্রয়োজন। পরবর্তীতে মিডিয়া ফ্রন্ট-এন্ড যোগ করলেও একই হিসাব প্রযোজ্য, কারণ Jellyfin লাইব্রেরিকে 90-এর দশকের ভিডিও রেন্টাল স্টোরের মতো সাজাতে অতিরিক্ত কন্টেইনার এবং ট্রান্সকোডিংয়ের জন্য বাড়তি রিসোর্সের প্রয়োজন হয়।
  • একটি ডোমেইন যার A record (এবং IPv6 থাকলে AAAA record) vault.example.com সরাসরি আপনার VPS-এর IP-তে পয়েন্ট করা আছে। TLS সার্টিফিকেট এই নির্দিষ্ট নামের জন্যই ইস্যু করা হয়, তাই কাজ শুরু করার আগেই DNS রেজোলিউশন নিশ্চিত করতে হবে।
  • 80 এবং 443 নম্বর পোর্ট ইন্টারনেটের জন্য খোলা থাকতে হবে, যা আপনার reverse proxy দ্বারা টার্মিনেট হবে, সরাসরি Vaultwarden দ্বারা কখনোই নয়। 80 নম্বর পোর্ট শুধুমাত্র ACME সার্টিফিকেট চ্যালেঞ্জ এবং HTTP-to-HTTPS রিডাইরেক্টের জন্য ব্যবহৃত হয়।
  • সবচেয়ে বড় সতর্কতা: Bitwarden ক্লায়েন্টগুলো HTTPS ছাড়া অন্য কোনো সার্ভারের সাথে সংযোগ স্থাপন করে না। এখানে "প্রথমে HTTP দিয়ে পরীক্ষা করে দেখি" এমন কোনো সুযোগ নেই, কারণ পরবর্তী অংশে বর্ণিত সুনির্দিষ্ট কারণে এই পদ্ধতি কাজ করে না।

কেন অফিসিয়াল Bitwarden স্ট্যাকের পরিবর্তে Vaultwarden ব্যবহার করবেন

একই ক্লায়েন্ট, কিন্তু অনেক কম রিসোর্স খরচ। অফিসিয়াল Bitwarden-এর স্ট্যান্ডার্ড সেলফ-হোস্টেড ডেপ্লয়মেন্টে বেশ কয়েকটি কন্টেইনারের (MSSQL Express, Identity, Api, Admin এবং অন্যান্য) একটি বান্ডেল থাকে, যার জন্য কমপক্ষে 2 GB RAM প্রয়োজন। Bitwarden-এর একটি 'Bitwarden lite' সংস্করণও আছে, যা একটি মাত্র Docker ইমেজ এবং কমপক্ষে 200 MB RAM ব্যবহার করে। তবে এটি মূলত ব্যক্তিগত ব্যবহার এবং হোম ল্যাবের জন্য তৈরি, ব্যবসায়িক ব্যবহারের জন্য নয় এবং এতে ডেটাবেস ও ব্যাকআপের সম্পূর্ণ দায়িত্ব আপনার নিজের। Vaultwarden একটি সিঙ্গেল বাইনারি যা ডিফল্টভাবে সবকিছু একটি SQLite ডেটাবেসে জমা রাখে এবং অলস অবস্থায় মাত্র কয়েক ডজন মেগাবাইট RAM খরচ করে। একজন ব্যক্তি, একটি পরিবার বা ছোট দলের জন্য এটিই সবচেয়ে যৌক্তিক পছন্দ। যেহেতু এটি Bitwarden API যথাযথভাবে অনুসরণ করে, তাই আপনার ডেটা Vaultwarden এবং bitwarden.com-এর মধ্যে সহজেই স্থানান্তর করা সম্ভব।

এর বিনিময়ে আপনি এন্টারপ্রাইজ ফিচারের বেশিরভাগই পাবেন না: এতে কোনো SCIM প্রোভিশনিং নেই (যদিও 1.35.0 ভার্সনে OpenID Connect SSO সাপোর্ট যুক্ত হয়েছে)। এছাড়া, যেহেতু আপনি নিজেই অপারেটর, তাই প্যাচিং, HTTPS এবং ব্যাকআপের দায়িত্ব আপনার। এই নির্দেশিকাটি মূলত এই তিনটি কাজের জন্যই তৈরি।

কেন HTTPS ঐচ্ছিক নয়

Bitwarden ওয়েব ভল্ট এবং ব্রাউজার এক্সটেনশনগুলো ব্রাউজারের Web Crypto API (window.crypto.subtle) ব্যবহার করে আপনার এনক্রিপশন কি (encryption keys) তৈরি করে। ব্রাউজারগুলো শুধুমাত্র secure context, HTTPS, অথবা http://localhost ও http://127.0.0.1-এর মতো লুপব্যাক অ্যাড্রেসের বিশেষ ক্ষেত্রে crypto.subtle ব্যবহারের অনুমতি দেয়। সাধারণ http://vault.example.com কানেকশনে এটি undefined, তাই অ্যাপটি কি (key) তৈরি করার সাথে সাথেই ত্রুটি দেখায় এবং কনসোলে নিচের বার্তাটি আসে:

Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'importKey')

পেজটি হ্যাং হয়ে যায় অথবা একটি সাধারণ ক্রিপ্টো এরর দেখায় এবং কোনো কিছুই লগ-ইন হয় না। ডেস্কটপ, মোবাইল এবং ব্রাউজার ক্লায়েন্টগুলো একটি self-hosted URL-এর বিপরীতে নিজস্ব চেক চালায় এবং 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 এবং রিভার্স প্রক্সি (প্রথমে TLS)

আপনার রেকর্ডটি VPS-এর দিকে নির্দেশ করুন এবং নিশ্চিত করুন যে এটি সঠিক ঠিকানায় resolve হচ্ছে:

dig +short vault.example.com

এটি যে লাইনটি প্রিন্ট করবে তা অবশ্যই আপনার VPS IP হতে হবে। যদি এটি খালি থাকে বা ভুল হয়, তবে DNS ঠিক করুন এবং TTL শেষ হওয়া পর্যন্ত অপেক্ষা করুন, কারণ যে নামের বিপরীতে IP resolve হয় না তার জন্য সার্টিফিকেট ইস্যু করা ব্যর্থ হয়।

HTTPS ফ্রন্ট-এন্ডের জন্য এই নির্দেশিকায় Traefik ব্যবহার করা হয়েছে, যা স্বয়ংক্রিয়ভাবে Let's Encrypt সার্টিফিকেট ইস্যু ও রিনিউ করে এবং সরাসরি Compose-এর সাথে কাজ করে। আপনি যদি এটি আগে থেকে ব্যবহার না করে থাকেন, তবে প্রথমে Traefik রিভার্স প্রক্সি এবং স্বয়ংক্রিয় TLS সেটআপ অনুসরণ করুন; এটি একটি এক্সটারনাল Docker নেটওয়ার্ক (নিচে proxy) এবং একটি ACME রিজলভার (letsencrypt) তৈরি করে যার সাথে Vaultwarden সার্ভিস যুক্ত হয়। Vaultwarden-এর দিক থেকে হাতে ইস্যু করা সার্টিফিকেটসহ সাধারণ nginx একইভাবে কাজ করে।

Traefik-এর পরিবর্তে nginx এবং Certbot পছন্দ করেন? Vaultwarden-কে 127.0.0.1:8080-এ রাখুন (সার্ভিসে ports: ["127.0.0.1:8080:80"] যোগ করুন এবং Traefik লেবেলগুলো বাদ দিন), তারপর একটি সার্টিফিকেট ইস্যু করুন এবং সেটির দিকে প্রক্সি করুন। সার্টিফিকেটের অংশটি Certbot এবং nginx দিয়ে Let's Encrypt সার্টিফিকেট ইস্যু করা-তে কভার করা হয়েছে। এখানে গুরুত্বপূর্ণ অতিরিক্ত অংশটি হলো নোটিফিকেশন পাথে WebSocket আপগ্রেড:

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 প্রজেক্টের নাম এবং সেই অনুযায়ী ডেটা ভলিউমের নাম vaultwarden_vw-data নিশ্চিত করে; নিচে উল্লিখিত Fail2ban এবং ব্যাকআপ ধাপগুলো এই নির্দিষ্ট নামের ওপর নির্ভরশীল।

sudo mkdir -p /opt/vaultwarden
cd /opt/vaultwarden

সেই ডিরেক্টরিতে অ্যাডমিন সিক্রেট এবং Compose ফাইলের জন্য একটি .env তৈরি করুন।

# .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

এই ফাইলের দুটি বিষয় পুরো ডিজাইনটিকে নিয়ন্ত্রণ করে। এখানে কোনো ports: ম্যাপিং নেই, তাই Vaultwarden শুধুমাত্র Traefik এবং এর TLS-এর মাধ্যমেই অ্যাক্সেস করা সম্ভব; হোস্ট মেশিনে পোর্ট পাবলিশ করা হলে মানুষ ভুলবশত http-এর মাধ্যমে ভল্টটি সার্ভ করে ফেলে। এবং DOMAIN অবশ্যই সম্পূর্ণ পাবলিক HTTPS URL হতে হবে: এটি অ্যাটাচমেন্ট লিঙ্ক, WebAuthn 2FA এবং নোটিফিকেশন এন্ডপয়েন্টে যুক্ত থাকে, তাই ভুল বা http ভ্যালু থাকলে সাইট লোড হলেও এই ফিচারগুলো কাজ করবে না। latest ট্যাগটি সাধারণত never-latest নিয়মের একটি সচেতন ব্যতিক্রম, Vaultwarden তাদের স্টেবল রিলিজগুলো একটি সিঙ্গেল রোলিং ইমেজ হিসেবে প্রকাশ করে, যেখানে :testing হলো আলাদা প্রি-রিলিজ চ্যানেল, তাই ইচ্ছাকৃতভাবে আপডেট করুন এবং নতুন ইমেজ পুল করার আগে রিলিজ নোটগুলো দেখে নিন। তবে এই ব্যতিক্রমটি সীমিত: বেশিরভাগ দীর্ঘস্থায়ী কন্টেইনারের ক্ষেত্রে একটি নির্দিষ্ট ট্যাগ ব্যবহার করাই ভালো, যা একই VPS-এ হোস্ট করা একটি অলওয়েজ-অন এজেন্টকে রিবুট এবং পুল করার পরেও স্থিতিশীল রাখে।

এটি চালু করুন এবং লগ পর্যবেক্ষণ করুন:

docker compose up -d
docker compose logs -f vaultwarden

সঠিকভাবে শুরু হলে শেষে Rocket has launched from http://0.0.0.0:80-এর মতো একটি লাইন দেখা যাবে। Traefik-কে সার্টিফিকেট আনার জন্য কয়েক সেকেন্ড সময় দিন, তারপর https://vault.example.com লোড করুন, আপনি একটি বৈধ প্যাডলক এবং কোনো সার্টিফিকেট সতর্কতা ছাড়াই Bitwarden ওয়েব ভল্ট দেখতে পাবেন।

ধাপ 3, একটি শক্তিশালী ADMIN_TOKEN এবং $$ ট্র্যাপ

ADMIN_TOKEN হলো /admin-এর রক্ষক, এই প্যানেলটি আপনার ইনস্ট্যান্সের প্রতিটি ব্যবহারকারী এবং সেটিংস পড়তে পারে, তাই এটিকে root পাসওয়ার্ডের মতোই গুরুত্ব দিন। এটি দুইভাবে কাজ করে।

সহজ পদ্ধতি হলো সেই র‍্যান্ডম স্ট্রিংটি যা আপনি ইতিমধ্যে openssl rand -base64 48 দিয়ে তৈরি করেছেন। যেহেতু base64-এ কখনোই $ থাকে না, তাই এটি কোনো এস্কেপিং ছাড়াই সরাসরি .env-এ কাজ করে।

শক্তিশালী পদ্ধতি হলো একটি Argon2 PHC হ্যাশ ব্যবহার করা, যাতে প্লেইনটেক্সট টোকেনটি কখনোই ডিস্কে জমা না থাকে। একই ইমেজ ব্যবহার করে একটি হ্যাশ তৈরি করুন:

docker run --rm -it vaultwarden/server /vaultwarden hash --preset owasp

এটি আপনাকে দুইবার ইনপুট দিতে বলবে এবং $argon2id$v=19$... দিয়ে শুরু হওয়া একটি স্ট্রিং প্রদর্শন করবে। এখানেই সেই ট্র্যাপটি রয়েছে যা অনেকের এক ঘণ্টা সময় নষ্ট করে: Docker Compose $-কে ভেরিয়েবল ইন্টারপোলেশন হিসেবে গণ্য করে, তাই আপনি যদি সরাসরি Compose ফাইলে environment:-এর নিচে হ্যাশটি পেস্ট করেন, তবে আপনাকে অবশ্যই প্রতিটি $-কে $$ দিয়ে ডাবল করতে হবে। সেখানে ভ্যালুটিকে কোটেশনের ভেতরে রাখা ঠিক আছে; আসল বিষয় হলো এস্কেপিং:

    environment:
      ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$c29tZXNhbHQ$$RdescudvJCsgt3ub+b+dWRWJTmaaJObG

আপনি যদি হ্যাশটিকে .env-এ রাখতে চান, তবে নিয়মটি উল্টে যাবে: সিঙ্গেল $ চিহ্নগুলো অপরিবর্তিত রাখুন, পুরো ভ্যালুটিকে সিঙ্গেল কোট (ADMIN_TOKEN='$argon2id$v=19$...') দিয়ে ঘিরে দিন এবং Compose ফাইলের বিদ্যমান ${ADMIN_TOKEN} লাইনটি এটি গ্রহণ করবে। .env-এর ভেতরে কখনোই $ ডাবল করবেন না। যদি আপনি Compose ফাইলে সিঙ্গেল $ চিহ্ন রেখে দেন, তবে Compose The "argon2id" variable is not set ওয়ার্নিং দেবে এবং টোকেনটিকে খালি করে দেবে, ফলে /admin আপনার সঠিক পাসওয়ার্ডটি প্রত্যাখ্যান করবে। docker compose up -d চালান এবং প্রম্পটে যে প্লেইনটেক্সটটি টাইপ করেছিলেন তা আপনার নিজের পাসওয়ার্ড স্টোরে সংরক্ষণ করুন।

ধাপ 4, আপনার অ্যাকাউন্ট নিবন্ধন করুন, তারপর দরজা বন্ধ করুন

SIGNUPS_ALLOWED: "true" ব্যবহার করে https://vault.example.com খুলুন, Create account-এ ক্লিক করুন এবং আপনার ইমেইল ও একটি শক্তিশালী মাস্টার পাসওয়ার্ড দিয়ে নিবন্ধন করুন। এই মাস্টার পাসওয়ার্ডটি পুনরুদ্ধার করা সম্ভব নয়, এটি রিসেট করার কোনো উপায় নেই, তাই প্রথমে এটি কোথাও নিরাপদে সংরক্ষণ করুন।

এখন দরজা বন্ধ করুন। Compose ফাইলটি এডিট করে সাইনআপ বন্ধ করুন:

      SIGNUPS_ALLOWED: "false"

docker compose up -d ব্যবহার করে পুনরায় প্রয়োগ করুন। এটি এমন একটি নিরাপত্তা ব্যবস্থা যা আপনি এড়িয়ে যেতে পারবেন না। এটি খোলা রাখলে, যে কেউ আপনার URL খুঁজে পেলে—এবং ক্রলাররা তা খুঁজে পায়—আপনার সার্ভারে অ্যাকাউন্ট তৈরি করতে পারবে। তারা আপনার ভল্ট পড়তে পারবে না, কিন্তু তারা রিসোর্স ব্যবহার করবে এবং আপনার ব্যক্তিগত ইনস্ট্যান্সকে একটি উন্মুক্ত সার্ভিসে পরিণত করবে। আপনি এটি খোলা রেখেছেন কি না তা বোঝার উপায় হলো: /admin এমন সব অ্যাকাউন্টের তালিকা দেখাবে যা আপনি তৈরি করেননি।

পরবর্তীতে পরিবার বা দলের সদস্যদের যোগ করতে পাবলিক সাইনআপ পুনরায় খোলার প্রয়োজন নেই, এর পরিবর্তে /admin-এ থাকা Invite User বাটনটি ব্যবহার করুন; এই প্রক্রিয়ার জন্য SMTP কনফিগার করা থাকতে হবে যাতে আমন্ত্রিত ব্যক্তি তাদের লিঙ্কটি পেতে পারেন।

ধাপ 5, /admin-এ প্রবেশ

https://vault.example.com/admin-এ ব্রাউজ করুন এবং plaintext admin token (র‍্যান্ডম স্ট্রিং বা আপনার হ্যাশ করা পাসওয়ার্ডটি, হ্যাশটি নয়) প্রদান করুন। এর ভেতরে আপনি ব্যবহারকারীদের তালিকা দেখতে পারবেন, সেটিংস পরিবর্তন করতে পারবেন, টেস্ট ইমেইল পাঠাতে পারবেন এবং ডাটাবেসের স্ন্যাপশট নিতে পারবেন।

যদি পেজটিতে The admin panel is disabled, please configure the 'ADMIN_TOKEN' variable to enable it দেখায়, তবে এর অর্থ হলো ADMIN_TOKEN খালি বা সেট করা নেই, যা প্যানেলটিকে পুরোপুরি নিষ্ক্রিয় করে রাখে; যদি আপনার এটি প্রয়োজন না হয় তবে এটি একটি বৈধ পছন্দ। যদি পেজটি লোড হয় কিন্তু আপনার টোকেন প্রত্যাখ্যান করে, তবে নিচের ব্যর্থতার তালিকা থেকে $$ এস্কেপিং ট্র্যাপটি দেখুন। টোকেন ভুলে গেছেন? এখানে কোনো রিকভারি প্রম্পট নেই; .env বা Compose ফাইলটি এডিট করুন, একটি নতুন টোকেন সেট করুন এবং docker compose up -d করুন।

ধাপ 6, Bitwarden ক্লায়েন্ট সংযুক্ত করা

প্রতিটি অফিসিয়াল ক্লায়েন্ট একটি self-hosted সার্ভারের সাথে সংযুক্ত হতে পারে, তাই সাধারণ স্টোর থেকে Bitwarden ডেস্কটপ, মোবাইল বা ব্রাউজার ক্লায়েন্ট ইনস্টল করুন। আপনার কোনো বিশেষ Vaultwarden বিল্ডের প্রয়োজন নেই।

লগ ইন করার আগে, লগইন স্ক্রিনে থাকা সেটিংস গিয়ার আইকনটি (যা Self-hosted বা Region → Self-hosted হিসেবে চিহ্নিত) খুলুন, Server URL-এ https://vault.example.com সেট করুন এবং সংরক্ষণ করুন। এরপর আপনার নিবন্ধিত ইমেইল এবং মাস্টার পাসওয়ার্ড দিয়ে লগ ইন করুন; ক্লায়েন্টটি অবিলম্বে সংযুক্ত হবে এবং ক্রেডেনশিয়াল পূরণ ও সংরক্ষণের প্রস্তাব দেবে।

যদি কোনো ক্লায়েন্ট 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, লগইন এন্ডপয়েন্টের জন্য একটি Fail2ban jail

Vaultwarden প্রতিটি ব্যর্থ লগইন প্রচেষ্টাকে LOG_FILE দ্বারা নির্ধারিত ফাইলে লগ করে, যা brute-force প্রতিরোধের জন্য ঠিক যা প্রয়োজন। আপনি যদি ইতিমধ্যে Fail2ban ব্যবহার না করে থাকেন, তবে এর ইনস্টলেশন এবং প্রাথমিক বিষয়গুলো Fail2ban SSH হার্ডেনিং গাইডে পাবেন; এখানে আমরা ভল্টের জন্য একটি নতুন jail যোগ করব।

প্রথমে হোস্ট মেশিনে named 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 বা আপনার প্রক্সির ঠিকানা দেখা যায়, তবে Vaultwarden প্রক্সিকে ব্যান করছে। সেক্ষেত্রে IP_HEADER-কে আপনার প্রক্সির পাঠানো সঠিক হেডারে সেট করুন (Traefik-এর জন্য X-Forwarded-For, উপরের nginx ব্লকের জন্য X-Real-IP, এবং Cloudflare-এর পেছনে থাকলে CF-Connecting-IP)। 1.37.4 ভার্সন থেকে, X-Forwarded-For-এর মাধ্যমে Vaultwarden এমন ডানদিকের ঠিকানা গ্রহণ করে যা IP_HEADER_TRUSTED_PROXIES-এর মধ্যে নেই (ডিফল্ট local, যা একই হোস্ট বা Docker নেটওয়ার্কে থাকা প্রক্সিকে কভার করে)। তাই যদি আপনার প্রক্সির সামনে কোনো CDN থাকে, তবে সেটির ঠিকানাও সেখানে তালিকাভুক্ত করুন। দ্বিতীয়ত, সঠিক iptables চেইন আপনার প্রক্সির ওপর নির্ভর করে: যদি Traefik একটি কন্টেইনার হিসেবে পাবলিশড পোর্টে চলে, তবে ট্রাফিক Docker-এর FORWARD পাথ দিয়ে যায়, তাই ব্যানটি উপরের মতো DOCKER-USER-এ থাকতে হবে। কিন্তু যদি আপনি ধাপ 1 থেকে host-nginx অপশনটি বেছে নিয়ে থাকেন, তবে সংযোগগুলো হোস্টের INPUT চেইনে nginx-এ টার্মিনেট হয় এবং একটি DOCKER-USER ব্যান সেগুলো দেখতে পায় না। সেক্ষেত্রে chain = DOCKER-USER লাইনটি মুছে ফেলুন যাতে Fail2ban ডিফল্ট INPUT চেইন ব্যবহার করে। তৃতীয়ত, পোর্ট-ভিত্তিক ডিফল্টের পরিবর্তে banaction = iptables-allports ব্যবহার করুন। এই jail-এ কোনো পোর্ট সংজ্ঞায়িত করা নেই, এবং DOCKER-USER-এ একটি all-ports ব্যান আক্রমণকারীকে বক্সের প্রতিটি পাবলিশড সার্ভিস থেকে কার্যকরভাবে ব্লক করে দেয়।

ধাপ 8, ভল্টের ব্যাকআপ নিন এবং তারপর তা পুনরুদ্ধার করুন

vw-data ভলিউমটিই আপনার পাসওয়ার্ড ম্যানেজার। এটি db.sqlite3 (প্রতিটি এন্ট্রি), attachments/ এবং sends/ ডিরেক্টরি, লগইন সেশন সাইন করার জন্য rsa_key.* ফাইল এবং অ্যাডমিন প্যানেল থেকে config.json ধারণ করে। এমন কোনো ব্যাকআপ যা এর কোনো একটি অংশ বাদ দেয়, তা প্রয়োজনের সময় ব্যর্থ হবে।

Vaultwarden যখন ডেটা লিখছে তখন db.sqlite3 কপি করলে তা অসম্পূর্ণ বা ক্ষতিগ্রস্ত ফাইল হতে পারে, তাই একটি কোল্ড স্ন্যাপশট নিন; এতে মাত্র কয়েক সেকেন্ডের ডাউনটাইম প্রয়োজন:

#!/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 ব্যাকআপ, যা আর্কাইভটিকে এনক্রিপ্ট করে এবং বারবার নেওয়া স্ন্যাপশটগুলোকে ডিডুপ্লিকেট (deduplicate) করে। অ্যাডমিন প্যানেলের Backup Database বাটনটি শুধুমাত্র SQLite ফাইলের একটি সহজ হট স্ন্যাপশট, কিন্তু এটি অ্যাটাচমেন্ট এবং কি (keys) বাদ দেয়।

এখন সেই প্রক্রিয়াটি অনুসরণ করুন যা একটি আশাবাদী ব্যাকআপ থেকে একটি প্রকৃত ব্যাকআপকে আলাদা করে: একবার এটি পুনরুদ্ধার করুন এবং নিশ্চিত করুন যে এটি কাজ করছে:

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 (অথবা http://127.0.0.1:8888) খুলুন। যেহেতু লুপব্যাক অ্যাড্রেসগুলোকে নিরাপদ কনটেক্সট হিসেবে গণ্য করা হয়, তাই crypto.subtle উপলব্ধ থাকে এবং ভল্ট এখানে plain http-এর মাধ্যমে ডিক্রিপ্ট হয়, যা একমাত্র অনুমোদিত অ্যাড্রেস। আপনার মাস্টার পাসওয়ার্ড দিয়ে লগইন করুন এবং নিশ্চিত করুন যে আপনার এন্ট্রিগুলো সেখানে আছে: যদি থাকে, তবে আপনার ডেটাবেস, RSA কি এবং মাস্টার পাসওয়ার্ড সফলভাবে কাজ করছে এবং আপনি কয়েক মিনিটের মধ্যেই একটি নতুন VPS-এ সবকিছু পুনরায় তৈরি করতে পারবেন। Ctrl-C চেপে কন্টেইনারটি বন্ধ করুন এবং /tmp/vw-restore মুছে ফেলুন। সার্ভারের অন্য যেকোনো অ্যাডমিন UI-এর জন্য এই টানেলিং পদ্ধতি বজায় রাখুন যা কখনোই ইন্টারনেটের মুখোমুখি হওয়া উচিত নয়; একইভাবে আপনি পোর্ট 5173-এ একটি self-hosted open-kritt security scanner-এও পৌঁছাতে পারবেন।

ব্যর্থতার ধরন এবং যে বার্তাগুলো আপনি দেখবেন

ব্রাউজার কনসোলে Cannot read properties of undefined (reading 'importKey')। ভল্টটি http-এর মাধ্যমে লোড করা হয়েছে, তাই crypto.subtle অনির্ধারিত (undefined); এটি শুধুমাত্র https://-এর মাধ্যমে অ্যাক্সেস করুন এবং প্রক্সিতে HTTP-to-HTTPS রিডাইরেক্ট যোগ করুন।

ক্লায়েন্টে This is not a recognized Bitwarden server...। সার্ভার URL-টি http, ভুলভাবে টাইপ করা, অথবা সার্টিফিকেটটি বিশ্বস্ত নয়; নিশ্চিত করুন যে https://vault.example.com একটি বৈধ প্যাডলক দেখাচ্ছে, তারপর ক্লায়েন্টের self-hosted সেটিংসে এটি পুনরায় লিখুন।

/admin সঠিক পাসওয়ার্ড প্রত্যাখ্যান করে। Argon2 হ্যাশ তার এস্কেপিং হারিয়ে ফেলেছে, Compose ফাইলে প্রতিটি $ অবশ্যই $$ হতে হবে (তবে .env-এর ভেতরে সিঙ্গেল কোটেশনের মধ্যে সিঙ্গেল $), অথবা আপনি প্লেইনটেক্সটের পরিবর্তে হ্যাশটি প্রবেশ করিয়েছেন।

ডিভাইসগুলোর মধ্যে ধীরগতিতে সিঙ্ক; কনসোলে WebSocket connection to 'wss://vault.example.com/notifications/hub' failed দেখাচ্ছে। প্রক্সিটি Upgrade/Connection হেডারগুলো ফরোয়ার্ড করছে না; Traefik এটি স্বয়ংক্রিয়ভাবে করে, কিন্তু nginx-এর জন্য ধাপ 1 থেকে দুটি upgrade লাইন প্রয়োজন। ভল্টটি কাজ করবে, তবে শুধুমাত্র খোলার সময় সিঙ্ক হবে। v1.31.0 থেকে পুরনো ডেডিকেটেড পোর্ট 3012 সরিয়ে ফেলা হয়েছে, তাই আলাদা কোনো WebSocket রুটের প্রয়োজন নেই।

Fail2ban একটি ব্যান রিপোর্ট করছে কিন্তু আক্রমণকারী সংযোগ চালিয়ে যাচ্ছে। এটি 127.0.0.1-কে ব্যান করছে কারণ IP_HEADER ভুল, অথবা ব্যানটি ভুল iptables চেইনে রয়েছে, chain = DOCKER-USER এবং banaction = iptables-allports সেট করুন।

আপগ্রেড

নতুন image-টি pull করুন এবং কন্টেইনারটি পুনরায় তৈরি করুন; named volume এবং আপনার সমস্ত ডেটা অক্ষত থাকবে:

docker compose pull
docker compose up -d

Vaultwarden নিয়মিত নতুন রিলিজ প্রকাশ করে। কোনো নির্দিষ্ট patch version-এ আটকে না থেকে প্রজেক্টের রিলিজ নোট অনুসরণ করুন, কারণ কিছু রিলিজে ডেটা মাইগ্রেশন সংক্রান্ত নির্দেশনা থাকে। যেকোনো বড় ধরনের আপগ্রেডের আগে নতুন করে ব্যাকআপ নিন; কোনো সমস্যা হলে tarball থেকে নতুন volume-এ ডেটা রিস্টোর করে আপনি আগের অবস্থায় ফিরে যেতে পারবেন।

FAQ

Vaultwarden কি Bitwarden-এর মতোই?

এটি একটি সামঞ্জস্যপূর্ণ এবং স্বতন্ত্র সার্ভার, অফিসিয়াল কোনো সংস্করণ নয়। Vaultwarden মূলত Rust ল্যাঙ্গুয়েজে Bitwarden সার্ভার API-এর একটি পুনঃবাস্তবায়ন। তাই অফিসিয়াল ডেস্কটপ, মোবাইল, ব্রাউজার এবং CLI ক্লায়েন্টগুলো এতে কাজ করে, কিন্তু এটি অফিসিয়াল স্ট্যাকের তুলনায় অনেক কম রিসোর্স ব্যবহার করে। ভল্টের ফরম্যাট একই, তাই এক্সপোর্ট এবং ইম্পোর্ট করার মাধ্যমে আপনি যেকোনো দিকে ডেটা স্থানান্তর করতে পারেন।

আমার কি সত্যিই HTTPS প্রয়োজন, নাকি LAN-এ http ব্যবহার করা যাবে?

লুপব্যাক টেস্ট ছাড়া অন্য যেকোনো কাজের জন্য আপনার HTTPS প্রয়োজন। Bitwarden ওয়েব ভল্ট এবং এক্সটেনশনগুলো ব্রাউজারের Web Crypto API ব্যবহার করে, যা শুধুমাত্র নিরাপদ কনটেক্সটেই কাজ করে। তাই সাধারণ http ব্যবহার করলে ক্লায়েন্ট Cannot read properties of undefined ত্রুটি দেখায় এবং লগইন করতে দেয় না। শুধুমাত্র লুপব্যাক অ্যাড্রেস যেমন http://localhost বা http://127.0.0.1-এ http কাজ করে, আর এই কারণেই 8 নম্বর ধাপে রিস্টোর টেস্টের জন্য SSH টানেল ব্যবহার করা হয়েছে।

অপরিচিত কাউকে আমার সার্ভারে রেজিস্ট্রেশন করা থেকে কীভাবে আটকাব?

আপনার নিজের অ্যাকাউন্ট তৈরি করার পরপরই Compose ফাইলে SIGNUPS_ALLOWED: "false" সেট করুন এবং docker compose up -d কমান্ডটি চালান। এরপর থেকে নতুন কাউকে যোগ করতে হলে /admin-এর Invite User বাটন ব্যবহার করুন। এর জন্য SMTP কনফিগার করা থাকতে হবে যাতে তারা ইনভাইটেশন লিঙ্কটি পায়। মাঝে মাঝে অ্যাডমিন ইউজার লিস্ট চেক করুন যাতে কোনো অনাকাঙ্ক্ষিত অ্যাকাউন্ট তৈরি হয়েছে কি না তা নিশ্চিত হওয়া যায়।

আমার Vaultwarden ভল্ট কীভাবে ব্যাকআপ নেব?

কিছুক্ষণের জন্য কন্টেইনারটি বন্ধ করুন এবং পুরো vw-data ভলিউম, db.sqlite3, attachments/, sends/, config.json এবং rsa_key.* ফাইলগুলো আর্কাইভ করুন। এরপর আর্কাইভটি সার্ভারের বাইরে কোথাও কপি করে রাখুন, যা প্রতিদিন রাতে ক্রন (cron) জব হিসেবে চালানো আদর্শ। সার্ভার চলাকালীন লাইভ SQLite ফাইল কপি করলে তা নষ্ট হওয়ার ঝুঁকি থাকে, তাই এটি বন্ধ থাকা অবস্থায় ব্যাকআপ নিন। সবচেয়ে গুরুত্বপূর্ণ হলো, ব্যাকআপটি একবার একটি অস্থায়ী কন্টেইনারে রিস্টোর করে লগইন করে দেখুন, যাতে আপনি নিশ্চিত হতে পারেন যে ব্যাকআপটি সঠিক আছে।

পাসওয়ার্ড নিজে হোস্ট করা কি আসলেই নিরাপদ?

হ্যাঁ, যদি আপনি এই গাইডে বর্ণিত তিনটি কাজ করেন: সঠিক HTTPS, নতুন রেজিস্ট্রেশন বন্ধ রাখা এবং শক্তিশালী অ্যাডমিন টোকেন ব্যবহার, এবং নিয়মিত ব্যাকআপ পরীক্ষা করা। আপনার ভল্ট ক্লায়েন্ট-সাইডে মাস্টার পাসওয়ার্ড দিয়ে এনক্রিপ্ট করা থাকে, তাই সার্ভার কখনোই আপনার পাসওয়ার্ডগুলো সরাসরি দেখতে পায় না। এমনকি চুরি হওয়া db.sqlite3 ফাইল থেকেও মাস্টার পাসওয়ার্ড ছাড়া এন্ট্রিগুলো দেখা সম্ভব নয়। তবে সার্ভারে অ্যাকাউন্টের ইমেইল এবং মাস্টার পাসওয়ার্ড থেকে তৈরি সল্টেড হ্যাশ থাকে, যা আক্রমণকারীরা অফলাইনে ক্র্যাক করার চেষ্টা করতে পারে। তাই ডেটাবেস ফাইল এবং এর প্রতিটি কপি সুরক্ষিত রাখুন। এর বিনিময়ে প্যাচিং এবং ব্যাকআপের দায়িত্ব আপনার ওপর বর্তায়, আর এই কারণেই Fail2ban এবং রিস্টোর প্রক্রিয়া এখানে ঐচ্ছিক নয়। একবার এগুলো ঠিকঠাক হয়ে গেলে, সেলফ-হোস্টেড ভল্টে আক্রমণের সম্ভাব্য ক্ষেত্রগুলো সম্পর্কে আরও বিস্তারিত জানা আপনার পরবর্তী কার্যকর পদক্ষেপ হতে পারে। কারণ ক্লায়েন্টে এন্ট্রিগুলো এনক্রিপ্ট করা থাকায়, এখন আপনার মূল কাজ হলো অ্যাডমিন টোকেন এবং ব্যাকআপ আর্কাইভ সুরক্ষিত রাখা।