自建Bitwarden服务 + fail2ban防爆破 + OneDrive每日备份
2025/4/11约 673 字大约 2 分钟
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/bitwarden.log
- DOMAIN=https://api.naomi.plus/vault/
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/rclone
upstream 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 api.naomi.plus;
ssl_certificate conf.d/cert/naomi.plus.crt;
ssl_certificate_key conf.d/cert/naomi.plus.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;
location /robots.txt {
alias $root/robots-deny.txt;
}
## 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 api.naomi.plus;
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 <SERVER>: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