自建Bitwarden服务 + fail2ban防爆破 + OneDrive每日备份
2025/4/11约 725 字大约 2 分钟
使用 vaultwarden 开源后端,配合 fail2ban 防止暴力破解,同时使用 rclone 每日备份到 OneDrive,服务使用 docker compose 来管理。
vaultwarden
# docker-compose.yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      - TZ=Asia/Shanghai
      # - SIGNUPS_ALLOWED=false
      - INVITATIONS_ALLOWED=false
      - WEBSOCKET_ENABLED=true
      - LOG_FILE=/data/vaultwarden.log
      - DOMAIN=https://<你的域名>
    volumes:
      - ./data/:/data/
    mem_limit: 128M
  backup:
    image: ttionya/vaultwarden-backup:latest
    restart: always
    environment:
      - TZ=Asia/Shanghai
      - TIMEZONE=Asia/Shanghai
      - BACKUP_KEEP_DAYS=7
      - ZIP_PASSWORD=PASSWORD
    volumes:
      - ./data/:/bitwarden/data/
      - ./rclone/:/config/rcloneupstream vaultwarden-default {
    zone vaultwarden-default 64k;
    server vaultwarden:80;
    keepalive 2;
}
# Needed to support websocket connections
# See: https://nginx.org/en/docs/http/websocket.html
# Instead of "close" as stated in the above link we send an empty value.
# Else all keepalive connections will not work.
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      "";
}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name <你的域名>;
    ssl_certificate <你的证书>;
    ssl_certificate_key <你的证书>;
    ssl_session_timeout 5m;
    ssl_prefer_server_ciphers on;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
    client_max_body_size 525M;
    ## Using a Sub Path Config
    # Path to the root of your installation
    # Be sure to DO ADD a trailing /, else you will experience issues
    # But only for this location, all other locations should NOT add this.
    location /vault/ {
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
        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_pass http://vaultwarden-default;
    }
}
server {
    listen 80;
    listen [::]:80;
    server_name <你的域名>;
    rewrite ^(.*)$ https://$host$1 permanent;
    location /vault/ {
        rewrite ^(.*)$ https://$host$1 permanent;
    }
}# Uncomment this in addition with the import admin_redir statement allow access to the admin interface only from local networks
# (admin_redir) {
#        @admin {
#                path /admin*
#                not remote_ip private_ranges
#        }
#        redir @admin /
# }
{$DOMAIN} {
  log {
    level INFO
    output file {$LOG_FILE} {
      roll_size 10MB
      roll_keep 10
    }
  }
  # Uncomment this if you want to get a cert via ACME (Let's Encrypt or ZeroSSL).
  # tls {$EMAIL}
  # Or uncomment this if you're providing your own cert. You would also use this option
  # if you're running behind Cloudflare.
  # tls {$SSL_CERT_PATH} {$SSL_KEY_PATH}
  # This setting may have compatibility issues with some browsers
  # (e.g., attachment downloading on Firefox). Try disabling this
  # if you encounter issues.
  encode zstd gzip
  # Uncomment to improve security (WARNING: only use if you understand the implications!)
  # If you want to use FIDO2 WebAuthn, set X-Frame-Options to "SAMEORIGIN" or the Browser will block those requests
  # header / {
  # # Enable HTTP Strict Transport Security (HSTS)
  # Strict-Transport-Security "max-age=31536000;"
  # # Disable cross-site filter (XSS)
  # X-XSS-Protection "0"
  # # Disallow the site to be rendered within a frame (clickjacking protection)
  # X-Frame-Options "DENY"
  # # Prevent search engines from indexing (optional)
  # X-Robots-Tag "noindex, nofollow"
  # # Disallow sniffing of X-Content-Type-Options
  # X-Content-Type-Options "nosniff"
  # # Server name removing
  # -Server
  # # Remove X-Powered-By though this shouldn't be an issue, better opsec to remove
  # -X-Powered-By
  # # Remove Last-Modified because etag is the same and is as effective
  # -Last-Modified
  # }
  # Uncomment to allow access to the admin interface only from local networks
  # import admin_redir
  # Proxy everything to Rocket
  # if located at a sub-path the reverse_proxy line will look like:
  #   reverse_proxy /subpath/* <SERVER>:80
  reverse_proxy <你的域名>:80 {
       # Send the true remote IP to Rocket, so that Vaultwarden can put this in the
       # log, so that fail2ban can ban the correct IP.
       header_up X-Real-IP {remote_host}
       # If you use Cloudflare proxying, replace remote_host with http.request.header.Cf-Connecting-Ip
       # See https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/
       # and https://caddy.community/t/forward-auth-copy-headers-value-not-replaced/16998/4
  }
}fail2ban
添加文件 /etc/fail2ban/filter.d/vaultwarden.local
[INCLUDES]
before = common.conf
[Definition]
failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =添加文件 /etc/fail2ban/jail.d/vaultwarden.local
[vaultwarden]
enabled = true
# Docker部署 需要使用 FORWARD
chain = FORWARD
port = http,https
filter = vaultwarden
banaction = iptables-allports
# 修改为你的日志路径
logpath = /path/vaultwarden.log
maxretry = 3
bantime = 86400
findtime = 14400