# 关于

{% hint style="success" %}
2021-04-27：从 [v1.21.0](https://github.com/dani-garcia/vaultwarden/releases/tag/1.21.0) 开始，bitwarden\_rs 项目更名为 Vaultwarden。参阅 [#1642](https://github.com/dani-garcia/vaultwarden/discussions/1642) 了解更多说明。
{% endhint %}

这里是对官方 [Vaultwarden](https://github.com/dani-garcia/vaultwarden)（以前叫 bitwarden\_rs）[Wiki](https://github.com/dani-garcia/vaultwarden/wiki) 的中文翻译。

原文有太多口语化内容，翻译起来比较费脑，这里我尽力翻译准确并使之不那么生硬。

译者：[@wcjxixi](mailto:wcjxixi@gmail.com)

致谢 [Google Translate](https://translate.google.com) 以及 [DeepL](https://www.deepl.com)！

{% hint style="warning" %}
个人能力有限，具体请以官方 [Vaultwarden Wiki](https://github.com/dani-garcia/vaultwarden/wiki) 页面为准。使用本内容所产生的一切后果，与 @wcjxixi 无关。Use at your own risk！！！
{% endhint %}

{% hint style="info" %}
**备注：**&#x6807;题前有 \* 的表示官方曾经有但现已移除的页面和/或分类，我将其保留仅作为参考之用。
{% endhint %}

## Vaultwarden 是什么 <a href="#what-is-vaultwarden" id="what-is-vaultwarden"></a>

Vaultwarden 是一个用于本地搭建 Bitwarden 服务器的第三方 Docker 项目。仅在部署的时候使用 Vaultwarden 镜像，桌面端、移动端、浏览器扩展等客户端均使用官方 Bitwarden 客户端。

Vaultwarden 很轻量，对于不希望使用占用大量资源的官方 Bitwarden 自托管部署而言，它是理想的选择。

## Vaultwarden 与 Bitwarden 的区别 <a href="#difference-between-vaultwarden-and-bitwarden" id="difference-between-vaultwarden-and-bitwarden"></a>

* 除不支持 Bitwarden 官方企业版的部分功能（详情见[这里](/home#missing-features)）外，其他大部分功能均**免费**支持。并跟随官方版本保持及时更新。
* Vaultwarden 比 Bitwarden 官方版更轻量。官方版使用 .Net 开发，使用 MSSQL 数据库，要求至少 2GB 内存；Vaultwarden 使用 Rust 编写，改用 SQLite 数据库（现在也支持 MySQL 和 PostgreSQL），运行时只需要 10M 内存，可以说对硬件基本没有要求。

> [NodeWarden](https://github.com/shuaiplus/nodewarden) 是另一个与 Vaultwarden 类似的 Bitwarden 兼容的服务端。它运行在 Cloudflare Workers 上，原创 Web Vault 界面，比 Vaultwarden 更轻量。类似的还有 [Warden](https://github.com/qaz741wsd856/warden-worker)，是运行在 Cloudflare Workers 上的 Vaultwarden。它们均兼容 Bitwarden 官方客户端。
>
> 除官方客户端外，还有兼容  Bitwarden 的第三方客户端。[Keyguard](https://github.com/AChep/keyguard-app) 是一款面向 Bitwarden® 平台和 KeePass (KDBX) 的多客户端 App。KeyGuard 通过兼容 Bitwarden 的 API 来实现密码管理功能，支持 Android、Windows、Mac、Linux。

## 免费 Vaultwarden 公共实例 <a href="#public-instances" id="public-instances"></a>

使用 Vaultwarden 搭建的免费公共实例。更多实例请自行使用关键词「Vaultwarden Web Vault」进行网页搜索。

{% hint style="danger" %}
注意：请自行决定使用这些公共实例所存在的安全风险。
{% endhint %}

* [https://bitwarden.garudalinux.org/](https://bitwarden.garudalinux.org)
* [https://vault.tedomum.net/](https://vault.tedomum.net)
* [https://passwd.hostux.net/](https://passwd.hostux.net)
* [https://bitwarden.scutech.com](<&#xD;&#xA;https://bitwarden.scutech.com>)


# 首页

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki)
{% endhint %}

Vaultwarden 是一个使用 Rust 编写的非官方 Bitwarden 服务器实现，它与[官方 Bitwarden 客户端](https://bitwarden.com/download/)兼容，非常适合不希望运行官方资源密集型服务的自托管部署。

Vaultwarden 面向个人、家庭和小型组织。尽管开发主要针对大型组织的功能（例如单点登录、目录同步等）并不是优先事项，但欢迎能实现此类功能的高质量 PR。

Vaultwarden 已经进行了多项审计，其中一些是公开的，请在我们的 [Vaultwarden 审计](/faq/audits) wiki 页面上阅读更多相关信息。

> \[**译者注**]：PR 指 GitHub 中的 [pull requests](https://docs.github.com/cn/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests)（拉取请求）。

## 支持的功能 <a href="#supported-features" id="supported-features"></a>

Vaultwarden 实现了大多数功能所需的 Bitwarden API，其中包括：

* 网页界面（等效于 [https://vault.bitwarden.com/](https://vault.bitwarden.com/\))）
* 个人密码库支持
* [组织](https://help.ppgg.in/admin-console/organizations-quick-start)密码库支持
* [群组](https://help.ppgg.in/admin-console/organization-basics/groups)（需要设置[环境变量](https://github.com/dani-garcia/vaultwarden/blob/main/.env.template#L409-L414)才能启用它）
* [事件日志](https://help.ppgg.in/admin-console/reporting/event-logs)（需要设置[环境变量](https://github.com/dani-garcia/vaultwarden/blob/main/.env.template#L275-L278)才能启用它）
* [密码共享](https://help.ppgg.in/password-manager/vault-basics/sharing)和[访问控制](https://help.ppgg.in/admin-console/user-management/member-roles-and-permissions)
* [集合](https://help.ppgg.in/admin-console/organization-basics/collections)
* [文件附件](https://help.ppgg.in/password-manager/vault-basics/file-attachments)
* [文件夹](https://help.ppgg.in/password-manager/vault-administration/folders)
* [收藏](https://help.ppgg.in/password-manager/vault-administration/favorites)
* [网站图标](https://help.ppgg.in/security/website-icons)（需要内部服务/私有服务[配置](/configuration/allow-icon-fetching-from-internal-services)）
* [Bitwarden 验证器 (TOTP)](https://help.ppgg.in/password-manager/vault-basics/totp)
* [Bitwarden Send](https://help.ppgg.in/password-manager/bitwarden-send/about-send)
* [紧急访问](https://help.ppgg.in/my-account/more/emergency-access)
* [回收站](https://help.ppgg.in/password-manager/vault-basics/vault-items#vault-trash)（软删除，您可以[配置自动删除的等待天数](https://github.com/dani-garcia/vaultwarden/blob/main/.env.template#L234-L237)）
* [主密码重新提示](https://help.ppgg.in/password-manager/vault-basics/vault-items#protect-individual-items)
* [个人 API 密钥](https://help.ppgg.in/password-manager/developer-tools/personal-api-key-for-cli-authentication)
* [电子邮件](https://help.ppgg.in/my-account/two-step-login/setup-guides/two-step-login-via-email)、[Duo](https://help.ppgg.in/my-account/two-step-login/setup-guides/two-step-login-via-duo)、[YubiKey](https://help.ppgg.in/my-account/two-step-login/setup-guides/two-step-login-via-yubikey) 和 [FIDO2 WebAuthn](https://help.ppgg.in/my-account/two-step-login/setup-guides/two-step-login-via-fido)（包括 Nitrokeys 和 Solokeys）方式的两步登录
* SimpleLogin、AnonAddy 或 Firefox Relay 的用户名生成器集成
* [Directory Connector](https://help.ppgg.in/docs/admin-console/manage-members/directory-connector/about-directory-connector) 支持
* [账户恢复](https://help.ppgg.in/docs/admin-console/manage-members/account-recovery/about-account-recovery)（这需要[启用电子邮箱](/configuration/smtp-configuration)）
* 用于桌面端/浏览器客户端/扩展的[实时同步](https://bitwarden.com/blog/live-sync/)（仅 WebSocket）
* 用于移动客户端 (Android/iOS) 的[实时同步](https://bitwarden.com/blog/live-sync/)（[推送通知](/configuration/enabling-mobile-client-push-notification)）
* [单点登录 (SSO)](https://help.ppgg.in/admin-console/login-with-sso/about-login-with-sso)，请参阅[文档](/configuration/enabling-sso-support-using-openid-connect)
* 某些企业策略：
  * [要求两步登录](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#require-two-step-login)
  * [主密码要求](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#master-password-requirements)
  * [账户恢复管理](https://help.ppgg.in/docs/admin-console/oversight-visibility/enterprise-policies#account-recovery-administration)（仅在启用了电子邮箱时可用）
  * [密码生成器](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#password-generator)
  * [单一组织](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#single-organization)
  * [禁用个人密码库](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#remove-individual-vault)
  * [禁用 Send](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#disable-send)
  * [Send 选项](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#send-options)
  * [禁用支付卡项目类型](https://help.ppgg.in/docs/admin-console/oversight-visibility/enterprise-policies#remove-card-item-type)
  * [默认 URI 匹配检测](https://help.ppgg.in/docs/admin-console/oversight-visibility/enterprise-policies#default-uri-match-detection)

## 缺少的功能 <a href="#missing-features" id="missing-features"></a>

话题 [#246](https://github.com/dani-garcia/vaultwarden/issues/246) 包含了完整的功能请求列表，既包含官方服务器已具备但 Vaultwarden 尚未实现的功能，也包含 Vaultwarden 中特有的增强功能。

为了与官方服务器做简单的比较，本章节汇总了官方服务器中已经实现但在 Vaultwarden 中目前还没有实现的功能。

在时间允许的情况下，可能会添加的功能（欢迎贡献）：

* [Bitwarden 公共 API](https://help.ppgg.in/organizations/bitwarden-public-api) / [组织 API 密钥](https://help.ppgg.in/admin-console/bitwarden-public-api#authentication)。此功能做了部分添加，并且仅支持 Bitwarden Directory Connector
* [使用通行密钥登录](https://help.ppgg.in/docs/account/log-in-and-unlock/more-log-in-options/log-in-with-passkeys)。参阅 [#5929](https://github.com/dani-garcia/vaultwarden/pull/5929)
* [新设备登录保护](https://help.ppgg.in/docs/account/log-in-and-unlock/new-device-protection)

除非做出贡献，否则可能不会添加的功能：

* [自定义角色](https://help.ppgg.in/admin-console/user-management/member-roles-and-permissions#custom-role)
* 某些企业策略（[UI 非开源](https://github.com/bitwarden/clients/tree/main/bitwarden_license/bit-web/src/app/admin-console/policies)。可能需要通过管理页面进行配置）：
  * [要求单点登录验证](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#require-single-sign-on-authentication)
  * [密码库超时](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#vault-timeout)
  * [禁用个人密码库导出](https://help.ppgg.in/admin-console/organization-basics/enterprise-policies#disable-personal-vault-export)

## 保持联系 <a href="#get-in-touch" id="get-in-touch"></a>

要提出问题、提供建议、请求新功能或获得有关配置或安装软件的帮助，请[使用论坛](https://vaultwarden.discourse.group)。

如果您发现任何与 Vaultwarden 本身有关的 bug 或崩溃，请[创建一个话题](https://github.com/dani-garcia/vaultwarden/issues)。并确保不存在任何类似的话题！

我们通常在 [#vaultwarden:matrix.org](https://matrix.to/#/#vaultwarden:matrix.org) 房间闲逛，如果您喜欢聊天，欢迎随时加入我们！

***

<p align="center"><strong>🛡️ Vaultwarden — 一款使用 Rust 重构的 Bitwarden 服务器</strong></p>

<p align="center"><a href="/pages/-M3ch4A6JI2MFWqwnJZ2"><sup><sub><strong>🏠 Wiki 首页</strong></sub></sup></a> <sup><sub>·</sub></sup> <a href="/pages/-MZIJOVwrvB8J3oq1OMb"><sup><sub><strong>📖 FAQ</strong></sub></sup></a> <sup><sub>·</sub></sup> <a href="/pages/-M3ciWE0hDA9ySPsq5V5"><sup><sub><strong>⚙️ 配置</strong></sub></sup></a> <sup><sub>·</sub></sup> <a href="/pages/-M3cicqhtkZl9mcn9O2N"><sup><sub><strong>🔒 强化指南</strong></sub></sup></a> <sup><sub>·</sub></sup> <a href="/pages/-M3ciAkMEIYHCuS06B4E"><sup><sub><strong>🐳 Docker</strong></sub></sup></a></p>

***

<p align="center"><sup><sub><strong>💬 保持联系</strong></sub></sup></p>

<p align="center"><a href="https://vaultwarden.discourse.group/"><img src="https://camo.githubusercontent.com/765e304c5ba051b74fd1ed0262d20e8c08523e0855b802e23d9d88c5c4ad85f0/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f466f72756d2d446973636f757273652d3235393662653f7374796c653d666c61742d737175617265266c6f676f3d646973636f75727365" alt="Forum"></a> <a href="https://matrix.to/#/#vaultwarden:matrix.org"><img src="https://camo.githubusercontent.com/49c753898876a5f895bfdd8ee1ebfabdcca4f1789652998fd55e400ce4cda88a/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f436861742d2532337661756c7477617264656e2533416d61747269782e6f72672d3064626438623f7374796c653d666c61742d737175617265266c6f676f3d6d6174726978" alt="Matrix"></a> <a href="https://github.com/dani-garcia/vaultwarden/issues"><img src="https://camo.githubusercontent.com/fbdda3c37b06d0bb5d65af5d0621973db08d963f4e4cb1de525f4ad50c59f680/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f64616e692d6761726369612f7661756c7477617264656e3f7374796c653d666c61742d737175617265266c6f676f3d676974687562" alt="Issues"></a> <a href="https://github.com/dani-garcia/vaultwarden/stargazers"><img src="https://camo.githubusercontent.com/325e1350f77def0d7dc32c11fc5ba604fb0456bc1aa2fd42dda84ee6177b7d5b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f64616e692d6761726369612f7661756c7477617264656e3f7374796c653d666c61742d737175617265266c6f676f3d676974687562" alt="Stars"></a> <a href="https://github.com/dani-garcia/vaultwarden/blob/main/LICENSE.txt"><img src="https://camo.githubusercontent.com/21f489b23b45334005af96c4ea5b058b0628f4eddbf59d8b40ce40e187791e51/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f64616e692d6761726369612f7661756c7477617264656e3f7374796c653d666c61742d737175617265" alt="License"></a></p>

***

<p align="center"><sup><sub><strong>❤️ 喜欢</strong></sub><sub> </sub><sub>Vaultwarden</sub><sub> </sub><sub><strong>吗？</strong></sub><sub>考虑</sub></sup><a href="/pages/-M3cid06l2dtCj986FlT"><sup><sub>支持上游的 Bitwarden</sub></sup></a> <sup><sub>— 没有他们的工作，这个项目就不会存在。</sub></sup></p>

<p align="center"><sup><sub>Vaultwarden 是一款<strong>非官方</strong>的、由社区驱动的兼容 Bitwarden 的服务器。它与 Bitwarden, Inc 无任何关联、附属，亦未获得其认可。</sub></sup><br><sup><sub>—「Bitwarden」是 Bitwarden, Inc 的商标。</sub></sup></p>

<p align="center"><sup><sub>由</sub></sup> <a href="https://github.com/dani-garcia"><sup><sub>@dani-garcia</sub></sup></a> <sup><sub>和</sub></sup><a href="https://github.com/dani-garcia/vaultwarden/graphs/contributors"><sup><sub>贡献者</sub></sup></a><sup><sub>精心维护 · Wiki 内容遵循项目条款许可</sub></sup></p>

***


# FAQ


# 1.FAQ

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/FAQs)
{% endhint %}

## Vaultwarden 是否与 Bitwarden 项目或 Bitwarden, Inc 有关联？ <a href="#is-vaultwarden-associated-with-the-bitwarden-project-or-bitwarden" id="is-vaultwarden-associated-with-the-bitwarden-project-or-bitwarden"></a>

简短的回答，**没有**。两个项目的开发人员之间有时会有联系，但没有合作。除此之外，Vaultwarden 项目仅使用 Bitwarden, Inc 提供的 Web Vault 并打了一些[补丁](https://github.com/dani-garcia/bw_web_builds/tree/master/patches)，以使其与我们的实现兼容。

## 我发现了一个 Vaultwarden 公共实例。它与这个项目有关吗？使用它安全吗？  <a href="#ive-found-a-public-vaultwarden-instance.-is-it-associated-with-this-project-is-it-safe-to-use" id="ive-found-a-public-vaultwarden-instance.-is-it-associated-with-this-project-is-it-safe-to-use"></a>

本项目不托管任何公共 Vaultwarden 实例，我们也不提倡使用任何此类网站。参见 [#3233](https://github.com/dani-garcia/vaultwarden/discussions/3233#discussioncomment-4917141) [#4142](https://github.com/dani-garcia/vaultwarden/discussions/4142) [#4367](https://github.com/dani-garcia/vaultwarden/discussions/4367#discussioncomment-8529763)

## 我的 Bitwarden 客户端有问题，我需要在哪里报告这问题？ <a href="#i-have-an-issue-with-a-bitwarden-client-where-do-i-need-to-report-this" id="i-have-an-issue-with-a-bitwarden-client-where-do-i-need-to-report-this"></a>

如果您使用 Vaultwarden 作为任何官方 Bitwarden 客户端的服务器，您将无法在 Bitwarden 报告此问题，因为他们一看到您使用 Vaultwarden 就会关闭该问题，这确实是合理的做法。

要确定问题是服务器端还是客户端，请阅读以下 wiki 页面，以帮助 Vaultwarden 和 Bitwarden 确定问题以及在哪里和如何报告问题。

[https://github.com/dani-garcia/vaultwarden/wiki/Bitwarden-clients-troubleshooting](https://github.com/dani-garcia/vaultwarden/wiki/Bitwarden-clients-troubleshootinghttps://github.com/dani-garcia/vaultwarden/wiki/Bitwarden-clients-troubleshooting)

## 我对 web-vault（或任何其他客户端）有一个功能请求 <a href="#i-have-a-feature-request-for-the-web-vault-or-any-other-client" id="i-have-a-feature-request-for-the-web-vault-or-any-other-client"></a>

不幸的是我们不能在这里提供帮助。Vaultwarden 项目没有，也可能永远不会开发自定义客户端。我们尝试尽可能接近上游客户端的工作方式，并且由于我们只能向 web-vault 添加一些内容，这甚至可能会破坏其他客户端或导致与上游 web-vault 保持最新状态的问题。因此，我们不会向 Vaultwarden 添加任何需要在客户端处理的特殊或独特功能。

## Vaultwarden 的下一个版本是什么时候？您能给出一个 ETA 吗？ <a href="#when-is-the-next-release-of-vaultwarden-can-you-give-an-eta" id="when-is-the-next-release-of-vaultwarden-can-you-give-an-eta"></a>

Vaultwarden 没有发布时间表。如果维护者有时间并认为有必要发布新版本，那么可以立即发布，但鉴于这是一个由人们利用业余时间完成的项目，下一次发布可能需要几周甚至几个月的时间。

如果您「希望尽早获得最新功能、增强功能或错误修复」，您可以随时改用测试镜像，它总是基于最新的提交。参见容器镜像的选择。

> **\[译者注]**：ETA：Estimated Time of Arrival。在软件开发和日常交流中，它不再仅仅指「预计到达时间」，而是被广泛引申为「预计完成时间」或「预计发布日期」。

## Vaultwarden 能连接到 Oracle MySQL V8.x 数据库吗？ <a href="#can-bitwarden_rs-connect-to-an-oracle-mysql-v-8-x-database" id="can-bitwarden_rs-connect-to-an-oracle-mysql-v-8-x-database"></a>

在使用 Oracle MySQL v8.x 时，当您试图启动 Vaultwarden，可能会出现以下警告：

```
[vaultwarden::util][WARN] Can't connect to database, retrying: DieselConError.
[CAUSE] BadConnection(
    "Authentication plugin \'caching_sha2_password\' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory",
)
```

默认情况下，Oracle MySQL v8.x 使用更安全的密码散列方法，这是好事，但我们的构建目前不支持它。

您需要以一种特定的方法创建 Vaultwarden 用户，以便它能使用旧的原生密码散列：

```sql
-- 在 MySQLv8 安装上使用此命令
CREATE USER 'vaultwarden'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
```

如果您已经创建了用户，并且只想更改散列方法，请使用以下命令：

```sql
-- 将密码类型从 caching_sha2_password 更改为 native
ALTER USER 'vaultwarden'@'localhost' IDENTIFIED WITH mysql_native_password BY 'yourpassword';
```

另外可参阅：[使用 MariaDB - 创建数据库和用户](/configuration/database/using-the-mariadb-mysql-backend#create-database-and-user)

在版本 1.35.5 之后不再需要进行此更改，该版本支持「caching\_sha2\_password」。

## 客户端（桌面端、移动端、网页端）无法正常工作，无法登录或提示证书无效。 <a href="#my-client-desktop-mobile-web-does-not-work-i-can-not-login-or-it-complains-about-invalid-certificate" id="my-client-desktop-mobile-web-does-not-work-i-can-not-login-or-it-complains-about-invalid-certificate"></a>

Bitwarden 客户端需要一个安全的连接，才能正常工作且没有任何问题。虽然某些客户端也可以在没有安全连接的情况下工作，但我们并不推荐这样做。

大多数时候，当人们使用证书时仍然有问题，是因为他们使用的是所谓的自签名证书。虽然这些证书可以提供安全连接，但一些平台不允许或不支持它。

我们建议使用诸如 Let's Encrypt 这样的服务来提供一个有效的、被大多数设备默认接受的证书。请参阅以下页面：

* [启用 HTTPS](/reverse-proxy/https/enabling-https)
* [使用 Let's Encrypt 证书运行私有 Vaultwarden 实例](/reverse-proxy/https/running-a-private-vaultwarden-instance-with-lets-encrypt-certs)

## 为什么我密码库的所有项目都看不到图标？ <a href="#why-do-i-see-no-icons-for-all-my-vault-items" id="why-do-i-see-no-icons-for-all-my-vault-items"></a>

没有显示图标的原因有很多种。如果只是某几个密码库项目，可能是我们无法提取它。有些网站启用了一些保护措施，导致我们的实施失败。他们中的大多数需要 Javascript 才能工作。

这也可能是 Vaultwarden 服务器无法访问互联网或未解决 DNS 查询所致。您可以检查 `/admin/diagnostics` 页面（参阅[启用管理页面](/configuration/enabling-admin-page)），看看您是否能解决 DNS 查询以及是否有连接到互联网。如果都没问题，也有可能是防火墙或外发互联网代理阻止了这些请求。

## Websocket 连接显示错误的 IP 地址。 <a href="#websocket-connections-show-wrong-ip-address" id="websocket-connections-show-wrong-ip-address"></a>

这不是我们可以解决的问题。我们使用的库不支持任何形式的 `X-Forwarded-For` 或 `Forward` 标头。

它会始终显示所使用的反向代理的 IP，除非您在没有任何代理的情况下直接运行 Vaultwarden，或者运行透明代理，这可能会让它显示正确的 IP。这不是一个重要的日志记录部分，并且如果您使用反向代理，您可能还可以在其日志中看到此请求，该请求具有正确的 IP。

## 为什么 Vaultwarden 会提示 `[INFO] No .env file found`。即使我已经提供了一个？

启动时，Vaultwarden 将检查进程的当前工作目录中是否存在名为 `.env` 的文件（如果未通过环境变量 `ENV_FILE` 更改）。如果您没有提供此文件，Vaultwarden 将简单地通知您它没有找到它。此文件与您提供给 docker 的用于在创建容器时加载环境变量的 env 文件无关，也与在 [systemd .service](/alternative-deployments/creating-a-systemd-service) 中使用的环境文件无关。

## 可以将 Vaultwarden 作为 Azure WebApp 运行吗？ <a href="#can-i-run-bitwarden_rs-as-an-azure-webapp" id="can-i-run-bitwarden_rs-as-an-azure-webapp"></a>

不幸的是，Azure WebApp 使用 CIFS/Samba 作为卷存储，而 CIFS/Samba 不支持锁定。这导致 Vaultwarden 不能使用 SQLite 数据库文件。

有两种解决方式：

1. 不要使用 SQLite，改为使用 MariaDB/MySQL 或 Posgresql 作为数据库后端。
2. 尝试将 `ENABLE_DB_WAL` 环境变量的值设置为 `false` 以禁用 WAL。这需要在一个新的文件上完成，所以您需要移除之前创建的 `db.sqlite3` 文件，并再次重启 Vaultwarden 应用程序。

## 我在 FAQ 中找不到答案，下一步该怎么做？ <a href="#i-did-not-find-my-answer-here-in-the-faq-what-to-do-next" id="i-did-not-find-my-answer-here-in-the-faq-what-to-do-next"></a>

请尝试在我们精彩的 [Wiki](/) 中搜索和点击。如果这对您没有帮助，请尝试查看 [Github 讨论](https://github.com/dani-garcia/bitwarden_rs/discussions)或 [Vaultwarden 论坛](https://bitwardenrs.discourse.group/)。如果这也没有解决，您可以尝试搜索开放的和已关闭的[话题](https://github.com/dani-garcia/bitwarden_rs/issues)。

如果您仍然没有找到答案，您可以在 [Github 讨论](https://github.com/dani-garcia/bitwarden_rs/discussions)或 [Vaultwarden 论坛](https://bitwardenrs.discourse.group/)上发起一个主题，或者加入我们的[聊天室](https://matrix.to/#/#bitwarden_rs:matrix.org)。


# 2.审计

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Audits)
{% endhint %}

## Vaultwarden 审计 <a href="#vaultwarden-audits" id="vaultwarden-audits"></a>

Vaultwarden 已经过安全公司的审计，这有助于确保 Vaultwarden 的安全。

有些审计是在没有公开发布任何数据的情况下完成的，因为要求这些安全公司进行审计的公司不允许这样做，但这些研究人员确实提供了审计结果。

有些审计是公开发布的，任何人都可以访问。

## 由 BSI 进行的审计 <a href="#audit-by-bsi" id="audit-by-bsi"></a>

{% hint style="info" %}
网站和报告均为德语
{% endhint %}

德国安全机构 [BSI (Bundesamt für Sicherheit in der Informationstechnik)](https://www.bsi.bund.de/EN/Home/home_node.html) 在 [CAOS (Codeanalyse von Open Source Software)  项目](https://www.bsi.bund.de/DE/Service-Navi/Publikationen/Studien/Projekt_P486/projekt_P486_node.html)下对 [Vaultwarden v1.30.3](https://github.com/dani-garcia/vaultwarden/releases/tag/1.30.3) 进行了审计。

新闻稿（包含 Vaultwarden 结果的 PDF）可在此处找到：[https: //www.bsi.bund.de/DE/Service-Navi/Presse/Alle-Meldungen-News/Meldungen/Codeanalysis-KeePass-Vaultwarden\_241014 .html](https://www.bsi.bund.de/DE/Service-Navi/Presse/Alle-Meldungen-News/Meldungen/Codeanalyse-KeePass-Vaultwarden_241014.html)

他们甚至还有一个更详细的 ZIP 文件，其中包含所有原始信息： <https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Downloadserver/P486/CAOS_Vaultwarden.html>

作为参考，您可以在这里下载报告：

* [原文 - 德语 - Vaultwarden-Passwordmanager.pdf](https://github.com/user-attachments/files/17805671/Vaultwarden-Passwortmanager.pdf)
* [翻译 - 英语 - Vaultwarden-Passwortmanager.en.pdf](https://github.com/user-attachments/files/17805672/Vaultwarden-Passwortmanager.en.pdf)

## ERNW Enno Rey Netzwerke GmbH 进行的渗透测试 <a href="#penetration-test-by-ernw-enno-rey-netzwerke-gmbh" id="penetration-test-by-ernw-enno-rey-netzwerke-gmbh"></a>

[ERNW Enno Rey Netzwerke GmbH](https://ernw.de/) 在 2024 年 10 月为客户进行的渗透测试中对 Vaultwarden 进行了评估。2024 年 6 月，德国联邦信息安全办公室 (BSI) 公布了 Vaultwarden 服务器组件的静态和动态测试结果。因此，在评估过程中仅进行了部分源代码审计，同时还重点关注了其他软件和基础设施。ERNW 发现了 3 个漏洞，包括身份验证绕过，并负责任地向 Vaultwarden 披露了这些漏洞。ERNW 的博客 Insinuator 对漏洞进行了描述：

* <https://insinuator.net/2024/11/vulnerability-disclosure-authentication-bypass-in-vaultwarden-versions-1-32-5/>


# 3.支持上游的发展

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Supporting-upstream)
{% endhint %}

Vaultwarden 仅提供 API（服务器）端实现，用户仍依赖来自上游的客户端（移动 App、桌面 App 以及网页密码库），这些都是 Bitwarden 公司在上游完成的许多工作。同时 Vaultwarden 支持上游的某些付费功能但免费提供该功能。这就提出了一些有关[维持和支持上游发展的问题](https://github.com/dani-garcia/vaultwarden/issues/331)。许多用户提出了这个问题，并咨询他们如何在使用 Vaultwarden 的同时支持上游的发展。

## 购买订阅 <a href="#buying-a-subscription" id="buying-a-subscription"></a>

许多用户只是为他们的部署[订阅了适当的方案](https://bitwarden.com/pricing/)，而不使用许可证。这也是一种捐赠，因为 Vaultwarden 不能以任何方式使用已购买的许可证。

您还可以通过[从 Bitwarden 商店购买商品](https://bitwarden-shop.myshopify.com/)来支持上游。

## 帮助翻译 App <a href="#help-translating-the-apps" id="help-translating-the-apps"></a>

每一个 App 都有 [Crowdin 项目](https://crowdin.com/profile/kspearrin)。如果您精通英语以外的其他语言，则可以帮助翻译这些 App。

## 测试并报告客户端中的 bug <a href="#testing-reporting-bugs-in-clients" id="testing-reporting-bugs-in-clients"></a>

**请始终先在这里报告发现的 bug。**&#x8FD9;有可能不是上游的 bug，而是我们的实现或者您的配置中的 bug。[我们不想浪费 Kyle 的时间](https://github.com/dani-garcia/vaultwarden/issues/336)来排除第三方服务器上的 bug。在极少数情况下，上游会存在 bug，但是在此阶段，我们将排除其他可能的原因，以及确认上游服务器也存在该 bug。因此，重点是**不要**在上游报告 bug，而是在这里报告它，即使您认为这是客户端问题。我们可以一起查找问题出在哪里。

请参阅我们的 [Bitwarden 客户端故障排除](/faq/troubleshooting/bitwarden-clients-troubleshooting)页面了解更多信息。

## 帮助社区中的其他用户 <a href="#helping-other-users-in-the-community" id="helping-other-users-in-the-community"></a>

有很多新用户有时会遇到一些基础问题。帮助他们是支持此项目（并使社区发展壮大）的一个好方式。根据我在 Vaultwarden 周围的社区经验，很高兴看到人们在我回答他们的问题之前就真正地互相帮助了。这节省了时间，也使我经常学到新的东西。[Reddit 上的 Bitwarden 社区](https://www.reddit.com/r/bitwarden)，以及[官方论坛](https://community.bitwarden.com/)。


# 故障排除


# 1.日志记录

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Logging)
{% endhint %}

默认情况下，Vaultwarden 仅记录到[标准输出](https://zh.wikipedia.org/wiki/%E6%A8%99%E6%BA%96%E4%B8%B2%E6%B5%81) (stdout)。您也可以将它配置为记录到文件或 Syslog。

## 记录到文件 <a href="#logging-to-a-file" id="logging-to-a-file"></a>

从 1.5.0 版本开始支持记录到文件。您可以使用 `LOG_FILE` 环境变量来指定日志文件的路径：

```shellscript
docker run -d --name vaultwarden \
...
  -e LOG_FILE=/data/vaultwarden.log \
...
```

当设置此环境变量时，日志消息将被记录到标准输出和日志文件中。如果您在 Docker 中运行，则需要使用从 Docker 主机挂载的文件路径（如 `data` 文件夹）；否则，如果容器被重新启动或移除，您的日志文件将丢失（或至少难以找回）。

## 记录到 Syslog <a href="#logging-to-syslog" id="logging-to-syslog"></a>

您可以使用 `USE_SYSLOG` 环境变量以使用 Syslog，同时还需要设置 `EXTENDED_LOGGING=true`：

```shell
docker run -d --name vaultwarden \
...
  -e USE_SYSLOG=true -e EXTENDED_LOGGING=true \
..s
```

设置此环境变量后，日志消息将同时记录到 stdout 和 Syslog。

## 更改日志级别 <a href="#change-the-log-level" id="change-the-log-level"></a>

为了减少日志消息的数量，您可以将日志级别设置为 `warn`（默认为 `info`）。[日志级别](https://docs.rs/log/0.4.7/log/enum.Level.html#variants)可使用 `LOG_LEVEL` 环境变量进行调整，同时还需要设置 `EXTENDED_LOGGING=true`。注意：使用日志级别 `warn` 或 `error` 仍然可以让 [Fail2Ban](/configuration/security/fail2ban-setup) 正常工作。

`LOG_LEVEL` 选项包括：`trace`、`debug`、`info`、`warn`、`error` 以及 `off`。

```shell
docker run -d --name vaultwarden \
...
  -e LOG_LEVEL=warn -e EXTENDED_LOGGING=true \
...
```

## 查看日志记录 <a href="#viewing-logs" id="viewing-logs"></a>

如果在 Docker 中运行：`docker logs <container-name>`

如果使用 `systemd` 运行：`journalctl -u vaultwarden.service`（或您的服务名称）

否则，请检查标准输出被重定向到的位置，或设置 `LOG_FILE` 环境变量并查看该文件。


# 2.Bitwarden Android 故障排除

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Bitwarden-Android-troubleshooting)
{% endhint %}

## 通用 <a href="#general" id="general"></a>

自从新的 Bitwarden 移动客户端发布以后，一些问题不断出现。这些问题主要是因为新客户端对服务器返回的 JSON 更加严格。

由于旧客户端不太严格，以及 Vaultwarden 没有（现在仍然没有完全）对所有客户端的输入进行筛选或纠正，以便在 Bitwarden 添加新功能时保持尽可能的灵活。有时存储的数据可能包含无效值。我们会尝试在同步过程中纠正所有这些项目，以尽可能修复所有旧的无效值，并相信客户端会发送正确的新数据。

由于我们无法知道任何客户端生成的所有无效数据，因此开发人员有时很难找出具体的问题所在。为此，我们需要社区的帮助来排查问题并找出罪魁祸首。

以下是一些故障排除指南，可以帮助您找到问题所在，从而自行修复，或帮助开发人员在服务器端修复。

## 首先尝试的事情 <a href="#things-to-try-first" id="things-to-try-first"></a>

首先要确保客户端本地没有无效的缓存 JSON。这是在同步请求完成之前加载的，可能会导致我们无法解决服务器端的问题。

1. 确保安装了最新版本的 Android 客户端。查看已发布的版本：<https://github.com/bitwarden/android/releases>
2. 从移动客户端注销
3. 清除 Bitwarden App 的缓存和数据
4. 卸载 Bitwarden App
5. 为了确保彻底清除，请重启设备
6. 重新安装 Bitwarden App
7. 配置 App 以连接到您的自托管实例
8. 登录并祈祷

如果上述步骤没有解决您的问题，那可能是 Vaultwarden 返回的数据还是存在问题。这种情况下，请继续以下步骤。

## 使用 Flight Recorder <a href="#use-the-flight-recorder" id="use-the-flight-recorder"></a>

最新版的 Bitwarden 移动客户端新增了一项名为 Flight Recording 的功能，旨在帮助排查问题。这项功能对 Vaultwarden 也同样适用，因为它可以帮助显示客户端预期收到但实际未收到的内容。

如需了解关于此功能的更多信息，请访问 Bitwarden 文档：<https://bitwarden.com/help/flight-recorder/>

但请谨慎分享此日志，因为它可能包含个人或隐私信息，例如您的密码库地址。

## 安装 Android 调试工具 (adb) <a href="#install-android-debugging-tools-adb" id="install-android-debugging-tools-adb"></a>

大多数（并非全部）的 Android 设备都可以通过将设备连接到装有合适工具的计算机来提取设备日志。您可以在以下链接中找到各个平台的详细指南以了解如何安装这些工具：<https://www.xda-developers.com/install-adb-windows-macos-linux/>。

**在实际安装工具之前，请先阅读与您的平台相关的所有内容，有时会有多种方法介绍，而第一种方法可能不是最简单的。**

安装这些工具并能连接到您的手机后，继续下一步。

## 实际调试 <a href="#the-actual-debugging" id="the-actual-debugging"></a>

现在一切设置完成，我们开始提取日志，希望这些日志能够帮助追踪问题。

运行以下命令以仅显示 Bitwarden 客户端日志：

```sh
adb logcat --pid=$(adb shell pidof -s com.x8bit.bitwarden)
```

{% hint style="info" %}
您可以通过按 ctrl+c（或 cmd+c）来退出 logcat。
{% endhint %}

{% hint style="success" %}
如果您想在文件中记录所有内容，您至少可以在 Linux 使用如下的附加命令：

```sh
# 直接输出到文件：
> bitwarden-android.log
# 或者，输出到文件并同时输出到屏幕上：
> | tee -a bitwarden-android.log
# 完整的示例：
adb logcat --pid=$(adb shell pidof -s com.x8bit.bitwarden) > bitwarden-android.log
adb logcat --pid=$(adb shell pidof -s com.x8bit.bitwarden) | tee -a bitwarden-android.log
```

{% endhint %}

这应该会开始显示一些日志，如果是，请继续，如果没有，请检查错误信息并尝试解决问题。

现在，随着屏幕上的日志输出，请尝试触发客户端中的错误并检查输出。开发人员需要这些输出来找出问题所在。

### 获取更多详细信息 <a href="#getting-more-details" id="getting-more-details"></a>

如果没有有用的输出，可以通过使用 Bitwarden Dev/Debug Android 客户端来获取更多详细信息。

这些版本是通过 GitHub Actions 构建的，可以在以下链接找到：<https://github.com/bitwarden/android/actions/workflows/build.yml?query=is%3Asuccess>

基本上，任何成功的构建都应包含一个名为 `com.x8bit.bitwarden.dev.apk` 的工件文件。下载此文件，它是一个 zip 文件，解压该 zip 文件，然后安装解压后的 apk 文件。如果您的 Android 设备上有支持 zip 文件的文件管理器，您可以直接在设备上完成此操作。

或者，使用 `adb` 按如下方式安装：

```sh
adb install com.x8bit.bitwarden.dev.apk
```

完成此操作后，您就安装了一个额外的 Bitwarden 客户端，该客户端会输出更详细的日志。

按照您通常登录自托管实例的步骤进行操作。

要从该客户端提取日志，您需要稍微调整一下 `logcat` 命令，使其看起来像这样：

```sh
adb logcat --pid=$(adb shell pidof -s com.x8bit.bitwarden.dev)
```

这会提供更多详细信息，对于追踪问题将非常有帮助。

{% hint style="danger" %}
**Dev 客户端的输出包含由 Vaultwarden 服务器发送的响应，可能包含敏感数据！**

虽然大多数项目都进行了加密，但一些项目如电子邮箱地址或您的 Vaultwarden 域名则没有加密！

**请谨慎分享此输出！**

虽然完整的输出对我们开发者非常有用，有助于故障排除，以及我们无法解密数据，但仍需小心！
{% endhint %}

## 分享结果 <a href="#sharing-the-results" id="sharing-the-results"></a>

我们建议使用以下安全的方式之一分享这些文件：

1. （ ***首选***）通过我们的 Matrix 聊天室：[![Matrix Chat](https://img.shields.io/matrix/vaultwarden:matrix.org.svg?style=flat-square\&logo=matrix\&logoColor=fff\&color=953B00\&cacheSeconds=14400)](https://matrix.to/#/#vaultwarden:matrix.org)
2. 通过电子邮件，发送到 [![security-contact](https://github.com/dani-garcia/vaultwarden/raw/refs/heads/main/.github/security-contact.gif)](https://github.com/dani-garcia/vaultwarden/raw/refs/heads/main/.github/security-contact.gif)，以提供详细信息
3. 通过您自托管的 Vaultwarden 的带有密码的 **Send**（使用 Matrix 或电子邮件分享）

如果您对此主题有任何疑问，请在我们的 [![GitHub Discussions](https://img.shields.io/github/discussions/dani-garcia/vaultwarden?style=flat-square\&logo=github\&logoColor=fff\&color=953B00\&cacheSeconds=300)](https://github.com/dani-garcia/vaultwarden/discussions) 上发起一个新的主题。


# 3.Bitwarden 客户端故障排除

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Bitwarden-clients-troubleshooting)
{% endhint %}

## 通用 <a href="#general" id="general"></a>

如果您在使用任何官方 Bitwarden 客户端时遇到任何问题，尝试在任何 Bitwarden 存储库中报告该问题很可能会导致问题被关闭，并声明他们不支持第三方服务器 - 这确实是合理的做法。

然而有时问题确实源于客户端本身，无法通过服务器端修复，因此Vaultwarden也无能为力。为避免用户在Vaultwarden和Bitwarden之间反复推诿，建议遵循以下步骤定位问题根源，这有助于两个项目共同解决问题。这些步骤看似繁琐，但请记住：必须有人采取行动找出问题所在，而最适合执行测试的人，正是最初发现问题的人。

此外，在报告任何客户端（包括 web-vault）问题之前，请务必测试 Vaultwarden 的 `:testing` 标签镜像。因为 `:testing` 标签镜像可能已经包含了对新客户端的修复，但我们尚未将其视为稳定版本发布。

建议在运行 `:testing` 标签镜像之前备份您的数据库，因为它可能会更新或迁移一些数据，而这些数据与旧服务器版本不兼容！

## 如何排查问题 <a href="#how-to-troubleshoot-an-issue" id="how-to-troubleshoot-an-issue"></a>

最好的做法是创建一个免费的 Bitwarden Cloud 账户，然后尝试使用他们的在线云服务重现相同步骤。如果您可以通过 Bitwarden Cloud 环境重现此问题，请在 Bitwarden 上报告此问题，并说明您使用的是他们的在线云服务。

现在，如果由于某种原因在 Bitwarden Cloud 上无法重现此问题，它可能仍然是一个客户端问题，但与自托管系统相关，而 Bitwarden 也提供了自托管系统。不过，对于大多数用户来说，自托管系统的测试难度较大，因此不建议大多数用户尝试。

## 无法复现时，接下来该做什么？ <a href="#when-unable-to-reproduce-what-to-do-next" id="when-unable-to-reproduce-what-to-do-next"></a>

如果您无法使用 Bitwarden Cloud 重现此问题，并且 Vaultwarden 的 :testing 标签镜像也无效，那么您可能不知道该向哪里报告此问题。

为避免产生大量问题，最好先发起一个[讨论](https://github.com/dani-garcia/vaultwarden/discussions/categories/bitwarden-clients-q-a) ，一旦确定这可能是一个 Vaultwarden 的问题后，我们可以将此讨论转换为问题，或者可能要求您创建一个包含必要步骤和详细信息的新问题。这对用户和开发人员都有帮助。

## 测试客户端的技巧和窍门 <a href="#tips-and-tricks-to-test-clients" id="tips-and-tricks-to-test-clients"></a>

在这里添加一些关于如何排除客户端问题的技巧和窍门或许有所帮助。

我们已经有了一个 Android 客户端页面，其他客户端可能也将陆续跟进。

此外，最新版 Bitwarden 移动客户端有一个名为 Flight Recording（飞行记录仪）的功能，可辅助故障排查。该功能同样适用于Vaultwarden，它可能有助于显示客户端期望但没有接收到的内容。

要了解更多关于此功能的信息，请参阅 Bitwarden 文档：<https://bitwarden.com/help/flight-recorder/>


# 容器镜像的使用


# 1.容器镜像的选择

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Which-container-image-to-use)
{% endhint %}

从版本 1.17.0 开始，`vaultwarden` 提供了一个单一的 Docker 镜像，该镜像对 SQLite、MySQL 和 PostgreSQL 数据库后端提供统一的支持。在该版本之前，每一种数据库后端都有单独的镜像（请参阅[历史镜像](#historical-images)）。

`vaultwarden/server` 是一个多架构镜像，这意味着它在一个镜像名下支持多种 CPU 架构。假设您运行的是支持的架构之一，简单地拉取 `vaultwarden/server` 会自动产生适合您的环境的特定架构的镜像。如果您使用的是 ARMv6 开发板，比如 Raspberry Pi 1 和 Zero，您必须使用 Docker 20.10.0 以及更高版本才能使其正常运行（请参阅 [moby/moby#41017](https://github.com/moby/moby/issues/41017)）。~~运行 Docker 20.10.0 及更高版本的 ARMv6 用户可以像往常一样直接调用 `vaultwarden/server` 多架构镜像。运行早期 Docker 版本的 ARMv6 用户必须在镜像标签中指定 `arm32v6`，例如 `latest-arm32v6`。~~

SQLite 后端是最广泛被使用/测试的后端，除非有特殊需要使用其他数据库后端，否则建议大多数用户使用它。

## 容器注册中心 <a href="#container-registries" id="container-registries"></a>

官方构建镜像可从 3 个不同的容器注册中心获取：

* GitHub：[ghcr.io/dani-garcia/vaultwarden](https://github.com/dani-garcia/vaultwarden/pkgs/container/vaultwarden)
* Docker Hub：[docker.io/vaultwarden/server](https://hub.docker.com/r/vaultwarden/server)
* Quay：[quay.io/vaultwarden/server](https://quay.io/repository/vaultwarden/server)

## 镜像标签 <a href="#image-tags" id="image-tags"></a>

`vaultwarden/server` 镜像有一系列标签，每种标签都代表了镜像的一些变体或属性（例如特定的版本）。

* `latest` - 跟踪最新发布的版本（即标记有版本号）。推荐大多数用户使用这个标签，因为它通常是最稳定的。
* `testing` - 跟踪源代码库的最新提交的版本。这个标签推荐给想要提前获取最新功能或增强功能的用户。测试版一般都很稳定，但不可避免它偶尔也会出现一些问题。
* `x.y.z` (例如 `1.30.0`) - 代表一个特定的发布版本。
* `latest-alpine` - 该镜像功能上与 `latest` 相同，但它是基于 Alpine 而非 Debian，因此镜像更小，基础应用程序更新。选择 `latest` 或 `latest-alpine` 主要是一个喜好问题。
* `x.y.z-alpine` (例如 `1.30.0-alpine`) - 与 `latest-alpine` 类似，但它代表一个特定的发布版本。
* ~~`latest-arm32v6` - 与 `latest` 相同，但明确表示为 `arm32v6` 镜像。目前，对于使用 Armv6 板卡（如 Raspberry Pi 1 和 Zero）的用户来说，需要使用此标签。否则，Docker 会尝试拉取 `arm32v7` 镜像，这将无法正常工作（参阅~~ [~~moby/moby#41017~~](https://github.com/moby/moby/issues/41017)~~）。~~
* ~~`testing-arm32v6` - 与 `testing` 相同，但明确表示为 `arm32v6` 镜像。~~
* ~~`x.y.z-arm32v6` (例如 `1.16.0-arm32v6`) - 与 `latest-arm32v6` 类似，但它代表一个特定的发布版本。~~

## 镜像更新 <a href="#image-updates" id="image-updates"></a>

偶尔，上游的 Bitwarden 项目（即 Bitwarden Inc.）会对客户端做一些向后不兼容的改动，这就需要对服务器的实现做相应的改动。Vaultwarden 一般会及时推送新的版本来适应这些改动。

然而，由于上游控制着客户端的发布，而移动应用和浏览器扩展通常会自己自动更新，因此，对于 Vaultwarden 用户来说，保持更新为最新的 Vaultwarden 版本非常重要。否则，客户端与服务器版本不兼容可能会导致出现意外中断或异常。

网页密码库是唯一的例外：由于网页密码库与 Vaultwarden 镜像捆绑在一起，它的版本总是与 Vaultwarden 服务器的版本相匹配。如果您只把网页密码库用作客户端（可能性不大），那么您就不需要担心这些兼容性问题。

## 历史镜像 <a href="#historical-images" id="historical-images"></a>

在增加对多数据库支持的 v1.17.0 版本之前，MySQL 和 PostgreSQL 的支持仅包含在单独的特定数据库镜像中。您仍可以在 Docker Hub 中找到它们，并且它们现在仍然在更新，但是，这些特定数据库的镜像将来会被移除，因此您应尽快过渡到使用统一的 `vaultwarden/server` 镜像。

* [`bitwardenrs/server-mysql`](https://hub.docker.com/r/bitwardenrs/server-mysql) - 基于 Debian 的 `vaultwarden` 镜像，仅支持 MySQL（不支持 SQLite 和 PostgreSQL）。
* [`bitwardenrs/server-postgresql`](https://hub.docker.com/r/bitwardenrs/server-postgresql) - 基于 Debian 的 `vaultwarden` 镜像，仅支持 PostgreSQL（不支持 SQLite 和 MySQL）。

## 历史标签 <a href="#historical-tags" id="historical-tags"></a>

在增加对多架构支持的 v1.16.0 版本之前，所有特定架构镜像都有其自己的特定架构标签。自 2021-01-14 以来，这些标签已被移除，由于遵循过时的教程或未阅读发行说明，许多用户仍然最终拉取了这些旧的标签。

* `raspberry` - armv7hf 镜像。可以运行在 Raspberry Pi 2 或更新的版本上，也可以运行在任何其他兼容的板子上 。这个镜像不能在 Raspberry Pi 1 或 Raspberry Pi Zero 上运行，因为他们使用的是 armv6 CPU。
* `armv6` - Armv6 镜像。可以运行在 Raspberry Pi 1 和 Raspberry Pi Zero 上。
* `aarch64` - Aarch64 镜像。可以运行在 ARMv8 设备上，例如 Raspberry Pi 3 或其他基于 ARMv8 的设备。

需要**注意**的是，如果你在 Raspberry Pi 3 上使用 Raspbian，它要求在设备上安装 aarch64 发行版，但因为 Raspbian 是一个 `armv7hf` 发行版，您仍然需要使用 `raspberry` 标签。

## 已报告的兼容性表 <a href="#reported-compatibility-table" id="reported-compatibility-table"></a>

如果您在下表中尚未列出的硬件上可以正常运行镜像，请在此处添加您的详细信息。请注意，此处提到的某些镜像不再像上面提到的那样标记。

<table data-full-width="false"><thead><tr><th width="132">使用的硬件</th><th width="112">操作系统</th><th width="122">Docker 架构</th><th width="164">使用的镜像</th><th width="65">状态</th><th>备注</th></tr></thead><tbody><tr><td>常规 64bit 服务器</td><td>Ubuntu 18.04</td><td>x86_64</td><td><code>vaultwarden/server</code></td><td>OK</td><td></td></tr><tr><td>Raspberry Pi Zero W</td><td>Raspbian (4.14.98+)</td><td>linux/arm (armv6l)</td><td><code>vaultwarden/server:armv6</code></td><td>OK</td><td></td></tr><tr><td>Raspberry Pi Zero W</td><td>Raspbian (4.19.66+)</td><td>linux/arm (armv6l)</td><td><code>vaultwarden/server:latest</code> (Multiarch)</td><td>OK</td><td>只有在使用 docker 实验性功能 "docker pull --platform=linux/arm/v6" 时，才能使用。否则会选择错误的镜像 (<a href="https://github.com/dani-garcia/vaultwarden/issues/1064">https://github.com/dani-garcia/vaultwarden/issues/1064</a>)</td></tr><tr><td>Raspberry Pi 1 B</td><td>Raspbian (4.19.97+)</td><td>linux/arm (armv6l)</td><td><code>vaultwarden/server:armv6</code></td><td>OK</td><td></td></tr><tr><td>Raspberry Pi 3 B</td><td>Raspbian (4.14.98-v7+)</td><td>linux/arm (armv7l)</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>Raspberry Pi 4</td><td>Raspbian (4.19.118-v7l+)</td><td>linux/arm (armv7l)</td><td><code>vaultwarden/server:raspberry</code></td><td>OK</td><td>4go 版本, rev 1.1</td></tr><tr><td>Raspberry Pi 5</td><td>Raspberry Pi OS (Debian GNU/Linux 12)</td><td>linux/arm (arm64)</td><td><code>vaultwarden/server:latest</code> and <code>vaultwarden/server:testing-alpine</code></td><td>OK</td><td>测试于 02/16/2024</td></tr><tr><td>Synology</td><td>DSM (DSM 6.2.1-23824 Update 6)</td><td>Docker-x64-17.05.0-0367</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>Synology</td><td>DSM (DSM 6.2.2-24922 Update 4)</td><td>Docker-x64-18.09.0-0506</td><td><code>vaultwarden/server:1.13.0-alpine</code></td><td>OK</td><td></td></tr><tr><td>Synology</td><td>DSM (DSM 7.2-64570 Update 1)</td><td>Docker-20.10.23</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>常规 64bit 服务器</td><td>Unraid 6.8.0</td><td>19.03.5</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>QNAP TS-451DEU (Intel Celeron J4025)</td><td>QTS 5.0.0.1891</td><td>x86_64</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>常规 64bit 服务器</td><td>OpenMediaVault 6 (Debian Bullseye)</td><td>x86_64</td><td><code>vaultwarden/server:alpine</code></td><td>OK</td><td></td></tr><tr><td>Oracle 云基础设施 (OCI) Ampere Altra</td><td>Ubuntu 24.04 LTS</td><td>linux/arm (arm64)</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td></td></tr><tr><td>常规 64bit 服务器</td><td>Debian GNU/Linux 12 (bookworm)</td><td>x86_64</td><td><code>vaultwarden/server:latest</code></td><td>OK</td><td>v1.33.1</td></tr></tbody></table>


# 2.启动容器

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Starting-a-Container)
{% endhint %}

请注意，`docker run` 命令的名字略有误导性，因为它不仅会创建一个容器，它还会启动此容器。当在仅停止容器而不移除此容器后使用 `docker run` 命令时，会导致发生冲突。为了一个简单的开始，请接着往下看。

## 创建容器 <a href="#creating-the-container" id="creating-the-container"></a>

持久性数据存储在容器内的 `/data` 下，因此使用 Docker 进行持久性部署的唯一要求是挂载持久性卷。创建一个本地目录来映射容器的持久存储：

```shell
mkdir /vw-data
```

如果你碰巧使用 SELinux (RHEL & Clones / Fedora)，你必须设置持久存储的上下文，以便容器可以写入它：

```batch
semanage fcontext -a -t svirt_sandbox_file_t '/vw-data(/.*)?'
restorecon -Rv /vw-data
```

```shell
# 使用 Docker：
docker run -d --name vaultwarden -v /vw-data/:/data/ -p 80:80 vaultwarden/server:latest
# 使用 Podman as non-root：
podman run -d --name vaultwarden -v /vw-data/:/data/:Z -e ROCKET_PORT=8080 -p 8080:8080 vaultwarden/server:latest
# 使用 Podman as root：
sudo podman run -d --name vaultwarden -v vw-data:/data/:Z -p 80:80 vaultwarden/server:latest
```

所有持久性数据将保存在 `/vw-data/` 路径下，您可以根据自己的需要调整此路径。

该服务将暴露在主机的 80 或 8080 端口上。默认情况下，非 root 容器不允许使用特权端口 (<1024)，因此需要通过端口映射来传递 `ROCKET_PORT` 环境变量以更改 Vaultwarden 的监听端口。

对于非 x86 硬件或要运行特定版本，可以[选择其他镜像](/container-image-usage/which-container-image-to-use)。

如果您的 docker/vaultwarden 运行在具有固定 IP 的设备上，则可以将主机端口绑定到该 IP 地址，从而避免将主机端口暴露到网络上。如下所示，将 IP 地址（例如 192.168.0.2）添加到主机端口和容器端口前面：

```shell
# 使用 Docker：
docker run -d --name vaultwarden -v /vw-data/:/data/ -p 192.168.0.2:80:80 vaultwarden/server:latest
```

## 启动容器 <a href="#starting-the-container" id="starting-the-container"></a>

如果运行了 `docker stop vaultwarden` 命令，或重启，亦或任何其他原因，容器停止了，则可以使用以下命令将其启动：

```shell
docker start vaultwarden
```

## 自定义容器启动 <a href="#customizing-container-startup" id="customizing-container-startup"></a>

如果您想在容器启动时运行自定义启动脚本，可以将 `/etc/vaultwarden.sh` 作为单个脚本和/或将 `/etc/vaultwarden.d` 作为脚本目录挂载到容器中。对于后一种情况，只有扩展名为 `.sh` 的文件才会运行，因此具有其他扩展名的文件（例如，data/config 文件）则可以驻留在同一个目录中（具体的工作方式请参见 [start.sh](https://github.com/dani-garcia/vaultwarden/blob/main/docker/start.sh)）。

自定义启动脚本对于修补网页密码库文件或安装额外的包、CA 证书等非常有用，因为可以让您不必构建和维护您自己的 Docker 镜像。

### 示例 <a href="#example" id="example"></a>

假设您的脚本名为 `init.sh`，其包含以下内容：

```shell
echo "starting up"
```

您可以像这样在启动时运行此脚本：

```shell
docker run -d --name vaultwarden -v $(pwd)/init.sh:/etc/vaultwarden.sh <other docker args...> vaultwarden/server:latest
```

如果您运行 `docker logs vaultwarden`，现在您应该能看到 `starting up` 作为输出的第一行。

请注意，每次容器启动时都会运行初始化脚本（而不仅仅是第一次），所以这些脚本通常应该是幂等的（即，您可以多次运行这些脚本而不会出现不良/异常）。如果您的脚本天然没有此属性，你可以这样做：

```shell
if [ ! -e /.init ]; then
  touch /.init

  # 运行您的初始化步骤...
fi
```


# 3.使用 Docker Compose

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-Docker-Compose)
{% endhint %}

[Docker Compose](https://docs.docker.com/compose/) 是一个用于定义和配置多容器应用程序的工具。在我们的例子中，我们希望 Vaultwarden 服务器和代理都将 WebSocket 请求重定向到正确的地方。

## 无反向代理/您自己配置的反向代理的最小模板（以下以 Caddy 为例） <a href="#minimal-template-for-no-reverse-proxy-a-reverse-proxy-configured-by-yourself" id="minimal-template-for-no-reverse-proxy-a-reverse-proxy-configured-by-yourself"></a>

此示例假设您已[安装](https://docs.docker.com/compose/install/) Docker Compose。此配置可用于不向「外界」开放的本地服务器，也可用作[反向代理](/reverse-proxy/proxy-examples)的模板。

首先在您喜欢的位置创建一个新目录，然后更改到该目录下。然后，创建 `compose.yml` 文件（旧版本为 `docker-compose.yml`）：

```yaml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      # DOMAIN: "https://vaultwarden.example.com" # 使用反向代理时必填；您的域名；Vaultwarden 需要知道它是 https 才能正确处理附件
      SIGNUPS_ALLOWED: "true" # 创建账户后，使用 "false" 停用此选项，这样就不会有陌生人注册了
卷
    volumes:
      - ./vw-data:/data # : 前面的路径可以修改
    ports:
      - 11001:80 # 您可以将 11001 替换为您喜欢的端口
```

要创建并运行容器，请运行：

```bash
docker compose up -d && docker compose logs -f
```

要更新并运行容器，请运行：

```bash
docker compose pull && docker compose up -d && docker compose logs -f
```

## 带有 HTTP 挑战的 Caddy <a href="#caddy-with-http-challenge" id="caddy-with-http-challenge"></a>

本示例假定您[已安装](https://docs.docker.com/compose/install/) Docker Compose，并且您的 Vaultwarden 实例具有一个可以公开访问的域名（例如 `vaultwarden.example.com`）。

{% hint style="info" %}
Docker Compose 可能以 `docker-compose <command> ...`（带破折号）或 `docker compose <command> ...`（带空格）运行，具体取决于您安装 Docker Compose 的方式。当 Docker Compose 作为独立的可执行文件分发时，`docker-compose` 是原始语法。您也可以选择进行[独立](https://docs.docker.com/compose/install/other/#install-compose-standalone)安装，在这种情况下将继续使用此语法。但是，Docker 目前建议将 Docker Compose 作为 Docker 插件安装，其中 `compose` 作为 `docker` 的子命令，其语法为 `docker compose <command> ...`。
{% endhint %}

首先创建一个新的目录，然后切换到该目录下。接下来，创建如下的 `compose.yml` 文件（旧版本为 `docker-compose.yml`），确保将 `DOMAIN` 和 `EMAIL` 变量替换为实际的值。

```yaml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
      DOMAIN: "https://vaultwarden.example.com"  # 您的域名；Vaultwarden 需要知道它是 https 才能正确处理附件
      SIGNUPS_ALLOWED: "true"
    volumes:
      - ./vw-data:/data

  caddy:
    image: caddy:2
    container_name: caddy
    restart: always
    ports:
      - 80:80  #  ACME HTTP-01 验证需要
      - 443:443
      - 443:443/udp # HTTP/3 需要
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
    environment:
      DOMAIN: "https://vaultwarden.example.com"  # 您的域名，以 http 或 https 作为前缀
      EMAIL: "admin@example.com"                 # 用于 ACME 注册的电子邮件地址
      LOG_FILE: "/data/access.log"
```

在相同的目录下创建如下的 `Caddyfile` 文件（此文件不需要做修改）：

```nginx
{$DOMAIN} {
  log {
    level INFO
    output file {$LOG_FILE} {
      roll_size 10MB
      roll_keep 10
    }
  }

  # 使用 ACME HTTP-01 验证方式为已配置的域名获取证书
  tls {$EMAIL}

  # 此设置可能会在某些浏览器上出现兼容性问题（例如，在 Firefox 上下载附件）
  # 如果遇到问题，请尝试禁用此功能
  encode zstd gzip

  # 将所有代理到 Rocket
  reverse_proxy vaultwarden:80 {
       # 把真实的远程 IP 发送给 Rocket，让 Vaultwarden 把其放在日志中
       # 这样 fail2ban 就可以阻止正确的 IP 了
       header_up X-Real-IP {remote_host}
  }
}
```

运行以下命令创建并启动容器。这将为 `compose.yml` 文件（旧版本为 `docker-compose.yml`）中的服务创建私有网络，这样就只有 Caddy 暴露在外面了：

```shell
docker compose up -d # 或者 'docker-compose up -d' 如果使用独立的 Docker Compose 的话
```

停止并销毁容器：

```shell
docker compose down # 或者 'docker-compose down' 如果使用独立的 Docker Compose 的话
```

[此处](https://github.com/sosandroid/docker-bitwarden_rs-caddy-synology)提供了一个类似的基于 Caddy 的适用于 Synology 的示例。

## 带有 DNS 挑战的 Caddy <a href="#caddy-with-dns-challenge" id="caddy-with-dns-challenge"></a>

这个示例和上一个示例一样，但适用于您不希望您的实例被公开访问的情况（即您只能从您的本地网络访问它）。这个示例使用 Duck DNS 作为 DNS 提供商。更多的背景资料，以及如何设置 Duck DNS 的细节，请参考[使用 Let's Encrypt 证书运行私有 Vaultwarden 实例](/reverse-proxy/https/running-a-private-vaultwarden-instance-with-lets-encrypt-certs)。

首先创建一个新的目录，然后切换到该目录下。接下来，创建如下的 `compose.yml` 文件（旧版本为 `docker-compose.yml`），确保将 `DOMAIN` 和 `EMAIL` 变量替换为实际的值。

```yaml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: always
    environment:
       DOMAIN: "https://vaultwarden.example.com"  # 您的域名；Vaultwarden 需要知道它是 https 才能正确处理附件
    volumes:
       - ./vw-data:/data

  caddy:
    image: caddy:2
    container_name: caddy
    restart: always
    ports:
      - 80:80
      - 443:443
      - 443:443/udp # HTTP/3 需要
    volumes:
      - ./caddy:/usr/bin/caddy  # 您的 Caddy 自定义构建
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./caddy-config:/config
      - ./caddy-data:/data
    environment:
      DOMAIN: "https://vaultwarden.example.com"  # 您的域名，以 http 或 https 作为前缀
      EMAIL: "admin@example.com"                 # 用于 ACME 注册的电子邮件地址
      DUCKDNS_TOKEN: "<token>"                   # 您的 Duck DNS 令牌
      LOG_FILE: "/data/access.log"
```

原有的 Caddy 构建（包括 Docker 映像中的构建）不包含 DNS 挑战模块，因此接下来您需要[获取自定义 Caddy 构建](/reverse-proxy/https/running-a-private-vaultwarden-instance-with-lets-encrypt-certs#getting-a-custom-caddy-build)。将自定义构建重命名为 `caddy` 并将其移动到与 `compose.yml`（旧版本为 `docker-compose.yml`）相同的目录下。确保 `caddy` 文件是可执行的（例如 `chmod a + x caddy`）。上面的 `compose.yml` 文件（旧版本为 `docker-compose.yml`）会将自定义构建绑定挂载到 `caddy:2` 容器中，并替换原有的构建。

在相同的目录下，创建如下的 `Caddyfile` 文件（此文件不需要做修改）。

```nginx
{$DOMAIN} {
  log {
    level INFO
    output file {$LOG_FILE} {
      roll_size 10MB
      roll_keep 10
    }
  }

  # 使用 ACME HTTP-01 验证方式为已配置的域名获取证书
  tls {
    dns duckdns {$DUCKDNS_TOKEN}
  }

  # 此设置可能会在某些浏览器上出现兼容性问题（例如，在 Firefox 上下载附件）
  # 如果遇到问题，请尝试禁用此功能
  encode zstd gzip

  # 将所有代理到 Rocket
  reverse_proxy vaultwarden:80
}
```

与 HTTP 挑战的示例一样，运行下面的命令以创建并启动容器：

```shell
docker compose up -d # 或者 'docker-compose up -d' 如果使用独立的 Docker Compose 的话
```


# 4.使用 Podman

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-Podman)
{% endhint %}

[Podman](https://podman.io/) 是替代 Docker 的无守护程序，它与大部分 Docker 容器兼容。

## 创建 Quadlet（适用于 Podman 4.4+） <a href="#creating-a-quadlet-podman-4.4" id="creating-a-quadlet-podman-4.4"></a>

从版本 4.4 开始，Podman 使用 [quadlets](https://docs.podman.io/en/latest/markdown/podman-systemd.unit.5.html)，如果您使用以前的 `generate systemd` 方法，则会显示一个警告。

额外的好处是此方法将使容器保持更新。

### 通过环境文件配置 <a href="#configuration-via-environment-file" id="configuration-via-environment-file"></a>

在环境文件中进行配置可能会更容易并且不易出错。

注意：此文件包含机密，请确保只有 root 拥有访问权限！

```shell
sudo install -o0 -g0 -m600 /dev/null /etc/vaultwarden.env
sudo vi /etc/vaultwarden.env
```

```systemd
# Contents of /etc/vaultwarden.env
ROCKET_PORT=8080

# DISABLE_ADMIN_TOKEN=true
# ADMIN_TOKEN=$argon2id$...

# LOG_LEVEL=debug
```

### 创建 podman Quadlet <a href="#creating-the-podman-quadlet" id="creating-the-podman-quadlet"></a>

配置看起来像 systemd 的，但我们配置的是容器，而不是单元。请参阅所有 `[Container]` 指令的[文档](https://man.archlinux.org/man/quadlet.5.en#Container_units_%5BContainer%5D)。

```systemd
# Content of /usr/share/containers/systemd/vaultwarden.container
[Unit]
Description=Vaultwarden container
After=network-online.target

[Container]
AutoUpdate=registry
Image=ghcr.io/dani-garcia/vaultwarden:latest
Exec=/start.sh
EnvironmentFile=/etc/vaultwarden.env
Volume=/vw-data/:/data/
PublishPort=8080:8080

[Install]
WantedBy=default.target
```

编辑 quadlet 后，运行 `systemctl daemon-reload` 以创建或更新 systemd 单元。您可以使用常规的 `systemctl` 命令控制此容器，例如 `systemctl start vaultwarden.service` 。

### 自动更新 <a href="#auto-update" id="auto-update"></a>

[自动更新](https://docs.podman.io/en/latest/markdown/podman-auto-update.1.html#description)可自动执行更新过程：

```sh
sudo podman auto-update
```

或者，您可以启用定时器，它会每天自动更新（默认情况。也可以编辑）：

```sh
sudo systemctl enable podman-auto-update.timer
```

## 创建 systemd 服务文件（适用于老版本的 Podman） <a href="#creating-a-systemd-service-file-older-podman-versions" id="creating-a-systemd-service-file-older-podman-versions"></a>

由于 Podman 的无守护程序架构，它比 Docker 更容易在 systemd 中运行。它带有一个便捷的 [generate syetemd 命令](http://docs.podman.io/en/latest/markdown/podman-generate-systemd.1.html)，该命令可以生成 systemd 文件。[这一篇不错的文章详细介绍了它](https://www.redhat.com/zh/blog/podman-shareable-systemd-services)，还有[这篇文章也详细介绍了一些最新的更新](https://www.redhat.com/zh/blog/improved-systemd-podman)。

```systemd
$ podman run -d --name vaultwarden -v /vw-data/:/data/:Z -e ROCKET_PORT=8080 -p 8080:8080 vaultwarden/server:latest
54502f309f3092d32b4c496ef3d099b270b2af7b5464e7cb4887bc16a4d38597
$ podman generate systemd --name vaultwarden
# container-foo.service
# autogenerated by Podman 1.6.2
# Tue Nov 19 15:49:15 CET 2019

[Unit]
Description=Podman container-foo.service
Documentation=man:podman-generate-systemd(1)

[Service]
Restart=on-failure
ExecStart=/usr/bin/podman start vaultwarden
ExecStop=/usr/bin/podman stop -t 10 vaultwarden
KillMode=none
Type=forking
PIDFile=/run/user/1000/overlay-containers/54502f309f3092d32b4c496ef3d099b270b2af7b5464e7cb4887bc16a4d38597/userdata/conmon.pid

[Install]
WantedBy=multi-user.target default.target
```

您可以提供 `--files` 标志告诉 podman 将 systemd 服务放到某个文件中，或使用 `podman generate systemd --name vaultwarden > /etc/systemd/system/container-vaultwarden.service`。这样，我们就可以像任何正常的服务文件一样启用和启动容器了。

```shell
$ systemctl --user enable /etc/systemd/system/container-vaultwarden.service
$ systemctl --user start container-vaultwarden.service
```

### 每次重启时新建容器 <a href="#new-container-every-restart" id="new-container-every-restart"></a>

如果我们希望每次服务启动时都创建一个新的容器，可以使用 `podman generate systemd --new` 命令生成一个重新创建容器的服务文件：

```shell
$ podman generate systemd --new --name vaultwarden
```

如果您使用的是旧版 Podman，则可以编辑服务文件以包含如下内容：

```systemd
[Unit]
Description=Podman container-vaultwarden.service

[Service]
Restart=on-failure
ExecStartPre=/usr/bin/rm -f /%t/%n-pid /%t/%n-cid
ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /%t/%n-cid --env-file=/home/spytec/Vaultwarden/vaultwarden.conf -d -p 8080:8080 -v /home/spytec/Vaultwarden/vw-data:/data/:Z vaultwarden/server:latest
ExecStop=/usr/bin/podman stop -t "15" --cidfile /%t/%n-cid
ExecStop=/usr/bin/podman rm -f --cidfile /%t/%n-cid
KillMode=none
Type=forking
PIDFile=/%t/%n-pid

[Install]
WantedBy=multi-user.target default.target
```

环境文件 `vaultwarden.conf` 可以包含您需要的容器的所有环境值，比如：

```systemd
ROCKET_PORT=8080
```

如果您希望此容器拥有特定的名称，则需要添加 `ExecStartPre=/usr/bin/podman rm -i -f vaultwarden`，如果进程未被正确清理的话。注意，此方式当前无法与具有 `User=` 选项的用户一起正常工作（见 [https://github.com/containers/podman/issues/5572](https://github.com/wcjxixi/Vaultwarden-Wiki-Chn/blob/master/container-image-usage/%20https:/github.com/containers/podman/issues/5572/README.md)）。

## 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>

### 调试 systemd 服务文件 <a href="#debugging-systemd-service-file" id="debugging-systemd-service-file"></a>

如果主机出现故障或容器崩溃，则 systemd 服务文件应自动停止现有容器并将其重新启动。可以通过 `journalctl --user -u container-vaultwarden -t 100` 来定位错误。

在大多数情况下，我们可以通过简单地增加服务文件中的 podman 命令的超时时间来解决我们看到的错误。

### 充分利用 Vaultwarden 和数据库的 quadlet 文件

应用程序和 PostgreSQL 数据库被容器化并放置在 pod 中。应用程序通过 Podman 网络功能使用自己的网络。持久卷用于数据库数据和 Vaultwarden 应用程序数据。部署容器使用的机密由 Podman 机密功能管理。

{% @mermaid/diagram content="flowchart TD
A(vaultwarden.network) --- B(vaultwarden.pod)
B --- C(vaultwarden-app.container)
B --- D(vaultwarden-db.container)
C --- G\[/env\_file=/etc/vaultwarden/config/]
C --- E\[(vaultwarden-app.volume)]
D --- F\[(vaultwarden-db.volume)]
D --- H\[/env\_file=/home/vaultwarden/vaultwarden/vaultwarden-db.env/]
C --- I{{podman-secret: database\_url, admin\_token}}
D --- J{{podman-secret: postgres\_password}}
style A fill:#ffec99
style B fill:#ffc9c9
style C fill:#b2f2bb
style D fill:#b2f2bb
style E fill:#a5d8ff
style F fill:#a5d8ff
style G fill:#f08c00
style H fill:#f08c00
style I fill:#d0bfff
style J fill:#d0bfff" %}

该基础设施使用以下 quadlet 文件定义：

* `vaultwarden-app.container`
* `vaultwarden-app.volume`
* `vaultwarden-db.container`
* `vaultwarden-db.volume`
* `vaultwarden.network`
* `vaultwarden.pod`

#### Pod 的定义 <a href="#definition-of-the-pod" id="definition-of-the-pod"></a>

创建 `~/.config/containers/systemd/vaultwarden.pod` 文件：

```systemd
[Pod]
PodName=vaultwarden
Network=vaultwarden.network
PublishPort=8080:8080
```

#### 网络的定义 <a href="#definition-of-the-network" id="definition-of-the-network"></a>

创建 `~/.config/containers/systemd/vaultwarden.network` 文件：

```systemd
[Network]
NetworkName=vaultwarden
Gateway=192.168.220.1
Subnet=192.168.220.0/24
```

#### 持久卷的定义 <a href="#definition-of-the-persistent-volumes" id="definition-of-the-persistent-volumes"></a>

创建 `~/.config/containers/systemd/vaultwarden-app.volume` 文件：

```systemd
[Volume]
VolumeName=vaultwarden-app
```

以及 `~/.config/containers/systemd/vaultwarden-db.volume` 文件：

```systemd
[Volume]
VolumeName=vaultwarden-db
```

#### 容器的定义 <a href="#definition-of-the-containers" id="definition-of-the-containers"></a>

创建 `~/.config/containers/systemd/vaultwarden-app.container` 文件：

```systemd
[Container]
ContainerName=vaultwarden-app
EnvironmentFile=/etc/vaultwarden/config
HealthCmd=/healthcheck.sh
HealthInterval=120s
HealthRetries=10
HealthTimeout=45s
Image=docker.io/vaultwarden/server:1.34.3
Pod=vaultwarden.pod
Secret=database_url,type=env,target=DATABASE_URL
Secret=admin_token,type=env,target=ADMIN_TOKEN
Volume=vaultwarden-app.volume:/data
[Unit]
Requires=vaultwarden-db.service
After=vaultwarden-db.service

[Install]
WantedBy=default.target
```

以及 `~/.config/containers/systemd/vaultwarden-db.container` 文件：

```systemd
[Container]
ContainerName=vaultwarden-db
EnvironmentFile=/home/vaultwarden/vaultwarden/vaultwarden-db.env
HealthCmd=/usr/bin/pg_isready -q -d vaultwarden -U vaultwarden
HealthInterval=120s
HealthRetries=10
HealthTimeout=45s
Image=docker.io/library/postgres:17
Pod=vaultwarden.pod
Secret=postgres_password,type=env,target=POSTGRES_PASSWORD
Volume=vaultwarden-db.volume:/var/lib/postgresql/data

[Install]
WantedBy=default.target
```

#### 配置 <a href="#configuration" id="configuration"></a>

使用环境文件 `/etc/vaultwarden/config` 和 `~/vaultwarden/vaultwarden-db.env` 完成配置。

在 `~/vaultwarden/vaultwarden-db.env` 文件中设置变量 `POSTGRES_USER` 和 `POSTGRES_DB` 。

#### 机密 <a href="#secrets" id="secrets"></a>

您需要定义机密 `postgres_password`、`database_url` 和 `admin_token`：

我假设 `POSTGRES_USER=vaultwarden` 和 `POSTGRES_DB=vaultwarden`&#x20;

```bash
openssl rand -base64 32|podman secret create postgres_password -
echo "postgres://vaultwarden:$(podman secret inspect --showsecret --format '{{.SecretData}}' postgres_password)@vaultwarden-db/vaultwarden" | tr -d '\n' | podman secret create database_url -
echo -n "MySecretPassword" | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4| tr -d '\n' | podman secret create admin_token -
```

#### 部署 <a href="#deploy" id="deploy"></a>

```bash
systemctl --user daemon-reload
systemctl --user start vaultwarden-pod.service
```


# 5.更新 Vaultwarden 镜像

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Updating-the-vaultwarden-image)
{% endhint %}

更新非常简单，您只需确保保留了已挂载的卷。如果您使用[此处](/container-image-usage/starting-a-container)示例中的 bind-mounted 路径（绑定挂载路径）的方式，则只需使用 `pull` 拉取最新版本的镜像，再使用 `stop` 和 `rm` 来停止和移除当前容器，然后与之前相同的方式启动一个新的容器即可：

```shell
# 拉取最新版本的镜像
docker pull vaultwarden/server:latest

# 停止并移除旧版本容器
docker stop vaultwarden
docker rm vaultwarden

# 使用已挂载的数据启动容器
docker run -d --name vaultwarden -v /vw-data/:/data/ -p 80:80 vaultwarden/server:latest
```

然后访问 [http://localhost:80](http://localhost/)

如果您没有为持久性数据绑定挂载卷，则多一个中间步骤，就是使用中间容器来保留数据：

```shell
# 拉取最新版本的镜像
docker pull vaultwarden/server:latest

# 创建中间容器以保留数据
docker run --volumes-from vaultwarden --name vaultwarden_data busybox true

# 停止并移除旧版本容器
docker stop vaultwarden
docker rm vaultwarden

# 使用已挂载的数据启动容器
docker run -d --volumes-from vaultwarden_data --name vaultwarden -p 80:80 vaultwarden/server:latest

# 移除中间容器（可选）
docker rm vaultwarden_data

# 您可以保留数据容器以用于将来的更新，这样的话，可以跳过最后的移除中间容器这一步。
```

您也可以使用 [Watchtower](https://containrrr.dev/watchtower/) 这样的工具来自动化更新过程。Watchtower 可以定期检查 Docker 镜像的更新，拉取更新后的镜像，并使用更新后的镜像重新创建容器。

## 使用 Docker Compose 时的更新 <a href="#updating-when-using-docker-compose" id="updating-when-using-docker-compose"></a>

```shell
docker compose pull # 或者 `docker-compose pull` 如果使用后独立的 Docker Compose 的话
docker compose up -d # 或者 `docker-compose up -d` 如果使用后独立的 Docker Compose 的话
```

## 使用 systemd 服务时的更新（在本例中为 Debian/Raspbian） <a href="#updating-when-using-systemd-service-in-this-case-debian-raspbian" id="updating-when-using-systemd-service-in-this-case-debian-raspbian"></a>

```shell
sudo systemctl restart vaultwarden.service
sudo docker system prune -f
# 警告！这将删除已停止或未使用的容器，例如与 Vaultwarden 无关的容器
# 请仔细查看哪个容器是您需要的

docker ps -a
# 查看已停止的容器

#WARNING! This will remove:
#        - all stopped #containers
#        - all networks not used by at least one container
#        - all dangling images
#        - all dangling build cache
# 使用以下命令列出所有 Docker 镜像
docker images
# 这里您将看到所有未使用的镜像
#
```

`restart` 命令将会依次停止容器、提取最新镜像、然后运行容器。`prune` 命令将会移除当前较旧的容器（`-f` 表示不需要确认）。

如果需要，可以将它们放入 cronjob 中以计划任务自动运行（根据您的需要修改时间）：

```shell
$ sudo crontab -e
0 2 * * * sudo systemctl restart vaultwarden.service

0 3 * * * sudo /usr/bin/docker system prune -f
```

如果 `/usr/bin/docker` 不是 docker 的正确路径，可以使用 `which docker` 命令查看它的实际路径。

## 使用 DietPi 时的更新 <a href="#updating-when-using-dietpi" id="updating-when-using-dietpi"></a>

[DietPi](https://dietpi.com/) 是一个轻量级的基于 Debian 的发行版（镜像），适用于各种设备，例如 Raspberry Pi、Odroid、NanoPi 等。它提供了一个软件脚本，用于安装包括 Vaultwarden 在内的各种程序。这样可以让用户免去使用安装命令的烦恼。

Vaultwarden 的更新必须由用户在 DietPi 上手动启动，没有自动安装方式，运行 `apt update && apt upgrade` 也不会执行更新。要更新以前使用 DietPi 软件安装脚本安装的 Vautwarden 实例，请在 DietPi 的命令行中输入以下命令：

```sh
dietpi-software reinstall 183
```

建议使用 DietPi 8.7 或更新版本，因为与以前的版本相比，更新过程已大大加快。

如果您自定义了 Vaultwarden 的配置文件，它将被更新脚本保留。


# 反向代理


# 1.代理示例

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Proxy-examples)
{% endhint %}

以下是用户收集的不同[反向代理](https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BB%A3%E7%90%86)配置示例列表。我们建议使用反向代理终止 TLS/SSL 连接（最好是 443 端口，即 HTTPS 的标准端口），而不是使用 Vaultwarden 内置的 HTTPS 功能。有关更多信息，请参阅[启用 HTTPS](/reverse-proxy/https/enabling-https)。

在本文档中，我们假设您在与反向代理相同的主机上运行 Vaultwarden。如果您将 Vaultwarden 作为一个容器运行，假设您已经向主机发布了 `-p 127.0.0.1:8000:80`，因为容器内的 Vaultwarden 已经被配置为监听所有 IPv4 接口（`ROCKET_ADDRESS=0.0.0.0`）上的 `80` 端口（通过 `ROCKET_PORT`）。

示例还假定您没有加密反向代理和 Vaultwarden 之间的连接，即没有配置 `ROCKET_TLS`，因此反向代理可以直接通过 `http://127.0.0.1:8000` 连接到 Vaultwarden。

如果您使用 [Docker Compose](https://docs.docker.com/compose/) 将容器化的服务（例如，Vaultwarden 与反向代理）链接在一起，您必须调整示例代码以考虑到这一点（例如，将 `127.0.0.1:8000` 改为 `service_name:80`，而 `service_name` 通常是 `vaultwarden`）。请参阅[使用 Docker Compose](/container-image-usage/using-docker-compose) 了解这方面的示例。

{% hint style="success" %}
可以使用 Mozilla 的 [SSL Configuration Generator](https://ssl-config.mozilla.org/) 来生成用于网页服务器的安全 TLS 协议和密码配置。已知所有受支持的浏览器和移动应用程序都可以使用这种「现代化的」配置。
{% endhint %}

***

<details>

<summary>Caddy 2.x</summary>

在大多数情况下 Caddy 2 会自动启用 HTTPS，参考[此文档](https://caddyserver.com/docs/automatic-https#activation)。

在 Caddyfile 语法中，`{$VAR}` 表示环境变量 `VAR` 的值。如果您喜欢，也可以直接指定一个值，而不是用一个环境变量的值来代替。

```nginx
# 取消注释以下语句以及取消注释 import admin_redir 语句，以仅允许从本地网络访问管理界面
# {
#        servers {
#                trusted_proxies static private_ranges
#                client_ip_headers X-Forwarded-For X-Real-IP
#                # client_ip_headers CF-Connecting-IP X-Forwarded-For X-Real-IP
#                # If using Cloudflare proxy, insert CF-Connecting-IP as first priority
#                # since Cloudflare doesn't prevent X-Forwarded-For spoofing.
#        }
# }
# (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
    }
  }

  # 如果您想通过 ACME（Let's Encrypt 或 ZeroSSL）获取证书，请取消注释
  # tls {$EMAIL}

  # 或者如果您提供自己的证书，请取消注释
  # 如果您在 Cloudflare 后面运行，您也会使用此选项
  # tls {$SSL_CERT_PATH} {$SSL_KEY_PATH}

  # 此设置可能会在某些浏览器上出现兼容性问题（例如，在 Firefox 上下载附件）
  # 如果遇到问题，请尝试禁用此功能
  encode zstd gzip
  
  # 取消注释以提高安全性（警告：只有在您了解其影响的情况下才能使用！）
  # 如果您想使用 FIDO2 WebAuthn，请将 X-Frame-Options 设置为 "SAMEORIGIN"，否则浏览器将阻止这些请求
  # header / {
  #	# 启用 HTTP Strict Transport Security (HSTS)
  #	Strict-Transport-Security "max-age=31536000;"
  #	# 禁用 cross-site filter (XSS)
  #	X-XSS-Protection "0"
  #	# 禁止在框架内呈现网站 (clickjacking protection)
  #	X-Frame-Options "DENY"
  #	# 阻止搜索引擎建立索引（可选）
  #	X-Robots-Tag "noindex, nofollow"
  #	# 禁止嗅探 X-Content-Type-Options
  #	X-Content-Type-Options "nosniff"
  #	# 服务器名称移除
  #	-Server
  #	# 移除 X-Powered-By，虽然这不应该是一个问题，但最好移除
  #	-X-Powered-By
  #	# 移除 Last-Modified，因为 etag 相同并且同样有效
  #	-Last-Modified
  # }
  
  # 取消注释以仅允许从本地网络访问管理界面
  # import admin_redir
  
  # 取消注释以只允许从指定的转发 IP（例如 Cloudflare 代理）访问管理界面
  # @not_allowed_admin {
  #     path /admin*
  #     Trusted IPs one and two
  #     not client_ip xx.xx.xx.xx/32 xx.xx.xx.xx/32
  #     # remote_ip's forwarded mode is deprecated; client_ip matcher with global options client_ip_headers and trusted_proxies
  # }

  # respond @not_allowed_admin "401 - {http.request.header.Cf-Connecting-Ip} is not an allowed IP." 401

  # 将所有代理到 Rocket
  # 如果位于子路径中，则 reverse_proxy 行将如下所示：
  # reverse_proxy /vault/* 127.0.0.1:8000
  reverse_proxy 127.0.0.1:8000 {
       # 把真实的远程 IP 发送给 Rocket，以便 Vaultwarden 将其放入日志中，
       # 这样 fail2ban 就可以阻止正确的 IP 了
       header_up X-Real-IP {remote_host}
       # 如果您使用 Cloudflare 代理，请将 remote_host 替换为 http.request.header.Cf-Connecting-Ip
       # 如果使用全局选项 'client_ip_headers CF-Connecting-IP' 则不需要
       # 请参阅 https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/
       # 以及 https://caddy.community/t/forward-auth-copy-headers-value-not-replaced/16998/4
  }
}
```

</details>

<details>

<summary><del>lighttpd (by forkbomb9)</del></summary>

```nginx
erver.modules += ( "mod_proxy" )

$HTTP["host"] == "vault.example.net" {
    $HTTP["url"] == "/notifications/hub" {
       # WebSocket proxy
       proxy.server  = ( "" => ("vaultwarden" => ( "host" => "<SERVER>", "port" => 3012 )))
       proxy.forwarded = ( "for" => 1 )
       proxy.header = (
           "https-remap" => "enable",
           "upgrade" => "enable",
           "connect" => "enable"
       )
    } else {
       proxy.server  = ( "" => ("vaultwarden" => ( "host" => "<SERVER>", "port" => 4567 )))
       proxy.forwarded = ( "for" => 1 )
       proxy.header = ( "https-remap" => "enable" )
    }
}
```

在 Vaultwarden 环境中，您必须将 `IP_HEADER` 设置为 `X-Forwarded-For` 而不是 `X-Real-IP`。

</details>

<details>

<summary>lighttpd with sub-path (by FlakyPi)</summary>

在这个示例中，通过 <https://shared.example.tld/vault/> 访问 Vaultwarden。如果您想使用其他子路径，如 `vaultwarden` 或 `secret-vault`，则应更修改下面示例中的 `vault` 以匹配。

您还需要在 `DOMAIN` 环境变量的值中包含子路径（例如 `DOMAIN: "https://shared.example.tld/vault"`），才能使代理正常工作。

```nginx
server.modules += (
"mod_openssl",
"mod_redirect"
)

$SERVER["socket"] == ":443" {  
    ssl.engine   = "enable"   
    ssl.pemfile  = "/etc/letsencrypt/live/shared.example.tld/fullchain.pem"
    ssl.privkey  = "/etc/letsencrypt/live/shared.example.tld/privkey.pem"
}

# Redirect HTTP requests (port 80) to HTTPS (port 443)
$SERVER["socket"] == ":80" {  
    $HTTP["host"] =~ "shared.example.tld" {  
         url.redirect = ( "^/(.*)" => "https://shared.example.tld/$1" )  
         server.name = "shared.example.tld"   
    }  
}

server.modules += ( "mod_proxy" )

$HTTP["host"] == "shared.example.tld" {
    $HTTP["url"] =~ "/vault" {
       proxy.server  = ( "" => ("vaultwarden" => ( "host" => "127.0.0.1", "port" => 8000 )))
       proxy.forwarded = ( "for" => 1 )
       proxy.header = (
           "https-remap" => "enable",
           "upgrade" => "enable",
           "connect" => "enable"
       )
    }
}
```

您必须将 Vaultwarden 环境配置中的 `IP_HEADER` 设置为 `X-Forwarded-For` 而不是默认的 `X-Real-IP`。

</details>

<details>

<summary>Nginx (by <a href="https://github.com/BlackDex">@BlackDex</a>)</summary>

```nginx
# 'upstream' 指令确保您有一个 http/1.1 连接
# 这里启用了 keepalive 选项以拥有更好的性能
#
# 此处定义服务器的 IP 和端口。
upstream vaultwarden-default {
  zone vaultwarden-default 64k;
  server 127.0.0.1:8000;
  keepalive 2;
}

# 要支持 websocket 连接的话才需要
# 参阅：https://nginx.org/en/docs/http/websocket.html
# 我们不发送上述链接中所说的 "close"，而是发送一个空值，
# 否则所有的 keepalive 连接都将无法工作。
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      "";
}

# 将 HTTP 重定向到 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name vaultwarden.example.tld;

    return 301 https://$host$request_uri;
}

server {
    # 对于旧版本的 nginx，在 ssl 后面的 listen 行中加入 http2，并移除 'http2 on'
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name vaultwarden.example.tld;

    # 根据需要指定 SSL 配置
    #ssl_certificate /path/to/certificate/letsencrypt/live/vaultwarden.example.tld/fullchain.pem;
    #ssl_certificate_key /path/to/certificate/letsencrypt/live/vaultwarden.example.tld/privkey.pem;
    #ssl_trusted_certificate /path/to/certificate/letsencrypt/live/vaultwarden.example.tld/fullchain.pem;
    #add_header Strict-Transport-Security "max-age=31536000;";

    client_max_body_size 525M;

    location / {
    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;
    # 如果您使用 Cloudflare 代理，请将 $remote_addr 替换为 $http_cf_connecting_ip
    # 参阅 https://developers.cloudflare.com/support/troubleshooting/restoring-visitor-ips/restoring-original-visitor-ips/#nginx-1
    # 或者使用 ngx_http_realip_module
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;

    location / {
      proxy_pass http://vaultwarden-default;
    }

    # 除了 ADMIN_TOKEN 之外，还可以选择添加额外的身份验证
    # 删除下面的 '#' 注释并创建 htpasswd_file 以使其处于活动状态
    #
    #location /admin {
    #  # 参阅：https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/
    #  auth_basic "Private";
    #  auth_basic_user_file /path/to/htpasswd_file;
    #
    #  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;
    #}
}
```

如果遇到 504 Gateway Timeout（网关超时）故障，可以通过在 `server {` 部分添加更长的超时时间来告诉 nginx 等待 Vaultwarden 的时间，例如：

```nginx
  proxy_connect_timeout       777;
  proxy_send_timeout          777;
  proxy_read_timeout          777;
  send_timeout                777;
```

</details>

<details>

<summary>Nginx with sub-path (by <a href="https://github.com/BlackDex">@BlackDex</a>)</summary>

在这个示例中，Vaultwarden 的访问地址为 `https://shared.example.tld/vault/`，如果您想使用任何其他的子路径，比如 `vaultwarden` 或 `secret-vault`，您需要更改下面示例中相应的地方。

为此，您需要配置 `DOMAIN` 变量以使其匹配，它应类似于：

```systemd
; 添加子路径！否则将无法正常工作！
DOMAIN=https://shared.example.tld/vault/
```

```nginx
# 'upstream' 指令确保您有一个 http/1.1 连接
# 这里启用了 keepalive 选项以拥有更好的性能
#
# 此处定义服务器的 IP 和端口
upstream vaultwarden-default {
  zone vaultwarden-default 64k;
  server 127.0.0.1:8000;
  keepalive 2;
}

# 需要这些以支持 websocket 连接
# 参阅：https://nginx.org/en/docs/http/websocket.html
# 我们发送的是空值，而不是上述链接中的 "close"
# 否则所有 keepalive 连接都将失效
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      "";
}

# 将 HTTP 重定向到 HTTPS
server {
    listen 80;
    listen [::]:80;
    server_name shared.example.tld;

    location /vault/ { # <-- 替换为所需的子路径
        return 301 https://$host$request_uri;
    }
    
    # 如果您想对整个域名而不是只对 Vaultwarden 强制 HTTPS，
    # 那么您可以使用下面的内容代替上面的 location 块：
    return 301 https://$host$request_uri;
}

server {
    # 对于旧版本的 nginx，在 ssl 后面的 listen 行中加入 http2，并移除 'http2 on;'
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    server_name shared.example.tld;

    # 根据需要指定 SSL 配置
    #ssl_certificate /path/to/certificate/letsencrypt/live/shared.example.tld/fullchain.pem;
    #ssl_certificate_key /path/to/certificate/letsencrypt/live/shared.example.tld/privkey.pem;
    #ssl_trusted_certificate /path/to/certificate/letsencrypt/live/shared.example.tld/fullchain.pem;
    #add_header Strict-Transport-Security "max-age=31536000;";

    client_max_body_size 525M;

    ## 使用子路径配置
    # 您的安装的 root 目录的路径
    # 请务必添加尾部的 /，否则您可能会遇到问题
    # 但仅限于这个位置，所有其他位置不应添加这些内容
    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;
    }

    # 除了 ADMIN_TOKEN 之外，还可以选择添加额外的身份验证
    # 删除下面的 '#' 注释并创建 htpasswd_file 以使其处于活动状态
    #
    # 不要添加尾部的/，否则您会遇到问题
    #location /vault/admin {
    #  # 参阅：https://docs.nginx.com/nginx/admin-guide/security-controls/configuring-http-basic-authentication/
    #  auth_basic "Private";
    #  auth_basic_user_file /path/to/htpasswd_file;
    #
    #  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;
    #}
}
```

</details>

<details>

<summary><del>Nginx configured by Ansible/DebOps (by ypid)</del></summary>

使用 [DebOps](https://debops.org) 配置 nginx 作为 Vaultwarden 的反向代理的清单示例。我选择在 URL 中使用 PSK 以获得额外的安全性，从而不会将 API 暴露给 Internet 上的每个人，因为客户端应用程序尚不支持客户端证书（我测试过）。 参考[强化指南 - 隐藏在子目录下](/configuration/security/hardening-guide#hiding-under-a-subdir)

```nginx
vaultwarden__fqdn: 'vault.example.org'
vaultwarden__http_psk_subpath_enabled: True
vaultwarden__http_psk_subpath: '{{ lookup("password", secret + "/vaultwarden/" +
                                     inventory_hostname + "/config/subpath chars=ascii_letters,digits length=23")
                                   if vaultwarden__http_psk_subpath_enabled | bool
                                   else "" }}'

nginx__upstreams:

  - name: 'vaultwarden-default'
    type: 'default'
    enabled: True
    server: 'localhost:8000'

  - name: 'vaultwarden-ws'
    type: 'default'
    enabled: True
    server: 'localhost:3012'

nginx__servers:

  - name: '{{ vaultwarden__fqdn }}'
    filename: 'debops.vaultwarden'
    by_role: 'debops.vaultwarden'
    favicon: False
    # root: '/usr/share/vaultwarden/web-vault'

    location_list:

      - pattern: '/'
        options: |-
          deny all;

      - pattern: '= /{{ vaultwarden__http_psk_subpath }}'
        options: |-
          return 307 $scheme://$host$request_uri/;

      ## 所有安全 HTTP 标头也需要由 nginx 设置。
      # - pattern: '/{{ vaultwarden__http_psk_subpath }}/'
      #   options: |-
      #     alias /usr/share/vaultwarden/web-vault/;

      - pattern: '/{{ vaultwarden__http_psk_subpath }}/'
        options: |-
          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_set_header X-Forwarded-Port  443;

          proxy_pass http://vaultwarden-default;

      - pattern: '/{{ vaultwarden__http_psk_subpath }}/notifications/hub/negotiate'
        options: |-
          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_set_header X-Forwarded-Port  443;

          proxy_pass http://vaultwarden-default;

      - pattern: '/{{ vaultwarden__http_psk_subpath }}/notifications/hub'
        options: |-
          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_set_header X-Forwarded-Port  443;

          proxy_pass http://vaultwarden-ws;

      # 不要使用图标功能，因为它会显示从我们的凭据到服务器的所有域名
      - pattern: '/{{ vaultwarden__http_psk_subpath }}/icons/'
        options: |-
          access_log off;
          log_not_found off;
          deny all;
```

</details>

<details>

<summary>Nginx (NixOS) (by tklitschi, samdoshi)</summary>

NixOS Nginx 配置示例。关于 NixOS 部署的更多信息，请参阅[部署示例](/alternative-deployments/deployment-examples)页面。

```nginx
{ config, ... }:
{
  security.acme = {
    defaults = {
      acceptTerms = true;
      email = "me@example.com";
    };
    certs."vaultwarden.example.tld".group = "vaultwarden";
  };

  services.nginx = {
    enable = true;

    recommendedGzipSettings = true;
    recommendedOptimisation = true;
    recommendedProxySettings = true;
    recommendedTlsSettings = true;

    virtualHosts = {
      "vaultwarden.example.ltd" = {
        enableACME = true;
        forceSSL = true;
        locations."/" = {
          proxyPass = "http://127.0.0.1:8000";
          proxyWebsockets = true;
        };
      };
    };
  };
}
```

</details>

<details>

<summary>Nginx with proxy_protocol in front (by dionysius)</summary>

在这个例子中，有一个下游代理在[这个 nginx 前面的 proxy\_protocol](https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/) 中进行通信（例如，[启用了 proxy\_protocol 的 LXD 代理设备](https://linuxcontainers.org/lxd/docs/master/reference/devices_proxy/)）。Nginx 需要从这里设置正确使用协议和要转发的标头。标有 `# <---` 的行与 blackdex 的示例内容不同。

参考这个 LXD 下游代理设备配置：

```nginx
devices:
  http:
    connect: tcp:[::1]:80
    listen: tcp:[::]:80
    proxy_protocol: "true"
    type: proxy
  https:
    connect: tcp:[::1]:443
    listen: tcp:[::]:443
    proxy_protocol: "true"
    type: proxy
```

<pre class="language-nginx"><code class="lang-nginx"># proxy_protocol 相关:

set_real_ip_from ::1; # 要信任哪个下游代理，请在前面输入您的代理地址
real_ip_header proxy_protocol; # 可选。如果您希望 nginx 使用来自 proxy_protocol 的信息覆盖 remote_addr。 取决于您在日志模板和服务器或流块中使用的关于远程地址的变量。

# 以下基于 blackdex 的示例:

# 'upstream' 指令确保您有一个 http/1.1 连接
# 这里启用了 keepalive 选项以拥有更好的性能
#
# 这里定义服务器 IP 和端口
upstream vaultwarden-default {
  zone vaultwarden-default 64k;
  server 127.0.0.1:8000;
  keepalive 2;
}
# 需要这些以支持 websocket 连接
# 参阅：https://nginx.org/en/docs/http/websocket.html
# 我们发送的是空值，而不是上述链接中的 "close"
# 否则所有 keepalive 连接都将失效
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      "";
}

# HTTP 重定向到 HTTPS
server {
    listen 80 proxy_protocol; # &#x3C;---
    listen [::]:80 proxy_protocol; # &#x3C;---
    server_name shared.example.tld;
    
    return 301 https://$host$request_uri;
}

server {
<strong>    listen 443 ssl proxy_protocol; # &#x3C;---
</strong>    listen [::]:443 ssl proxy_protocol; # &#x3C;---
    http2 on;
    server_name shared.example.tld;

    # 需要时指定 SSL Config
    #ssl_certificate /path/to/certificate/letsencrypt/live/shared.example.tld/fullchain.pem;
    #ssl_certificate_key /path/to/certificate/letsencrypt/live/shared.example.tld/privkey.pem;
    #ssl_trusted_certificate /path/to/certificate/letsencrypt/live/shared.example.tld/fullchain.pem;

    client_max_body_size 525M;

    ## 使用子路径配置
    # 您的安装的 root 目录的路径
    # 请务必添加尾部的 /，否则您可能会遇到问题
    # 但仅限于这个位置，所有其他位置不应添加这些内容
    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;
    }
}
</code></pre>

</details>

<details>

<summary>Apache (by fbartels)</summary>

请记得启用 `mod_proxy_http`，例如使用：`a2enmod proxy_http`。这要求 Apache >= 2.4.47。

如果您通过公共 https 地址访问您的密码库（服务器内部再将请求重定向到 http（例如 80 端口）），则必须启用 `RequestHeader set X-Forwarded-Proto "https"`，否则，密码库虽然可以加载，但您的数据将无法加载。

```apache
<VirtualHost *:443>
    SSLEngine on
    ServerName vaultwarden.example.tld

    SSLCertificateFile ${SSLCERTIFICATE}
    SSLCertificateKeyFile ${SSLKEY}
    SSLCACertificateFile ${SSLCA}
    ${SSLCHAIN}

    ErrorLog ${APACHE_LOG_DIR}/vaultwarden-error.log
    CustomLog ${APACHE_LOG_DIR}/vaultwarden-access.log combined

    ProxyPass / http://127.0.0.1:8000/ upgrade=websocket

    ProxyPreserveHost On
    ProxyRequests Off
    RequestHeader set X-Real-IP %{REMOTE_ADDR}s
    # 如果您的 url 属性报告为 http://... ，请添加此行：
    # RequestHeader add X-Forwarded-Proto https
</VirtualHost>
```

</details>

<details>

<summary>Apache in a sub-location (by <a href="https://github.com/agentdr8">@agentdr8</a> &#x26; <a href="https://github.com/NoseyNick">@NoseyNick</a>)</summary>

修改 docker 启动以包含 sub-location。

```systemd
; 添加子位置！否则将不起作用！
DOMAIN=https://shared.example.tld/vault/
```

请记得启用 `mod_proxy_http`，例如使用：`a2enmod proxy_http`。这要求 Apache >= 2.4.47。

```apache
<VirtualHost *:443>
    SSLEngine on
    ServerName $hostname.$domainname

    SSLCertificateFile ${SSLCERTIFICATE}
    SSLCertificateKeyFile ${SSLKEY}
    SSLCACertificateFile ${SSLCA}
    ${SSLCHAIN}

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    <Location /vault> # 如果需要，调整此处
        ProxyPass http://127.0.0.1:8000/vault/ upgrade=websocket

        ProxyPreserveHost On
        RequestHeader set X-Real-IP %{REMOTE_ADDR}s
    </Location>
</VirtualHost>
```

</details>

<details>

<summary><del>Apache 2.4.47 (or later) in a sub-location (by</del> <a href="https://github.com/NoseyNick"><del>@NoseyNick</del></a><del>)</del></summary>

现在，常规的 `mod_proxy` 支持使用 `upgrade=websocket` 升级到 WebSocket，而不需要 `mod_proxy_wstunnel`。

复制上面的说明，除非使用更简单的...

```apache
<VirtualHost *:443>
  [ blah blah ]
  <Location /vault> #adjust here if necessary
    ProxyPass http://127.0.0.1:8000/vault/ upgrade=websocket
    ProxyPreserveHost On
    ProxyRequests Off # ... is the default, but as a safety-net
    RequestHeader set X-Real-IP %{REMOTE_ADDR}s
  </Location>
</VirtualHost>
```

</details>

<details>

<summary><del>Traefik v1 (docker-compose 示例)</del></summary>

```yaml
labels:
    - traefik.enable=true
    - traefik.docker.network=traefik
    - traefik.web.frontend.rule=Host:vaultwarden.example.tld
    - traefik.web.port=80
```

</details>

<details>

<summary>Traefik v2 (docker-compose 示例 by hwwilliams, gzfrozen)</summary>

#### 将 Traefik v1 标签迁移到 Traefik v2 <a href="#traefik-v-1-labels-migrated-to-traefik-v2" id="traefik-v-1-labels-migrated-to-traefik-v2"></a>

```yaml
labels:
  - traefik.enable=true
  - traefik.docker.network=traefik
  - traefik.http.routers.vaultwarden.rule=Host(`vaultwarden.example.tld`)
  - traefik.http.routers.vaultwarden.service=vaultwarden
  - traefik.http.services.vaultwarden.loadbalancer.server.port=80
```

#### 迁移的标签加上 HTTP 到 HTTPS 重定向 <a href="#migrated-labels-plus-http-to-https-redirect" id="migrated-labels-plus-http-to-https-redirect"></a>

这些标签假定 Traefik 中为端口 80 和 443 定义的入口点分别是「web」和「websecure」。

这些标签还假定您已经在 Traefik 中定义了默认的证书解析器。

```yaml
labels:
  - traefik.enable=true
  - traefik.docker.network=traefik
  - traefik.http.middlewares.redirect-https.redirectScheme.scheme=https
  - traefik.http.middlewares.redirect-https.redirectScheme.permanent=true
  - traefik.http.routers.vaultwarden-https.rule=Host(`vaultwarden.domain.tld`)
  - traefik.http.routers.vaultwarden-https.entrypoints=websecure
  - traefik.http.routers.vaultwarden-https.tls=true
  - traefik.http.routers.vaultwarden-https.service=vaultwarden
  - traefik.http.routers.vaultwarden-http.rule=Host(`vaultwarden.domain.tld`)
  - traefik.http.routers.vaultwarden-http.entrypoints=web
  - traefik.http.routers.vaultwarden-http.middlewares=redirect-https
  - traefik.http.routers.vaultwarden-http.service=vaultwarden
  - traefik.http.services.vaultwarden.loadbalancer.server.port=80
```

</details>

<details>

<summary>HAproxy (by <a href="https://github.com/BlackDex">@BlackDex</a>)</summary>

将这些行添加到您的 HAproxy 配置中。

```nginx
frontend vaultwarden
    bind 0.0.0.0:80
    option forwardfor header X-Real-IP
    http-request set-header X-Real-IP %[src]
    default_backend vaultwarden_http

backend vaultwarden_http
    # 启用压缩（如果您需要）
    # 压缩算法 gzip
    # 压缩类型 text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript
    # Vaultwarden 不支持 forwarded 头，但您可以启用它
    # option forward
    # 添加 x-forwarded-for 头
    option forwardfor
    # 在 `X-Real-IP` 头中设置来源 IP
    http-request set-header X-Real-IP %[src]
    # 将流量发送到本地实例
    server vwhttp 0.0.0.0:8000alpn http/1.1
```

</details>

<details>

<summary><del>HAproxy - before v1.29.0 (by</del> <a href="https://github.com/williamdes"><del>@williamdes</del></a><del>)</del></summary>

将这些行添加到您的 HAproxy 配置中。

```apache
backend static-success-default
  mode http
  errorfile 503 /usr/local/etc/haproxy/static/index.static.default.html
  errorfile 200 /usr/local/etc/haproxy/static/index.static.default.html

frontend http-in
    bind *:443 ssl crt /acme.sh/domain.tld/domain.tld.pem alpn h2,http/1.1
    option forwardfor header X-Real-IP
    http-request set-header X-Real-IP %[src]
    default_backend static-success-default

    # 定义主机
    acl host_vaultwarden_domain_tld hdr(Host) -i vaultwarden.domain.tld

    ## 谋划要使用哪一个
    use_backend vaultwarden_http if host_bitwarden_domain_tld

backend vaultwarden_http
    # 启用压缩（如果您需要）
    # 压缩算法 gzip
    # 压缩类型 text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript
    # 如果您在 docker-compose 中使用 haproxy，则可以使用容器主机名
    server vw_http 0.0.0.0:8080 alpn http/1.1
```

</details>

<details>

<summary><del>HAproxy inside PfSense (by</del> <a href="https://github.com/RichardMawdsley"><del>@RichardMawdsley</del></a><del>)</del></summary>

作为 GUI 设置，下面的详细信息\说明供您在需要的地方添加。

* 假设您已经设置好了基本的 HTTP > HTTPS 重定向设置。[基本设置](https://blog.devita.co/pfsense-to-proxy-traffic-for-websites-using-pfsense/)

### 后端创建

后端 1：

```
Mode	  Name	                     Forwardto	    Address	      Port	 Encrypt(SSL)	 SSL checks	  Weight	 Actions
active 	Vaultwarden                Address+Port:  IPADDRESSHERE 80     no            no
```

后端 2：

```
Mode	  Name	                     Forwardto	    Address	      Port	 Encrypt(SSL)	 SSL checks 	Weight	Actions
active 	Vaultwarden-Notifications  Address+Port:  IPADDRESSHERE 3012   no            no
```

### 前端创建-1-域名 <a href="#frontend-creation-1-domain" id="frontend-creation-1-domain"></a>

**ACCESS CONTROL LIST**

```yaml
ACL00
Host matches:
no
no
FQDN.com     -  注意：这需要是您的根域名。
 	
ACL00
Path starts with:
no
yes
/big-ass-randomized-test-that-really-no-one-is-ever-going-to-type-DONT-USE-THIS-LINE-THOUGH-make-your-own-up

ACL01
Host matches:
no
no
VAULTWARDEN.MYDOMAIN.COM

ACL01
Host matches:
no
no
EXAMPLE-OTHER-SUB-DOMAIN-1.MYDOMAIN.COM

ACL01
Host matches:
no
no
EXAMPLE-OTHER-SUB-DOMAIN-2.MYDOMAIN.COM
```

**ACTIONS-1-Domain**

```yaml
http-request allow
See below
ACL01

http-request deny
See below
ACL00
```

### 前端创建-2-VaultWarden <a href="#frontend-creation-2-vaultwarden" id="frontend-creation-2-vaultwarden"></a>

**ACCESS CONTROL LIST**

```yaml
ACL1
Path starts with:
no
yes
/notifications/hub  
 	
ACL2
Path starts with:
no
no
/notifications/hub/negotiate  
 	
ACL3
Path starts with:
no
no
/notifications/hub  
 	
ACL4
Path starts with:
no
yes
/notifications/hub/negotiate

ACL5
Path starts with:
no
no
/admin
```

**ACTIONS - 2 - VaultWarden**

```yaml
Use Backend
See below
ACL1  
backend: VaultWarden
 	
Use Backend
See below
ACL2  
backend: VaultWarden
 	
Use Backend
See below
ACL3  
backend: VaultWarden-Notifications
 	
Use Backend
See below
ACL4
backend: VaultWarden-Notifications

http-request deny
See below
ACL5
```

#### **更新记录** <a href="#updates" id="updates"></a>

```
Updated above 30/07 - 我在第一次配置后意识到，因为 ACL1-4 有 'Not'，他们正在将任何内容与他们的动作相匹配。所以 BlahBlahMcGee.FQDN.com 通过了。这不是故意的，所以上面添加了 ACL5 来解决这个问题，它还移除了对默认后端的需要。
Updated again 30/07 - ^ 是的，没用。这一切都源于 HaProxy 不允许在 ACL 中使用 'AND'。唉。现在有了上面的内容，您可以为根域配置一个前端。这有一个否认本身，以及任何未指定的内容。因此，如果您要通过多个其他子域，则需要将它们全部添加到 ACL01 下。现在一切正常了！
```

#### 重要提示 <a href="#important-notes" id="important-notes"></a>

```
1) 您必须使域名前端与允许列表中的任何其他子域名保持同步
2) 在域名前端，ACL01 必须位于 Actions 表的顶部 - 或至少在 ACL00 的上面
3) ACL 名称的重复使用是故意的。是的，我没有打错它们。ACL00、ACL01 等等
```

#### 可选 <a href="#optional" id="optional"></a>

```
上面的 ACL5 拒绝访问 /admin 门户。我不是特别喜欢没有任何形式的 2FA 且只有密码的管理门户。因此，当我不使用它时，我只是拒绝访问。如果我需要它，请取消阻止，完成所需的工作并重新阻止。
```

完成！可以去做测试了！

反过来，可以将下面的等效项添加到您的配置中（请注意，这是一个示例摘要）。

```yaml
acl			ACL00	var(txn.txnhost) -m str -i VAULTWARDEN.MYDOMAIN.COM
acl			ACL00	var(txn.txnpath) -m beg -i /big-ass-randomised-test-that-really-no-one-is-ever-going-to-type-DONT-USE-THIS-LINE-THOUGH-make-your-own-up
acl			ACL01	var(txn.txnhost) -m str -i EXAMPLE-OTHER-SUB-DOMAIN-1.MYDOMAIN.COM
acl			ACL01	var(txn.txnhost) -m str -i EXAMPLE-OTHER-SUB-DOMAIN-2.MYDOMAIN.COM
acl			ACL1	var(txn.txnpath) -m beg -i /notifications/hub
acl			ACL2	var(txn.txnpath) -m beg -i /notifications/hub/negotiate
acl			ACL3	var(txn.txnpath) -m beg -i /notifications/hub
acl			ACL4	var(txn.txnpath) -m beg -i /notifications/hub/negotiate
acl			ACL5	var(txn.txnpath) -m beg -i /admin

http-request allow  if  ACL01 
http-request deny   if  !ACL00 
http-request deny   if  !ACL5 
http-request deny   if  ACL5 
use_backend VaultWarden_ipvANY  if  !ACL1 
use_backend VaultWarden_ipvANY  if  ACL2 
use_backend VaultWarden-Notifications_ipvANY  if  ACL3 
use_backend VaultWarden-Notifications_ipvANY  if  !ACL4 
```

为了进行测试，如果您在浏览器中导航到 /notifications/hub，那么您应该会看到一个页面，上面写着「WebSocket Protocol Error: Unable to parse WebSocket key.」（WebSocket 协议错误：无法解析 WebSocket 密钥）……这意味着它可以正常工作！ - 所有其他子页面都应该出现 Rocket 错误。

</details>

<details>

<summary>HAproxy Kubernetes Ingress(by <a href="https://github.com/devinslick">@devinslick</a>)</summary>

控制器安装详情可在此处找到：<https://www.haproxy.com/documentation/kubernetes-ingress/community/installation/on-prem/>。请注意，仅当您使用 Cloudflare 时才需要 CF-Connecting-IP 标头

添加以下资源定义：

```yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vaultwarden
  namespace: default
  annotations:
    haproxy.org/forwarded-for: "true"
    haproxy.org/compression-algo: "gzip"
    haproxy.org/compression-type: "text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript"
    haproxy.org/http2-enabled: "true"
spec:
  ingressClassName: haproxy
  tls:
  - hosts:
    - vaultwarden.example.tld
  rules:
  - host: vaultwarden.example.tld
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: vaultwarden-http
            port:
              number: 80
```

</details>

<details>

<summary>Istio k8s (by <a href="https://github.com/asenyaev">@asenyaev</a>)</summary>

```yml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: vaultwarden-gateway
  namespace: vaultwarden
spec:
  selector:
    istio: ingressgateway-internal # 使用 Istio 默认网关实现
  servers:
  - hosts:
    - vw.k8s.prod
    port:
      number: 80
      name: http
      protocol: HTTP
    tls:
      httpsRedirect: true
  - hosts:
    - vw.k8s.prod
    port:
      name: https-443
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: vw-k8s-prod-tls
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vaultwarden-vs
  namespace: vaultwarden
spec:
  hosts:
  - vw.k8s.prod
  gateways:
  - vaultwarden-gateway
  http:
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        port:
          number: 80
        host: vaultwarden
```

</details>

<details>

<summary><del>Istio k8s - before v1.29.0 (by</del> <a href="https://github.com/dpoke"><del>@dpoke</del></a><del>)</del></summary>

```yml
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: vaultwarden-gateway
  namespace: vaultwarden
spec:
  selector:
    istio: ingressgateway-internal # 使用 Istio 默认网关实现
  servers:
  - hosts:
    - vw.k8s.prod
    port:
      number: 80
      name: http
      protocol: HTTP
    tls:
      httpsRedirect: true
  - hosts:
    - vw.k8s.prod
    port:
      name: https-443
      number: 443
      protocol: HTTPS
    tls:
      mode: SIMPLE
      credentialName: vw-k8s-prod-tls
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: vaultwarden-vs
  namespace: vaultwarden
spec:
  hosts:
  - vw.k8s.prod
  gateways:
  - vaultwarden-gateway
  http:
  - match:
    - uri:
        exact: /notifications/hub
    route:
    - destination:
        port:
          number: 3012
        host: vaultwarden-ws
  - match:
    - uri:
        prefix: /
    route:
    - destination:
        port:
          number: 80
        host: vaultwarden
```

</details>

<details>

<summary><del>relayd on openbsd (by olliestrickland)</del></summary>

经测试可正常运行（包括 websockets） - /etc/relayd.conf - 在 openbsd 7.2 上使用来自 OpenBSD Ports 的 Vaultwarden - <https://openports.se/security/vaultwarden>

此配置取决于 tls 的正确设置 - 我使用 <https://man.openbsd.org/acme-client>

```nginx
table <vaultwarden-default-host> { localhost }
table <vaultwarden-websocket-host> { localhost }

# 带有 tls 的 Vaultwarden 协议定义

http protocol vaultwarden-https {
        # 添加 Vaultwarden 所需要的标头
        match request header append "X-Real-IP" value "$REMOTE_ADDR"

        # 添加一些 Vaultwarden 可能不需要的标头
        match request header append "Host" value "$HOST"
        match request header append "X-Forwarded-For" value "$REMOTE_ADDR"
        match request header append "X-Forwarded-By" value "$SERVER_ADDR:$SERVER_PORT"

        # 最普通的规则 - 转发到 Vaultwarden Rocket
        match request path "/*" forward to <vaultwarden-default-host>

        # 将用于 websocket 的路径转发到 Vaultwarden websocket 端口
        match request path "/notifications/hub" forward to <vaultwarden-websocket-host>

        # 将最具体的路径保存在最后 - 此路径不应转发到 websocket 服务器
        match request path "/notifications/hub/negotiate" forward to <vaultwarden-default-host>

        # 各种 TCP 选项
        tcp { nodelay, sack, backlog 128 }

        # tls 配置
        tls keypair bitwarden.example.tld
        tls { no tlsv1.0, ciphers HIGH }

        # 允许 websockets - 这很好，它可以处理连接升级，而无需手动编辑标头
        http websockets
}

# Vaultwarden 的中继定义 - 将出口接口上的入站 443 tls 转发到默认 8000 端口上的 rocket 和 3012 上的 websocket

relay vaultwarden-https-relay {
        listen on egress port 443 tls
        protocol vaultwarden-https
        forward to <vaultwarden-default-host> port 8000
        forward to <vaultwarden-websocket-host> port 3012
}
```

</details>

<details>

<summary><del>CloudFlare - before v1.29.0 (by</del> <a href="https://github.com/williamdes"><del>@williamdes</del></a><del>)</del></summary>

按照下面的截图创建新的规则。用于查找此设置的示例仪表板 URL：`https://dash.cloudflare.com/xxxxxx/example.org/rules/origin-rules/new`

<img src="https://user-images.githubusercontent.com/7784660/251004005-e27d9152-219b-4b6a-bf96-dcfce30ebd73.png" alt="" data-size="original">

</details>

<details>

<summary>CloudFlare Tunnel (by <a href="https://github.com/calvin-li-developer">@calvin-li-developer</a>)</summary>

`docker-compose.yml`：

```yaml
version: '3'

services:
  vaultwarden:
    container_name: vaultwarden
    image: vaultwarden/server:latest
    restart: unless-stopped
    environment:
      DOMAIN: "https://vaultwarden.example.ltd"  # 您的域名；vaultwarden 需要知道您的域名是 https，才能正常处理附件
    volumes:
      - ./vw-data:/data
    networks:
      - vaultwarden-network

  cloudflared:
    image: cloudflare/cloudflared:2024.1.2
    container_name: vaultwarden-cloudflared
    restart: unless-stopped
    read_only: true
    volumes:
      - ./cloudflared-config:/root/.cloudflared/
    command: [ "tunnel", "run", "${TUNNEL_ID}" ]
    user: root
    depends_on:
      - vaultwarden
    networks:
      - vaultwarden-network
networks:
  vaultwarden-network:
    name: vaultwarden-network
    external: false
```

`cloudflared-config` 文件夹中的内容：

```
config.yml  aaaaa-bbbb-cccc-dddd-eeeeeeeee.json
```

请使用[本指南](https://thedxt.ca/2022/10/cloudflare-tunnel-with-docker/)找出您的 cloudflare 账户的以下内容/值。注意：`aaaaa-bbbb-cccc-dddd-eeeeeeeee` 只是一个随机的 tunnelID，请使用真实的 ID。

`config.yml`：

```yaml
tunnel: aaaaa-bbbb-cccc-dddd-eeeeeeeee
credentials-file: /root/.cloudflared/aaaaa-bbbb-cccc-dddd-eeeeeeeee.json

originRequest:
  noHappyEyeballs: true
  disableChunkedEncoding: true
  noTLSVerify: true

ingress:
  - hostname: vault.example.com # 更改为您自己的域名
    service: http_status:404
    path: admin
  - hostname: vault.example.com # 更改为您自己的域名
    service: http://vaultwarden
  - service: http_status:404
```

`aaaaa-bbbb-cccc-dddd-eeeeeeeee.json`：

```
{"AccountTag":"changeme","TunnelSecret":"changeme","TunnelID":"aaaaa-bbbb-cccc-dddd-eeeeeeeee"}
```

</details>

<details>

<summary>Pound</summary>

```apache
Alive		15

ListenHTTP
	Address 127.0.0.1
	Port    80
	xHTTP 3
	HeadRemove "X-Forwarded-For"
	Service
		Host "vaultwarden.example.tld"
		Redirect 301 "https://vaultwarden.example.tld"
	End
End

ListenHTTPS
	Address 127.0.0.1
	Port    443
	Cert    "/path/to/certificate/letsencrypt/live/vaultwarden.example.tld/fullchain.pem"
	xHTTP 3
	AddHeader "Front-End-Https: on"
	RewriteLocation 0
	HeadRemove "X-Forwarded-Proto"
	AddHeader "X-Forwarded-Proto: https"
End

Service
	Host "vaultwarden.example.tld"
	BackEnd
		Address 127.0.0.1
		Port    8000
	End
End
```

</details>


# 2.使用备用基本目录

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-an-alternate-base-dir)
{% endhint %}

通常，Vaultwarden 被限制驻留在子域名的根目录中，比如 `https://vaultwarden.example.com`。

此限制源自后端和网页密码库，他们尚未被设计为容纳备用基本目录（请参阅 [bitwarden/server#277](https://github.com/bitwarden/server/issues/277)）。实际上，移动端/桌面端应用程序和浏览器扩展都可以使用带路径的基本 URL。

随着对 Vaultwarden 的更改（[PR#868](https://github.com/dani-garcia/vaultwarden/pull/868)（后端）和 [PR#11](https://github.com/dani-garcia/bw_web_builds/pull/11)（网页密码库）），您现在已经可以使用备用基本目录配置功能齐全的实例了。

## 配置 <a href="#configuration" id="configuration"></a>

只需将您的域名 URL 简单配置为包括基本目录即可。例如，假设您想使用 `https://vaultwarden.example.com/base-dir` 访问您的实例。（提示，您也可以根据需要使用多级目录，例如 `https://vaultwarden.example.com/multi/level/base/dir`）

1、停止 Vaultwarden。

2、如果您通常使用管理页面来配置 Vaultwarden，则将 `config.json` 编辑为如下所示：

```json
{
  "domain": "https://vaultwarden.example.com/base-dir",
  // ... other values ...
}
```

3、如果您通常通过环境变量来配置 Vaultwarden，请更新您的配置文件/脚本，将 `DOMAIN` 环境变量设置为基本 URL 。例如：

```shell
docker run -e DOMAIN="https://vaultwarden.example.com/base-dir" ...
```

4、重新启动 Vaultwarden。

5、现在，您应该可以使用 `https://vaultwarden.example.com/base-dir/`（请注意最后面的斜杠）访问网页密码库了。出于尚不完全清楚的原因，如果您使用 `https://vaultwarden.example.com/base-dir`（最后面不带斜线），可能会遇到问题。

6、使用 `https://vaultwarden.example.com/base-dir` 配置您的应用程序或浏览器扩展。注意：这里如果添加斜杠，则应用程序和浏览器扩展会在保存前自动将其删除。

7、注意对于**步骤 5**。尾部的斜杠 `/` 问题可以通过在路由位置字符串后添加 `/` 来解决。例如，在 nginx 中：

```nginx
location /my-base-path {
  # 此配置将导致`/`问题
}

location /my-base-path-2/ {
  # 此配置完美运行
}
```

## 反向代理 <a href="#reverse-proxying" id="reverse-proxying"></a>

既然 Vaultwarden API 路由已设置为期望的基本目录，如果您将 Vaultwarden 放置在反向代理后面，请确保将您的代理配置为将请求路径传递到 Vaultwarden。假如反向代理在 `localhost:8080` 上监听您的 Vaultwarden，来自 `https://vaultwarden.example.com/base-dir/api/sync` 的请求到达了您的反向代理，则该请求必须转发到 `http://localhost:8080/base-dir/api/sync`，而不是 `http://localhost:8080/api/sync`。


# HTTPS


# 1.启用 HTTPS

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-HTTPS)
{% endhint %}

如今，要正常运行 Vaultwarden，几乎必须启用 [HTTPS](https://en.wikipedia.org/wiki/HTTPS)，这是因为 Bitwarden 网络密码库使用的 [Web Crypto API](https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto)，大多数浏览器只有在 HTTPS 环境下才能使用。

启用 HTTPS 的几种方式：

* （推荐）把 Vaultwarden 放在一个[反向代理](https://en.wikipedia.org/wiki/Reverse_proxy)后面，代替 Vaultwarden 处理 HTTPS 连接。
* （不推荐）启用 Vaultwarden 内置的 HTTPS 功能（通过 [Rocket](https://rocket.rs/) 网络框架）。Rocket 的 HTTPS 实现相对不成熟且功能有限。

有关这些选项的更多细节，请参阅[启用 HTTPS](#enabling-https) 部分。

要使 HTTPS 服务器工作，它还需要 SSL/TLS 证书，因此您需要决定如何获取该证书。同样，有几种方式：

* （推荐）使用 [ACME 客户端](https://letsencrypt.org/docs/client-options/)获取 [Let's Encrypt](https://letsencrypt.org/) 证书。一些反向代理（例如 [Caddy](https://caddyserver.com/)）也内置支持使用 ACME 协议获取证书。
* （推荐）如果您信任 [Cloudflare](https://www.cloudflare.com/) 来代理您的流量，您可以让他们处理您的 SSL/TLS 证书的发放。请注意，上游的 Bitwarden 网络密码库 (<https://vault.bitwarden.com/>) 运行在 Cloudflare 后面。
* （不推荐）[建立一个私人 CA](/other-information/private-ca-and-self-signed-certs-that-work-with-chrome)，并发行您自己的（自签名）证书。这样做存在各种隐患和不便，所以请自行考虑是否使用此选项。

有关这些选项的更多细节，请参考[获取 SSL/TLS 证书](#getting-ssl-tls-certificates)部分。要使移动应用程序能正常运行，必须设置正确的 [OCSP 装订](https://en.wikipedia.org/wiki/OCSP_stapling)设置。

## 启用 HTTPS <a href="#enabling-https" id="enabling-https"></a>

### 通过反向代理 <a href="#via-a-reverse-proxy" id="via-a-reverse-proxy"></a>

有很多常用的反向代理，在[代理示例](/reverse-proxy/proxy-examples)中可以找到一些配置的示例。如果您不熟悉反向代理并且没有特别偏好，请首先考虑使用 [Caddy](https://caddyserver.com/)，因为它内置了对获取 Let's Encrypt 证书的支持。[使用 Docker Compose](/container-image-usage/using-docker-compose) 文章中有一个使用 Caddy 的很好的例子。

### 通过 Rocket <a href="#via-rocket" id="via-rocket"></a>

{% hint style="danger" %}
不建议使用此方式。
{% endhint %}

要对 `vaultwarden` 本身启用 HTTPS，请设置如下格式的 `ROCKET_TLS` 环境变量：

```json
ROCKET_TLS={certs="/path/to/certs.pem",key="/path/to/key.pem"}
```

位置：

* `certs`：PEM 格式的 SSL/TLS 证书链的路径。
* `key`：PEM 格式的 SSL/TLS 证书对应的私钥文件的路径。

说明：

* `ROCKET_TLS` 行中使用的文&#x4EF6;***扩展***&#x540D;不一定非要像示例中那样是 `.PEM`。某些地方可能会使用其他扩展名，例如，`.crt` 作为证书，`.key` 作为私钥。这些文件&#x7684;***格式***&#x5FC5;须是 PEM，即 base64 编码。PEM 是 openssl 的默认格式，因此您可以将 .cert、.cer、.crt 和 .key 文件重命名为 .pem 以作为 `ROCKET_TLS` 行中的文件扩展名，或者使用 .crt 或 .key 作为 `ROCKET_TLS` 行中的文件扩展名。
* 使用 RSA 证书/密钥。Rocket 目前无法处理 ECC 证书/密钥，会输出类似下面的误导性错误消息：

  > `[ERROR] environment variable ROCKET_TLS={certs="/ssl/ecdsa.crt",key="/ssl/ecdsa.key"} could not be parsed`

  （环境变量本身的格式没有错误；只是因为 Rocket 无法解析证书/密钥的内容。）
* 如果在 Docker 下运行，请记住，Vaultwarden 在容器内部运行时将解析 `ROCKET_TLS` 值 ，所以请确保 `certs` 和 `key` 路径是容器内部呈现的样子（可能与 Docker 主机系统上的路径不同）。

```sh
docker run -d --name vaultwarden \
  -e ROCKET_TLS='{certs="/ssl/certs.pem",key="/ssl/key.pem"}' \
  -v /ssl/keys/:/ssl/ \
  -v /vw-data/:/data/ \
  -p 443:80 \
  vaultwarden/server:latest
```

您需要挂载 ssl 文件夹（使用 `-v` 参数），同时需要转发合适的端口（使用 `-p` 参数），通常是用于 HTTPS 连接的 443 端口。如果您选择的端口号不是 443，比如是 3456，请记住在连接到服务时需要明确提供该端口号，例如：`https://vaultwarden.local:3456`。

~~有关如何在本地系统上设置和使用私有 CA 的更多信息，请参阅~~[~~此页面~~](/other-information/private-ca-and-self-signed-certs-that-work-with-chrome)~~。如果遵循该指南，您的 ROCKET\_TLS 行看起来应该像这样：`-e ROCKET_TLS='{certs="/ssl/vaultwarden.crt",key="/ssl/vaultwarden.key"}' \`~~

{% hint style="danger" %}
确保您的证书文件包含了完整的信任链。对于 certbot，这意味着应使用 `fullchain.pem` 而不是 `cert.pem`。完整的信任链应该包含两个证书：叶证书（与 `cert.pem` 中的内容相同），后面跟随 R3 或 E1 [中间证书](https://letsencrypt.org/certificates/#intermediate-certificates)。例如，Android 默认不在其系统信任存储中包含任何 Let's Encrypt 中间证书，所以如果您不提供完整的证书链，Android 客户端很可能无法连接。
{% endhint %}

用于获取证书的软件通常使用符号链接。如果是这样的话，需要确保这两个位置能被 docker 容器访问到。

例如：[certbot](https://certbot.eff.org/) 会在 `/etc/letsencrypt/live/mydomain/` 下创建一个包含所需要的 `fullchain.pem` 和 `privkey.pem` 文件的文件夹。

这些文件链接到 `../../archive/mydomain/privkey.pem`。

因此，从 Vaultwarden 容器中使用，应像这样：

```sh
docker run -d --name vaultwarden \
  -e ROCKET_TLS='{certs="/ssl/live/mydomain/fullchain.pem",key="/ssl/live/mydomain/privkey.pem"}' \
  -v /etc/letsencrypt/:/ssl/ \
  -v /vw-data/:/data/ \
  -p 443:80 \
  vaultwarden/server:latest
```

### 检查证书是否有效 <a href="#check-if-certificate-is-valid" id="check-if-certificate-is-valid"></a>

当您的 Vaultwarden 服务器对外界可用时，您可以使用 [Comodo SSL Checker](https://comodosslstore.com/ssltools/ssl-checker.php)，[Qualys' SSL Labs](https://www.ssllabs.com/ssltest/) 或 [Digicert SSL Certficate Checker](https://www.digicert.com/help/) 来检查您的 SSL 证书（包括证书链）是否有效。缺少证书链，Android 设备将连接失败。

您可以使用 [Qualys' SSL Labs](https://www.ssllabs.com/ssltest/analyze.html) 检查，但它不支持自定义端口。另外，请记住选中「Do not show the results on the boards」复选框，否则您的系统将在「Recently Seen」列表中可见。

如果您运行的是没有与公共 Internet 连接的本地服务器，则可以使用 `openssl` 命令 [testssl.sh](https://testssl.sh/) 或 [SSLScan](https://github.com/rbsec/sslscan/) 来验证证书的有效性。

执行以下操作以验证证书是否随链安装（注意将 `vault.domain.com` 更改为您自己的域名）：

```sh
openssl s_client -showcerts -connect vault.domain.com:443 -servername vault.domain.com

# 或者不同的端口，比如 7070
openssl s_client -showcerts -connect vault.domain.com:7070 -servername vault.domain.com
```

输出的开头应类似于以下内容（使用 Let's Encrypt 证书）：

```
CONNECTED(00000003)
depth=2 O = Digital Signature Trust Co., CN = DST Root CA X3
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = Let's Encrypt Authority X3
verify return:1
depth=0 CN = vault.domain.com
verify return:1
```

有 3 个不同深度（请注意，它是从 0 开始的）级别的验证。在接下来的输出中，您应该看到来自 Let's Encryptbase 的使用 base64 编码的证书信息。

### 检查 OCSP 有效性 <a href="#check-oscp-validity" id="check-oscp-validity"></a>

> \[**译者注**]：OCSP：Online Certificate Status Protocol，在线证书状态协议。OCSP 是一个用于获取 X.509 数字证书撤销状态的网络协议，用于检验证书合法性。OCSP 查询需要建立一次完整的 HTTP 查询请求，期间的 DNS 查询、建立 TCP 连接、服务端响应和数据传输都是额外开销，使得建立 TLS 连接花费更多时长。后来出现了OCSP Stapling ，将原本需要客户端发起的 OCSP 请求转嫁给服务端，并随证书一起发送给客户端，因此能提高 TLS 握手效率。
>
> OCSP Stapling 一般翻译为 OCSP 装订或 OCSP 封套。

如果 OCSP Stapling 无法正常工作，则连接移动应用程序将失败，并显示 `Chain validation failed` 消息。

正确设置 OCSP Stapling 后，[Digicert SSL Checker](https://www.digicert.com/help/) 的吊销检查部分将包含「OCSP Staple: Good」。您的网络服务器必须能够连接到证书的 X509v3 扩展中的「Authority Information Access」URL，才能使 OCSP Stapling 正常工作。

您还可以使用如下命令行检查 OCSP 的状态：

```sh
openssl s_client -showcerts -connect vault.domain.com:443 -servername vault.domain.com -status
```

在其输出中必须包含：

```sh
OCSP Response Status: successful (0x0)
```

## 获取 SSL/TLS 证书 <a href="#getting-ssl-tls-certificates" id="getting-ssl-tls-certificates"></a>

### 通过 Let's Encrypt <a href="#via-lets-encrypt" id="via-lets-encrypt"></a>

[Let's Encrypt](https://letsencrypt.org/) 免费发放 SSL/TLS 证书。

为了使之工作，您的 Vaultwarden 实例必须拥有一个 DNS 名称（即您不能简单地使用 IP 地址）。如果您的 Vaultwarden 可以在公共互联网上访问，那么设置 Let's Encrypt 就比较容易，但即使您的实例是私有的（即只能在您的局域网内访问），也可以通过 [DNS 挑战](/reverse-proxy/https/running-a-private-vaultwarden-instance-with-lets-encrypt-certs)获取 Let's Encrypt 证书。

如果您已经拥有或控制了一个域名，那么只需为您的 Vaultwarden 实例的 IP 地址添加一个 DNS 名称即可。如果您没有，可以购买一个域名，尝试在 [Freenom](https://www.freenom.com/) 免费获得一个，或者使用像 [Duck DNS](https://www.duckdns.org/) 这样的服务来获取一个现有域名下的名称（例如，`my-bitwarden.duckdns.org`）。

拥有了实例的 DNS 名称后，您就可以使用 [ACME 客户端](https://letsencrypt.org/docs/client-options/)为你的 DNS 名称获取证书。[Certbot](https://certbot.eff.org/) 和 [acme.sh](https://github.com/acmesh-official/acme.sh) 是两个最流行的独立客户端。一些反向代理（例如 [Caddy](https://caddyserver.com/)）也内置了 ACME 客户端。

### 通过 Cloudflare <a href="#via-cloudflare" id="via-cloudflare"></a>

[Cloudflare](https://www.cloudflare.com/) 为个人提供免费服务。如果您信任他们代理你的流量，并作为您的 DNS 提供商，您也可以让他们处理您的 SSL/TLS 证书的发放。

注册您的域名并为您的 Vaultwarden 实例添加了 DNS 记录后，登录 Cloudflare 仪表板并选择 `SSL/TLS`，然后选择 `Origin Server`。生成一个原始证书（您可以选择最长 15 年的有效期），并配置 Vaultwarden 来使用它。如果您选择了 15 年有效期，那么在可预见的未来，无需续签此原始证书。

请注意，原始证书仅用于确保 Cloudflare 和 Vaultwarden 之间的通信。Cloudflare 将自动处理用于客户端和 Cloudflare 之间通信的证书的发放和更新。

另外，如果您使用的是 Vaultwarden 内置的 Rocket HTTPS 服务器，请确保选择 `RSA` 作为原始证书的私钥类型，因为 Rocket 目前不支持 ECC/ECDSA 证书。


# 2.使用 Let's Encrypt 证书运行私有 Vaultwarden 实例

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Running-a-private-vaultwarden-instance-with-Let%27s-Encrypt-certs)
{% endhint %}

假设您希望运行一个只能从本地网络访问的 Vaultwarden 实例，但您又希望此实例启用由一个被广泛接受的 CA 而不是你自己的[私有 CA](/other-information/private-ca-and-self-signed-certs-that-work-with-chrome) 来签署的 HTTPS（以避免将专用 CA 证书加载到所有设备中的麻烦）。

本文将演示如何使用 [Caddy](https://caddyserver.com/) 网页服务器创建这样的设置，Caddy 内置了对诸多 DNS 提供程序的 ACME 支持。我们将通过 ACME [DNS 验证方式](https://letsencrypt.org/docs/challenge-types/#dns-01-challenge)获取 Let's Encrypt 证书来配置 Caddy -- 在这里使用普通的 HTTP 验证方式的话会有问题，因为它依赖于 Let's Encrypt 服务器能够访问到您的内部网页服务器。

{% hint style="danger" %}
本文涵盖了更通用的 DNS 验证设置，但许多用户可能会发现使用 Docker Compose 来集成 Caddy 和 Vaultwarden 是最简单的。具体的例子请参见[使用 Docker Compose](/container-image-usage/using-docker-compose#caddy-with-dns-challenge)。
{% endhint %}

涵盖了两个 DNS 提供程序：

* [Duck DNS](https://www.duckdns.org/) -- 为你提供一个 `duckdns.org` 下的子域名（例如 `my-bwrs.duckdns.org`）。如果您没有自己的域名，此选项是最简单的。
* [Cloudflare](https://www.cloudflare.com/) -- 这可以让您把您的 Vaultwarden 实例放在您拥有或控制的域名下。请注意，Cloudflare 可以只作为一个 DNS 提供程序使用（即不使用 Cloudflare 最著名的代理功能）。如果您目前没有自己的域名，您也许可以在 [Freenom](https://www.freenom.com/) 获得一个免费的域名。

当然也可以使用其他的网络服务器、[ACME 客户端](https://letsencrypt.org/docs/client-options/)和 DNS 提供程序的组合来创建类似的设置，但您必须解决细节上的差异。

## 获取自定义 Caddy 构建 <a href="#getting-a-custom-caddy-build" id="getting-a-custom-caddy-build"></a>

Caddy 默认情况下没有内置 DNS 验证挑战支持，因为大多数人不使用这种验证挑战方式，并且它需要为每个 DNS 提供程序进行自定义实现。

最简单的方式是通过 <https://caddyserver.com/download> 获取带有 DNS 验证挑战模块的 Caddy 版本。选择您的平台，选中 `github.com/caddy-dns/cloudflare`（用于 Cloudflare）和/或 `github.com/caddy-dns/duckdns`（用于 Duck DNS），然后点击下载。

如果您喜欢从源代码构建，可以使用 [`xcaddy`](https://caddyserver.com/docs/build#xcaddy)。例如，要创建一个包含 Cloudflare 和 Duck DNS 支持的构建：

```sh
xcaddy build --with github.com/caddy-dns/cloudflare --with github.com/caddy-dns/duckdns
```

将 `caddy` 二进制移动到 `/usr/local/bin/caddy` 或其他合适的目录中。使文件可执行。（可选）运行语句 `sudo setcap cap_net_bind_service=+ep /usr/local/bin/caddy` 以允许 `caddy` 在特权端口 (< 1024) 上监听，而无须以 root 身份运行。

## Duck DNS 设置 <a href="#duck-dns-setup" id="duck-dns-setup"></a>

如果您还没有账户，请在 <https://www.duckdns.org/> 创建一个。给您的 Vaultwarden 实例创建一个子域名（例如，`my-vw.duckdns.org`），将其 IP 地址设置为您的 Vaultwarden 主机的私有 IP（例如，`192.168.1.100`）。记下您的账户的 token 值（[UUID](https://en.wikipedia.org/wiki/UUID) 格式的字符串）。Caddy 将需要此 token 来完成 DNS 验证挑战。

在 Caddy 可执行文件所在的同一目录中创建一个名为 `Caddyfile`（大写 C，无文件扩展名）的文件，其中包含以下内容，并将 `localhost:` 端口替换为 Vaultwarden 在其 `ROCKET_PORT=` 指令中使用的端口（Vaultwarden 的默认 Rocket\_port 为 8001）：

```nginx
{$DOMAIN}:443 {
    tls {
        dns duckdns {$DUCKDNS_TOKEN}
    }
    reverse_proxy localhost:8001
}
```

创建一个名为 `caddy.env` 的文件，内容如下（替换相应的值）：

```systemd
DOMAIN=my-vw.duckdns.org
DUCKDNS_TOKEN=00112233-4455-6677-8899-aabbccddeeff
```

切换到 caddy 所在目录然后运行以下命令以首次启动 `caddy`：

```sh
caddy run --envfile caddy.env
```

Duck DNS 域名（例如 `my-vw.duckns.org`）的 Caddy 首次启动需要几秒钟的时间来解决 DNS 验证挑战和获取 HTTPS 证书。Caddy 通常将它们存储在 `/root/.local/share/caddy` 中，以及 Caddy 的配置会自动保存到 `/root/.config/caddy`。

运行命令以启动 `vaultwarden`：

```sh
export ROCKET_PORT=8001

./vaultwarden
```

{% hint style="info" %}
在设置 Caddy 之前，Vaultwarden 是否已运行并不重要。
{% endhint %}

您现在应该可以通过 `https://my-vw.duckdns.org` 访问到您的 Vaultwarden 实例了。如果没有，请检查 Caddy 的输出。

您可以使用 \[STRG]-\[C] 来停止 caddy。接下来通过以下命令在后台启动 Caddy：

```sh
caddy start --envfile caddy.env
```

**重要提示：**&#x5982;有必要，在某些路由器（例如 FritzBox）或 DNS 解析器（例如 unbound）中，由于 DNS 重新绑定保护，必须为域名（例如 `my-vw.example.com`）设置例外。

## Cloudflare 设置 <a href="#cloudflare-setup" id="cloudflare-setup"></a>

如果您还没有账户，请在 <https://www.cloudflare.com/> 创建一个；您还需要到您的域名注册商那里将名称服务器设置为 Cloudflare 分配给您的值。为您的 Vaultwarden 实例创建一个子域名（例如，`vw.example.com`），将其 IP 地址设置为您的 Vaultwarden 主机的私有 IP（例如，`192.168.1.100`）。例如：

<figure><img src="https://i.imgur.com/BBvy4Yj.png" alt=""><figcaption></figcaption></figure>

创建一个用于 DNS 验证挑战的 API token（更多背景知识，请参阅 <https://github.com/libdns/cloudflare/blob/master/README.md>）：

1. 点击右上角的个人图标并导航到 `My Profile`，然后选择 `API Tokens` 选项卡。
2. 点击 `Create Token` 按钮，然后点击`Edit zone DNS` 右边的 `Use template`。
3. 编辑 `Token name` 字段（如果您希望使用更具描述性的名称）。
4. 在 `Permissions` 下应出现一个权限：`Zone / DNS / Edit`。添加其他权限：`Zone / Zone / Read`。
5. 在 `Zone Resources` 下，设置 `Include / Specific zone / example.com`（使用您自己的域名替换 `example.com`）。
6. 在 `TTL` 下，为您的 tokan 设置一个变为非活动状态的 End Date（结束日期）。您也可以在以后设置。
7. 创建 token 并复制 token 值。

您的 token 列表看起来应该像这样：

<figure><img src="https://i.imgur.com/FoOv9Ww.png" alt=""><figcaption></figcaption></figure>

创建一个名为 `Caddyfile` 的文件，内容如下：

```nginx
{$DOMAIN}:443 {
    tls {
        dns cloudflare {$CLOUDFLARE_API_TOKEN}
    }
    reverse_proxy localhost:8080
}
```

创建一个名为 `caddy.env` 的文件，内容如下（替换相应的值）：

```systemd
DOMAIN=vw.example.com
CLOUDFLARE_API_TOKEN=<your-api-token>
```

运行命令以启动 `caddy`：

```sh
caddy run --envfile caddy.env
```

运行命令以启动 `vaultwarden`：

```sh
export ROCKET_PORT=8080

./vaultwarden
```

您现在应该可以通过 `https://vw.example.com` 访问到您的实例了。

**重要提示：**&#x5982;有必要，在某些路由器（例如 FritzBox）中，由于 DNS 重新绑定保护，必须为域名（例如 `vw.example.com`）设置例外。

## 使用 `lego` CLI 获取证书 <a href="#getting-certs-using-the-lego-cli" id="getting-certs-using-the-lego-cli"></a>

在上面的 DuckDNS 例子中，Caddy 使用 `lego` 库通过 DNS 验证获取证书。`lego` 也有一个 CLI，您可以直接使用它来获取证书，例如，如果你想使用 Caddy 以外的反向代理。 (注意：这个例子使用 `lego`，但也有其他独立的 ACME 客户端支持 DNS 验证挑战方式（参阅 [DNS 验证](#dns-challenge)部分）。

下面是一个如何做到这一点的例子。

1. 从 <https://github.com/go-acme/lego/releases> 下载预建的 `lego` 二进制文件到您的系统中。将其解压到某个目录，比如 `/usr/local/lego`。
2. 从那个目录中，运行 `DUCKDNS_TOKEN=<token> ./lego -a --dns duckdns -d my-vm.duckdns.org -m me@example.com run`（用合适的值替换令牌、域名和电子邮件地址）。这将使您在 Let's Encrypt 注册，并为您的域名获取一个证书。
3. 设置一个每周的 cron 作业来运行 `DUCKDNS_TOKEN=<token> ./lego --dns duckdns -d my-vw.duckdns.org -m me@example.com renew`。这将在你的证书即将到期时更新它。

{% hint style="info" %}
`lego` 默认请求 ECC/ECDSA 证书。如果您使用 Vaultwarden 中内置的 [Rocket HTTPS 服务器](/reverse-proxy/https/enabling-https#via-rocket)，您需要请求 RSA 证书。在上面的 `lego` 命令中，添加选项 `--key-type rsa2048`。
{% endhint %}

在这个例子中，您需要用生成的输出来配置您的反向代理：

* `/usr/local/lego/.lego/certificates/my-vw.duckdns.org.crt` （证书）
* `/usr/local/lego/.lego/certificates/my-vw.duckdns.org.key` （私钥）

## 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>

### DNS 问题 <a href="#dns-issues" id="dns-issues"></a>

如果您的子域名出现 DNS 解析错误（例如，`DNS_PROBE_FINISHED_NXDOMAIN` 或 `ERR_NAME_NOT_RESOLVED`），可能是您的 DNS 解析器阻止了解析，有以下原因：

1. 出于安全原因，它会阻止动态 DNS 服务。
2. 为防止 [DNS 重新绑定](https://en.wikipedia.org/wiki/DNS_rebinding)攻击，或出于其他一些原因，它会阻止域名解析到私有 (RFC 1918) IP 地址。

无论哪种情况，您都可以尝试使用其他 DNS 解析器，例如 Google 的 `8.8.8.8` 或 Cloudflare 的 `1.1.1.1`。对于第二种情况，如果您在 dnsmasq 或 Unbound 等本地 DNS 服务器后面运行，则可以将其配置为完全禁用 DNS 重新绑定保护，或允许某些域名返回私有地址。关于 Unbound，您可以通过将以下指令添加到其配置文件中来实现（使用您自己的 Duck DNS 域名替换该域名）：

```yaml
private-domain: "my-vw.duckdns.org"
```

然后通过 `unbound-control reload` 或 `systemctl restart unbound` 重新启动 unbound 以使其加载新配置。

此外，请确保关闭您之前为 Vaultwarden 设置的 HTTPS 设置，特别是通过 Rocket TLS 使用您自己的（自签名）证书的私有 CA，因为这会干扰您新的 Let's Encrypt 受保护的域名。只需在 Vaultwarden 的环境文件中注释掉（# 符号）`ROCKET_TLS` 指令即可：

```systemd
# ROCKET_TLS={certs="./cert.pem",key="./privkey.pem"}
```

### Vaultwarden 登录问题 <a href="#vaultwarden-login-issues" id="vaultwarden-login-issues"></a>

更改域名后不要忘记更新 Vaultwarden 的环境文件：

```systemd
DOMAIN=https://my-vw.duckdns.org
```

## 参考 <a href="#references" id="references"></a>

### DNS 验证挑战 <a href="#dns-challenge" id="dns-challenge"></a>

* <https://caddy.community/t/how-to-use-dns-provider-modules-in-caddy-2/8148>
* <https://community.letsencrypt.org/t/dns-providers-who-easily-integrate-with-lets-encrypt-dns-validation/86438>

### Caddy Cloudflare 组件 <a href="#caddy-cloudflare-module" id="caddy-cloudflare-module"></a>

* <https://github.com/caddy-dns/cloudflare>
* <https://go-acme.github.io/lego/dns/cloudflare/>

### Caddy Duck DNS 组件 <a href="#caddy-duck-dns-module" id="caddy-duck-dns-module"></a>

* <https://github.com/caddy-dns/duckdns>
* <https://go-acme.github.io/lego/dns/duckdns/>


# 配置


# 1.配置概述

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Configuration-overview)
{% endhint %}

> **\[译者注]**：
>
> 1. 某些设置只能通过环境变量配置，如管理页面 `Read-Only Config` 中的配置
> 2. 通过管理页面修改配置后马上生效
> 3. 若直接修改 `config.json` 文件，则需要重启 Vaultwarden 才能生效（因为只有启动时才会读取 `config.json` 文件）

## 如何配置 Vaultwarden <a href="#how-to-configure-vaultwarden" id="how-to-configure-vaultwarden"></a>

基本上有三种不同的方式配置 Vaultwarden：

1. 设置环境变量
2. 使用 `ENV_FILE`，以及
3. 通过 `config.json`（**不推荐**）（这可以通过[管理页面](/configuration/enabling-admin-page)生成和管理）

您可以在 [`.env.template`](https://github.com/dani-garcia/vaultwarden/blob/main/.env.template) 文件中找到大多数配置选项的文档列表。通常，注释内容中的值表示默认值，但这并不一定。如果不是，事实来源将是 [`src/config.rs`](https://github.com/dani-garcia/vaultwarden/blob/main/src/config.rs)。

如果您启用了[管理页面](/configuration/enabling-admin-page)，您还可以看到带有配置值的配置选项（并且如果您使用 `config.json`，还可以看到这些值与初始值相比是否有变化）。

{% hint style="warning" %}
**注意：**`config.json` 文&#x4EF6;***不是***&#x914D;置您的设置的推荐方式！要么使用环境变量，您可以通过多种方式为您的容器环境（Docker、Docker-Compose、K8s 等）进行配置；或者，如果使用独立的二进制文件（其不是由 Vaultwarden 本身分发的），请使用位于当前工作目录下的 `.env` 文件。在管理界面中保存设置时会创建并覆盖 `config.json` 文件！
{% endhint %}

如果您依赖[第三方软件包](/alternative-deployments/third-party-packages)，则必须检查提供的文档（例如 Arch Linux 的 `vaultwarden` 软件包的安装通知），因为下游维护者通常会对他们的软件包做出一些假设。

### 使用环境变量 <a href="#using-environment-variables" id="using-environment-variables"></a>

配置 Vaultwarden 的推荐方法是通过环境变量。根据您运行 Vaultwarden 的方式（例如直接运行、在容器化环境中运行、通过 systemd 运行等），设置环境变量的方法有多种，因此请熟悉您的平台和安装方法。

大多数可以设置的环境变量都可以在 `.env.template` 文件中找到。您还可以使用该文件作为容器环境的环境文件的基础（例如，通过 [`env_file`](https://docs.docker.com/compose/environment-variables/set-environment-variables/#use-the-env_file-attribute) 属性）或与 systemd 服务一起使用（参见 [`EnvironmentFile=`](https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html#EnvironmentFile=)） - 只是不要将此文件与下面的 [`ENV_FILE` 方式](#using-an-env_file)混淆！

{% hint style="info" %}
请注意，不同平台之间的环境文件解释方式可能存在一些细微的差异（关于变量扩展或是否可以或应该在值周围使用引号等）。
{% endhint %}

您还需要确保在正确的环境中设置变量。如果您使用容器化环境，`vaultwarden` 进程将与主机平台隔离运行。如果您使用可以设置环境变量的容器管理平台（例如使用 `docker-compose` 时），这一点尤其重要。因为通常这些环境变量可以在创建容器时使用，但它们不会被传递到正在运行的容器中。

{% hint style="danger" %}
如果更改值，则需要重新创建使用环境变量配置的容器，因为这些值绑定到容器。因此，除非[从（已更改的）文件中读取](https://github.com/dani-garcia/vaultwarden/wiki/Configuration-overview#loading-individual-values-from-files)该值，否则重新启动不会执行任何操作。
{% endhint %}

### 使用 `ENV_FILE` <a href="#using-an-env_file" id="using-an-env_file"></a>

Vaultwarden 还可以直接从环境文件本身读取配置选项，这在开发 Vaultwarden 时特别有用。

默认情况下，Vaultwarden 将尝试从当前工作目录读取一个名为 `.env` 的文件（例如，如果您从签出存储库的根目录运行 `cargo run`，它应该位于同一根目录中）。

{% hint style="info" %}
使用环境文件设置进程的运行时环境（无论是使用 docker 还是 systemd）与在 Vaultwarden 中使用 env 文件之间存在差异。例如。您还可以在使用[容器镜像](/container-image-usage/which-container-image-to-use)时将环境文件挂载到 `/.env` ，而不是[通过 `--env-file`](https://docs.docker.com/compose/environment-variables/set-environment-variables/#substitute-with---env-file) （创建容器时读取）传递环境文件。参见上面的解释。
{% endhint %}

直接在环境中设置的值将优先于此方法。这意味着可以在不更改 `ENV_FILE` 中的值的情况下覆盖这些值（这对于调试目的可能很有用，例如，当您临时设置 `LOG_LEVEL=debug` 时）。

### 从文件加载单个值 <a href="#loading-individual-values-from-files" id="loading-individual-values-from-files"></a>

Vaultwarden 支持从磁盘加载配置选项的值（通过环境变量或在 `ENV_FILE` 中设置）。您可以通过将 `_FILE` 添加到相关配置选项并将值设置为包含该值的文件的路径来实现此目的。

如果您想使用 `docker secrets` 这样的功能，这非常有用。例如，通过设置 `SMTP_PASSWORD_FILE=/run/secrets/smtp_password` ，它将从文件加载 SMTP 密码，而不将其作为环境变量提供给进程或容器）。

### 使用 `/admin` 页面 <a href="#using-the-admin-page" id="using-the-admin-page"></a>

在一定程度上，也可以通过 `config.json` 文件对 Vaultwarden 进行配置，该文件可以通过 `/admin` 面板生成和编辑，并保存在数据文件夹中。

{% hint style="info" %}
🙏 虽然从技术上讲可以手动创建和编辑 `config.json` 文件，**但我们强烈建议不要这样做**。[JSON](https://www.json.org/) 具有相当严格的语法，如果您不知道自己在做什么，这可能会成为调试的噩梦。
{% endhint %}

`config.json` 中的设置将覆盖任何其他配置方法，并且您将在启动时收到哪些设置已被 `config.json` 覆盖的警告。

由于生成的 `config.json` 在保存时将包含**所有**可编辑选项，因此请注意，一旦通过 `/admin` 页面生成配置文件，您就无法通过任何其他方法修改这些选项（至少在不修改或删除配置的情况下无法修改 `config.json` 文件）。

{% hint style="danger" %}
只读配置部分中的选项**无法**通过 `/admin` 页面修改，因为它们需要重新启动服务器，如果您手动将它们添加到 `config.json` 并且点击了「保存」，**它们将被移除**。请使用上述其他方法来修改它们。在大多数情况下，这意味着您还需要重新创建容器！
{% endhint %}

某些环境变量（例如 `ROCKET_ADDRESS` 或 `ROCKET_PORT`）不是 Vaultwarden 配置系统的一部分，因此无法通过 `config.json` 来设置。

## 配置优先级 <a href="#configuration-precedence" id="configuration-precedence"></a>

1. 编译时，默认值通过 `src/config.rs` 进行硬编码
2. 无需重新编译二进制文件。这些默认值可以通过配置 `ENV_FILE` 来更改
3. 也可以通过设置环境变量（这将推翻 `ENV_FILE` 中的设置）来更改
4. 最终用户（具有 `/admin` 面板访问权限）可以选择创建具有最高优先级的 `config.json`

## 设置域名 URL <a href="#setting-the-domain-url" id="setting-the-domain-url"></a>

确保将 `DOMAIN` 环境变量（或配置文件中的 `domain`）设置为您的 Vaultwarden 实例的基础 URL。如果不这样做，可能会出现莫名其妙的功能性问题。一些示例：

* `https://vaultwarden.example.com`
* `https://vaultwarden.example.com:8443`（非默认端口）
* `https://host.example.com/vaultwarden`（[子目录托管](/reverse-proxy/using-an-alternate-base-dir) - 尽可能避免 URL 重写）

## 有关不同配置选项的更多信息 <a href="#further-information-about-different-configuration-options" id="further-information-about-different-configuration-options"></a>

* 邀请和注册设置
  * [禁用邀请](/configuration/disable-invitations)
  * [禁用新用户注册](/configuration/disable-registration-of-new-users)
* 管理后台
  * [启用管理页面](/configuration/enabling-admin-page)
  * [禁用管理令牌](/alternative-deployments/disable-the-admin-token)
  * [翻译管理页面](/customization/translating-admin-page)
* [SMTP 配置](/configuration/smtp-configuration)
* 通知
  * [启用 WebSocket 通知](/configuration/enabling-websocket-notifications)
  * [启用移动客户端推送通知](/configuration/enabling-mobile-client-push-notification)
* 2FA 设置
  * [启用 U2F 和 FIDO2 WebAuthn 身份验证](/configuration/security/enabling-u2f-and-fido2-webauthn-authentication)
  * [启用 YubiKey OTP 身份验证](/configuration/security/enabling-yubikey-otp-authentication)
* [日志记录](/faq/troubleshooting/logging)
* [其他配置](/configuration/other-configuration)
  * [更改持久数据位置](/other-information/changing-persistent-data-location)
  * [更改 API 请求大小限制](/configuration/performance/changing-the-api-request-size-limit)
  * [更改 worker 数量](/configuration/performance/changing-the-number-of-workers)
* [翻译电子邮件模板](/customization/translating-the-email-templates)


# 2.启用管理页面

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page)
{% endhint %}

{% hint style="warning" %}
强烈建议在启用此功能之前激活 HTTPS，以避免潜在的 [MITM](https://zh.wikipedia.org/wiki/%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB) 攻击。
{% endhint %}

Vaultwarden 管理面板允许服务器管理员配置 Vaultwarden，查看所有已注册的用户和组织，以及删除它们。它也允许邀请新用户，即使禁用了注册功能。它还提供了一个诊断页面，您可以在其中生成支持字符串。

<div align="left" data-with-frame="true"><figure><img src="https://github.com/user-attachments/assets/7deeb859-b84a-45d6-97ab-50932ce8a6a0" alt=""><figcaption></figcaption></figure></div>

## 如何启用管理页面 <a href="#how-to-enable-the-admin-page" id="how-to-enable-the-admin-page"></a>

要启用管理页面，您需要配置一个身份验证令牌。该令牌可以是任何内容，但建议使用一个长且随机生成的字符串，例如，通过运行 `openssl rand -base64 32` 来生成。

**请保管好这个令牌。如果您将其配置为 `ADMIN_TOKEN` ，它将用作访问服务器管理区域的密码！**&#x7531;于配置通常以明文形式存储，建议[保护管理令牌](#secure-the-admin_token)。

您也可以通过[禁用管理令牌](/alternative-deployments/disable-the-admin-token)来启用管理员面板。由于这会给予管理面板无限制的访问权限，因此您只有在清楚自己在做什么的情况下才应该这样做。

### 会话管理 <a href="#session-management" id="session-management"></a>

如果您输入 `ADMIN_TOKEN` 的密码，您将获得一个授权您使用 `/admin` 面板的 JSON Web Token (JWT)。管理会话默认长度[设置为 20 分钟](https://github.com/dani-garcia/vaultwarden/blob/0c6817cb4e24964deaf765fd676da6c49e47d099/src/config.rs#L776-L777)。您可以通过更改 `ADMIN_SESSION_LIFETIME` 来配置会话长度。

由于 JWT 的特性以及管理面板没有额外的会话处理，任何拥有有效 JWT 的人都可以使用存储的令牌访问 Vaultwarden 管理页面。更改会话有效期甚至管理令牌本身都不会影响当前已登录的用户，因此您应避免不必要地增加管理会话长度。

要使任何会话失效，可以从 `DATA_FOLDER` 中移除 [`rsa_key.pem`](/backup/backing-up-your-vault#the-rsa_key-files) 然后重启 Vaultwarden 以重新创建 RSA 密钥。

## 禁用管理页面 <a href="#disabling-the-admin-page" id="disabling-the-admin-page"></a>

要禁用管理页面，请确保没有设置 `ADMIN_TOKEN` 或 `DISABLE_ADMIN_TOKEN` 环境变量，并且 `config.json`（如果该文件存在）中不存在 `"admin_token"` 键。之后重新创建容器并重启 Vaultwarden 以使更改生效。

## 保护 `ADMIN_TOKEN` <a href="#secure-the-admin_token" id="secure-the-admin_token"></a>

> **\[译者注]**：此功能自 [1.28.0+](https://github.com/dani-garcia/vaultwarden/releases/tag/1.28.0) 后可用。

您可以通过使用 Argon2 生成 [PHC 字符串](https://github.com/P-H-C/phc-string-format/blob/master/phc-sf-spec.md)来对 `ADMIN_TOKEN` 进行哈希处理。这样可确保管理令牌以哈希格式存储，因此不能被直接读取。

PHC 字符串可以通过[使用内置的 `hash` 命令](#using-vaultwarden-hash)或[使用 `argon2` CLI 工具](#using-argon2)生成。

### 使用 `vaultwarden hash` <a href="#using-vaultwarden-hash" id="using-vaultwarden-hash"></a>

Vaultwarden 内置了一个 PHC 生成器，您可以通过 CLI 调用 `vaultwarden hash` 来运行它。默认情况下，此命令使用 [Bitwarden 的默认设置](https://github.com/bitwarden/clients/blob/04d1fbb716bc7676c60a009906e183bb3cbb6047/libs/common/src/enums/kdfType.ts#L8-L10)（m=64 MiB，t=3 迭代，p=4 线程）。您可以通过传递 `--preset owasp` 以使用 [OWASP 最低的推荐设置](https://cheatsheetseries.owasp.org/cheatsheets/Password_Storage_Cheat_Sheet.html#argon2id)（m=19MiB，t=2，p=1）。

Vaultwarden hash 命令会要求输入两次密码，如果两次输入的密码相同，则会输出生成的 PHC 字符串。

运行该命令的一些示例：

```shell
# 直接使用 vaultwarden 二进制文件
./vaultwarden hash

# 通过 docker 并创建一个临时容器
docker run --rm -it vaultwarden/server /vaultwarden hash

# 通过正在运行的容器上的 docker（相应地替换 vwcontainer）
docker exec -it vwcontainer /vaultwarden hash
```

### 使用 `argon2` <a href="#using-argon2" id="using-argon2"></a>

您还可以使用大多数 Linux 发行版上提供的 `argon2` 命令。

```sh
# 使用 Bitwarden 默认
echo -n <YOUR_PASSWORD> | argon2 "$(openssl rand -base64 32)" -e -id -k 65540 -t 3 -p 4
# 输出：$argon2id$v=19$m=65540,t=3,p=4$bXBGMENBZUVzT3VUSFErTzQzK25Jck1BN2Z0amFuWjdSdVlIQVZqYzAzYz0$T9m73OdD2mz9+aJKLuOAdbvoARdaKxtOZ+jZcSL9/N0

# 使用 OWASP 最低的推荐设置
echo -n <YOUR_PASSWORD> | argon2 "$(openssl rand -base64 32)" -e -id -k 19456 -t 2 -p 1
# 输出：$argon2id$v=19$m=19456,t=2,p=1$cXpKdUxHSWhlaUs1QVVsSStkbTRPQVFPSmdpamFCMHdvYjVkWTVKaDdpYz0$E1UgBKjUCD2Roy0jdHAJvXihugpG+N9WcAaR8P6Qn/8
```

### 使用已生成的 PHC 字符串 <a href="#using-the-generated-phc-string" id="using-the-generated-phc-string"></a>

在环境变量中使用已生成的 PHC 字符串作为管理令牌，或者将 PHC 字符串传递给 docker/podman CLI 命令。对于 `docker-compose.yml` 文件，请按照以下说明操作。

如果您通过 `/admin` 页面配置了 Vaultwarden，您应该将字符串粘贴到 `Admin token/Argon2 PHC` 字段（位于 General settings）：

<div align="left" data-with-frame="true"><figure><img src="https://github.com/user-attachments/assets/52bf60df-1880-41b2-aab7-eac9982f7505" alt=""><figcaption></figcaption></figure></div>

设置 PHC 字符串后，您可以使用生成该 PHC 字符串时使用的密码进行登录，例如上述示例中的 \<YOUR\_PASSWORD>。

{% hint style="info" %}
如果您可以将整个 `$argon2id$…` PHC 字符串作为管理密码输入，那么您可能正在使用一个过时的 Vaultwarden 版本，该版本尚未支持 argon2id。请确保您使用的至少是[最新版本](https://github.com/dani-garcia/vaultwarden/releases/latest)。
{% endhint %}

### 如何防止 `docker-compose.yml` 中的变量插值 <a href="#how-to-prevent-variable-interpolation-in-docker-compose.yml" id="how-to-prevent-variable-interpolation-in-docker-compose.yml"></a>

当[使用 Docker Compose](/container-image-usage/using-docker-compose) 并且您通过 `environment` 指令配置 `ADMIN_TOKEN` 时，您需要使用两个美元符号 `$$` 来转义已生成的 argon2 PHC 字符串中出现的所有五个美元符号 `$` 以防止[变量插值](https://docs.docker.com/compose/compose-file/#interpolation)，例如：

```yaml
  environment:
    ADMIN_TOKEN: $$argon2id$$v=19$$m=19456,t=2,p=1$$UUZxK1FZMkZoRHFQRlVrTXZvS0E3bHpNQW55c2dBN2NORzdsa0Nxd1JhND0$$cUoId+JBUsJutlG4rfDZayExfjq4TCt48aBc9qsc3UI
```

这可以自动完成，例如通过在上面的 `argon2` 命令行的末尾添加 `| sed 's#\$#\$\$#g'` 并使用 sed 来完成。

否则您将收到警告消息，且变量将无法正确设置：

```
WARNING: The argon2id variable is not set. Defaulting to a blank string.
WARNING: The v variable is not set. Defaulting to a blank string.
WARNING: The m variable is not set. Defaulting to a blank string.
...
```

{% hint style="info" %}
当为 `docker-compose.yaml` 使用 `.env` 文件时，不需要变量插值。

如下面的示例所示。在这种情况下，只需使用单个 `$` 变体。与使用 docker/podman CLI 时使用 `-e ADMIN_TOKEN`，或者在[配置为 Vaultwarden 使用 `ENV_FILE`](/configuration/configuration-overview#using-an-env_file) 的方式相同。
{% endhint %}

```
/docker-data
├── .env
├── docker-compose.yaml
├── vaultwarden/data
```

**.env：**

*确保在 docker-compose 所使用的 `env` 文件中使用单引号。*

```systemd
VAULTWARDEN_ADMIN_TOKEN='$argon2id$v=19$m=65540,t=3,p=4$MmeK.....'
```

**docker-compose.yaml：**

```yaml
services:
  vaultwarden:
    image: ghcr.io/dani-garcia/vaultwarden
    container_name: vaultwarden
    restart: unless-stopped
    volumes:
      - /path/to/vaultwarden/data/:/data/
    environment:
      - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN}
```

您可以通过调用 `docker compose config` 来检查您的配置，您应该会看到 `$` 符号已自动转义成了两个 `$$`。

### 故障排除提示 <a href="#troubleshooting-tips" id="troubleshooting-tips"></a>

如果您持续收到 `You are using a plain text ADMIN_TOKEN which is insecure.`（您正在使用不安全的纯文本 `ADMIN_TOKEN`。）消息，则说明您已经通过管理界面保存了设置，环境变量将不会被使用（请参阅配置优先级）。或者您需要验证是否使用了正确的格式。

您需要确保配置的 PHC 字符串被正确传递给 Vaultwarden，以避免实际值被加上不必要的引号（如 `'` 或 `"` ）包围，以及避免美元符号 `$` 被重复转义为 `$$`，比如把\
`$argon2id$v=19$m=65540…` 变成 `$$argon2id$$v=19$$m=65540…` 。

如果您使用环境变量传递了该配置，可以通过调用 `printenv ADMIN_TOKEN` （或者如果您使用 Docker，则运行 `docker exec vwcontainer printenv ADMIN_TOKEN` ）来检查输出结果是否仅返回配置的 PHC 字符串，例如：

```yaml
$argon2id$v=19$m=65540,t=3,p=4$bXBGMENBZUVzT3VUSFErTzQzK25Jck1BN2Z0amFuWjdSdVlIQVZqYzAzYz0$T9m73OdD2mz9+aJKLuOAdbvoARdaKxtOZ+jZcSL9/N0
```

或者，如果您使用管理页面配置 Vaultwarden，可以通过运行 `grep admin_token data/config.json` 来检查是否返回预期的 PHC 字符串，如下所示：

```yaml
  "admin_token": "$argon2id$v=19$m=65540,t=3,p=4$bXBGMENBZUVzT3VUSFErTzQzK25Jck1BN2Z0amFuWjdSdVlIQVZqYzAzYz0$T9m73OdD2mz9+aJKLuOAdbvoARdaKxtOZ+jZcSL9/N0",
```

## 使用 Vaultwarden 管理面板 <a href="#using-the-vaultwarden-admin-panel" id="using-the-vaultwarden-admin-panel"></a>

### 设置 <a href="#settings" id="settings"></a>

您在管理页面首次保存配置时，将在您的 `DATA_FOLDER` 中生成一个名为 `config.json` 的文件。该文件中的值将优先于相应的环境变量。

{% hint style="warning" %}
创建 `config.json` 会为当前配置中的大多数值设置默认值，因此您将来需要使用管理面板来配置您的实例。唯一的例外是只读部分中的配置选项以及更高级的配置选项。
{% endhint %}

在您点击 `Save` 按钮之前，管理页面中的配置更改是不会生效的。例如，如果您正在测试 SMTP 设置，您更改了 `SMTP Auth mechanism` 设置，然后点击 `Send test email` 来测试更改，这将不会像预期的那样工作 -- 因为您没有点击 `Save`，`SMTP Auth mechanism` 的更改不会生效。

### 用户 <a href="#users" id="users"></a>

用户概览允许您管理所有用户账户，并检查他们是否已完成注册，他们加入了哪些组织以及他们的用户角色是什么。组织的颜色表示用户的当前角色：<mark style="color:blue;">蓝色</mark>表示普通用户，<mark style="color:green;">绿色</mark>表示经理/自定义角色，<mark style="color:purple;">紫色</mark>表示管理员，<mark style="color:orange;">橙色</mark>表示所有者。

<div align="left" data-with-frame="true"><figure><img src="https://github.com/user-attachments/assets/ffb94abc-9ce4-4be5-ac87-d89e51e5b7b1" alt=""><figcaption></figcaption></figure></div>

通过右侧的操作，您可以移除 2FA 提供程序，为用户取消授权任何现有会话，以及禁用或删除任何用户。

如果您点击组织按钮，也可以更改指定成员的角色。

<div align="left" data-with-frame="true"><figure><img src="https://github.com/user-attachments/assets/1910822f-a297-431a-9309-8262c6563b5e" alt=""><figcaption></figcaption></figure></div>

由于组织至少需要一位所有者，因此您无法移除最后一位所有者的所有者角色。

您也无法通过管理面板将用户添加到组织中。您只能将组织中的现有成员晋升为其他角色。

### 组织 <a href="#organizations" id="organizations"></a>

在组织概览中，您可以删除任何组织。由于您无法删除组织的最后一位所有者，您可能必须先删除所有者的组织。

<div align="left" data-with-frame="true"><figure><img src="https://github.com/user-attachments/assets/88444e11-04ca-430c-a2e4-8fba2f126ad9" alt=""><figcaption></figcaption></figure></div>

### 诊断 <a href="#diagnostics" id="diagnostics"></a>

诊断页面会收集一些基本信息，有助于定位某些配置错误，同时也会检查是否有可用更新。这也是您可以生成支持字符串的页面，该字符串会自动收集您系统中的最重要信息，并使其易于分享到我们的问题追踪系统（以及我们的支持论坛）。


# 3.SMTP 配置

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/SMTP-Configuration)
{% endhint %}

{% hint style="danger" %}
**注意**：v1.25.0 版本之前的 Vaultwarden 有一个关于 SSL 和 TLS 的漏洞/误导性的配置设置项。这已在测试版和新发布的版本中得到修复。

旧设置项是 `SMTP_SSL` 和 `SMTP_EXPLICIT_TLS`。

新设置项是 `SMTP_SECURITY`，它具有以下可用选项：`starttls`、`force_tls` 以及 `off`。

* `SMTP_SECURITY=starttls` 等同于 `SMTP_SSL=true`
* `SMTP_SECURITY=force_tls` 等同于 `SMTP_EXPLICIT_TLS=true`
  {% endhint %}

{% hint style="info" %}
若您选择不配置 SMTP，当您通过网页密码库、浏览器扩展和移动 App 以外的方式（如 Bitwarden CLI）登录时，Vaultwarden 可能无法发送验证电子邮件，并可能拒绝验证请求。要规避此行为，请在您的账户中设置双重验证。请参阅：<https://github.com/dani-garcia/vaultwarden/discussions/6410>
{% endhint %}

***

您可以配置 Vaultwarden 通过 SMTP 代理来发送电子邮件：

```shell
docker run -d --name vaultwarden \
  -e SMTP_HOST=smtp.domain.tld \
  -e SMTP_FROM=vaultwarden@domain.tld \
  -e SMTP_PORT=587 \
  -e SMTP_SECURITY=starttls \
  -e SMTP_USERNAME=myusername \
  -e SMTP_PASSWORD=MyPassw0rd \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

从 v1.25.0 开始，用于 SMTP SSL/TLS 配置的环境变量已更新为 `SMTP_SECURITY`（之前的有误导性，参阅[错误 #851](https://github.com/dani-garcia/vaultwarden/issues/851)）。当 `SMTP_SECURIT` 设置为 `starttls` 时（这是默认值），将仅接受 TLSv1.1 和 TLSv1.2 协议，并且 `SMTP_PORT` 默认为`587`。如果设置为 `off`，`SMTP_PORT` 则默认设置为 `25` 并将尝试加密（2020 年 3 月 12 日之前的代码不会尝试加密）。这是非常不安全的，仅在您知道您在做什么时才使用此设置。要以隐式模式（强制 TLS）运行 SMTP，请将 `SMTP_SECURITY` 设置为 `force_tls`。如果您不登录也可以发送电子邮件，简单地将 `SMTP_USERNAME` 和 `SMTP_PASSWORD` 设置为空即可。

请注意，如果启用了 SMTP 和邀请，邀请将通过电子邮件发送给新用户。您必须使用 Vaultwarden 实例的基础 URL 来设置 `DOMAIN` 配置项，以生成正确的邀请链接：

```shell
docker run -d --name vaultwarden \
...
-e DOMAIN=https://vault.example.com \
...
```

用户邀请链接有效期为 5 天，过期后需要重新发送邀请。

## SMTP 服务器 <a href="#smtp-servers" id="smtp-servers"></a>

正确配置 SMTP 服务器/中继并不是一件容易的事。Vaultwarden 使用的邮件程序库也不是最容易排除故障的。所以，除非您特别有兴趣自己设置，否则使用外部服务可能会更简单。

这里有几个对于大部分使用场景来说已经足够的免费服务：

* [~~SendGrid~~](https://sendgrid.com)~~（每天 100 封电子邮件）~~
* [MailJet](https://www.mailjet.com)（每天 200 封电子邮件）
* [SendinBlue](https://www.sendinblue.com/)（每天 200 封电子邮件）
* [SMTP2GO](https://www.smtp2go.com/)（每月 1000 封电子邮件）

## 一些知名服务的默认设置 <a href="#here-some-sane-defaults-for-well-known-services" id="here-some-sane-defaults-for-well-known-services"></a>

### 通用 <a href="#general" id="general"></a>

邮件服务器侦听端口 25 主要只是为了接受来自其他邮件服务器的邮件，并且仅用于它们是最终位置的邮件。此外，许多互联网提供商会阻止传出端口 25 以防止垃圾邮件。大多数需要登录的邮件服务器使用端口 587 或端口 465。端口 587 称为提交端口，大多数时候只能在使用用户名和密码时使用。在客户端和服务器之间的通信期间，端口 587 开始时未加密然后升级为 TLS 加密连接。端口 465 从一开始就是 SSL 加密的，该端口根本没有纯文本通信。

针对每一种端口的常见设置：

* 对于使用端口 465 的邮件服务器

```systemd
SMTP_PORT=465
SMTP_SECURITY=force_tls
```

* 对于使用端口 587（有时候是 25）的邮件服务器

```systemd
SMTP_PORT=587
SMTP_SECURITY=starttls
```

* 对于根本不支持加密的邮件服务器

```systemd
SMTP_PORT=25
SMTP_SECURITY=off
```

### HELO 主机名 <a href="#helo-hostname" id="helo-hostname"></a>

默认情况下，机器的主机名被用来作为 HELO 命令中的主机名。要覆盖它，您可以在配置中设置 `HELO_NAME`。

### Google/Gmail

您需要为 Vaultwarden 生成应用专用密码才能使用 Gmail。按照此处的步骤操作：[使用应用专用密码登录](https://support.google.com/accounts/answer/185833?hl=zh-Hans\&ref_topic=7189145)~~（自 2022 年 5 月 30 日起不可用）~~，最后您会得到一个密码（中间有空格但无需使用，只是为了方便输入），使用这个密码。

{% hint style="info" %}
如果这个无法完成（由于您的安全设置），您可以参阅下面有关 [OAuth2 支持](#oauth2-support)的部分以获取更多信息。
{% endhint %}

StartTLS：

```systemd
  # Domains: gmail.com, googlemail.com
  SMTP_HOST=smtp.gmail.com
  SMTP_PORT=587
  SMTP_SECURITY=starttls
  SMTP_FROM=user@gmail.tld
  SMTP_USERNAME=user@gmail.tld
  SMTP_PASSWORD=Less-Secure-App-Passw0rd
```

FullSSL：

```systemd
  # Domains: gmail.com, googlemail.com
  SMTP_HOST=smtp.gmail.com
  SMTP_PORT=465
  SMTP_SECURITY=force_tls
  SMTP_FROM=user@gmail.tld
  SMTP_USERNAME=user@gmail.tld
  SMTP_PASSWORD=Less-Secure-App-Passw0rd
```

另请参阅：[Using Lettre With Gmail](https://web.archive.org/web/20210925161633/https://webewizard.com/2019/09/17/Using-Lettre-With-Gmail/)

### Hotmail/Outlook/Office365

{% hint style="danger" %}
由于微软要求支持 OAuth2，下面的方法将不再起作用。有关详细信息，请参阅[下面的故障排除](#troubleshooting)。
{% endhint %}

```systemd
  # Domains: hotmail.com, outlook.com, office365.com
  SMTP_HOST=smtp-mail.outlook.com
  SMTP_PORT=587
  SMTP_SECURITY=starttls
  SMTP_FROM=user@hotmail.tld
  SMTP_USERNAME=user@hotmail.tld
  SMTP_PASSWORD=MyPassw0rd
  SMTP_AUTH_MECHANISM="Login"
```

### SendGrid

将 `<full-api-key>` 替换为从 SendGrid 生成的以 `SG` 开头的 API-Key。还要确保 API-Key 具有完整的 `Mail Send` 权限，否则您无法使用此密钥登录。

StartTLS：

```systemd
  SMTP_HOST=smtp.sendgrid.net
  SMTP_PORT=587
  SMTP_SECURITY=starttls
  SMTP_USERNAME=apikey
  SMTP_PASSWORD=<full-api-key>
  SMTP_AUTH_MECHANISM="Login"
  SMTP_FROM=user@domain.tld
```

FullSSL：

```systemd
  SMTP_HOST=smtp.sendgrid.net
  SMTP_PORT=465
  SMTP_SECURITY=force_tls
  SMTP_USERNAME=apikey
  SMTP_PASSWORD=<full-api-key>
  SMTP_AUTH_MECHANISM="Login"
  SMTP_FROM=user@domain.tld
```

## 带特殊字符的密码 <a href="#passwords-with-special-characters" id="passwords-with-special-characters"></a>

如果您想在密码中使用一些特殊字符，可能需要对其中的一些字符进行转义，以免混淆环境变量解析器。

例如，可以使用 `\` 或 `'` 或 `"`，但在实际使用的时候，需要对它们进行转义。如果您使用特殊字符，最好总是使用单引号将密码括起来。

我们以下面这个密码为例：`~^",a.%\,'}b&@|/c!1(#}`

它包含了一些可能会破坏环境变量解析的字符，比如 `\`、`'` 和 `"`。单个 `\` 通常用于转义其他字符，因此如果您想使用单个 `\`，则需要键入 `\\`。 此外，引号 `'` 和 `"` 可能会引起一些问题，因此让我们将此密码括在单引号中并转义特殊字符。为了让上面的密码起作用，我们需要输入 `'~^",a.%\\,\'}b&@|/c!1(#}'`，在这里你看到我们转义了 `\` 和 `'` 字符并使用单引号将整个密码括了起来。所以：`~^",a.%\,'}b&@|/c!1(#}` 变成了 `'~^",a.%\\,\'}b&@|/c!1(#}'`。

## 使用已弃用的 `SMTP_SSL` 和 `SMTP_EXPLICIT_TLS` SMTP 环境变量（适用于 v1.24.0 及更低版本） <a href="#using-deprecated-smtp-environment-variable-smtp_ssl-and-smtp_explicit_tls-for-v1.24.0-and-lower" id="using-deprecated-smtp-environment-variable-smtp_ssl-and-smtp_explicit_tls-for-v1.24.0-and-lower"></a>

您可以配置 Vaultwarden 通过 SMTP 代理来发送电子邮件：

```shell
docker run -d --name vaultwarden \
  -e SMTP_HOST=<smtp.domain.tld> \
  -e SMTP_FROM=<vaultwarden@domain.tld> \
  -e SMTP_PORT=587 \
  -e SMTP_SSL=true \
  -e SMTP_USERNAME=<username> \
  -e SMTP_PASSWORD=<password> \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

当 `SMTP_SSL` 设置为 `true` 时（这是默认值），将仅接受 TLSv1.1 和 TLSv1.2 协议，并且 `SMTP_PORT` 默认为`587`（等同于 `SMTP_SECURITY=starttls`）。如果设置为 `false`，`SMTP_PORT` 则默认设置为 `25` 并将尝试加密（2020 年 3 月 12 日之前的代码不会尝试加密）（等同于 `SMTP_SECURITY=off`）。这是非常不安全的，仅在您知道您在做什么时才使用此设置。要以隐式模式（强制 TLS）运行 SMTP，请将 `SMTP_EXPLICIT_TLS` 设置为 `true`（等同于 `SMTP_SECURITY=force_tls`）。如果您不登录也可以发送电子邮件，简单地将 `SMTP_USERNAME` 和 `SMTP_PASSWORD` 设置为空即可。

{% hint style="info" %}
**注意**：如果您在 v1.25.0 及更高版本上使用 `SMTP_SSL` 和 `SMTP_EXPLICIT_TLS` 设置，Vaultwarden 会对已弃用的设置产生的错误进行忽略。
{% endhint %}

## 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>

人们经常遇到 Vaultwarden 连接 SMTP 服务器的问题。大多数情况下，是因为错误的配置或 ISP/主机屏蔽了端口或 IP。

检查您是否可以访问 SMTP 服务器的一些基本步骤是通过在您运行 Vaultwarden（无论是使用 Docker 还是作为一个独立的二进制文件）的主机上运行以下命令来完成。

{% hint style="info" %}
**注意**：将 `smtp.google.com` 和 `587`、`465` 或 `25` 替换为与您的 SMTP 服务器对应的主机和端口。
{% endhint %}

这些命令的输出应该是 `0`，如果它返回的不是 `0`，就意味着连接到此服务器时有问题。

```bash
# 首先通过检查对 google.com 的 HTTPS 访问来确认是否可以使用此检查
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/www.google.com/443'; echo $?

# 检查 SMTP 提交端口 587
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/smtp.gmail.com/587'; echo $?

# 检查 SMTP SSL 端口 465
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/smtp.gmail.com/465'; echo $?

# 检查默认 SMTP 端口 25
timeout 5 bash -c 'cat < /dev/null > /dev/tcp/smtp.gmail.com/25'; echo $?

# 或者使用一个叫做 nc 的工具（这个工具并不总是在主机上或容器内可用）
nc -vz smtp.gmail.com 587
```

要从 docker 容器内部检查，请首先在 docker 主机上运行以下命令以登录到容器。在下面的示例中，我假设容器名称是 `vaultwarden`，将其更改为您使用的容器名称。运行下面的命令后，再运行上述命令之一以从容器内部检查访问性。

```bash
docker exec -it vaultwarden sh
```

### OAuth2 支持 <a href="#oauth2-support" id="oauth2-support"></a>

如果您收到以下错误消息：

> No compatible authentication mechanism was found（未找到兼容的身份验证机制）

这很可能是因为 Microsoft（以及某些用例的 Google Mail）已切换到 OAuth2（参阅 [RFC 6749](https://datatracker.ietf.org/doc/html/rfc6749)）作为唯一受支持的身份验证方法，而我们（暂时）还不支持，即使 lettre crate 已经有对它的非标准支持（参阅 [#4518](https://github.com/dani-garcia/vaultwarden/discussions/4518#discussioncomment-9196455)）。

推荐的处理方法（如果您不想或可以使用不同的 SMTP 服务器）是设置 [email-oauth2-proxy](https://github.com/simonrob/email-oauth2-proxy)。

## 使用 `sendmail`（非 Docker）

如果您的系统上已经有一个正在运行的 SMTP 服务器（例如 Postfix），并且您在没有 docker 的情况下安装了 Vaultwarden，那么还需要一些额外的步骤来允许服务器通过 sendmail 使用您的 SMTP 服务器：

* 在 Vaultwarden 配置文件（通常是 `/etc/vaultwarden.env`）中，设置 `USE_SENDMAIL=true`
* 在同一文件中，设置 `SMTP_FROM=user@example.com`（替换为您自己的！）变量，因为它也被 sendmail 使用
* 以 `root` 用户身份（或使用 `sudo`），使用 `gpasswd -a vaultwarden postdrop` 命令将 `vaultwarden` 用户加入到 `postdrop` 组
* 使用 `systemctl edit vaultwarden` 编辑 vaultwarden systemd 服务然后在 `[Service]` 部分添加如下两行：

```systemd
RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6 AF_LOCAL AF_NETLINK
ReadWritePaths=/var/lib/vaultwarden /var/log/vaultwarden.log /var/spool/postfix/maildrop
```

最后，别忘了使用 `systemctl restart vaultwarden` 重启服务。


# 4.禁用新用户注册

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Disable-registration-of-new-users)
{% endhint %}

默认情况下，可以访问实例的任何人均可以注册新的账户。要禁用该功能，请将 `SIGNUPS_ALLOWED` 环境变量设置为 `false`：

```shell
docker run -d --name vaultwarden \
  -e SIGNUPS_ALLOWED=false \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

**注意**：当 `SIGNUPS_ALLOWED=false` 时，网页密码库用户界面将不会显示 `Create Account` 按钮。 无论设置如何，仍然可以邀请。

## 禁用组织邀请 <a href="#disabling-organization-invitations" id="disabling-organization-invitations"></a>

即使 `SIGNUPS_ALLOWED=false`，作为组织的所有者或管理员的现有用户仍然可以邀请新用户。如果您也想禁用此功能，请参阅[禁用邀请](/configuration/disable-invitations)。

## 将注册限制为某些电子邮箱域名 <a href="#restricting-registrations-to-certain-email-domains" id="restricting-registrations-to-certain-email-domains"></a>

您可以通过设置 `SIGNUPS_DOMAINS_WHITELIST` 来限制只能某些域名的电子邮箱地址可以注册。示例：

* `SIGNUPS_DOMAINS_WHITELIST=example.com` （单个域名）
* `SIGNUPS_DOMAINS_WHITELIST=example.com,example.net,example.org` （多个域名）

{% hint style="warning" %}
如果设置了 `SIGNUPS_DOMAINS_WHITELIST`，`SIGNUPS_ALLOWED=false`的值将被忽略。
{% endhint %}

您可能还想设置 `SIGNUPS_VERIFY=true`，这要求新注册的用户在成功登录前进行电子邮箱验证。这可以防止有人用一个拥有正确域名的假电子邮箱地址注册。

## 创建账户链接的可见性 <a href="#visibility-of-the-create-account-link" id="visibility-of-the-create-account-link"></a>

当 `SIGNUPS_ALLOWED=false`（且 `SIGNUPS_DOMAINS_WHITELIST` 为空）时，网页密码库 UI 中的创建账户链接将隐藏，除非您没有[配置电子邮箱](/configuration/smtp-configuration)和允许邀请（参见 [#6109](https://github.com/dani-garcia/vaultwarden/issues/6109)）。如果在后一种情况下也不想让链接可见，可以使用[自定义 CSS](/customization/customize-vaultwarden-css) 隐藏链接。

## 通过管理页面邀请 <a href="#invitations-via-the-admin-page" id="invitations-via-the-admin-page"></a>

Vaultwarden 管理员可以通过[管理页面](/configuration/enabling-admin-page)邀请任何人，不受以上限制。如果 SMTP 被禁用，用户应访问 `https://vaultwarden.example.tld/#/signup` 然后使用邀请的电子邮箱注册。


# 5.禁用邀请

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Disable-invitations)
{% endhint %}

即使禁用了注册功能，组织管理员或所有者也可以邀请用户加入组织。受邀请后，他们也可以使用受邀请的电子邮箱来注册，即使 `SIGNUPS_ALLOWED` 已设置为 `false`。您可以通过将 `INVITATIONS_ALLOWED` 环境变量设置为 `false` 来完全禁用此功能：

```shell
docker run -d --name vaultwarden \
  -e SIGNUPS_ALLOWED=false \
  -e INVITATIONS_ALLOWED=false \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```


# 6.启用 WebSocket 通知

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-WebSocket-notifications)
{% endhint %}

WebSocket 通知用于将发生的一些相关事件通告给浏览器、Bitwarden 的桌面和浏览器扩展客户端，例如密码数据库中有条目被修改了或被删除了。收到通知后，客户端可以采取适当的操作，例如刷新已修改的条目，或从其本地缓存中移除已删除的条目。在此通知方案中，Bitwarden 客户端与 Bitwarden 服务器（在本案例中为 Vaultwarden）建立持久的 WebSocket 连接。每当服务器有需要报告的事件时，它都会通过此持久连接将其发送给客户端。

请注意，WebSocket 通知不适用于移动 (Android/iOS) Bitwarden 客户端。这些客户端使用原生推送通知服务（Android 为 [FCM](https://firebase.google.com/docs/cloud-messaging)，iOS 为 [APN](https://developer.apple.com/go/?id=push-notifications)）。这些必须使用 Bitwarden 云服务的推送证书单独配置，自 v1.29.0 起可用。

自 Vaultwarden v1.29.0 起，WebSocket 默认启用。以前的版本需要反向代理，因为 WebSocket 运行在与默认的 HTTPS 端口不同的端口上。

旧的实现在 v1.29.0 中仍然可用，暂时不会在更新期间中断。但将来这将被移除。

如果您确实使用像 nginx 或 Apache HTTPd 这样的反向代理，那么您需要确保正确配置它以传递 WebSocket `Upgrade` 和 `Connection` 标头。一些反向代理默认执行此操作，例如 Traefik。

自 Vaultwarden v1.29.0 版本起，旧的 `WEBSOCKET_ENABLED` 和 `WEBSOCKET_PORT` 已被弃用并将被忽略。在 v1.29.0 版本之后，您可以通过将 `ENABLE_WEBSOCKET` 设置为 `false` 值来禁用 Websocket 通知，这将减少 Vaultwarden 使用的资源（尽管不会太多）。自 v1.31.0 起，已移除对 3012 端口 WebSocket 流量的支持，因为它已集成至主 HTTP 端口。

示例配置包含在[代理示例](/reverse-proxy/proxy-examples)中。&#x20;

**请注意，某些示例尚未针对 v1.29.0 进行更新。**

## 测试 WebSocket 连接 <a href="#test-the-websockets-connection" id="test-the-websockets-connection"></a>

有两种方式可以测试连接是否正常工作：

1. 打开浏览器的开发人员工具，转到网络选项卡然后筛选 `WS`/`WebSockets`。注销或刷新页面并再次登录，您应该会看到升级后的 WebSocket 连接的 101 响应。如果您单击该行，您应该能够看到消息。如果您没有在 `/notifications/hub` 上获得状态代码 101，则表示某些配置不正确。消息将显示在浏览器的控制台窗口中：`[2023-12-01T00:00:00.000Z] Information: WebSocket connected to wss://HOST_NAME/notifications/hub?access_token=eyJ0eX......`
2. 打开两个不同的浏览器或隐身/隐私窗口。在两个浏览器上登录您的账户。创建一个新的条目，或者重命名一个条目，在另一个浏览器中应该会立即收到更改。


# 7.启用移动客户端推送通知

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Mobile-Client-push-notification)
{% endhint %}

从 Vaultwarden 1.29.0 版本开始，您可以激活移动客户端的推送通知，以在移动应用程序、网页扩展程序和网页密码库之间[自动同步](https://help.ppgg.in/password-manager/vault-administration/syncing-your-vault#automatic-sync)您的个人密码库，而无需手动同步。

### 启用移动客户端推送通知 <a href="#enable-mobile-client-push-notification" id="enable-mobile-client-push-notification"></a>

1、访问 <https://bitwarden.com/host/>，输入您的电子邮箱地址，然后您将获得一个 INSTALLATION ID 和 KEY。

2、将以下设置添加到 `docker-compose.yml`（并确保插入上一步获取到的正确 ID 和 KEY）：

```yaml
    environment:
      - PUSH_ENABLED=true
      - PUSH_INSTALLATION_ID=
      - PUSH_INSTALLATION_KEY= 
```

{% hint style="info" %}
如果您在上一步中请求了 `bitwarden.eu (European Union)` 的安装 ID 和 KEY，您还必须设置：

```yaml
      - PUSH_RELAY_URI=https://api.bitwarden.eu
      - PUSH_IDENTITY_URI=https://identity.bitwarden.eu
```

{% endhint %}

3、重新创建您的容器，例如：

```sh
docker compose up -d vaultwarden
```

4、注销然后重新登录 Bitwarden 客户端，这样它们就能从服务器上获取推送配置。

{% hint style="danger" %}
如果您在 [v1.30.2](https://github.com/dani-garcia/vaultwarden/releases/tag/1.30.2) 之前已经连接了 Bitwarden 应用程序，则推送通知**将不适用于**您的设备（因为设备令牌从未保存）。您必须**清除应用程序数据**（或**重新安装应用程序**）然后再次连接您的 Vaultwarden 账户，才能向 [Bitwarden 的 Azure 通知中心](https://contributing.bitwarden.com/architecture/deep-dives/push-notifications/mobile/#self-hosted-implementation)注册推送令牌。
{% endhint %}

{% hint style="warning" %}
推送通知**仅适用于**从官方移动商店（App Store、Google Play 商店）或使用 Google Play 商店的替代客户端（如 Aurora 商店）获取的 Bitwarden 应用程序。从 [F-Droid](https://mobileapp.bitwarden.com/fdroid/)、NeoStore 或其他替代商店安装的 Bitwarden，推送通知**将不起作用**。因为这些应用程序是在不支持 Firebase Messaging 的情况下构建的。为保证推送通知正常，请确保 `firebaseinstallations.googleapis.com` 未被阻止，因为该功能需要它才能正常工作。
{% endhint %}

5、测试移动端的推送通知是否正常工作，例如通过重命名网页密码库中的文件夹，然后查看移动应用程序中的文件夹在几秒钟后是否发生变化。

## 从美国服务器切换到欧盟服务器（反之亦然） <a href="#switching-from-us-to-eu-servers-or-vice-versa" id="switching-from-us-to-eu-servers-or-vice-versa"></a>

{% hint style="danger" %}
在进行此更改之前，请确保您使用的是最新版本 [![GitHub Release](https://img.shields.io/github/release/dani-garcia/vaultwarden.svg)](https://github.com/dani-garcia/vaultwarden/releases/latest)。
{% endhint %}

要从一个数据区域切换到另一数据区域，您必须：

1. 取消所有会话授权并清除移动应用程序上的应用程序数据
2. 使用不同的数据区域重复上一节中的步骤 1 到步骤 5

除了步骤 1 之外，您还可以清除数据库中 `devices` 表的 `push_uuid` 字段，例如：

```sql
UPDATE devices SET push_uuid = NULL;
```

这将触发在您下次登录该设备时重新注册您的推送设备。


# 8.使用 OpenId Connect 启用 SSO 支持

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-SSO-support-using-OpenId-Connect)
{% endhint %}

要使用外部身份验证源，您的 SSO 需要支持 OpenID Connect：

* OpenID Connect 发现端点需要可用
* 客户端认证将使用 ID 和 Secret 完成

仍然需要主密码，且不由 SSO 控制（根据您的观点，这可能是一个功能）。这引入了另一种控制谁可以使用密码库的方式，而无需使用邀请或使用 LDAP。

## 配置 <a href="#configuration" id="configuration"></a>

以下配置可用：

* `SSO_ENABLED`：激活 SSO
* `SSO_ONLY`：禁用电子邮箱 + 主密码身份验证
* `SSO_SIGNUPS_MATCH_EMAIL`：在 SSO 注册时，如果存在具有相同电子邮件地址的用户，则进行关联（默认为 `true`）
* `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION`：允许未知电子邮箱验证状态（默认为 `false`）。允许此功能与 `SSO_SIGNUPS_MATCH_EMAIL` 结合使用可能会带来账户接管的风险。
* `SSO_AUTHORITY`：您的 SSO 的 OpenID Connect Discovery 端点
  * 此 URL 不能包含 `/.well-known/openid-configuration`
  * `$SSO_AUTHORITY/.well-known/openid-configuration` 必须返回一个 JSON 文档：[https://openid.net/specs/openid-connect-discovery-1\_0.html#ProviderConfigurationRespons](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse)（具有 [HTTP 状态代码 200 OK](https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfigurationResponse:~:text=A%20successful%20response%20MUST%20use%20the%20200%20OK%20HTTP%20status%20code)！）
  * `SSO_AUTHORITY` 必须与该 JSON 返回的颁发者字段的确切值匹配（因此，如果您不确定是否包含尾部斜杠，请采用文件的 `issuer` 值）。
* `SSO_SCOPES`：可选。允许在需要时覆盖范围（默认为 `profile email`。`openid` 是隐式的）
* `SSO_AUTHORIZE_EXTRA_PARAMS`：可选。允许在授权重定向时添加额外参数（默认为 `""`）
* `SSO_PKCE`：为授权代码流程激活 PKCE（默认为 `true`）。
* `SSO_AUDIENCE_TRUSTED`：可选。用于信任 ID Token 的额外受众的正则表达式（`client_id` 始终受信任）。编写正则表达式时使用单引号： `'^$'`。
* `SSO_CLIENT_ID`：客户端 ID
* `SSO_CLIENT_SECRET`：客户端机密
* `SSO_MASTER_PASSWORD_POLICY`：可选。主密码策略（不支持 `enforceOnLogin`。格式 `{"minComplexity:3,"minLength":12,"requireLower":false,"requireNumbers":false,"requireSpecial":false,"requireUpper":false}`）。
* `SSO_AUTH_ONLY_NOT_SESSION`：启用的话表示仅用于身份验证，不用于会话生命周期
* `SSO_CLIENT_CACHE_EXPIRATION`：缓存对发现端点的调用，持续时间（秒）， `0` 禁用（默认为 `0`）;
* `SSO_DEBUG_TOKENS`：记录所有令牌以便于调试（默认为 `false` ，需要设置 `LOG_LEVEL=debug` 或 `LOG_LEVEL=info,vaultwarden::sso=debug`）

回调 URL 是从 `DOMAIN` [自动生成](https://github.com/dani-garcia/vaultwarden/blob/1e1f9957cd037fad87e5cd33245720f865942016/src/config.rs#L1333)的。如果您设置 `DOMAIN=https://vaultwarden.example.tld`，则您的回调 URL 将是 `https://vaultwarden.example.tld/identity/connect/oidc-signin`。

要正确填充账户名称，您需要配置 IdP 以将声明的 `preferred_username` 作为显示名称提供。

如果您在您的 SSO 权威上使用的是私有证书权威或自签名证书，则需要将根证书添加到 `/etc/ssl/certs` 中，或者将 `SSL_CERT_DIR` 或 `SSL_CERT_FILE` 环境变量指向它。

## 账户和电子邮箱处理 <a href="#account-and-email-handling" id="account-and-email-handling"></a>

使用 SSO 登录时，一个标识符（来自 IdToken 的 `{iss}/{sub}` 声明）会保存在一个单独的表（`sso_users`）中。该标识符用于链接到 SSO 提供程序标识符，而无需更改默认用户 `uuid`。之所以需要这样做，是因为：

* 存储 SSO 标识对于防止因更改电子邮箱而导致账户被接管非常重要。
* 我们不能使用标识符作为用户 uuid，因为它太长了（`sub` 部分最多 255 个字符，参见[规范](https://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken)）。
* 我们希望能基于他们的 `email` 关联现有账户，但仅限于用户首次登录时（由 `SSO_SIGNUPS_MATCH_EMAIL` 控制）。
* 我们需要能够关联现有的存根账户，例如在邀请用户加入组织时创建的账户（只有在用户没有私钥的情况下才能关联）。

此外：

* 如果提供程序报告电子邮箱 `unverified`，注册将被阻止。
* 更改电子邮箱需要用户自己完成，因为这需要更新 `key`。登录时，如果提供程序返回的电子邮箱不是已保存的电子邮箱，系统将向用户发送一封电子邮件，要求他更新电子邮箱。
* 如果设置了 `SIGNUPS_DOMAINS_WHITELIST`，则会在 SSO 注册和尝试更改电子邮箱时应用。

这意味着，如果需要更改提供程序 URL 或提供程序本身，必须先删除关联，然后确保 `SSO_SIGNUPS_MATCH_EMAIL` 已激活，以允许新的关联。

要删除关联（这对 `Vaultwarden` 用户没有影响）：

```sql
TRUNCATE TABLE sso_users;
```

### 对于 `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION`  <a href="#on-sso_allow_unknown_email_verification" id="on-sso_allow_unknown_email_verification"></a>

如果提供程序不发送电子邮箱的验证状态 (`email_verified` [claim](https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims))，则您需要激活此设置。

如果设置为 `SSO_SIGNUPS_MATCH_EMAIL=true`（默认值），那么即使用户不控制电子邮箱地址，也可以与现有的非 SSO 账户关联。这样，用户就可以访问敏感信息，但仍需要主密码才能读取密码。

因此，在使用 `SSO_ALLOW_UNKNOWN_EMAIL_VERIFICATION` 时，建议禁用 `SSO_SIGNUPS_MATCH_EMAIL`。如果需要关联非 SSO 用户，请尽量在最短时间内同时激活这两个设置。

## 客户端缓存 <a href="#client-cache" id="client-cache"></a>

默认情况下，客户端缓存是禁用的，因为它会导致签名密钥出现问题。

这意味着每次我们需要与提供程序交互（生成 authorize\_url、交换授权代码、刷新令牌）时，都要再次调用发现端点。这种情况并不理想，因此 `SSO_CLIENT_CACHE_EXPIRATION` 允许您配置一个适合您的提供程序的过期时间。

如果 `IdToken` 验证失败，客户端缓存就会失效（但您会定期遇到一个倒霉的用户 ^^），这是防止过期时间配置错误的一种保护措施。

### Google 示例（滚动密钥） <a href="#google-example-rolling-keys" id="google-example-rolling-keys"></a>

以 Goole 为例，在检查发现[端点](https://accounts.google.com/.well-known/openid-configuration)响应报头时，我们可以看到缓存控制的 `max-age` 被设置为 `3600` 秒。而 [jwk\_uri](https://www.googleapis.com/oauth2/v3/certs) 响应头通常包含一个更大值的 `max-age`。结合用户[反馈](https://github.com/ramosbugs/openidconnect-rs/issues/152)，我们可以得出结论：Goole 每周都会更新签名密钥。

缓存过期时间设置过高会导致回报率降低，但使用 `600`（10 分钟）这样的过期时间应该会带来很多好处。

### 手动滚动密钥 <a href="#rolling-keys-manually" id="rolling-keys-manually"></a>

如果要滚动已使用的密钥，请先添加一个新的密钥，但不要立即开始使用它签名。等待在 `SSO_CLIENT_CACHE_EXPIRATION` 中配置的延迟时间后，然后就可以开始使用它签名了。

正如 Google 示例中提到的，即使不打算滚动密钥，设置过高的值也会导致回报率降低。

## Keycloak

默认访问令牌生命周期可能只有 `5min`，请将其设置为更长的时间，否则会与同样设置为 `5min` 的 Bitwarden 前端过期检测发生冲突

在 Realm 级别：

* `Realm settings / Tokens / Access Token Lifespan` 至少设置为 `10min`（使用 `kcadm.sh` 时的 `accessTokenLifespan` 设置）。
* `Realm settings / Sessions / SSO Session Idle/Max` 用于刷新令牌的生命周期

或者对于在 `Clients / Client details / Advanced / Advanced settings` 中的特定客户端，可以找到 `Access Token Lifespan` 和 `Client Session Idle/Max`。

服务器配置：

* `SSO_AUTHORITY=https://${keycloak_domain}/realms/${realm_name}`
* `SSO_SCOPES=openid profile email offline_access`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

注意：默认情况下，可以在 `Clients / Client details / Client scopes` 中的的客户端级别或者在 `Realm settings / Client scopes` 中的 Realm 级别分配 `offline_access` 范围，否则必须通过 `SSO_SCOPES` 显式请求才能使刷新令牌生效。

### 测试 <a href="#testing" id="testing"></a>

如果您想运行 Keycloak 的测试实例，可以使用 Playwright [docker-compose](https://github.com/dani-garcia/vaultwarden/blob/main/playwright/docker-compose.yml)。具体使用方法请参阅 [README.md](https://github.com/dani-garcia/vaultwarden/blob/main/playwright/README.md#openid-connect-test-setup)。

## Auth0

由于以下问题 <https://github.com/ramosbugs/openidconnect-rs/issues/23>（它们似乎没有遵循规范），其无法正常工作。目前提供了一个功能标志 (`oidc-accept-rfc3339-timestamps`) 可用于绕过这个问题，但您需要用它来编译服务器。目前还没有计划始终激活该功能或为 Auth0 制作专门的发行版本。

## Authelia

要获取 `refresh_token` 以扩展会话，您需要添加 `Offline_Access` 范围。

配置看起来如下：

* `SSO_SCOPES=openid profile email offline_access`

## Authentik

默认访问令牌生命周期可能只有 `5min`，请设置更大的值，否则会与同样设置为 `5min` 的 Bitwarden 前端过期检测产生冲突。

要更改令牌生命周期，请转到 `Applications / Providers / Edit / Advanced protocol settings`。

从 2024.2 版本开始，您需要添加 `Offline_Access` 范围，并确保在 `Applications / Providers / Edit / Advanced protocol settings / Scopes` 中选中它（[文档](https://docs.goauthentik.io/docs/providers/oauth2/#authorization_code)）。

服务器配置看起来应如下：

* `SSO_AUTHORITY=https://${authentik_domain}/application/o/${application_name}/`：尾部的 `/` 很重要
* `SSO_SCOPES=openid profile email offline_access`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

### 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>

#### **`Failed to discover OpenID provider`  / `Failed to parse server response`**：

首先确保可以从 Vaultwarden 容器访问附加了 `/.well-known/openid-configuration` 的 Authority 端点。

接下来检查响应是否包含 `id_token_signing_alg_values_supported: ["RS256"]`。

如果返回 `HS256`，那么然后选择默认签名密钥应该能解决该问题。

解决[步骤](https://github.com/Timshel/vaultwarden/issues/107#issuecomment-3200007338)：

1. 打开 **Authentik admin panel** > **Providers** > 打开您的 **Vaultwarden provider**
2. 点击 **Edit** > 将 **Signing key** 更改为您的任意密钥
   * 若不确定，请选择 Authentik 内置的 Signing key
3. 点击 **Update**
4. 重试

#### **`Failed to contact token endpoint: Parse(Error ... Invalid JSON web token: found 5 parts`：**

该错误可能是由加密令牌 (JWE) 导致的，请确保未使用加密密钥。

解决[步骤](https://github.com/dani-garcia/vaultwarden/issues/6230#issuecomment-3245196399)：

1. 打开 **Authentik admin panel** > **Providers** > 打开您的 **Vaultwarden provider**
2. 点击 **Edit** > 确保 **Encryption Key** 为空
3. **若不为空**：请在下拉菜单中选择 `-------`
4. 请勿修改 **Signing Key**，必须选择一个有效的证书
5. 点击 **Update**
6. 重试

## Casdoor

创建应用程序时，您需要选择 `Token format -> JWT-Standard`。自版本 [v1.639.0](https://github.com/casdoor/casdoor/releases/tag/v1.639.0) 起应该这可以正常运行（已使用版本 [v1.686.0](https://github.com/casdoor/casdoor/releases/tag/v1.686.0) 进行测试）。

然后使用以下内容配置您的服务器：

* `SSO_AUTHORITY=https://${provider_host}`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

## GitLab

使用以下内容在 Gitlab 设置中创建一个应用程序：

* `redirectURI`：`https://vaultwarden.example.tld/identity/connect/oidc-signin`
* `Confidential`：`true`
* `scopes`：`openid`, `profile`, `email`

然后使用以下内容配置您的服务器：

* `SSO_AUTHORITY=https://gitlab.com`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

## Google Auth

Google [文档](https://developers.google.com/identity/openid-connect/openid-connect?hl=zh-cn)。

默认情况下，如果没有额外的[配置](https://developers.google.com/identity/protocols/oauth2/web-server#creatingclient)，您将没有 `refresh_token`，并且会话时间将被限制为 1 小时。

在 *Google Auth Platform* > *Clients* 中，使用以下内容创建一个新的 Client ID：

* 已授权的 JavaScript 来源：`https://vaultwarden.example.tld`
* 已授权的重定向 URI：`https://vaultwarden.example.tld/identity/connect/oidc-signin`

然后，使用以下内容配置您的服务器：

* `SSO_AUTHORITY=https://accounts.google.com`
* `SSO_AUTHORIZE_EXTRA_PARAMS="access_type=offline&prompt=consent"`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

## Kanidm

不需要特殊配置。

使用以下内容配置您的服务器：

* `SSO_AUTHORITY=https://{AUTHORITY_DOMAIN}/oauth2/openid/${SSO_CLIENT_ID}`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`

## Microsoft Entra ID

1. 在 [Entra ID](https://entra.microsoft.com/) 中按照 [Identity | Applications | App registrations](https://entra.microsoft.com/#blade/Microsoft_AAD_RegisteredApps/ApplicationsListBlade/quickStartType//sourceType/Microsoft_AAD_IAM) 创建「应用程序注册」。
2. 在「应用程序注册」的「概述」中，您需要「目录（租户）ID」以用于 `SSO_AUTHORITY` 变量，「应用程序（客户端）ID」以用于 `SSO_CLIENT_ID` 值。
3. 在「证书和秘钥」中创建「应用程序秘钥」，您需要「秘钥值」以用于 `SSO_CLIENT_SECRET`。
4. 在「身份验证」中添加 `https://vaultwarden.example.tld/identity/connect/oidc-signin` 作为「网页重定向 URI」。
5. 在「API 权限」中，确保在「API / 权限名称」下列出 `profile`、`email` 和 `offline_access`（`offline_access` 是必需的，否则不会返回 `refresh_token`，请参阅 <https://github.com/MicrosoftDocs/azure-docs/issues/17134>）。

只有 v2 端点符合 OpenID 规范，请参阅 <https://github.com/MicrosoftDocs/azure-docs/issues/38427> 和 <https://github.com/ramosbugs/openidconnect-rs/issues/122>。

您的服务器配置看起来应如下：

* `SSO_AUTHORITY=https://login.microsoftonline.com/${Directory_ID}/v2.0` #租户
* `SSO_SCOPES=openid profile offline_access User.Read`
* `SSO_CLIENT_ID=${Application_ID}` #客户端
* `SSO_CLIENT_SECRET=${Secret_Value}`

## Rauthy

要使用提供程序控制的会话，您需要在运行 `Rauthy` 时使用 `DISABLE_REFRESH_TOKEN_NBF=true`，否则服务器在尝试读取尚未生效的 `refresh_token` 时会失败（即使 `access_token` 有效，Bitwarden 客户端也会触发刷新。详情参阅 [rauthy](https://github.com/sebadob/rauthy/issues/651)）。另一种方法是使用 `SSO_AUTH_ONLY_NOT_SESSION=true` 的默认会话处理方式。

创建客户端时不需要特殊配置。

您的配置看起来应如下：

* `SSO_AUTHORITY=http://${provider_host}/auth/v1`
* `SSO_CLIENT_ID=${Client ID}`
* `SSO_CLIENT_SECRET=${Client Secret}`
* `SSO_AUTH_ONLY_NOT_SESSION=true`：仅在不使用 `DISABLE_REFRESH_TOKEN_NBF=true` 运行 `Rauthy` 时才需要

## Slack

您需要在 <https://api.slack.com/apps/> 中创建一个 App。

看起来返回的 `access_token` 不是 JWT 格式，并且没有使用它发送到期日期。因此，您需要使用默认的会话生命周期。

您的配置看起来应如下：

* `SSO_AUTHORITY=https://slack.com`
* `SSO_CLIENT_ID=${Application Client ID}`
* `SSO_CLIENT_SECRET=${Application Client Secret}`
* `SSO_AUTH_ONLY_NOT_SESSION=true`

## Zitadel

要获取 `refresh_token` 以扩展会话，您需要添加 `Offline_Access` 范围。

此外，Zitadel 还在 Id Token 的受众中加入了 `Project id` 和客户 `Client Id`。为使验证生效，您需要将 `Resource Id` 添加为受信任的受众（默认情况下 `Client Id` 是受信任的）。您可以使用 `SSO_AUDIENCE_TRUSTED` 配置来控制受信任的受众。

根据 [Zitadel#9200](https://github.com/zitadel/zitadel/issues/9200)，`id_token` 会传递一个受信任受众列表，其中包括 `Project Id`。如果最终有许多受信任的 `aud` 字符串，`SSO_AUDIENCE_TRUSTED` 可能会变得难以管理。在这种情况下，`SSO_AUDIENCE_TRUSTED: '^\d{18}$'`（18 是 `aud` 列表中每个字符串的大小，可能因 Zitadel 实现而异）会对您有所帮助，但单独添加所有审核字符串也是安全的，如 `SSO_AUDIENCE_TRUSTED:'^abcd|def|xyz$'`。

自 [zitadel#721](https://github.com/zitadel/oidc/pull/721) 以来，PKCE 应该可以使用客户端机密。但旧版本可能需要禁用它（`SSO_PKCE=false`）。

配置看起来应如下：

* `SSO_AUTHORITY=https://${provider_host}`
* `SSO_SCOPES=openid profile email offline_access`
* `SSO_CLIENT_ID`
* `SSO_CLIENT_SECRET`
* `SSO_AUDIENCE_TRUSTED='^${Project Id}$'`

## 会话生命周期 <a href="#session-lifetime" id="session-lifetime"></a>

会话生命周期取决于刷新令牌和调用 SSO 令牌端点（授权类型：`authorization_code`）后返回的访问令牌。如果没有返回刷新令牌，会话将仅限于访问令牌的生命周期。

令牌不会持久保存在服务器中，而是封装在 JWT 令牌中并返回给应用程序（Vaultwarden `identity/connect/token` 端点返回的 `refresh_token` 和 `access_token` 值）。请注意，出于与 Web 前端兼容的原因，服务器将始终返回一个 `refresh_token`，它的存在并不表明 SSO 返回了刷新令牌（但您可以使用 [https://jwt.io](https://jwt.io/) 对其值进行解码，然后检查 `token` 字段是否包含任何内容）。

有了刷新令牌，应用程序中的活动就会在访问令牌快过期时（网页客户端为 [5 分钟](https://github.com/bitwarden/clients/blob/0bcb45ed5caa990abaff735553a5046e85250f24/libs/common/src/auth/services/token.service.ts#L126)）触发刷新。

此外，在执行某些操作时还会进行令牌检查，如果有刷新令牌，就会执行刷新，否则就会调用用户信息端点来检查访问令牌的有效性。

### 禁用 SSO 会话处理 <a href="#disabling-sso-session-handling" id="disabling-sso-session-handling"></a>

如果无法获取 `refresh_token` 或出于其他原因，可以禁用 SSO 会话处理，以恢复到默认的处理方式。您需要启用 `SSO_AUTH_ONLY_NOT_SESSION=true`，然后访问令牌的有效期将为 2 小时，刷新令牌的空闲时间为 7 天（可无限延长）。

### 调试信息 <a href="#debug-information" id="debug-information"></a>

使用 `LOG_LEVEL=debug` 运行，您就能看到令牌过期的信息。

## 桌面客户端 <a href="#desktop-client" id="desktop-client"></a>

在处理从浏览器（用于 SSO 登录）到应用程序的重定向方面存在一些问题。

## Chrome

一些用户报告有说存在[问题](https://github.com/bitwarden/clients/issues/12929)。

## Firefox

在 Windows 系统中，首次登录时会出现一个提示，以确认应启动哪个应用程序（但目前存在一个 bug，即登录后可能会出现空的密码库）。

在 Linux 系统上，稍微麻烦些。首先，您需要在 `about:config` 中添加一些配置：

```systemd
network.protocol-handler.expose.bitwarden=false
network.protocol-handler.external.bitwarden=true
```

如果您有任何疑问，可以检查 `mailto` 以查看它是如何配置的。

重定向仍然不起作用，因为与应用程序的关联似乎只能通过链接/点击来完成。您可以用一个虚拟页面来触发它，例如：

```html
data:text/html,<a href="bitwarden:///dummy">Click me to register Bitwarden</a>
```

从现在起，重定向应该可以正常工作了。如果需要更改启动的应用程序，现在可以使用搜索功能在 `Settings` 中输入 `application` 进行查找。


# 9.允许从内部服务获取图标

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Allow-icon-fetching-from-internal-services)
{% endhint %}

此配置适用于 Vaultwarden 需要从托管在内部/私有网络上的服务中获取图标的自托管环境，例如：

* 托管了多个自托管应用程序的 NAS 或服务器
* 通过本地网络访问的各种服务
* 仅通过 VPN（例如 Tailscale）才能访问的服务
* 使用内部 IP 或拆分式 DNS 的反向代理设置

默认情况下，出于安全考虑，Vaultwarden 会阻止对非全局/私有 IP 地址的请求。因此，解析到以下地址的服务图标可能无法加载：

* 局域网 IP 地址（`192.168.x.x`、`10.x.x.x` 等）
* Tailscale/CGNAT 范围（`100.x.x.x`）
* 其他仅供内部使用的地址

> **\[译者注]**：[CGNAT](https://zh.wikipedia.org/wiki/%E7%94%B5%E4%BF%A1%E7%BA%A7NAT) - 电信级 NAT 或运营商级 NAT（Carrier-grade NAT，缩写为 CGNAT 或 CGN），也称大规模 NAT（large-scale NAT，缩写 LSN），是运营商为了缓解 IPv4 地址枯竭问题，向客户分配私网 IPv4 地址而非公网地址，并通过自身的中间件完成的网络地址转换 (NAT) 操作。电信级 NAT 可以让更多的终端设备共享一个公网地址。

## 配置 <a href="#configuration" id="configuration"></a>

设置以下环境变量：

```systemd
HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS=false
```

然后重启/重新部署 Vaultwarden。

## TrueNAS SCALE 重要提示 <a href="#truenas-scale-important-note" id="truenas-scale-important-note"></a>

当将 Vaultwarden 作为 TrueNAS SCALE App 来运行时，仅设置环境变量可能还不够。

> **\[译者注]**：[TrueNAS](https://www.truenas.com/) 是一个基于 ZFS 的开源 NAS（网络附加存储）系统，类似于群晖 DSM、威联通 QNAP。TrueNAS  由 [iXsystems](https://www.ixsystems.com/) 开发。
>
> TrueNAS 有两个主要版本：TrueNAS CORE（原 FreeNAS）和 TrueNAS SCALE。TrueNAS CORE 基于 FreeBSD，TrueNAS SCALE 基于 Linux。

TrueNAS 可以通过应用程序配置界面来覆盖 Vaultwarden 的一些内部设置。

您还必须：

1. 打开 Vaultwarden 管理面板
2. 前往 `Advanced Settings`
3. 定位到 `Block non global IPs`
4. 将其设置为 `false` / 禁用
5. 保存然后重启 App

如果此设置保持启用状态，即使环境变量已存在，Vaultwarden 仍将继续阻止来自内部 IP 范围的图标下载。

## 安全考量 <a href="#security-considerations" id="security-considerations"></a>

禁用 `HTTP_REQUEST_BLOCK_NON_GLOBAL_IPS` 会降低对 SSRF（Server-Side Request Forgery - 服务器端请求伪造）攻击的防护能力。

> **\[译者注]**：SSRF 是一种由攻击者构造形成由服务端发起请求的安全漏洞。一般情况下，SSRF 攻击的目标是从外网无法访问的内部系统。详见[《深入理解 WEB 漏洞之 SSRF 漏洞》](https://github.com/ASTTeam/SSRF)。

禁用此设置后，Vaultwarden 可以向内部/私有 IP 地址范围发出 HTTP 请求。这对于仅通过内部网络、VPN 或私有 DNS 公开自托管服务的环境是必需的。

仅当满足以下条件时才禁用此设置：

* 您信任那些可以创建/编辑密码库条目的用户。
* 您的 Vaultwarden 实例是私有的，并且安全可靠。
* 您理解 Vaultwarden 将能够访问内部网络资源。

对于大多数自托管家庭实验室或内部基础设施设置而言，这种权衡是可以接受的，并且是实现正确图标获取功能的必要条件。

## 症状 <a href="#symptoms" id="symptoms"></a>

Vaultwarden 日志可能包含类似如下的警告：

```
IP 100.x.x.x for domain 'service.example.com' is not a global IP!
```

或者：

```
IP 192.168.x.x for domain 'service.example.com' is not a global IP!
```

禁用此限制后，内部/自托管服务的图标应该可以开始正常工作了。


# 10.其他配置

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Other-configuration)
{% endhint %}

尽管在小规模部署中可能不需要，但您可以使用由 [Rocket](https://rocket.rs/) 处理的环境变量来微调一些其他设置，例如 worker 数量。请查阅[此文档](https://rocket.rs/guide/v0.5/configuration/#environment-variables)了解详细信息。

> \[**译者注**]：更多配置项的详细说明请参阅 [Vaultwarden 部署和使用 - 配置](https://host.ppgg.in/vaultwarden/configuration)。


# 数据库


# 1.使用 MariaDB (MySQL) 后端

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-the-MariaDB-%28MySQL%29-Backend)
{% endhint %}

{% hint style="danger" %}
⚠️ 💩 ⚠️尽管 MySQL 数据库工作正常，但请注意，我们的构建基于 MariaDB 客户端库，因为这是 Debian 提供的。⚠️ 💩 ⚠️
{% endhint %}

要使用 MySQL 后端，你可以使用[官方 Docker 镜像](https://hub.docker.com/r/bitwardenrs/server-mysql)，也可以构建您自己的[启用了 MySQL](/development/building-binary#mysql-backend) 的二进制。

要运行二进制或容器，请确保已设置 `DATABASE_URL` 环境变量（即 `DATABASE_URL='mysql://<user>:<password>@mysql/vaultwarden[?ssl_mode=(disabled|required|preferred)&ssl_ca=/path/to/cart.(crt|pem)]'`）。

**连接字符串语法：**

```systemd
DATABASE_URL=mysql://[[user]:[password]@]host[:port][/database]
```

如果密码包含特殊字符，则需要使用百分号编码。

| !   | #   | $   | %   | &   | '   | (   | )   | \*  | +   | ,   | /   | :   | ;   | =   | ?   | @   | \[  | ]   |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| %21 | %23 | %24 | %25 | %26 | %27 | %28 | %29 | %2A | %2B | %2C | %2F | %3A | %3B | %3D | %3F | %40 | %5B | %5D |

完整的代码列表可以在 [Wikipedia 的百分号编码页面](https://zh.wikipedia.org/wiki/%E7%99%BE%E5%88%86%E5%8F%B7%E7%BC%96%E7%A0%81)上找到。

## 使用 Docker 的示例 <a href="#example-using-docker" id="example-using-docker"></a>

```shell
# 启动 mysql 容器
docker run --name mysql --net <some-docker-network>\
 -e MYSQL_ROOT_PASSWORD=<my-secret-pw>\
 -e MYSQL_DATABASE=vaultwarden\
 -e MYSQL_USER=<vaultwarden_user>\
 -e MYSQL_PASSWORD=<vaultwarden_pw> -d mysql:5.7

# 使用 MySQL 环境变量值启动 Vaultwarden
docker run -d --name vaultwarden --net <some-docker-network>\
 -v $(pwd)/vw-data/:/data/ -v <Path to ssl certs>:/ssl/\
 -p 443:80 -e ROCKET_TLS='{certs="/ssl/<your ssl cert>",key="/ssl/<your ssl key>"}'\
 -e RUST_BACKTRACE=1 -e DATABASE_URL='mysql://<vaultwarden_user>:<vaultwarden_pw>@mysql/vaultwarden'\
 -e ADMIN_TOKEN=<some_random_token_as_per_above_explanation>\
 -e ENABLE_DB_WAL='false' <you vaultwarden image name>
```

### 使用非 Docker MySQL 服务器的示例 <a href="#example-using-non-docker-mysql-server" id="example-using-non-docker-mysql-server"></a>

```shell
Server IP/Port 192.168.1.10:3306 UN: dbuser / PW: yourpassword / DB: vaultwarden
mysql://dbuser:yourpassword@192.168.1.10:3306/vaultwarden
```

### 使用 docker-compose 的示例 <a href="#example-using-docker-compose" id="example-using-docker-compose"></a>

```yml
services:
 vaultwarden-db:
  image: "mariadb" # or "mysql"
  container_name: "vaultwarden-db"
  restart: always
  env_file:
   - ".env"
  volumes:
   - "vaultwarden-db_vol:/var/lib/mysql"
   - "/etc/localtime:/etc/localtime:ro"
  environment:
   - "MYSQL_ROOT_PASSWORD=<my-secret-pw>"
   - "MYSQL_PASSWORD=<vaultwarden_pw>"
   - "MYSQL_DATABASE=vaultwarden_db"
   - "MYSQL_USER=<vaultwarden_user>"
  healthcheck:
   test: mariadb-admin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
   start_period: 5s
   interval: 5s
   timeout: 5s
   retries: 55
   
 vaultwarden:
  image: "vaultwarden/server-mysql:latest"
  container_name: "vaultwarden"
  hostname: "vaultwarden"
  depends_on:
   vaultwarden-db:
    condition: service_healthy
  restart: always
  env_file:
   - ".env"
  volumes:
   - "vaultwarden_vol:/data/"
  environment:
   - DATABASE_URL=mysql://<vaultwarden_user>:${VAULTWARDEN_MYSQL_PASSWORD}@vaultwarden-db/vaultwarden
   - ADMIN_TOKEN=<some_random_token_as_per_above_explanation> # https://github.com/dani-garcia/vaultwarden/wiki/Enabling-admin-page
   - RUST_BACKTRACE=1
  ports:
   - "80:80"

volumes:
 vaultwarden_vol:
 vaultwarden-db_vol:
```

## 手动创建数据库（例如，使用现有的数据库服务器） <a href="#manually-create-a-database-for-example-using-an-existing-database-server" id="manually-create-a-database-for-example-using-an-existing-database-server"></a>

{% hint style="danger" %}
要执行这些查询，您需要有一个可以创建新数据库和用户的用户。大多数情况下，这将是 `root` 用户，但根据您的数据库可能会有所不同。
{% endhint %}

> 使用上面的 docker-compose 示例使这些步骤变得不必要。数据库、排序规则和字符集在启动时将被自动创建。

### 创建数据库和用户 <a href="#create-database-and-user" id="create-database-and-user"></a>

1、为 Vaultwarden 创建一个新的（空）数据库（确保字符集和排序规则正确！）：

```sql
CREATE DATABASE vaultwarden CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

2、创建一个新的数据库用户并授予数据库权限（MariaDB，MySQL）：

```sql
CREATE USER 'vaultwarden'@'localhost' IDENTIFIED BY 'yourpassword';
GRANT ALL ON `vaultwarden`.* TO 'vaultwarden'@'localhost';
FLUSH PRIVILEGES;
```

您可能想尝试一组受限的授权：

```sql
GRANT ALTER, CREATE, DELETE, DROP, INDEX, INSERT, REFERENCES, SELECT, UPDATE ON `vaultwarden`.* TO 'vaultwarden'@'localhost';
FLUSH PRIVILEGES;
```

## 从 SQLite 迁移到 MySQL <a href="#migrating-from-sqlite-to-mysql" id="migrating-from-sqlite-to-mysql"></a>

此[话题评论](https://github.com/dani-garcia/vaultwarden/issues/497#issuecomment-511827057)中描述了一种从 SQLite 迁移到 MySQL 的简单方法。下面重复这些步骤。请注意，使用此方法风险自负，强烈建议备份您的安装和数据！

1、首先遵循上面的步骤 1 和步骤 2。

2、配置 Vaultwarden 并启动它，以便 [diesel](http://diesel.rs/) 可以运行迁移并正确设置模式。除此之外不要做别的。

3、停止 Vaultwarden。

4、使用下面的命令转储您现有的 SQLite 数据库。再次检查您的 sqlite 数据库的名称，默认应该是 `db.sqlite`。

**注意**：在您的 Linux 系统上需要已经安装了 sqlite3 命令。

我们需要从 sqlite 转储的输出中移除一些查询，如创建表等，我们将在这里进行。

您可以使用以下单行命令：

```sql
sqlite3 db.sqlite3 .dump | grep "^INSERT INTO" | grep -v "__diesel_schema_migrations" > sqlitedump.sql ; echo -ne "SET FOREIGN_KEY_CHECKS=0;\n$(cat sqlitedump.sql)" > mysqldump.sql
```

或者逐行运行下列命令：

```sql
sqlite3 db.sqlite3 .dump | grep "^INSERT INTO" | grep -v "__diesel_schema_migrations" > sqlitedump.sql
echo "SET FOREIGN_KEY_CHECKS=0;" > mysqldump.sql
cat sqlitedump.sql >> mysqldump.sql
```

5、加载 MySQL 转储：

```sql
mysql --force --password --user=vaultwarden --database=vaultwarden < mysqldump.sql
```

6、重新启动 Vaultwarden。

*注意：使用* *`--show-warnings`* *加载* *MySQL* *转储时，会突出显示 datetime* *字段在导入期间被截断了，这**似乎**也不会有问题。*

```
Note (Code 1265): Data truncated for column 'created_at' at row 1
Note (Code 1265): Data truncated for column 'updated_at' at row 1
```

*注意 1：加载 mysqldump.sql 数据过程中出现加载错误*

```
error (1064): Syntax error near '"users" VALUES('9b5c2d13-8c4f-47e9-bd94-f0d7036ff581'*********)
```

修复：

```bash
sed -i s#\"#\#g mysqldump.sql
```

```shell
mysql --password --user=vaultwarden
use vaultwarden
source /vw-data/mysqldump.sql
exit
```

*注意 2：如果 SQLite 数据库是从以前的某个旧版本迁移而来 ，MariaDB 可能会提示不匹配的值计数，例如：*

```
ERROR 1136 (21S01) at line ###: Column count doesn't match value count at row 1
```

由于版本跳转，可能添加了新的数据库列。首先使用 SQLite 后端升级 Vaultwarden 以在 SQLite 数据库上运行迁移，切换到 MariaDB 后端，然后重复上述迁移步骤。或者，查找自您安装的版本以来添加迁移的提交并使用 `sqlite3` 手动运行迁移。

## 外键错误、排列规则和字符集 <a href="#foreign-key-errors-collation-and-charset" id="foreign-key-errors-collation-and-charset"></a>

由于密码库中存储的某些数据是二进制或纯文本（如邮件地址、用户名或组织名称），其中可能包含 Unicode 字符，因此您需要确保正确设置数据库和表的排序规则和字符集。如果不是这种情况，则可能会在更新期间导致问题，然后生成诸如 `Cannot add or update a child row: a foreign key constraint fails ...`（无法添加或更新子行：外键约束失败...）或 `Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126.`（行大小太大。所用表类型的最大行大小（不包括 BLOB）为 8126。）之类的消息。

要解决此问题，您需要更新/更改整个数据库及其包含的表的排序规则和字符集。您可以通过您喜欢的 SQL 工具或使用 CLI 跟踪和执行以下设置来完成此操作。

在下面的示例中，我将使用数据库名称 `vaultwarden`，如果您使用不同的名称，请更改它。

在开始之前，通过运行以下两个查询来验证是否存在任何问题。它应该返回 `utf8mb4` 和 `utf8mb4_unicode_ci`。

同样要在下面的查询末尾运行这些查询以验证它是否有效！

```sql
SELECT DEFAULT_CHARACTER_SET_NAME, DEFAULT_COLLATION_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = "vaultwarden";
SELECT CHARACTER_SET_NAME, COLLATION_NAME FROM information_schema.`COLUMNS` WHERE TABLE_SCHEMA = "vaultwarden" AND CHARACTER_SET_NAME IS NOT NULL;
```

首先更改数据库本身的排序规则和字符集：

```sql
ALTER DATABASE `vaultwarden` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```

然后转换所有表（包括文本字段）。执行以下命令，并复制输出：

```sql
SELECT CONCAT('ALTER TABLE `', TABLE_NAME,'` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;') AS CharSetConvert
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA="vaultwarden"
AND TABLE_TYPE="BASE TABLE";
```

这将生成几个查询，您需要执行这些查询来转换这些表的排序规则和字符集。为了使这些更改生效，我们需要暂时禁用外键检查。将上面查询生成的输出复制/粘贴到以下行的中间：

```sql
SET foreign_key_checks=0;
-- 复制/粘贴上面的输出内容到这里
SET foreign_key_checks=1;
```

最后，它看起来应该类似于以下内容（但根据数据库结构的更新或更改，可能会有所不同）：

```sql
SET foreign_key_checks=0;
ALTER TABLE `__diesel_schema_migrations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `attachments` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `ciphers_collections` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `ciphers` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `collections` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `devices` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `emergency_access` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `favorites` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `folders_ciphers` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `folders` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `invitations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `org_policies` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `organizations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `sends` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `twofactor_incomplete` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `twofactor` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users_collections` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users_organizations` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
ALTER TABLE `users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
SET foreign_key_checks=1;
```

您需要运行这些查询以将它们转换为正确的排序规则和字符集。您可以通过对至少一张表运行以下查询来验证它是否有效：

```sql
SHOW CREATE TABLE `users`; 
```

它应该输出如下，注意最后的 `CHARSET=utf8mb4`：

```sql
CREATE TABLE `users` (
  `uuid` char(36) NOT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `email` varchar(255) NOT NULL,
  `name` text NOT NULL,
  --- CUT ---
  `enabled` tinyint(1) NOT NULL DEFAULT 1,
  `stamp_exception` text DEFAULT NULL,
  PRIMARY KEY (`uuid`),
  UNIQUE KEY `email` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
```

您可以对数据库执行相同的操作：

```sql
SHOW CREATE DATABASE `vaultwarden`;
```

它应该看起来像这样，注意 `DEFAULT CHARACTER SET utf8mb4`：

```sql
CREATE DATABASE `vaultwarden` /*!40100 DEFAULT CHARACTER SET utf8mb4 */
```


# 2.使用 PostgreSQL 后端

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-the-PostgreSQL-Backend)
{% endhint %}

要使用 PostgreSQ 后端，您可以使用[官方 Docker 镜像](https://hub.docker.com/r/bitwardenrs/server-postgresql)，也可以构建您自己的[启用了 PostgreSQL](/development/building-binary#postgresql-backend) 的二进制。

要运行二进制或容器，请确保已设置 `DATABASE_URL` 环境变量（即 `DATABASE_URL='postgresql://<user>:<password>@postgresql/vaultwarden'`）。

**字符串连接语法：**

```systemd
DATABASE_URL=postgresql://[[user]:[password]@]host[:port][/database]
```

docker 运行环境变量的一个示例：`-e 'DATABASE_URL=postgresql://user_name:user_password@db_host:5432/vaultwarden'`。

如果您需要设置额外的连接参数，请注意 `DATABASE_URL` 的值最终会被 `libpq` 解析，因此您可以使用 libpq [文档](https://www.postgresql.org/docs/current/libpq-envars.html)中所列出的任何参数。您可以将连接参数添加到 `DATABASE_URL` 中或通过其相应的 `PG*` 环境变量指定它。如果在 Docker 下运行，请记住提供的任何路径都需要从 Docker 容器的角度来看，而不是 Docker 主机。

如果您要使用自定义架构/搜索路径，则需要使用以下连接字符串（注意 URL 编码的字符，比如 `%20` 表示空格，`%3D` 表示 `=` 符号）：

```systemd
DATABASE_URL=postgresql://user_name:user_password@db_host:5432/vaultwarden?application_name=vaultwarden&options=-c%20search_path%3Ddb_schema
```

如果您的密码包含特殊字符，则需要使用百分号编码。

| !   | #   | $   | %   | &   | '   | (   | )   | \*  | +   | ,   | /   | :   | ;   | =   | ?   | @   | \[  | ]   |
| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- |
| %21 | %23 | %24 | %25 | %26 | %27 | %28 | %29 | %2A | %2B | %2C | %2F | %3A | %3B | %3D | %3F | %40 | %5B | %5D |

完整的代码列表可以在 [Wikipedia 的百分号编码页面](https://zh.wikipedia.org/wiki/%E7%99%BE%E5%88%86%E5%8F%B7%E7%BC%96%E7%A0%81)上找到。

## **从 SQLite 迁移到 PostgreSQL** <a href="#migrating-from-sqlite-to-postgresql" id="migrating-from-sqlite-to-postgresql"></a>

> 使用 SQLite3 3.37.2、PostgreSQL 16.10 和 Vaultwarden 1.34.3 测试

从 SQLite 迁移到 PostgreSQL 或 MySQL 的方法比较简单，但请注意，**使用此方法风险自负，并且强烈建议备份您的安装和数据**！这**不受支持**，也没有经过强有力的测试。

1、创建一个新的数据库用户：

```sql
CREATE USER vaultwarden WITH ENCRYPTED PASSWORD 'yourpassword';
```

2、为 Vaultwarden 创建一个新的（空）数据库，将该用户设置为数据库的所有者：

```sql
CREATE DATABASE vaultwarden OWNER vaultwarden;
```

3、配置一个（新） Vaultwarden 实例然后启动它，以便 [diesel](http://diesel.rs/) 可以运行迁移并设置正确的模式。除此之外不要做别的。

4、停止新的 Vaultwarden 实例。

5、安装 [pgloader](http://pgloader.io/) 。

6、对 SQLite 数据库[禁用 WAL](/configuration/database/running-without-wal-enabled#id-1-disable-wal-on-old-db)。

7、使用如下内容创建 `vaultwarden.load` 文件：

```sql
load database
     from sqlite:///where/you/keep/your/vaultwarden/db.sqlite3 
     into postgresql://yourpgsqluser:yourpgsqlpassword@yourpgsqlserver:yourpgsqlport/yourpgsqldatabase
     WITH data only, include no drop, reset sequences
     EXCLUDING TABLE NAMES LIKE '__diesel_schema_migrations'
     ALTER SCHEMA 'vaultwarden' RENAME TO 'public'
;
```

8、运行 `pgloader vaultwarden.load` 命令，您可能会看到一些警告，（不用理会）迁移会成功完成。

9、重新启动 Vaultwarden。

## 从 MySQL 迁移到 PostgreSQL <a href="#migrating-from-mysql-to-postgresql" id="migrating-from-mysql-to-postgresql"></a>

> 使用 MariaDB 10.11.9、PostgreSQL 15.8-1 和 Vaultwarden 1.32.0 测试

请注意，**使用此方法风险自负，并且强烈建议备份您的安装和数据**！这**不受支持**，也没有经过强有力的测试。

1、创建一个新的数据库用户：

```sql
CREATE USER vaultwarden WITH ENCRYPTED PASSWORD 'yourpassword';
```

2、为 Vaultwarden 创建一个新的（空）数据库，将该用户设置为数据库的所有者：

```sql
CREATE DATABASE vaultwarden OWNER vaultwarden;
```

3、配置一个（新） Vaultwarden 实例然后启动它，以便 [diesel](http://diesel.rs/) 可以运行迁移并设置正确的模式。除此之外不要做别的。

4、停止新的 Vaultwarden 实例。

5、安装 [pgloader](http://pgloader.io/)。确保您使用的是最新 3.x 版本的 pgloader，官方的 Ubuntu 存储库有一个过时的版本，它不能与新版本的 PostgreSQL 一起正常工作。最新版本可以从 [PostgreSQL Apt 存储库](https://www.postgresql.org/download/linux/ubuntu/)获取。

6、使用如下内容创建 `vaultwarden.load` 文件：

```sql
load database
     from mysql://yourmysqluser:yourmysqlpassword@yourmysqlserver:yourmysqlport/yourmysqldatabase 
     into postgresql://yourpgsqluser:yourpgsqlpassword@yourpgsqlserver:yourpgsqlport/yourpgsqldatabase
     WITH data only
     EXCLUDING TABLE NAMES MATCHING '__diesel_schema_migrations'
     ALTER SCHEMA 'vaultwarden' RENAME TO 'public'
;
```

*如果您的连接需要 SSL，可以选择将 `?sslmode=require` 添加到 PostgreSQL 连接字符串中。*

7、运行 `pgloader vaultwarden.load` 命令，您可能会看到一些警告，（不用理会）迁移会成功完成。如果有错误，很可能是您的 pgloader 版本过时了！

8、重新启动 Vaultwarden。


# 3.在未启用 WAL 的情况下运行

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Running-without-WAL-enabled)
{% endhint %}

{% hint style="warning" %}
WAL 是专用于 SQLite 的设置，它在 Postgres 或 MySQL 上不起作用；如果您使用这些后端之一，则 `ENABLE_DB_WAL` 配置选项无效。
{% endhint %}

默认情况下，`vaultwarden` 在启动期间将尝试为数据库启用 [WAL](https://sqlite.org/wal.html)。添加此功能可以提高性能，并且在某些情况下有助于避免请求失败。

## 关闭 WAL 的原因 <a href="#reasons-to-turn-wal-off" id="reasons-to-turn-wal-off"></a>

一般而言，除非您相当确定需要关闭 WAL，否则应将其保持为启用状态。但是，可能有一些情况需要将其关闭，比如：

* 某些文件系统不支持 WAL（对于网络文件系统尤其如此）。如果您使用的是这样的文件系统，该服务将无法启动并显示 `Failed to turn on WAL` 错误。
* （要启用 WAL）数据库要求 sqlite 的版本为 `3.7.0` 或更高，因此，出于某种原因（例如备份）您需要使用无法更新的低版本工具来直接访问数据库，此时也需要禁用 WAL。
* 某个[这里描述的缺陷](https://sqlite.org/wal.html#advantages)也会影响您（不得不禁用 WAL）。

## 关闭 WAL 的步骤 <a href="#how-to-turn-wal-off" id="how-to-turn-wal-off"></a>

### 0、执行备份 <a href="#id-0-make-backup" id="id-0-make-backup"></a>

这些更改通常是安全的，可以顺利完成并且不会丢失数据，但是强烈建议在进行任何更改之前[备份您的数据](/backup/backing-up-your-vault)。

### 1、在低版本数据库上禁用 WAL <a href="#id-1-disable-wal-on-old-db" id="id-1-disable-wal-on-old-db"></a>

如果您使用启用了 WAL 的低版本数据库，则需要使用 sqlite 来禁用它：

1）停止 `vaultwarden`

2）定位您的[数据文件夹](/other-information/changing-persistent-data-location)。除非您指定了其他名称，否则这里通常会有一个名为 `db.sqlite3` 的文件。

3）使用 sqlite 打开此文件：

```sql
sqlite3 db.sqlite3
```

4）键入 `PRAGMA journal_mode=delete;` 并按 Enter，以禁用 WAL：

```sql
sqlite> PRAGMA journal_mode=delete;
delete
```

5）键入 `.quit` 并按回车退出 sqlite 实用程序（注意前面的点）。

### 2、在 `vaultwarden` 中禁用 WAL <a href="#id-2-disable-wal-in-vaultwarden" id="id-2-disable-wal-in-vaultwarden"></a>

要关闭 WAL，您需要通过将 `ENABLE_DB_WAL` 变量的值设置为 `false` 来启动 `vaultwarden`。

```shell
docker run -d --name vaultwarden \
  -e ENABLE_DB_WAL=false \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

确保在启动前始终使用了此变量，否则一旦没有此变量将会再次启用 WAL（如果发生这种情况，请从[第 1 步](#1-disable-wal-on-old-db)开始再次禁用它）。

## 如何开启 WAL <a href="#how-to-turn-wal-on" id="how-to-turn-wal-on"></a>

通常来说，只要您在未将 `ENABLE_DB_WAL` 变量的值设置为 `false` 的情况下启动 `vaultwarden`，服务器将自动为您启用 WAL。您可以通过运行以下命令进行验证：

```sql
sqlite3 db.sqlite3 'PRAGMA journal_mode'
```

`db.sqlite3` 是 `vaultwarden` 所使用的数据库文件。此命令将报告当前使用的模式，在我们的例子中将返回 `wal`。如果已禁用 WAL，默认通常返回 `delete` 。


# 4.从 MariaDB (MySQL) 迁移到 SQLite

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Migrating-from-MariaDB-%28MySQL%29-to-SQLite)
{% endhint %}

{% hint style="danger" %}
⚠️ ☠️ ⚠️ 使用这些命令的风险自负！⚠️ ☠️ ⚠️

在做任何可能破坏整个密码库的事情之前，请务必创建备份！
{% endhint %}

***

## 常规 <a href="#general" id="general"></a>

Vaultwarden 最初设计时仅使用 SQLite，但后来又加入了MariaDB（MySQL）和PostgreSQL。对于 SQLite，您不需要运行单独的服务器或容器，而对于其他两个，您确实需要运行一些额外的东西。

现在，如果您一开始使用的是 MariaDB，但又想回到 SQLite，该怎么办呢？嗯，这是可能的，但是使用以下步骤可能会出现一些我们不知道的奇怪故障。如果您遇到任何奇怪的问题然后需要帮助，或者您解决了这些问题，请在此处开启一个新的讨论：<https://github.com/dani-garcia/vaultwarden/discussions>，以帮助您和其他人。

## 如何从 MariaDB 迁移到 SQLite <a href="#how-to-migrate-from-mariadb-to-sqlite" id="how-to-migrate-from-mariadb-to-sqlite"></a>

确保您对 SQLite 和 MariaDB 使用的是相同版本的 Vaultwarden（Docker 或自定义构建），不要在这些步骤之间更新 Docker 镜像。要迁移到 SQLite，我们首先需要有一个 SQLite 数据库文件，我们可以用它来传输数据。要创建此文件，您需要停止当前的 Vaultwarden 实例，并将其配置为使用 SQLite。例如，您可以通过将 `DATABASE_URL` 从 `DATABASE_URL=mysql://<vaultwarden_user>:<vaultwarden_pw>@mariadb/vaultwarden` 更改为 `DATABASE_URL=/data/db.sqlite3` 来实现。（ `/data` 是您使用的 `-v` 值的 Docker 容器内的内部路径）。

更改此配置后，启动 Vaultwarden，检查以 `Executing migration script .....` 开头的行的日志信息，这些信息显示它执行了一些迁移。

现在再次停止 Vaultwarden，以便您可以开始迁移过程。需要 MariaDB 的数据库主机和凭据才能继续。

现在运行以下单行程序并将 `<dbhost>`、`<dbuser>` 以及 `<database>` 调整为您用于 MariaDB 连接的实际内容：

```bash
mysqldump \
  --host=<dbhost> \
  --user=<dbuser> --password \
  --skip-create-options \
  --compatible=ansi \
  --default-character-set=utf8 \
  --skip-extended-insert \
  --compact \
  --single-transaction \
  --no-create-db \
  --no-create-info \
  --hex-blob <database> \
  | grep -a "^INSERT INTO" | grep -a -v "__diesel_schema_migrations" \
  | sed 's#\\"#"#gm' \
  | sed -sE "s#,0x([^,]*)#,X'\L\1'#gm" \
   > mysql-to-sqlite.sql
```

系统会提示您输入密码，输入密码然后按回车键。

这一步将生成一个用于包含您的数据库的 `mysql-to-sqlite.sql` 文件。现在查找上一步中在您第一次使用 SQLite 作为数据库启动 Vaultwarden 时由 Vaultwarden 创建的 `db.sqlite3` 文件。复制或移动 `mysql-to-sqlite.sql` 到与 `db.sqlite3` 于同一目录中。现在您可以执行以下命令：

```bash
sqlite3 db.sqlite3 < mysql-to-sqlite.sql
```

这一步将使用转储填充 SQLite 数据库，您现在可以使用 SQLite 而非 MySQL 再次启动 Vaultwarden 了。


# 安全


# 1.强化指南

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Hardening-Guide)
{% endhint %}

## 应用程序配置 <a href="#application-configuration" id="application-configuration"></a>

下面的小节涵盖了 Vaultwarden 本身相关的强化。

### 禁用注册和（可选）邀请 <a href="#disable-registration-and-optionally-invitations" id="disable-registration-and-optionally-invitations"></a>

默认情况下，Vaultwarden 允许任何匿名用户在未被邀请的情况下在服务器上注册新账户。如果您可以访问管理页面，则这不是必需的，如果您是服务器上的第一个用户，则这很有用。建议您在管理面板中（如果启用了管理面板的话）或[使用环境变量](/configuration/disable-registration-of-new-users)将其禁用，以防止攻击者在您的 Vaultwarden 服务器上创建账户。

Vaultwarden 还允许注册用户邀请其他新用户在服务器上创建账户并加入其组织。只要您信任您的用户，这不会带来直接风险，但是可以在管理面板或[使用环境变量](/configuration/disable-registration-of-new-users)将其禁用。

### 禁用显示密码提示 <a href="#disable-password-hint-display" id="disable-password-hint-display"></a>

Vaultwarden 在登录页面上显示密码提示，以适应没有配置 SMTP 的小型/本地部署，这可能被攻击者滥用，以方便对服务器上的用户进行密码猜测攻击。可以在管理面板中通过取消勾选 `Show password hints` 选项或[使用环境变量](/configuration/disable-registration-of-new-users)来禁用它。

## HTTPS / TLS 配置 <a href="#https-tls-configuration" id="https-tls-configuration"></a>

下面的小节涵盖了 HTTPS/TLS 相关的强化。

### 严格 SNI <a href="#strict-sni" id="strict-sni"></a>

[SNI](https://zh.wikipedia.org/wiki/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%90%8D%E7%A7%B0%E6%8C%87%E7%A4%BA) 是网络浏览器请求 HTTPS 服务器为特定网站（如 `vaultwarden.example.com`）提供 SSL/TLS 证书的方式。假设`vaultwarden.example.com` 的 IP 地址是 `1.2.3.4`。理想情况下，您希望您的实例只能通过 <https://vaultwarden.example.com> 访问，并且不能通过 <https://1.2.3.4> 进行访问。这是因为 IP 地址会因为各种原因被不断扫描，如果能通过这种方式检测到您的 Vaultwarden 实例，就会成为一个更明显的目标。例如，一个简单的 [Shodan 搜索](https://www.shodan.io/search?query=bitwarden)就会发现一些通过 IP 地址访问的 Bitwarden 实例。

### 反向代理 <a href="#reverse-proxying" id="reverse-proxying"></a>

一般来说，您应该避免通过 Vaultwarden 内置的 [Rocket TLS 支持](/reverse-proxy/https/enabling-https)启用 HTTPS，特别是当您的实例是公开访问的时候。Rocket 本身列出了如下[警告](https://rocket.rs/v0.4/guide/configuration/#configuring-tls)：

> Rocket's built-in TLS is not considered ready for production use. It is intended for development use only.（Rocket 内置的 TLS 还不能用于生产。它只用于开发用途。）

比如，Rocket TLS 不支持严格 SNI 或 ECC 证书（仅 RSA）。

请参看[代理示例](/reverse-proxy/proxy-examples)，以了解反向代理配置的示例。

#### 访问日志包含 `access_token` 参数 <a href="#access-logs-contain-access_token-parameter" id="access-logs-contain-access_token-parameter"></a>

通过调用具有 JWT 密钥的 GET 请求来建立用于通知的 WSS 连接。

GET 请求示例：

```
/notifications/hub?access_token=[this part is always the same].eyJuYmYi[redacted]sImV4cCI6MTcxNzc1NzQ1OCwiaXN[redacted]M6Ly92YXVsdC5zZWMuYXJwYXxsb2dpbiIsInN1YiI6ImY5YmVhN[redacted]tNGJjNS05MDY2LTQ3NjFlZmY4ND[redacted]sInByZW1pdW0iOnRydWU[redacted]JjaXBoZXIiLCJlbWFpbCI6ImNpc[redacted]ljdSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJzc3RhbXAiOiJlZjM3[redacted]MjctODE2OS1hZTQ3NmFjNDc4MGQiLCJkZX[redacted]02ZTk3LTQ2N2M[redacted]jM3NmEiLCJzY29wZSI6WyJhcG[redacted]5lX2FjY2VzcyJdLCJhbXIiOlsiQXBwbGljY[redacted]hGDeCNdjTs1cOL2fV_OR96Sey-gA5eRa8OCGNgCrDeyYAPyk[redacted]BkQGwjEhD7fcWILxRYqQ7W6rkC2o[redacted]LB_nztpAgeRUbsPgsd3RNTWJDKdlH8aMf1[redacted]vB_doENJPeyaeMuEG85KqpAN2A[redacted]GeeCztxmQIe21PMtBG-SAgGeI[redacted]X_9mmyv0nISHBuHjhQ_km[redacted]VCLoFneb-MEzN[redacted]T8VcXSKhGXpwJUx8j1[redacted]k_nH27vrD2Dg
```

如果您的反向代理配置为保存访问日志，或者访问日志被发送到外部服务（例如 Prometheus + Promtail），建议在外部日志存储上编辑 `access_token` 参数的值，或者选择直接在您的反向代理上编辑，如果支持的话。

任何其他数据都不会通过 GET 请求发送，无论是加密的还是未加密的。

请注意，内部 Vaultwarden 日志将查询截断为 30 个字符，因此 access\_token 会被截断。这意味着默认情况下如果没有使用反向代理，您也应该是安全的。

## Docker 配置 <a href="#docker-configuration" id="docker-configuration"></a>

下面的小节涵盖了 Docker 相关的强化。

### 以非 root 用户运行 <a href="#run-as-a-non-root-user" id="run-as-a-non-root-user"></a>

Vaultwarden Docker 镜像被配置为默认以 `root` 用户的身份运行容器进程。这允许 Vaultwarden 读取/写入 [bind-mounted](https://docs.docker.com/storage/bind-mounts/) 到容器中的任何数据，而无需权限问题，即使这些数据是由另一个用户（例如，您在 Docker 主机上的用户账户）拥有的。

默认配置在安全性和可用性之间取得了很好的平衡 -- 在一个非特权 Docker 容器中以 root 身份运行，本身就提供了合理的隔离级别，同时也让那些不是非常精通如何在 Linux 上管理所有权/权限的用户更容易进行设置。然而，作为通用策略，从安全的角度来说，以所需的最低权限运行进程是更好的；对于用 Rust 等内存安全语言编写的程序来说，这一点就不那么重要了，但请注意，Vaultwarden 也使用了一些用 C 语言编写的库代码（例如 SQLite、OpenSSL、MySQL、PostgreSQL 等）。

要在 Docker 中以非 root 用户 (uid/gid 1000) 的身份运行容器进程 (vaultwarden)：

```shell
docker run -u 1000:1000 [...other args...] vaultwarden/server:latest
```

在 `docker-compose` 中类似操作：

```yml
services:
  vaultwarden:
    image: vaultwarden/server:latest
    container_name: bitwarden
    user: 1000:1000
    ... other configuration ...c
```

如果您使用 podman 作为无根用户运行 Vaultwarden，则主机（例如 1000:1000）上用户的 uid/gid将默认映射到容器 (0:0) 中的 root。您可以使用 `--userns keep-id` 选项进一步限制权限，该选项会将容器用户映射到与主机（例如 1000:1000）相同的 uid/gid 。

```sh
podman run --userns keep-id [other args] vaultwarden/server:latest
```

在许多 Linux 发行版中，默认用户的 uid/gid 为 1000（运行 `id` 命令进行验证），所以如果您想在不换成其他用户的情况下轻松地访问您的 Vaultwarden 数据，这是一个很好的值，但你可以根据需要调整 uid/gid。请注意，您很可能需要指定一个数字 uid/gid，因为 Vaultwarden 容器不共享用户/组名到 uid/gid 的相同映射（例如，将容器中的 `/etc/passwd` 和 `/etc/group` 文件与 Docker 主机上的文件对比）。

Vaultwarden Docker 镜像的设置使得 `vaultwarden` 可执行文件绑定到端口 80，这工作正常，因为它默认以 root 身份运行。但是，非 root 进程通常无法绑定到[特权端口](https://www.w3.org/Daemon/User/Installation/PrivilegedPorts.html)（即低于 1024 的端口）。从版本 20.10.0 开始（参见 [moby/moby#41030](https://github.com/moby/moby/pull/41030)），Docker 专门配置其容器，以便默认情况下允许非 root 进程绑定到特权端口。对于早期版本的 Docker 或其他没有这种特殊行为的容器运行时，Vaultwarden Docker 镜像还在 `vaultwarden` 可执行文件上设置 [`cap_net_bind_service`](https://man7.org/linux/man-pages/man7/capabilities.7.html) 功能，这是另一种允许可执行文件在以非 root 用户身份运行时绑定到特权端口的方法。

### 挂载数据到容器中 <a href="#mounting-data-into-the-container" id="mounting-data-into-the-container"></a>

一般来说，只有 Vaultwarden 正常运行所需要的数据才应该被挂载到 Vaultwarden 容器中（通常情况下，这只是您的数据目录，也许还有一个包含 SSL/TLS 证书和私钥的目录）。不要挂载您的整个主目录，例如，`/var/run/docker.sock` 等，除非您有特定的原因，并且知道您在做什么。

另外，如果您不希望 Vaultwarden 修改您挂载的数据（例如，certs），可以通过在卷规范中添加 `:ro` 来[只读挂载它](https://docs.docker.com/storage/bind-mounts/#use-a-read-only-bind-mount)（例如，`docker run -v /home/username/vaultwarden-ssl:/ssl:ro`）。

## 杂项 <a href="#miscellaneous" id="miscellaneous"></a>

### 暴力破解 <a href="#brute-force-mitigation" id="brute-force-mitigation"></a>

当不使用双重身份验证时，（理论上）有可能对用户的密码进行暴力破解，从而获得对账户的访问权限。缓解此问题的一种相对简单的方法是设置 fail2ban，设置后，在过多的失败登录尝试后将阻止访问者的 IP 地址。但是在许多反向代理（例如 cloudflare）后面使用此功能时，应格外注意。参阅：[Fail2Ban 设置](/configuration/security/fail2ban-setup)。

### 隐藏在子目录下 <a href="#hiding-under-a-subdir" id="hiding-under-a-subdir"></a>

通常，Bitwarden 实例驻留在子域的根目录下（即 `bitwarden.example.com`，而不是 `bitwarden.example.com/some/path`）。上游的 Bitwarden 服务器目前只支持子域根目录，而 Vaultwarden 则增加了对[备用基本目录](/reverse-proxy/using-an-alternate-base-dir)的支持。对于某些用户来说，这很有用，因为他们只能访问一个子域，并希望在不同的目录下运行多个服务。在这种情况下，他们通常可以做一些显而易见的选择，比如使用 `mysubdomain.example.com/bitwarden`。然而，您也可以通过把 Vaultwarden 放在类似 `mysubdomain.example.com/vaultwarden/<mysecretstring>` 这样的目录下来提供额外的保护，其中 `<mysecretstring>` 有效地充当一个密码。也许有人会说这是[通过隐藏实现安全](https://en.wikipedia.org/wiki/Security_through_obscurity)，但实际上这是深度防御 -- 子目录的隐蔽性只是额外的一层安全保护，而不是为了成为主要的安全手段（用户主密码的强度仍然是主要的安全手段）。

有关安全性子路径托管的一般性讨论，请参阅：<https://github.com/debops/debops/issues/1233>

如果你想让 Caddy 断开除 vaultwarden 之外的所有连接：

```nginx
mysubdomain.example.com {
	route {
		reverse_proxy /my-custom-path/* 10.0.0.150:8083 {
			header_up X-Real-IP {remote_host}
		}
		handle /* {
			abort
		}
	}
}
```


# 2.显示密码提示

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Password-hint-display)
{% endhint %}

> \[**译者注**]：此配置默认为 `true`，但当您未配置 SMTP 时才会起作用。输入您的电子邮箱后，右上角将显示一条错误信息，其内容即为您的密码提示信息。

通常，密码提示是通过电子邮件发送的。但是，由于 Vaultwarden 是为小型或个人部署而设计的，所以密码提示在密码提示页面上也是可用的，因此您不需要非得配置电子邮箱服务。如果要禁用此功能，可以使用 `SHOW_PASSWORD_HINT` 变量：

```shell
docker run -d --name vaultwarden \
  -e SHOW_PASSWORD_HINT=false \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```


# 3.启用 U2F 和 FIDO2 WebAuthn 身份验证

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-U2F-%28and-FIDO2-WebAuthn%29-authentication)
{% endhint %}

要启用 U2F 和 FIDO2 WebAuthn 身份验证，您必须使用带有效证书（使用内置的 HTTPS 选项或使用反向代理）的 HTTPS 域名访问 Vaultwarden。我们建议使用 Let's Encrypt 提供的免费证书。

之后，您需要将 `DOMAIN` 环境变量设置为与访问 Vaultwarden 相同的地址：

```shell
docker run -d --name vaultwarden \
  -e DOMAIN=https://vw.domain.tld \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，该值必须包含 `https://`，并且如果不使用默认的 `443`，在末尾还必须包含一个端口（格式为 `https://vw.domain.tld:port`）。


# 4.启用 YubiKey OTP 身份验证

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Enabling-Yubikey-OTP-authentication)
{% endhint %}

要启用 YubiKey 身份验证，必须设置 `YUBICO_CLIENT_ID` 和 `YUBICO_SECRET_KEY` 变量。

如果 `YUBICO_SERVER` 未指定，它将使用默认的 YubiCloud 服务器。您可以在[这里](https://upgrade.yubico.com/getapikey/)使用默认的 YubiCloud 生成 `YUBICO_CLIENT_ID` 和 `YUBICO_SECRET_KEY`。

备注：

* 要生成 API 密钥或在 OTP 服务器上使用 YubiKey，必须对其进行注册。在 [Manager CLI](https://www.yubico.com/support/download/yubikey-manager/) 或 [~~YubiKey 个性化工具~~](https://www.yubico.com/products/services-software/personalization-tools/use/)中配置好您的密钥后，然后在[这里](https://upload.yubico.com/)使用默认服务器注册。
* 由于上游的问题，服务器版本为 1.6.0 或更低的 aarch64 不支持 YubiKey 功能（请参阅 [＃262](https://github.com/dani-garcia/bitwarden_rs/issues/262)）。

```shell
docker run -d --name vaultwarden \
  -e YUBICO_CLIENT_ID=12345 \
  -e YUBICO_SECRET_KEY=ABCDEABCDEABCDEABCDE \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

> **\[译者注]**： [YubiKey 个性化工具](https://www.yubico.com/products/services-software/personalization-tools/use/)已于 2025 年 02 月 19 日开始停用，到 2026 年 02 月 19 日正式停用。


# 5.Fail2ban 设置

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Fail2Ban-Setup)
{% endhint %}

设置 Fail2ban 可以阻止攻击者暴力破解您的密码库登录。如果您的实例是公开的，这一点尤其重要。

## 目录 <a href="#table-of-contents" id="table-of-contents"></a>

* [预先说明](#pre-requisite)
* [安装](#installation)
  * [Debian / Ubuntu / Raspian](#debian-ubuntu-raspian)
  * [Fedora / Centos](#fedora-centos)
  * [群晖 DSM](#synology-dsm)
* [为网页密码库设置](#setup-for-web-vault)
  * [Filter](#filter)
  * [Jail](#jail)
* [为管理页面设置](#setup-for-admin-page)
  * [Filter](#filter-1)
  * [Jail](#jail-1)
* [为 TOTP 代码设置](#setup-for-totp)
  * [Filter](#filter-2)
  * [Jail](#jail-2)
* [测试 Fail2ban](#testing-fail-2-ban)
* [SELinux 中的问题](#selinux-problems)

## 预先说明 <a href="#pre-requisite" id="pre-requisite"></a>

* 文件名位于每个代码块的顶部。
* 从 1.5.0 版开始，Vaultwarden 支持记录到文件。请设置[日志记录](/faq/troubleshooting/logging)。
* 尝试使用错误的账户信息登录到网页版密码库，并检查日志文件中如下格式的记录项：

```
[YYYY-MM-DD hh:mm:ss][vaultwarden::api::identity][ERROR] Username or password is incorrect. Try again. IP: XXX.XXX.XXX.XXX. Username: email@domain.com.
```

## 安装 <a href="#installation" id="installation"></a>

### Debian / Ubuntu / Raspian Pi OS

```shell
sudo apt-get install fail2ban -y
```

### Fedora / Centos

需要 EPEL 库 (CentOS 7)

```shell
sudo yum install epel-release
sudo yum install fail2ban -y
```

### 群晖 DSM <a href="#synology-dsm" id="synology-dsm"></a>

使用 Synology 的话，由于各种原因需要做更多的工作。使用 Docker Compose 的完整的解决方案发布在[这里](https://github.com/sosandroid/docker-fail2ban-synology)。主要的问题是：

1. 嵌入式 IP 禁令系统不适用于 Docker 容器
2. 嵌入式 iptables 不支持 `REJECT` 块类型
3. Docker GUI 不允许某些高级设置
4. 修改系统配置不符合升级要求

因此，我们将在 Docker 容器中使用 Fail2ban。[Crazy-max/docker-fail2ban](https://github.com/crazy-max/docker-fail2ban) 提供了一个很好的解决方案，并且 Synology 的 Docker GUI 将被忽略。通过 SSH 的命令行，执行下列步骤（根据您的 Synology 配置调整 `volumeX`）：

1、获取 root 权限

```shell
sudo -i
```

2、创建持久性文件夹

```shell
mkdir -p /volumeX/docker/fail2ban/action.d/
mkdir -p /volumeX/docker/fail2ban/jail.d/
mkdir -p /volumeX/docker/fail2ban/filter.d/
```

3、将 blocktype 的 `REJECT` 替换为 `DROP` 块类型

```systemd
# /volumeX/docker/fail2ban/action.d/iptables.local

[Init]
blocktype = DROP
[Init?family=inet6]
blocktype = DROP
```

4、创建 docker-compose 文件

```batch
# /volumeX/docker/fail2ban/docker-compose.yml

version: '3'
services:
	fail2ban:
		container_name: fail2ban
		restart: always
		image: crazymax/fail2ban:latest
		environment: 
		- TZ=Europe/Paris
		- F2B_DB_PURGE_AGE=30d
		- F2B_LOG_TARGET=/data/fail2ban.log
		- F2B_LOG_LEVEL=INFO
		- F2B_IPTABLES_CHAIN=INPUT

		volumes:
		- /volumeX/docker/fail2ban:/data
		- /volumeX/docker/vw-data:/vaultwarden:ro

		network_mode: "host"

		privileged: true
		cap_add:
			- NET_ADMIN
			- NET_RAW
```

5、使用命令行启动容器

```shell
cd /volumeX/docker/fail2ban
docker-compose up -d
```

您现在应该看到该容器在 Synolog 的 Docker GUI 中运行了。在配置筛选器和 jail 后，您必须重新加载。

## 为网页密码库设置 <a href="#setup-for-web-vault" id="setup-for-web-vault"></a>

按照惯例，`path_f2b` 代表 Fail2ban 工作所需的路径。这取决于您的系统，例如在 Synology 上是 `/volumeX/docker/fail2ban/`，但在其他系统上是 `/etc/fail2ban/`。

### Filter <a href="#filter" id="filter"></a>

使用如下内容创建文件：

```systemd
# path_f2b/filter.d/vaultwarden.local

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$
ignoreregex =
```

**提示**：如果在 `fail2ban.log` 中出现以下错误消息 (CentOS 7, Fail2Ban v0.9.7) \
`fail2ban.filter [5291]: ERROR No 'host' group in '^.*Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'`\
请将 `vaultwarden.local` 中的 `<ADDR>` 改为 `<HOST>`。

**提示**：对于 Cloudflare 用户，请确保在**管理面板** -> **高级设置** -> **客户端 IP 标头**中将客户端 IP 标头设置为 `CF-Connecting-IP`，否则客户端的真实 IP 将不会被记录/阻止。如果您使用的代理已设置为配置使用哪些标头来确定客户端的 IP 地址，则不需要；否则，当 `CF-Connecting-IP` 不存在时，会记录 Docker 网络地址。

**提示**：如果您在 `vaultwarden.log` 中看到 127.0.0.1 是登录失败的 IP 地址，那么您可能正在使用反向代理，而 Fail2ban 无法正常工作：

```
[YYYY-MM-DD hh:mm:ss][vaultwarden::api::identity][ERROR] Username or password is incorrect. Try again. IP: 127.0.0.1. Username: email@example.com.
```

要解决这个问题，需要通过 X-Real-IP 头将真实的远程地址转发给 Vaultwarden。如何操作呢？根据你使用的代理服务器不同而不同。例如，在 Caddy 2.x 中，当您定义反向代理时，同时定义 `header_up X-Real-IP {remote_host}`。更多信息请参阅[代理示例](/reverse-proxy/proxy-examples)。

### Jail

> \[**译者注**]：[什么是 Jail](https://docs.freebsd.org/zh-cn/books/arch-handbook/jail/)

使用如下内容创建文件：

```systemd
# path_f2b/jail.d/vaultwarden.local

[vaultwarden]
enabled = true
port = 80,443,8081
filter = vaultwarden
banaction = %(banaction_allports)s
logpath = /path/to/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
```

#### Docker 用户注意事项 <a href="#note-for-docker-users" id="note-for-docker-users"></a>

Docker 使用 FORWARD 链而不是默认的 INPUT 链。如果接收请求的机器将他们直接映射到 Docker 容器，那么无论容器里有什么（反向代理、Vaultwarden 等），链都需要适当地设置。默认的 `action` 被设置为`action_`（它使用 `banaction`，其别名我们设置为 `banaction_allports`），`action_` 已经考虑了链的问题，因此，只需设置 `chain` 即可。参阅[这个类似的问题](https://forum.openwrt.org/t/resolved-fail2ban-and-iptables-ip-bans-not-blocked/90057)。

```systemd
chain = FORWARD
```

#### Synology DSM Docker 用户注意事项 <a href="#note-for-synology-dsm-docker-users" id="note-for-synology-dsm-docker-users"></a>

请将 `chain` 设置为 `DOCKER-USER`

```systemd
chain = DOCKER-USER
```

#### 使用 Fail2Ban v1.1.1.dev1（以及可能更高版本）的 Docker 用户注意事项 <a href="#note-for-docker-users-with-fail2ban-v1.1.1.dev1-and-possibly-newer" id="note-for-docker-users-with-fail2ban-v1.1.1.dev1-and-possibly-newer"></a>

在 Fail2Ban v1.1.1.dev1 中，Debian 的默认 `banactions` 从 iptables 变成了 nftables（参阅[此处](https://github.com/fail2ban/fail2ban/commit/d0d07285234871bad3dc0c359d0ec03365b6dddc)）。另一方面，Docker（至少是 25.0.3 版）仍在使用 iptables。因此，`banaction = %(banaction_allports)s` 无法阻止对 Docker 容器的请求。在这种情况下，使用：

```systemd
banaction = iptables
```

{% hint style="info" %}
如果您使用 systemd 来管理 Vaultwarden，您可以为 Fail2ban 使用 systemd-journal：

```systemd
backend = systemd
filter = vaultwarden[journalmatch='_SYSTEMD_UNIT=your_vaultwarden.service']
```

使用它们来代替 `logpath =` 和 `filter =` 变量。
{% endhint %}

**后端注意事项**：如果您使用 `sudo apt install` 等方式安装 fail2ban，`/etc/fail2ban/jail.conf` 可能会使用 systemd 作为默认的后端。此默认配置项将导致无法监控 logpath 日志。

将 `backend = pyinotify` 或 `backend = inotify` 添加到 `vaultwarden.local` 配置中：

```systemd
# path_f2b/jail.d/vaultwarden.local

[vaultwarden]
enabled = true
backend = pyinotify
port = 80,443,8081
filter = vaultwarden
banaction = %(banaction_allports)s
logpath = /path/to/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
```

重启 fail2ban 以使更改生效：

```sh
sudo systemctl restart fail2ban
```

**Cloudflare 用户注意事项：**&#x5982;果您使用 Cloudflare 代理，您需要将 Cloudflare 添加到您的操作列表中，如[这个指南](https://niksec.com/using-fail2ban-with-cloudflare/)中所示。

重新加载 Fail2ban 使更改生效：

```shell
sudo systemctl reload fail2ban
```

请根据您自己的需要自由修改这些选项。

## 为管理页面设置 <a href="#setup-for-admin-page" id="setup-for-admin-page"></a>

如果您通过设置 `ADMIN_TOKEN` 环境变量启用了管理控制台，则可以使用 Fail2ban 来阻止攻击者暴力破解您的管理令牌。该过程与网页密码库相同。

### Filter <a href="#filter" id="filter"></a>

使用如下内容创建文件：

```systemd
# path_f2b/filter.d/vaultwarden-admin.local

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*Invalid admin token\. IP: <ADDR>.*$
ignoreregex =
```

**提示**：如果在 `fail2ban.log` 中出现以下错误消息：`ERROR NOK: ("No 'host' group in '^.*Invalid admin token\\. IP: <ADDR>.*$'")`，请将 `vaultwarden-admin.local` 中的 `<ADDR>` 改为 `<HOST>`

### Jail

使用如下内容创建文件：

```systemd
# path_f2b/jail.d/vaultwarden-admin.local

[vaultwarden-admin]
enabled = true
port = 80,443
filter = vaultwarden-admin
banaction = %(banaction_allports)s
logpath = /path/to/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
```

**注意**：Docker 使用 FORWARD 链而不是默认的 INPUT 链。因此，当使用 Docker 时，请使用下面的 `action` 行替换掉 `banaction` 行：

```systemd
action = iptables-allports[name=vaultwarden, chain=FORWARD]
```

{% hint style="info" %}
如果您使用 systemd 来管理 Vaultwarden，您同样可以在这里为 Fail2ban 使用 systemd-journal：

```
backend = systemd
filter = vaultwarden-admin[journalmatch='_SYSTEMD_UNIT=your_vaultwarden.service']
```

使用它们来代替 `logpath =` 和 `filter =` 变量。
{% endhint %}

**后端注意事项**：如果您使用 `sudo apt install` 等方式安装 fail2ban，`/etc/fai2ban/jail.conf` 可能会使用 systemd 作为默认的后端。此默认配置项将导致无法监控 logpath 日志。

将 `backend = pyinotify` 或 `backend = inotify` 添加到 `vaultwarden.local` 配置中：

```systemd
# path_f2b/jail.d/vaultwarden.local

[vaultwarden]
enabled = true
backend = pyinotify
port = 80,443,8081
filter = vaultwarden
banaction = %(banaction_allports)s
logpath = /path/to/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
```

重启 fail2ban 以使更改生效：

```sh
sudo systemctl restart fail2ban
```

**Cloudflare 用户请注意事项：**&#x5982;果您使用 Cloudflare 代理，您需要将 Cloudflare 添加到您的操作列表中，如[本指南](https://niksec.com/using-fail2ban-with-cloudflare/)中所示。

重新加载 Fail2ban 使更改生效：

```shell
sudo systemctl reload fail2ban
```

## 为 TOTP 代码设置 <a href="#setup-for-totp" id="setup-for-totp"></a>

按照惯例，`path_f2b` 表示 Fail2ban 运行所需的路径。这取决于您的系统。例如，在 Synology 上，我们讨论的是 `/volumeX/docker/fail2ban/`，而在其他一些系统上，我们讨论的是 `/etc/fail2ban/`。

### Filter

使用如下内容创建文件：

```systemd
# path_f2b/filter.d/vaultwarden-totp.local
# Fail2Ban filter for Vaultwarden TOTP

[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*\[ERROR\] Invalid TOTP code! Server time: (.*) UTC IP: <ADDR>$
ignoreregex =
```

日志示例：

```
[YYYY-MM-DD hh:mm:ss][vaultwarden::api::core::two_factor::authenticator][ERROR] Invalid TOTP code! Server time: YYYY-MM-DD hh:mm:ss UTC IP: 1.2.3.4
```

### Jail

使用如下内容创建文件：

```systemd
# path_f2b/jail.d/vaultwarden-totp.local

[vaultwarden-totp]
enabled = true
port = 80,443
filter = vaultwarden-totp
banaction = iptables-multiport[name=vaultwarden-totp, port="80,443", protocol=tcp]
logpath = /path/to/vaultwarden.log
maxretry = 3
bantime = 14400
findtime = 14400
```

重启 fail2ban 以使更改生效：

```sh
sudo systemctl restart fail2ban
```

请根据您自己的需要自由修改这些选项。

## 测试 Fail2ban <a href="#testing-fail-2-ban" id="testing-fail-2-ban"></a>

现在，尝试使用任何电子邮件地址登录 Vaultwarden（不必是有效电子邮件，只需是电子邮件格式即可）。如果它可以正常工作，您的 IP 将被阻止。运行以下命令来取消阻止的 IP：

```shell
# 使用 Docker
sudo docker exec -t fail2ban fail2ban-client set vaultwarden unbanip XX.XX.XX.XX
# 未使用 Docker
sudo fail2ban-client set vaultwarden unbanip XX.XX.XX.XX
```

如果 Fail2ban 无法正常运行，请检查 Vaultwarden 日志文件的路径是否正确。对于 Docker：如果指定的日志文件未生成和/或更新，请确保将 `EXTENDED_LOGGING` 变量设置为 `true`（默认值），并且确保日志文件的路径是 Docker 内部的路径（当您使用 `/vw-data/:/data/` 时，日志文件应位于容器外部的 `/data/...` 中）。

还要确认 Docker 容器的时区与主机的时区是否一致。通过将日志文件中显示的时间与主机操作系统的时间进行比较来进行检查。如果它们不一致，则有多种解决方法。一种是使用 `-e "TZ = <timezone>"` 选项启动 Docker 。可用的时区（比如 `-e TZ = "Australia/Melbourne"`）列表在[这里](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones)查看。

如果您使用的是 podman 而不是 Docker，则无法通过 `-e "TZ = <timezone>"` 来设置时区。可以按照以下指南解决此问题（当使用 alpine 镜像时）：<https://wiki.alpinelinux.org/wiki/Setting_the_timezone>。

## SELinux 中的问题 <a href="#selinux-problems" id="selinux-problems"></a>

当使用 SELinux 时，SELinux 可能会阻止 Fail2ban 读取日志。如果是这样，请运行此命令： `sudo tail /var/log/audit/audit.log`。您应该会看到如下类似内容（当然，实际的审核 ID (pid) 会因您的情况而不一样）：

```systemd
type=AVC msg=audit(1571777936.719:2193): avc:  denied  { search } for  pid=5853 comm="fail2ban-server" name="containers" dev="dm-0" ino=1144588 scontext=system_u:system_r:fail2ban_t:s0 tcontext=unconfined_u:object_r:container_var_lib_t:s0 tclass=dir permissive=0
```

您可以使用 `grep 'type=AVC msg=audit(1571777936.719:2193)' /var/log/audit/audit.log | audit2why` 来找出真正的原因。`audit2allow -a` 将为您提供有关如何创建模块并允许 Fail2ban 访问日志的具体说明。

按照这些步骤操作后就结束了！Fail2ban 现在应该可以正常工作了。


# 6.Docker Traefik ModSecurity 设置

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Docker---Traefik---ModSecurity-Setup)
{% endhint %}

设置 ModSecurity 将通过 Web 应用程序防火墙 ([WAF](https://www.cloudflare-cn.com/learning/ddos/glossary/web-application-firewall-waf/)) 将所有请求代理到 Vaultwarden。这可能有助于过滤可疑请求（例如注入尝试）以减缓 Vaultwarden 中的未知漏洞（带来的威胁）。

## 前提条件 <a href="#pre-reqs" id="pre-reqs"></a>

* 设置了使用 Docker + Traefik 2.0 作为反向代理
* 正确设置了 Fail2Ban（[参阅此教程](/configuration/security/fail2ban-setup#debian-ubuntu-raspian-pi-os)）&#x20;
* 这仅在 Debian 上进行了测试（但应该可以在 Ubuntu 或 Raspbian 等类似系统上运行）

## 安装 <a href="#installation" id="installation"></a>

bash：

```batch
touch /opt/docker/waf-rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf && touch /opt/docker/waf-rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
```

`/opt/docker/docker-compose.yml`：

```yml
services:
  traefik:
    image: traefik:latest
    container_name: traefik
    command:
      - --providers.docker=true
      - --providers.docker.exposedByDefault=false
      - --entrypoints.web.address=:80
      - --entrypoints.websecure.address=:443
      - --certificatesresolvers.myresolver.acme.tlschallenge=true
      - --certificatesresolvers.myresolver.acme.email=you@domain.tld
      - --certificatesresolvers.myresolver.acme.storage=acme.json
      - --certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json
    restart: unless-stopped
    ports:
      - 80:80
      - 443:443
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /opt/docker/le:/letsencrypt

  waf:
    image: owasp/modsecurity-crs:apache
    container_name: waf
    environment:
      PARANOIA: 1
      ANOMALY_INBOUND: 10
      ANOMALY_OUTBOUND: 5
      PROXY: 1
      REMOTEIP_INT_PROXY: "172.20.0.1/16"
      BACKEND: "http://vaultwarden:80"
      BACKEND_WS: "ws://vaultwarden:80/notifications/hub"
      ERRORLOG: "/var/log/waf/waf.log"
      PROXY_ERROR_OVERRIDE: "off"
    volumes:
     - /opt/docker/waf:/var/log/waf
     - /opt/docker/waf-rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
     - /opt/docker/waf-rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.redirect-https.redirectScheme.scheme=https
      - traefik.http.middlewares.redirect-https.redirectScheme.permanent=true
      - traefik.http.routers.vw-ui-https.rule=Host(`sub.domain.tld`)
      - traefik.http.routers.vw-ui-https.entrypoints=websecure
      - traefik.http.routers.vw-ui-https.tls=true
      - traefik.http.routers.vw-ui-https.service=vw-ui
      - traefik.http.routers.vw-ui-http.rule=Host(`sub.domain.tld`)
      - traefik.http.routers.vw-ui-http.entrypoints=web
      - traefik.http.routers.vw-ui-http.middlewares=redirect-https
      - traefik.http.routers.vw-ui-http.service=vw-ui
      - traefik.http.services.vw-ui.loadbalancer.server.port=80
      - traefik.http.routers.vw-websocket-https.rule=Host(`sub.domain.tld`) && Path(`/notifications/hub`)
      - traefik.http.routers.vw-websocket-https.entrypoints=websecure
      - traefik.http.routers.vw-websocket-https.tls=true
      - traefik.http.routers.vw-websocket-https.service=vw-websocket
      - traefik.http.routers.vw-websocket-http.rule=Host(`sub.domain.tld`) && Path(`/notifications/hub`)
      - traefik.http.routers.vw-websocket-http.entrypoints=web
      - traefik.http.routers.vw-websocket-http.middlewares=redirect-https
      - traefik.http.routers.vw-websocket-http.service=vw-websocket
      - traefik.http.services.vw-websocket.loadbalancer.server.port=3012

  vaultwarden:
    image: vaultwarden/server:latest
    container_name: vaultwarden
    restart: unless-stopped
    environment:
      ENABLE_WEBSOCKET: "true"
      SENDS_ALLOWED: "true"
      PASSWORD_ITERATIONS: 500000
      SIGNUPS_ALLOWED: "true"
      SIGNUPS_VERIFY: "true"
      SIGNUPS_DOMAINS_WHITELIST: "yourdomain.tld"
      ADMIN_TOKEN: "some random string" #generate with openssl rand
      DOMAIN: "domain host name"
      SMTP_HOST: "smtp server"
      SMTP_FROM: "sender email e.g: you@domain.tld"
      SMTP_FROM_NAME: "sender name"
      SMTP_SECURITY: "starttls"
      SMTP_PORT: 587
      SMTP_USERNAME: "smtp username"
      SMTP_PASSWORD: "smtp password"
      SMTP_TIMEOUT: 15
      LOG_FILE: "/data/vaultwarden.log"
      LOG_LEVEL: "warn"
      EXTENDED_LOGGING: "true"
      TZ: "your time zone"
    volumes:
      - /opt/docker/vaultwarden:/data

networks:
  default:
    driver: bridge
    ipam:
      driver: default
      config:
      - subnet: 172.20.0.1/16
```

`/etc/fail2ban/filter.d/waf.conf`：

```systemd
[INCLUDES]
before = common.conf

[Definition]
failregex = ^.*\[client <ADDR>\] ModSecurity: Access denied with code 403 .*$
ignoreregex =
```

`/etc/fail2ban/jail.d/waf.conf`：

```systemd
[waf]
enabled = true
port = 80,443
filter = waf
action = iptables-allports[name=waf, chain=FORWARD]
logpath = /opt/docker/waf/waf.log
maxretry = 1
bantime = 14400
findtime = 14400
```

## 备注 <a href="#note" id="note"></a>

将 Fail2Ban 与 ModSecurity 集成将减缓/阻止攻击者的进一步利用/探测。这是设置为在第一次 ModSecurity 干预时禁止。

要增加 ModSecurity 的攻击性，可以增加 `PARANOIA`（[了解更多](https://coreruleset.org/20211028/working-with-paranoia-levels/)）和/或减少 `ANOMALY_INBOUND`（[了解更多](https://coreruleset.org/docs/concepts/anomaly_scoring/)）的值。

准备好在 PARANOIA > 2 的情况下对 ModSecurity 进行严格的调整，以便在不禁用大量规则的情况下使 UI 能勉强工作。

以下文件将使您能够对 ModSecurity 进行调整（[教程](https://coreruleset.org/docs/concepts/false_positives_tuning/)）：

```
/opt/docker/waf-rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
/opt/docker/waf-rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
```

☁️ 一些值得您仔细考虑的建议 ☁️

如果您的数据非常敏感，以至于您正在考虑设置 `PARANOIA` > 1，那么请考虑不要在公共端点上托管 Vaultwarden，并通过防火墙限制对主机本身的访问，以及授予用户仅能通过 VPN 连接访问。请记住，这并不能降低来自内部的威胁，而内部威胁往往被低估，所以请记住这一点！


# 性能


# 1.更改 API 请求大小限制

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Changing-the-API-request-size-limit)
{% endhint %}

默认情况下，API 调用被限制为 10MB。在大多数情况下，这应该足够了，但是，如果要支持大量访问，则可能会有影响。另一方面，您可能希望将请求大小限制为更小，以防止 API 滥用和可能的 DoS 攻击，尤其是在资源有限的情况下。

要设置限制，可以使用 `ROCKET_LIMITS` 变量。此处的示例设置限制为 10MB（这是默认设置）：

```shell
docker run -d --name vaultwarden \
  -e ROCKET_LIMITS={json=10485760} \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```


# 2.更改 worker 数量

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Changing-the-number-of-workers)
{% endhint %}

> \[**译者注**]：worker 相当于工人，就是干活的人。不知如何翻译准确，就不翻译这个词了。「Master-Worker 模式是常用的并行设计模式。核心思想是，系统由两个角色组成：Master 和 Worker。Master 负责接收和分配任务，Worker 负责处理子任务。任务处理过程中，Master 还负责监督任务进展和 Worker 的健康状态；Master 将接收 Client 提交的任务，并将任务的进展汇总反馈给 Client。」

当 Vaultwarden 运行时，默认它会产生 `2 * <cpu 核心数>` 个 worker 来处理请求。在某些系统上，这可能会由于 worker 数量太少，从而导致性能降低，因此在 docker 镜像中更改为默认产生 10 个线程。您可以通过设置 `ROCKET_WORKERS` 变量来增加或减少 worker 数量以覆盖此默认设置。

在下面的示例中，我们设置为 20 个 worker：

```shell
docker run -d --name vaultwarden \
  -e ROCKET_WORKERS=20 \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```


# 自定义


# 1.翻译电子邮件模板

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Translating-the-email-templates)
{% endhint %}

如果您[设置了电子邮件](/configuration/smtp-configuration)，Vaultwarden 将以英语发送邮件。由于服务器不知道用户的首选语言设置（完全在客户端完成），因此目前不太可能在同一服务器上为不同用户提供多种语言。

如果您的用户不懂英语，您可以将提供的标头模板翻译成您的首选语言。

## 如何翻译/定制模板？ <a href="#how-to-translate-customize-the-templates" id="how-to-translate-customize-the-templates"></a>

您可以通过如下方式使用自定义模板：

1. 将相应文件从存储库（`src/static/templates/email`）复制到具有相同文件夹结构的对应的 `TEMPLATES_FOLDER` 下（例如复制到 `data/templates/email`）
2. 更改它们（比如翻译它们 - 但一定要保持链接中的 `{{variables}}` 完好无损，这样才能确保有效），然后
3. 重新启动 Vaultwarden 以加载新的（覆盖）模板。

**注意**：为确保兼容性，您应该首先下载适合您的版本的模板，并且如果它们发生变化（或添加了新的模板），您还必须自行更新它们。

## 翻译 <a href="#translations" id="translations"></a>

* 德语 by @kennymc-c：<https://github.com/kennymc-c/vaultwarden-lang-de>
* 法语 by @YoanSimco：<https://github.com/YoanSimco/vaultwarden-lang-fr>
* 波兰语 by @olokelo：<https://github.com/olokelo/vaultwarden-lang-pl>
* 简体中文 by @vlian5：<https://github.com/vlian5/vaultwarden_zh_cn>
* 简体中文 by @wcjxixi：<https://github.com/wcjxixi/vaultwarden-lang-zhcn>
* 简体中文 by @zituoguan：<https://github.com/zituoguan/vaultwarden-lang-zh_CN>
* 简体中文 by @JinkaiNiu：<https://github.com/JinkaiNiu/vaultwarden-zh-cn>
* 意大利语 by @rizlas：<https://github.com/rizlas/vaultwarden-lang-it>
* 西班牙语 by @javier-varez：<https://github.com/javier-varez/vaultwarden-lang-es>
* 俄语 by @marat2509：<https://github.com/marat2509/vaultwarden-lang-ru>
* 巴西葡萄牙语 by @marivaldojr：<https://github.com/marivaldojr/vaultwarden-lang-pt_br>
* 荷兰语（AI 生成）by @demeesterroel：<https://github.com/demeesterroel/vaultwarden-lang-nl>

{% hint style="danger" %}
翻译由社区成员按原样提供，我们尚未对其进行测试。因此，使用它们需要您自担风险。如果发生重大的变更（例如，由 Vaultwarden 的新版本引起），请通知维护者和/或在此处做一个注释。
{% endhint %}


# 2.翻译管理页面

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Translating-admin-page)
{% endhint %}

由于 Vaultwarden 管理页面独立于官方的 Bitwarden 自托管[系统管理员门户](https://help.ppgg.in/self-hosting/system-administrator-portal)，因此目前只有英文版，并且目前不太可能在同一服务器上为不同用户提供多种语言。

如果您或您的用户不懂英语，或者您希望显示自己喜欢的语言，您可以将管理页面翻译成您的首选语言。

## 如何翻译/定制管理页面？ <a href="#how-to-translate-customize-the-admin-page" id="how-to-translate-customize-the-admin-page"></a>

您可以通过如下方式使用自定义模板：

1. 将相应文件从存储库（`src/static/templates/admin`）复制到具有相同文件夹结构的对应的 `TEMPLATES_FOLDER` 下（例如复制到 `data/templates/admin`）
2. 更改它们（比如翻译它们 - 但一定要保持链接中的 `{{variables}}` 完好无损，这样才能确保有效），然后
3. 重新启动 Vaultwarden 以加载新的（覆盖）模板。

**注意**：为确保兼容性，您应该首先下载适合您的版本的模板，并且如果它们发生变化（或添加了新的模板），您还必须自行更新它们。

## 翻译 <a href="#translations" id="translations"></a>

* 简体中文 by @wcjxixi：<https://github.com/wcjxixi/vaultwarden-lang-zhcn>
* 简体中文 by @zituoguan：<https://github.com/zituoguan/vaultwarden-lang-zh_CN>
* 简体中文 by @JinkaiNiu: <https://github.com/JinkaiNiu/vaultwarden-zh-cn>
* 俄语 by @marat2509：<https://github.com/marat2509/vaultwarden-lang-ru>
* 意大利语 by @rizlas：<https://github.com/rizlas/vaultwarden-lang-it>

{% hint style="danger" %}
翻译由社区成员按原样提供，我们尚未对其进行测试。因此，使用它们需要您自担风险。如果发生重大的变更（例如，由 Vaultwarden 的新版本引起），请通知维护者和/或在此处做一个注释。
{% endhint %}


# 3.自定义 Vaultwarden CSS

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Customize-Vaultwarden-CSS/)
{% endhint %}

{% hint style="info" %}
**此功能仅适用于 v1.33.0 及更高版本。**
{% endhint %}

从 v1.33.0 版本开始，您可以修改 Vaultwarden 的 CSS 样式（预先嵌入在 web-vault 中）。这可以让用户能够轻松调整样式和布局，甚至隐藏特定的元素。

要修改 CSS，您需要在 `data` 目录中创建 `templates` 目录（或通过 `TEMPLATES_FOLDER` 环境变量指定正确的路径）。

在此目录中，还需要创建另一个名为 `scss` 的目录，该目录将用于存放修改的 Vaultwarden CSS 文件。

您可以将以下两个文件放置在 `scss` 目录中：

* **`user.vaultwarden.scss.hbs`**：此文件是您要编辑并向其中添加自定义样式的文件。
* **`vaultwarden.scss.hbs`**：此文件不应存在，因为它将覆盖内置的默认值。***除非您完全清楚操作后果，否则不要覆盖此文件！***

```
.
├── templates
│   └── scss
│       ├── user.vaultwarden.scss.hbs
│       └── vaultwarden.scss.hbs
```

**以下是可以将其放入 `user.vaultwarden.scss.hbs` 中的示例代码片段：**

```css
/* 文件位置: /data/templates/scss/user.vaultwarden.scss.hbs */

/* --- 变量 --- */
/* 您可以为密码库（用户）和管理控制台（组织）设置不同的 Logo */
$logo-default: url('/vw_static/logo-gray.png');
$logo-admin:   url('/vw_static/logo-gray.png'); 

/* 侧边栏定制 */
$sidebar-width: 15rem; /* 如果需要，将其设置为匹配您的徽标的宽度 */

/* --- 混入 --- */
@mixin hide-element { display: none !important; }

/* --- 隐藏 2FA 提供程序 --- */
/* 0: Authenticator App, 1: Email, 2: Duo, 3: YubiKey OTP, 7: FIDO2 WebAuthn */
/*
 .providers-2fa-0, .providers-2fa-1, .providers-2fa-2, .providers-2fa-3, .providers-2fa-7 {
  @include hide-element;
}
*/

/* --- 加载界面 --- */
app-root img.new-logo-themed { content: $logo-default !important; }

/* --- 登录界面 --- */
auth-anon-layout bit-landing-header {
  bit-svg {
    /* 隐藏原始 SVG */
    > svg { @include hide-element; }

    /* 注入自定义 Logo */
    &::before {
      display: block !important;
      content: "" !important;
      width: 100% !important;
      height: 42px !important;
      background: $logo-default no-repeat center left !important;
      background-size: contain !important;
    }
  }
}

/* --- 仪表板侧边栏 --- */
bit-nav-logo {
  /* 
    如果您希望 Logo 在最小化时减少裁剪，请应
    如果您有类似 Vaultwarden 和 Bitwarden 的徽标
  */
  /* > div { padding-right: 2px !important; } */

  bit-svg {
    > svg { @include hide-element; }

    &::before {
      display: block !important;
      content: "" !important;
      width: 100% !important;
      height: 42px !important;
      background-repeat: no-repeat !important;
      background-size: auto 42px !important;
      background-position: center left !important;
    }
  }
}

/* --- 仪表板侧边栏 --- */
app-user-layout bit-nav-logo bit-svg::before { background-image: $logo-default !important; }
app-organization-layout bit-nav-logo bit-svg::before { background-image: $logo-admin !important; }

/* --- 侧边栏布局 & 逻辑 --- */
#bit-side-nav {
  /*
    仅当宽度与默认的 '18rem' 内联样式匹配时才覆盖宽度。
    这确保我们不会破坏 '折叠' 状态 (4.5rem) 或手动调整大小。
  */
  &[style*="18rem"] { max-width: $sidebar-width !important; }

  /*
    当侧边栏折叠时（宽度通常为 4.5rem），隐藏自定义 Logo
    以便让它看起来不会破坏或被裁剪。
  */
  &[style*="4.5rem"] {
    bit-nav-logo bit-svg::before { display: none !important; }
    /*
      可选：最小化时再次显示原始图标？
      移除下面的注释以启用：
    */
    /* bit-nav-logo bit-svg > svg { display: block !important; } */
  }
}
```

**固定搜索筛选器（使用「Stylus」浏览器扩展测试）：**

```css
/*
使 "筛选器" 框固定不动，只有条目列表滚动。
这样就能始终看到您筛选的内容，并能快速访问搜索筛选器，而无需滚动返回顶部。
*/
#main-content {
    /*Edit 2025.09.12*/
    contain: none;
}

#main-content > app-vault > .tw-flex .tw-basis-1\/4
{
    position: fixed;
    width: calc(25% - 55px);
}

#main-content > app-vault > .tw-flex .tw-basis-3\/4
{
    position: relative;
    left: calc(25% + 10px);
}
```


# 4.使用自定义网站图标

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Using-custom-website-icons)
{% endhint %}

{% hint style="info" %}
本页面介绍的是显示在您的条目旁边的[网站图标](https://help.ppgg.in/security/data/website-icons)（当使用 `internal` 图标服务时）。如果您想自定义 web-vault 的外观，请参考[自定义 Vaultwarden CSS](/customization/customize-vaultwarden-css)。
{% endhint %}

{% hint style="warning" %}
客户端仅会为已配置了自动填充 URI 的条目请求图标。请注意，您也可以在客户端设置中关闭网站图标功能，此时客户端将不会向 Vaultwarden 请求图标。
{% endhint %}

如果您想为您的网站条目添加自定义图标，您可以将它们放置在 `ICON_CACHE_FOLDER` 位置（默认为 `data/icon_cache` ）。命名规则基于条目的指定 IP 或完全限定域名 (FQDN)，即 Bitwarden 在[此图示](https://help.ppgg.in/password-manager/autofill/troubleshoot-autofill/forming-uris-for-autofill#match-detection-options)中叫做 Hostname 的字段：

<figure><img src="https://github.com/user-attachments/assets/47bdf0f1-46f9-41af-8030-d0f860e2a056" alt=""><figcaption></figcaption></figure>

这意味着在请求图标时将忽略方案和端口，因此您无法根据端口号提供不同的图标。

虽然 web-vault 支持多种图像类型，如 ICO、BMP、GIF、JPG、WEBP 和 PNG，但缓存的图标本身始终被命名为 `<fqdn>.png` 或 `<IP>.png` （例如 `data/icon_cache/en.wikipedia.org.png`）。因此，您应该相应地命名您的自定义图标。

## 图标缓存过期机制 <a href="#how-the-icon-cache-expiration-works" id="how-the-icon-cache-expiration-works"></a>

如果图标文件已存在，它将检查其最后修改时间是否已过期（可通过 `ICON_CACHE_TTL` 配置）。若已过期，则会尝试获取新图标而非直接使用现有图标。您可通过设置 `ICON_CACHE_TTL=0` 禁用过期功能，使 Vaultwarden 永久保留本地缓存的现有图标。

如果您无法使用 `ICON_CACHE_TTL=0` （因您希望为大多数网站获取新图标，仅提供少量自定义图标），您可以编写一个 cron 作业，对您自定义放置的图标定期调用 `touch`，从而保持其修改时间为最新状态以避免过期。

{% hint style="warning" %}
`ICON_CACHE_TTL` 默认设置为 2592000 秒（30 天），如果您未禁用过期或未定期更新修改时间，30 天后，任何手动放置的图标将被忽略并可能被覆盖。
{% endhint %}

如果获取图标失败（无论何种原因），Vaultwarden 将在 `ICON_CACHE_FOLDER` 设定的文件夹中为该域名创建一个空白的 `.miss` 文件（例如 `data/icon_cache/en.wikipedia.org.png.miss`），并在 `ICON_CACHE_NEGTTL` 设定的时间内不再尝试获取图标，而是使用备用图标。当 `.miss` 文件过期后，新的请求将自动移除该 `.miss` 文件（此处的「过期」指文件存在时间超过 `ICON_CACHE_NEGTTL` 中设定的秒数值，默认为 3 天）。

{% hint style="warning" %}
只要存在 `.miss` 文件（意味着未过期），即使存在有效的图标，Vaultwarden 仍会使用备用图标。因此对于已创建的自定义图标或已更新修改时间的图标，请务必移除对应的 `.miss` 文件。
{% endhint %}

## 网站图标故障排除 <a href="#website-icon-troubleshooting" id="website-icon-troubleshooting"></a>

如果您没有禁用图标下载（`DISABLE_ICON_DOWNLOAD`），Vaultwarden `internal` 图标服务将从指定的资源下载请求的图标。这是通过向指定的域名/IP（忽略端口）发起网络请求来完成的。如果您的 Vaultwarden 服务器无法发起出站请求（例如缺少互联网访问），则不会下载新图标。

默认情况下，出于安全考虑，Vaultwarden 会[屏蔽其认为非全局（即私有网络）的某些 IP 范围](https://github.com/dani-garcia/vaultwarden/blob/9059437c35e35ab8eb7d1d4716bf13eec0a4ee64/src/util.rs#L776-L819)。您还可以通过配置 `HTTP_REQUEST_BLOCK_REGEX` 来进一步配置 Vaultwarden 应额外屏蔽的主机。

如果您设置了 `ICON_CACHE_NEGTTL=0`，则会禁用 `.miss` 指示器文件过期，这意味着如果存在 `.miss` 文件，Vaultwarden 将始终为指定的域名使用默认备用图标。


# 5.禁用或覆盖密码库接口托管

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Disabling-or-overriding-the-Vault-interface-hosting)
{% endhint %}

为方便起见，Vaultwarden 镜像还将托管网页密码库界面的静态文件。您可以通过设置 `WEB_VAULT_ENABLED` 环境变量来完全禁用静态文件的托管。

```shell
docker run -d --name vaultwarden \
  -e WEB_VAULT_ENABLED=false \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

或者，您可以覆盖密码库文件并提供自己的静态文件来进行托管。您可以通过在容器中挂载您自己的文件路径（而不是 `/web-vault` 目录）来实现。只需确保此目录中至少包含 `index.html` 文件即可。

```shell
docker run -d --name vaultwarden \
  -v /path/to/static/files_directory:/web-vault \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，您还可以通过为 `WEB_VAULT_FOLDER` 环境变量设置路径来更改 Vaultwarden 查找静态文件的路径。


# 备份


# 1.通用（非 docker）

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/General-%28not-docker%29)
{% endhint %}

## 备份 <a href="#backup" id="backup"></a>

需要包含在备份中的内容：

* 启动 Vaultwarden 时使用的环境文件
* `data` 目录
* Vaultwarden 数据库
  * 使用 MariaDB/PostgreSQL/MySQL 的数据库备份功能创建备份

确保您记录了备份存储的过程和位置！

## 还原 <a href="#restore" id="restore"></a>

* 安装 Vaultwarden
* 从备份中恢复数据库
* 恢复环境文件
* 恢复您的 `data` 目录到正确的位置

## 特定平台 <a href="#platform-specific" id="platform-specific"></a>

### FreeBSD 端口 <a href="#freebsd-port" id="freebsd-port"></a>

| 项目          | 位置                                     |
| ----------- | -------------------------------------- |
| Environment | `/usr/local/etc/rc.conf.d/vaultwarden` |
| Data        | `/usr/local/www/vaultwarden/data`      |

### 数据库备份 <a href="#database-backups" id="database-backups"></a>

参阅 [MariaDB - Backup and Restore Overview](https://mariadb.com/kb/en/backup-and-restore-overview/)、[How to Backup SQLite Database](https://stackoverflow.com/questions/25675314/how-to-backup-sqlite-database)。


# 2.备份您的密码库

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Backing-up-your-vault)
{% endhint %}

## 概览 <a href="#overview" id="overview"></a>

应该定期备份 Vaultwarden 数据，并且最好是通过自动化的流程（例如，cron 作业）。理想情况下，应该至少存储一个远程（例如，云存储或不同的计算机）副本。避免依赖文件系统或虚拟机快照作为备份方法，因为这是更复杂的操作，可能会出现更多的问题，在这种情况下的恢复操作对普通用户来说很困难甚至是无法完成。在备份上添加额外的加密层通常是个好主意（尤其是当您的备份还包含配置数据时，例如您的[管理员令牌](/configuration/enabling-admin-page)），但如果您确信您的主密码（以及您的其他用户的主密码，如果有的话）足够强大，也可以选择跳过这一步。

## 备份您的数据 <a href="#backing-up-data" id="backing-up-data"></a>

默认情况下，Vaultwarden 将所有的数据存储在一个名为 `data` 的目录下（与 `vaultwarden` 可执行文件位于同一目录）。这个位置可以通过设置 [DATA\_FOLDER](/other-information/changing-persistent-data-location) 环境变量来更改。如果您使用 SQLite 运行 Vaultwarden（这是最常见的设置），那么 SQL 数据库只是 data 文件夹中的一个文件。如果您使用 MySQL 或 PostgreSQL 运行，则必须单独转储这些数据 -- 这超出了本文的范围，但在网上搜索会发现有许多此类话题的教程。

当使用默认的 SQLite 后端运行时，Vaultwarden 的 `data` 目录具有如下的结构：

```
data
├── attachments          # 每一个附件都作为单独的文件存储在此目录下。
│   └── <uuid>           # （如果未创建过附件，则此 attachments 目录将不存在）
│       └── <random_id>
├── config.json          # 存储管理页面配置；仅在之前已启用管理页面的情况下存在。
├── db.sqlite3           # 主 SQLite 数据库文件。
├── db.sqlite3-shm       # SQLite 共享内存文件（并非始终存在）。
├── db.sqlite3-wal       # SQLite 预写日志文件（并非始终存在）。
├── icon_cache           # 站点图标 (favicon) 缓存在此目录下。
│   ├── <domain>.png
│   ├── example.com.png
│   ├── example.net.png
│   └── example.org.png
├── log                  # 日志文件存储在此目录下。
│   ├── vaultwarden.log
│   └── vaultwarden.log-<date> 
├── rsa_key.der          # ‘rsa_key.*’ 文件用于签署验证令牌。
├── rsa_key.pem
├── rsa_key.pub.der
├── rsa_key.pub.pem
├── sends                # 每一个 Send 的附件都作为单独的文件存储在此目录下。
│   └── <uuid>           # （如果未创建过 Send 附件，则此 sends 目录将不存在）
│       └── <random_id>
├── templates            # 
│   ├── admin            # 自定义后台管理界面文件存储在此目录下。
│   ├── email            # 自定义电子邮件模板文件存储在此目录下。
│   ├── scss             # 自定义 Vaultwarden 的 CSS 样式文件存储在此目录下。
│   │   ├── user.vaultwarden.scss.hbs
│   │   └── vaultwarden.scss.hbs      # 此文件一般不应存在，因为它将覆盖内置的默认值。
│   └── 404.hbs          # 自定义 404 页面。
└── tmp
```

当使用 MySQL 或 PostgreSQL 后端运行时，目录结构是一样的，只是没有 SQLite 文件。您仍然需要备份数据目录中的文件，以及 MySQL 或 PostgreSQL 表的转储。

接下来详细讨论每一组文件。

### SQLite 数据库文件 <a href="#sqlite-database-files" id="sqlite-database-files"></a>

***需要备份。***

SQLite 数据库文件 (`db.sqlite3`) 存储了几乎所有重要的 Vaultwarden 数据/状态（数据库条目、用户/组织/设备元数据等），主要的例外是附件，附件作为单独的文件存储在文件系统中。

您通常应使用 SQLite CLI (`sqlite3`) 中的 `.backup` 命令来备份数据库文件。该命令使用 [Online Backup API](https://www.sqlite.org/backup.html)，它是备份可能正在被使用的数据库文件的[最佳方式](https://www.sqlite.org/howtocorrupt.html#_backup_or_restore_while_a_transaction_is_active)。如果您能确保数据库在备份运行时未被使用，您也可以使用其他方式，例如 `.dump` 命令，或者简单地复制所有 SQLite 数据库文件（包括 `-wal` 文件，如果存在的话）。

假设您的数据文件夹是 `data`（默认），一个基本的备份命令看起来像这样：

```sh
sqlite3 data/db.sqlite3 ".backup '/path/to/backups/db-$(date '+%Y%m%d-%H%M').sqlite3'"
```

您也可以使用 `VACUUM INTO`，这将压缩空闲空间，但需要更多的处理时间：

{% code fullWidth="false" %}

```sh
sqlite3 data/db.sqlite3 "VACUUM INTO '/path/to/backups/db-$(date '+%Y%m%d-%H%M').sqlite3'"
```

{% endcode %}

假设在 2021 年 1 月 1 日中午 12:34（当地时间）运行此命令，这将备份您的 SQLite 数据库文件到 `/path/to/backups/db-20210101-1234.sqlite3`。

您可以通过一个 cron 作业来定期运行这个命令（最好每天至少一次）。如果您通过 Docker 运行，请注意 Docker 映像不包含 sqlite3 二进制文件或 cron 守护程序，因此通常会将它们安装在 Docker 主机本身上并在容器外运行 cron 作业。如果您出于某种原因确实想从容器内运行备份，您可以在[容器启动](/container-image-usage/starting-a-container#customizing-container-startup)期间安装任何必要的包，或者使用您首选的 `vaultwarden/server:<tag>` 镜像作为父镜像创建您自己的自定义 Docker 镜像。

如果您想把备份数据复制到云存储上，[Rclone](https://rclone.org/) 是一个有用的工具，可以与各种云存储系统进行对接。[restic](https://restic.net/) 或 [rustic](https://rustic.cli.rs/) 是另一个不错的选择，特别是如果您有较大的附件，并想避免每次都将其作为备份的一部分的时候。

### `attachments` 目录 <a href="#the-attachments-dir" id="the-attachments-dir"></a>

***需要备份。***

[文件附件](https://help.ppgg.in/your-vault/file-attachments)是唯一不存储在数据库表中的重要数据，主要是因为它们可以是任意大小，而 SQL 数据库一般不是为了有效处理大的 blob 而设计的。如果未创建文件附件，则该目录将不存在。

### `sends` 目录 <a href="#the-sends-dir" id="the-sends-dir"></a>

***可选备份。***

与常规文件附件一样，Send 文件附件也不存储在数据库表中（但 Send 的文本注释存储在数据库中）。

与常规附件不同，Send 附件的目的是短暂的。因此，如果要尽量减小备份的大小，则可以选择不备份此目录。另一方面，如果要在还原后保持现有 Send 功能的正常性对您很重要，那么您应该备份此目录。

如果未创建任何 Send 附件，则该目录将不存在。

### `config.json` 文件 <a href="#the-config-json-file" id="the-config-json-file"></a>

***建议备份。***

如果您使用管理页面来配置你的 Vaultwarden 实例，并且没有使用其他方式来备份您的配置，那么您可能需要备份此文件，这样您以后就不必重新配置您想要的配置了。

请记住，这个文件确实包含了一些可能被认为是敏感的明文数据（管理员令牌、SMTP 凭据等），所以如果您担心别人可能会访问到这些数据（例如，当上传到云存储时），一定要对这些数据进行加密。

### `rsa_key*` 文件 <a href="#the-rsa_key-files" id="the-rsa_key-files"></a>

***建议备份。***

这些文件用于对当前已登录用户的 [JWT](https://en.wikipedia.org/wiki/JSON_Web_Token)（验证令牌）进行签名。删除这些文件将简单地注销所有用户，强制他们重新登录，并且会使已通过邮件发送了的所有已打开的邀请令牌失效。

> \[**译者注**]：[JWT](https://jwt.io/) (JSON Web Tokens)，是一种基于 JSON 的、用于在网络上声明某种主张的令牌 (token)。JWT 通常由三部分组成:：头信息 (header)、消息体 (payload) 和签名 (signature)。

此 `rsa_key.pem`（私钥）文件可能被认为具有一定的敏感性。原则上，它可用于伪造到服务器的密码库登录会话，但在实践中，这样做需要对各种 UUID（例如，从您的数据库副本中获取的）有额外的了解。此外，通过伪造会话获得的任何数据仍然是使用个人和/或组织密钥加密的，因此仍需要暴力破解相关主密码以获取这些密钥。然而，其可以轻松伪造管理面板登录会话（这仅在启用管理面板时才有效）。这不会提供对密码库数据的访问，但会允许一些管理操作，例如删除用户或删除 2FA。

总之，如果您担心其他人可能能够访问私钥（例如，当上传到云存储时），建议对私钥进行加密。

### `icon_cache` 目录 <a href="#the-icon_cache-dir" id="the-icon_cache-dir"></a>

***可选备份。***

图标缓存用于存储[网站图标](https://help.ppgg.in/security/privacy-when-using-website-icons)，这样就不需要从登录项目相关的站点反复获取图标了。这一般不值得去备份，除非您真的想避免重新获取大量的图标缓存。

## 恢复备份数据 <a href="#restoring-backup-data" id="restoring-backup-data"></a>

确保 Vaultwarden 已经停止，然后简单地将 `data` 文件夹中的每个文件或目录替换为它的备份版本即可。

当恢复使用 `.backup` 或 `VACUUM INTO` 创建的备份时，确保首先删除任何已存在的 `db.sqlite3-wal` 文件，因为当 SQLite 试图使用陈旧/不匹配的 WAL 文件恢复 `db.sqlite3` 时，有可能导致数据库损坏。然而，如果您直接拷贝 `db.sqlite3` 文件和其匹配的 `db.sqlite3-wal` 文件的方式来备份数据库，那么您必须将两个文件作为一对来恢复。不需要备份或恢复 `db.sqlite3-shm` 文件。

为了验证您的备份是否能正常工作，定期运行从备份中恢复的过程是个好主意。这样做的时候，请确保移动或保留原始数据的副本，以防备份实际上不能正常工作。

## 示例 <a href="#examples" id="examples"></a>

本部分是第三方备份示例的索引。在使用某个示例之前，您应该彻底审阅此示例并了解其工作方式。

* <https://github.com/ttionya/vaultwarden-backup>
* <https://github.com/shivpatel/bitwarden_rs-local-backup>
* <https://github.com/shivpatel/bitwarden_rs_dropbox_backup>
* <https://gitlab.com/1O/vaultwarden-backup>
* <https://github.com/jjlin/vaultwarden-backup>
* <https://github.com/jmqm/vaultwarden_backup>
* <https://github.com/Guru-25/bitwarden-export>
* <https://github.com/dockers-x/rclone-backup>

## 基于 Docker 的自动备份（示例） <a href="#docker-based-automated-backups-example" id="docker-based-automated-backups-example"></a>

如果您通过 Docker 使用 Vaultwarden 并希望自动备份到远程机器，以下方法可能会有帮助。它停止容器以确保一致性，压缩数据目录，通过 `scp` 转移它，然后重新启动 Vaultwarden。

**备份脚本示例：**

```bash
#!/bin/bash
docker-compose down
datestamp=$(date +%m-%d-%Y)
backup_dir="/home/<user>/vw-backups"
zip -9 -r "${backup_dir}/${datestamp}.zip" /opt/vw-data*
scp -i ~/.ssh/id_rsa "${backup_dir}/${datestamp}.zip" user@<REMOTE_IP>:~/vw-backups/
docker-compose up -d
```

您可以通过 cron 自动化执行此操作：

```bash
0 0 * * * /root/transfer_vaultwarden_logs.sh
```

**清理脚本（可选）**&#x4EE5;仅保留最新的备份：

```bash
#!/bin/bash
cd ~/backups || exit
find . -type f -name '*.zip' ! -mtime -1 -exec rm {} +
```

**请始终测试恢复**。要恢复，请将存档解压缩回 `/opt/vw-data`  替换之前的数据目录。


# 开发


# 1.构建二进制

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Building-binary)
{% endhint %}

{% hint style="info" %}
**注意**：最低支持 Rust 版本 (**MSRV -** Minimum Support Rust Version) 策略是 **N-2**，这意味着如果当前 Rust 版本是 **v1.67**，我们支持使用 **v1.65** 构建，如果是 **v1.69** 稳定版，MSRV 将是 **v1.67**。

这意味着新的稳定版发布时，新的稳定版 Rust 功能将无法使用，而必须等待另外两个版本。

为确保您使用的是稳定版本，我们强烈建议您使用 [rustup](https://rustup.rs/)，这使得安装和更新 Rust 变得非常容易。

低于 MSRV 的任何版本都会生成警告，在强制使用旧版本构建时，您只能靠您自己了。
{% endhint %}

这个页面主要是给那些对 Vaultwarden 开发感兴趣，或者有特殊原因想要构建自己的二进制的用户。

普通用户应该使用从基于 Alpine 的 Docker 镜像中[提取的预构建二进制](/alternative-deployments/pre-built-binaries)文件，[通过 Docker 部署](/container-image-usage/which-container-image-to-use)，或者[寻找第三方包](/alternative-deployments/third-party-packages)。

## 依赖 <a href="#dependencies" id="dependencies"></a>

* `Rust stable`（强烈建议使用 [rustup](https://rustup.rs/)）\
  ⚠️ 最低支持 Rust 版本 (MSRV) 策略是 **N-2**，这意味着如果当前 Rust 版本是 **v1.67**，我们支持使用 **v1.65** 构建。
* 在基于 Debian 的发行版上，请安装以下包：`build-essential`、`git`，这些通用包可确保构建能正常进行
* `OpenSSL`（应在路径中是可用的，请参阅 [openssl crate 文档](https://docs.rs/openssl/latest/openssl/#automatic)）。在基于 Debian 的发行版上，需要安装 `pkg-config` 和 `libssl-dev`
* 对于基于 Debian 发行版上的 SQLite3 后端，需要安装 `libsqlite3-dev`
* 对于基于 Debian 发行版上的 MySQL 后端，需要安装 `libmariadb-dev-compat` 和`libmariadb-dev`
* 对于基于 Debian 发行版上的 PostgreSQL 后端，需要安装 `libpq-dev` 和 `pkg-config`
* `NodeJS`（仅当编译网页密码库时使用。使用[预构建的二进制](https://nodejs.org/en/download/)，通过系统的包管理器安装）或 [nodesource 二进制发行版](https://github.com/nodesource/distributions)。*备注：构建 web-vault 当前要求 NodeJS v16 和 NPM v8.11*

## 运行/编译 <a href="#run-compile" id="run-compile"></a>

### 所有后端 <a href="#all-backends" id="all-backends"></a>

```shell
# 使用所有后端编译并运行
cargo run --features sqlite,mysql,postgresql --release
# 或仅使用所有后端编译（二进制位于 target/release/vaultwarden）
cargo build --features sqlite,mysql,postgresql --release
```

### SQLite 后端 <a href="#sqlite-backend" id="sqlite-backend"></a>

```shell
# 使用 sqlite 后端编译并运行
cargo run --features sqlite --release
# 或仅使用 sqlite 编译（二进制位于 target/release/vaultwarden）
cargo build --features sqlite --release
```

### MySQL 后端 <a href="#mysql-backend" id="mysql-backend"></a>

```shell
# 使用 mysql 后端编译并运行
cargo run --features mysql --release
# 或仅使用 mysql 编译（二进制位于 target/release/vaultwarden）
cargo build --features mysql --release
```

### PostgreSQL 后端 <a href="#postgresql-backend" id="postgresql-backend"></a>

```shell
# 使用 postgresql 后端编译并运行
cargo run --features postgresql --release
# 或仅使用 postgresql 编译（二进制位于 target/release/vaultwarden）
cargo build --features postgresql --release
```

运行后，通过 [http://localhost:8000](http://localhost:8000/) 访问服务器。

{% hint style="warning" %}
~~**注意**：一个先前的~~[~~话题~~](https://github.com/rust-lang/rust/issues/62896)~~表明由于 Rust 编译器和 LLVM 之间存在不兼容，导致编译可能会因段错误而失败。作为解决方法，可以使用较旧版本的编译器，例如 `cargo +nightly-2019-08-27 build --features yourbackend --release`~~
{% endhint %}

### 安装 web-vault <a href="#install-the-web-vault" id="install-the-web-vault"></a>

可以从 [dani-garcia/bw\_web\_builds](https://github.com/dani-garcia/bw_web_builds/releases) 下载网页密码库的编译版本。

{% hint style="info" %}
构建密码库需要约 1.5GB 的 RAM。在具有 1GB 或更小容量的 RaspberryPI 之类的系统上，请[启用交换功能](https://www.tecmint.com/create-a-linux-swap-file/)或在功能更强大的计算机上构建，然后从那里复制目录。仅构建时需要大量内存，而运行带密码库的 Vaultwarden 仅需要约 10MB 的 RAM。
{% endhint %}

如果您希望手动编译它，请遵循如下的步骤：

#### 新的（简单的方式） <a href="#new-easy-way" id="new-easy-way"></a>

克隆 [dani-garcia/bw\_web\_builds](https://github.com/dani-garcia/bw_web_builds) git 库：

```shell
# 克隆库
git clone https://github.com/dani-garcia/bw_web_builds.git bw_web_builds
cd bw_web_builds

# 使用 docker 作为构建环境（最安全的方式并使用正确的构建版本）
# 这将构建 web-vault，并将文件解压缩到 docker_build 目录
make docker-extract

# 改用主机提供的 npm 和节点
make full
```

{% hint style="warning" %}
该脚本要求您输入要构建的 web-vault 的[标签](https://github.com/vaultwarden/vw_web_builds/tags)或[分支](https://github.com/vaultwarden/vw_web_builds/branches)。`main` 分支是 [bitwarden/clients 存储库](https://github.com/bitwarden/clients/)的过期镜像，尚未打补丁，因此与 Vaultwarden 不兼容。
{% endhint %}

#### 旧的（更手动的方式） <a href="#old-very-manual-way" id="old-very-manual-way"></a>

1、克隆 [bitwarden/clients](https://github.com/bitwarden/clients) git 库，并检查最新的发行标签（例如 v2022.6.0）：

```shell
# 克隆库
git clone https://github.com/bitwarden/clients.git web-vault
cd web-vault
# 切换到最新的标签
git -c advice.detachedHead=false checkout web-v2022.6.0
# 或者使用此版本的提交哈希
git -c advice.detachedHead=false checkout bb5f9311a776b94a33bcf0a7bff44cd87a2fcc92
```

2、根据 [apply\_patches script](https://github.com/dani-garcia/bw_web_builds/blob/master/scripts/apply_patches.sh) 中的说明修补[资源](https://github.com/dani-garcia/bw_web_builds/tree/master/resources)中的所有镜像

3、从 [dani-garcia/bw\_web\_builds](https://github.com/dani-garcia/bw_web_builds/tree/master/patches) 下载补丁文件并将其复制到 `web-vault` 文件夹。补丁文件版本（假设网页密码库版本为 `vXXXX.Y.Z`）的选择：

* 如果有版本为 `vXXXX.Y.Z` 的补丁，则使用该版本
* 否则，选择小于 `vXXXX.Y.Z` 的最大的那一个版本

4、应用补丁：

```shell
# 在 web-vault 目录中
git apply vXXXX.Y.Z.patch
```

5、然后，构建密码库：

```shell
npm ci
# 阅读下方的备注（我们将其用于我们的 docker 构建）
# npm 审计修复

# 切换到 web-Vault 目录
cd apps/web
# 构建 web-Vault
npm run dist:oss:selfhost
```

{% hint style="warning" %}
可能会要求您运行 `npm audit fix` 以修复漏洞。这将自动尝试将包升级到较新的版本，该版本可能不兼容并破坏网页密码库功能。如果知道自己在做什么，请自行承担风险。顺便一提，我们会在自己的发行版中使用它！
{% endhint %}

6、最后将 `build` 文件夹的内容复制到目标文件夹中：

* 如果与 `cargo run --release` 一起运行，则目标文件夹为 `vaultwarden/web-vault`。
* 如果直接运行已编译的二进制，则它位于二进制旁，为 `vaultwarden/target/release/web-vault`。

## 配置 <a href="#configuration" id="configuration"></a>

可用的配置选项记录在默认的 `.env.template` 文件中，可以通过在该文件中取消注释所需的选项或设置它们各自的环境变量来对其进行修改。有关可用的主要配置选项，请参见本 wiki 的[配置](/configuration)章节。

{% hint style="danger" %}
环境变量将覆盖 `.env.template` 文件中设置的值。
{% endhint %}

## 有关部署的更多信息 <a href="#more-information-for-deployment" id="more-information-for-deployment"></a>

* [配置反向代理](/reverse-proxy/proxy-examples)
* [通过 systemd 设置自动启动](/alternative-deployments/creating-a-systemd-service)

## 如何为 SQLite 后端重建数据库模式（面向开发人员） <a href="#how-to-recreate-database-schemas-for-the-sqlite-backend-for-developers" id="how-to-recreate-database-schemas-for-the-sqlite-backend-for-developers"></a>

使用 cargo 安装 diesel\_cli：

```shell
cargo install diesel_cli --no-default-features --features sqlite-bundled
```

确保在 `.env` 文件中包含正确的数据库路径。

如果要修改模式，请使用以下命令创建新迁移：

```sh
diesel migration generate <name>
```

修改 `*.sql` 文件，确保在 `down.sql` 文件中还原了所有更改。

应用迁移并保存生成的模式，如下所示：

```sh
diesel migration redo

# 当使用的 diesel-cli > 1.3.0 时，此步骤会自动完成
# diesel print-schema > src/db/sqlite/schema.rs
```

## 如何从 SQLite 后端迁移到 MySQL 后端（面向开发人员） <a href="#how-to-migrate-from-sqlite-backend-to-mysql-backend-for-developers" id="how-to-migrate-from-sqlite-backend-to-mysql-backend-for-developers"></a>

如果要从 SQLite 迁移，请参考[使用 MariaDB (MySQL) 后端](/configuration/database/using-the-mariadb-mysql-backend)。

## 如何从 SQLite 后端迁移到 PostgreSQL 后端（面向开发人员） <a href="#how-to-migrate-from-sqlite-backend-to-postgresql-backend-for-developers" id="how-to-migrate-from-sqlite-backend-to-postgresql-backend-for-developers"></a>

如果要从 SQLite 迁移，请参考[使用 PostgreSQL 后端](/configuration/database/using-the-postgresql-backend)。


# 2.构建您自己的 Docker 镜像

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Building-your-own-docker-image)
{% endhint %}

克隆库，然后从库的根目录运行以使用默认的 SQLite 后端进行构建：

## 推荐的构建方法 <a href="#recommended-way-to-build" id="recommended-way-to-build"></a>

请阅读 docker 目录中提供的文档，了解有关如何在本地构建 Vaultwarden 的最新信息。

可以通过 docker 或 podman 来完成。请参阅：<https://github.com/dani-garcia/vaultwarden/tree/main/docker>。

## 简单的构建方法 <a href="#simple-ways-to-build" id="simple-ways-to-build"></a>

```bash
# 构建支持所有数据库的 docker 镜像：
docker buildx build -t vaultwarden .
```

要使用 SQLite 后端构建，只需运行：

```shell
# 构建 docker 镜像
docker buildx build -t vaultwarden --build-arg DB=sqlite .
```

要使用 MySQL 后端构建，只需运行：

```shell
# 构建 docker 镜像
docker buildx build -t vaultwarden --build-arg DB=mysql .
```

要使用 Postgresql 后端构建，只需运行：

```shell
# 构建 docker 镜像
docker buildx build -t vaultwarden --build-arg DB=postgresql .
```

在 docker-compose.yml 中它看起来像这样：

```yaml
  vaultwarden:
    image: vaultwarden
    build:
      context: vaultwarden
      args:
        DB: postgresql
```


# 3.Git hooks

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Git-hooks)
{% endhint %}

以下提交 hooks 可能对您有所帮助，请自行斟酌使用。

## `pre-commit`

```bash
#!/bin/bash

HAS_ISSUES=0
FIRST_FILE=1

colerr="$(tput setaf 9)"
colok="$(tput setaf 10)"
colreset="$(tput sgr0)"

for file in $(git diff --name-only --staged); do
    FMT_RESULT="$(rustfmt --edition 2021 --check --quiet $file 2>/dev/null || true)"
    if [ "$FMT_RESULT" != "" ]; then
        if [ $FIRST_FILE -eq 0 ]; then
            echo -n ", "
        fi
        echo -n "${colerr}${file}${colreset}"
        HAS_ISSUES=1
        FIRST_FILE=0
    fi
done

if [ $HAS_ISSUES -eq 0 ]; then
    exit 0
fi

echo "."
echo "Your code has formatting issues in the files listed above."
echo "Format your code with: ${colok}cargo fmt --all --${colreset}"
exit 1
```

## `commit-msg`

```bash
#!/bin/bash

HAS_ISSUES=0
MSG_FILE="$1"

colerr="$(tput setaf 9)"
colok="$(tput setaf 10)"
colreset="$(tput sgr0)"

MSG=`cat "$MSG_FILE" |grep -v -E "^$" |grep  -v -E "^#" |head -1`

if [ "`cat "$MSG_FILE" |grep -v -E "^$" |grep  -v -E "^#" |wc -l`" -gt 1 ]; then
	LINE2=`cat "$MSG_FILE" |grep  -v -E "^#" |head -2 |tail -1`
	if [ "$LINE2" != "" ]; then
		HAS_ISSUES=1
	fi
fi

echo $MSG |grep -qE '^(feat|fix|docs|style|refactor|perf|test|build|chore|revert|ci)(\(.+\))?!?: .*[^ ]$'

if [ "$?" != "0" ]; then
	HAS_ISSUES=1
fi

if [ $HAS_ISSUES -eq 0 ]; then
    exit 0
fi

echo "The commit message must follow the Conventional Commits specification:"
echo ""
echo "----------------------------------------------------------------------"
echo "${colok}type${colreset}[(optional scope)]: description"
echo ""
echo "[optional body]"
echo ""
echo "[optional footer(s)]"
echo "----------------------------------------------------------------------"
echo ""
echo "Where ${colok}type${colreset} must be one of:"
echo ""
echo "${colok}feat     ${colreset}| Features                 | A new feature"
echo "${colok}fix      ${colreset}| Bug Fixes                | A bug fix"
echo "${colok}docs     ${colreset}| Documentation            | Documentation only changes"
echo "${colok}style    ${colreset}| Styles                   | Changes that do not affect the meaning of the code (white-space, formatting)"
echo "${colok}refactor ${colreset}| Code Refactoring         | A code change that neither fixes a bug nor adds a feature"
echo "${colok}perf     ${colreset}| Performance Improvements | A code change that improves performance"
echo "${colok}test     ${colreset}| Tests                    | Adding missing tests or correcting existing tests"
echo "${colok}build    ${colreset}| Builds                   | Changes that affect the build system or external dependencies"
echo "${colok}ci       ${colreset}| Continuous Integrations  | Changes to our CI configuration files and scripts"
echo "${colok}chore    ${colreset}| Chores                   | Other changes that don't modify src or test files"
echo "${colok}revert   ${colreset}| Reverts                  | Reverts a previous commit"
echo ""
echo "Read the full specification here: https://www.conventionalcommits.org/en/v1.0.0/"
exit 1
```


# 4.与上游 API 实现的区别

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Differences-from-the-upstream-API-implementation)
{% endhint %}

## 邀请用户加入组织 <a href="#inviting-users-into-organization" id="inviting-users-into-organization"></a>

### 启用 S​​MTP 时 <a href="#with-smtp-enabled" id="with-smtp-enabled"></a>

被邀请的用户将收到一封包含有效期为 5 天的链接的电子邮件。单击链接后，用户可以选择创建一个帐户或登录。新​​用户需要创建一个新帐户；被邀请新加入组织的现有用户只需登录即可。之后，他们将在管理界面中显示为「已接受」，在组织管理员确认后他们将被添加到组织中。

### 未启用 SMTP 时 <a href="#without-smtp-enabled" id="without-smtp-enabled"></a>

被邀请的用户将不会收到邀请电子邮件，而是所有已经注册的用户都将显示在界面中，就像他们已经接受邀请一样。然后，组织管理员只需确认他们成为组织的成员，并授予他们访问共享密码的权限即可。

尚未注册的受邀用户将在组织管理界面中显示为「受邀」，同时创建邀请「记录」，以允许用户注册，即使[用户注册被禁用](/configuration/disable-registration-of-new-users)。（除非[禁用邀请功能](/configuration/disable-invitations)，否则）它们一旦注册将自动变为「已接受」。然后组织管理员可以确认他们以授予他们访问组织的权限。

## 在未加密的连接上运行 <a href="#running-on-unencrypted-connection" id="running-on-unencrypted-connection"></a>

强烈建议通过 HTTPS 运行 Vaultwarden 服务。但是，服务器本身在[支持上](/reverse-proxy/https/enabling-https)并不严格要求进行此类设置。如果您使用信任的连接（比如内部的安全网络、通过 VPN 访问等），或者想要将该服务置于 HTTP 代理之后，从而在代理端进行加密。这些情况下启动服务会更加简单和容易。

通过 HTTP 运行仍然是相当安全的，前提是您使用了非常强大的主密码，并且避免使用易受 MITM 攻击的基于网页密码库的连接，攻击者可能会在该接口中注入 javascript。但是，某些形式的两步登录可能无法在此设置中使用，并且[在此配置下的密码库无法在 Chrome 浏览器中使用](https://github.com/bitwarden/web/issues/254)。


# 替代部署


# 1.预构建二进制

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Pre-built-binaries)
{% endhint %}

Vaultwarden 目前并没有提供独立的二进制文件作为单独的下载，但您可以从基于 Alpine 的官方 Docker 镜像中提取独立的、静态链接的二进制文件。每个 Docker 镜像还包括一个相匹配的网页密码库构建（与平台无关）。

## 在已安装 Docker 情况下提取二进制文件 <a href="#extracting-binaries-with-docker-installed" id="extracting-binaries-with-docker-installed"></a>

假设要为您运行的平台提取二进制文件：

```shell
docker pull docker.io/vaultwarden/server:latest-alpine
docker create --name vw docker.io/vaultwarden/server:latest-alpine
docker cp vw:/vaultwarden .
docker cp vw:/web-vault .
docker rm vw
```

如果您想获取不同平台的二进制文件（例如，您的 x86-64 机器上只安装了 Docker，但您想在 Raspberry Pi 上运行 Vaultwarden）， 将 `--platform` 选项添加到 `docker pull` 命令中：

```shell
docker pull --platform linux/arm/v7 docker.io/vaultwarden/server:latest-alpine
# 按照上面的方法运行其余的命令。
# 注意， `docker create` 命令可能会输出如下类似的信息：
#   WARNING: The requested image's platform (linux/arm/v7) does not match the detected host platform (linux/amd64)
#   and no specific platform was requested
# 这是预料之中的，不用担心。
```

## 在未安装 Docker 情况下提取二进制文件 <a href="#extracting-binaries-without-docker-installed" id="extracting-binaries-without-docker-installed"></a>

如果您不能或不想安装 Docker，您可以使用 [docker-imag-extract](https://github.com/jjlin/docker-image-extract) 脚本来拉取和提取 Docker 镜像。例如，要拉取和提取 x86-64 镜像：

```shell
$ mkdir vm-image
$ cd vm-image
$ wget https://raw.githubusercontent.com/jjlin/docker-image-extract/main/docker-image-extract
$ chmod +x docker-image-extract
$ ./docker-image-extract docker.io/vaultwarden/server:latest-alpine
Getting API token...
Getting image manifest for docker.io/vaultwarden/server:latest-alpine...
Downloading layer 801bfaa63ef2094d770c809815b9e2b9c1194728e5e754ef7bc764030e140cea...
Extracting layer...
Downloading layer c6d331ed95271d8005dea195449ab4ef943017dc97ab134a4426faf441ae4fa6...
Extracting layer...
Downloading layer bfd9ec32f740ca8c86ccde057595d29a31eb093aafd7619fcdd4b956c7bf95e3...
Extracting layer...
Downloading layer e9bfb5d92e4629b1dcb4a13a470c90f51b9edde4e184d8520afc589728b8b675...
Extracting layer...
Downloading layer 5757963c858ce72bc4a1874f4971d326d21d2a844f03063a3c99e312150adf95...
Extracting layer...
Downloading layer f705bf64e4315fea1830cc137d1deda194e825da03bd7822e41ac52457bc83e7...
Extracting layer...
Downloading layer 909b5deb38cbce9f83598918bf7f38b7c2194d385456cf7ef15eff47f8a63108...
Extracting layer...
Downloading layer 8516f4cd818630cd60fa18254b072f8d9c3748bdb56f6e2527dc1c204e8e017c...
Extracting layer...
Image contents extracted into ./output.
$ ls -ld output/{vaultwarden,web-vault}
-rwx------ 1 user user 22054608 Feb  6 21:46 output/vaultwarden
drwx------ 8 user user     4096 Feb  6 21:46 output/web-vault/
```

要拉取并提取其他平台的镜像：

* ARMv6：`./docker-image-extract -p linux/arm/v6 docker.io/vaultwarden/server:latest-alpine`
* ARMv7：`./docker-image-extract -p linux/arm/v7 docker.io/vaultwarden/server:latest-alpine`
* ARMv8 / AArch64：`./docker-image-extract -p linux/arm64 docker.io/vaultwarden/server:latest-alpine`

~~或使用 github actions 从~~[~~此存储库~~](https://github.com/czyt/vaultwarden-binary)~~自动提取二进制文件。~~


# 2.设置为 systemd 服务

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Setup-as-a-systemd-service)
{% endhint %}

这部分的内容要求您已经[编译了 Vaultwarden 二进制](/development/building-binary)。如果您已生成了 docker 镜像，则需要查看[使用 systemd-docker 运行](/other-information/running-with-systemd-docker)。

## 设置 <a href="#setup" id="setup"></a>

要使 Vaultwarden 在系统启动的时候启动并使用 systemd 的其他功能（例如，隔离、日志记录等），则需要一个 `.service` 文件。以下是一个可行的起点：

```systemd
[Unit]
Description=Vaultwarden Server (Rust Edition)
Documentation=https://github.com/dani-garcia/vaultwarden
# 如果您使用 mariadb、mysql 或 postgresql 数据库， 
# 您必须像下面这样添加它们，并去掉前面的 # 以取消注释。
# 这将确保您的数据库服务器在 Vaultwarden 之前启动 ("After")，
# 并且在启动 Vaultwarden 之前成功启动 ("Requires")。

# 仅 sqlite
After=network.target

# MariaDB
# After=network.target mariadb.service
# Requires=mariadb.service

# Mysql
# After=network.target mysqld.service
# Requires=mysqld.service

# PostgreSQL
# After=network.target postgresql.service
# Requires=postgresql.service


[Service]
# 设置 Vaultwarden 用户/群组。此用户/群组对工作目录（见下文）允许有读写权限
User=vaultwarden
Group=vaultwarden
# 使用环境文件进行配置
EnvironmentFile=/etc/vaultwarden.env
# 已编译的二进制的位置
ExecStart=/usr/bin/vaultwarden
# 设置合理的连接和进程限制
LimitNOFILE=1048576
LimitNPROC=64
# 将 bitwarden_rs 与系统的其他部分隔离开
PrivateTmp=true
PrivateDevices=true
ProtectHome=true
ProtectSystem=strict
# 仅允许对以下目录进行写入，并将其设置为工作目录（用户和密码数据存储在这里）
WorkingDirectory=/var/lib/vaultwarden
ReadWritePaths=/var/lib/vaultwarden

[Install]
WantedBy=multi-user.target
```

更改以上所有路径以匹配您的安装（`WorkingDirectory` 与 `ReadWritePaths` 应相同），将此文件命名为 `vaultwarden.service` 并将其放入 `/etc/systemd/system` 中。

如果必须更改现有（而不是像上面那样新建）的 systemd 文件（您安装的软件包提供给您的），可以使用下面的命令来添加更改：

```shell
$ sudo systemctl edit vaultwarden.service
```

请运行以下命令，以让 systemd 知道您的新文件或您所做的任何更改：

```shell
$ sudo systemctl daemon-reload
```

## 用法 <a href="#usage" id="usage"></a>

要启动此「服务」，请运行：

```shell
$ sudo systemctl start vaultwarden.service
```

要启用自动启动，请运行：

```shell
$ sudo systemctl enable vaultwarden.service
```

同理，您可以使用 `stop`、`restart` 和 `disable` 来停止、重启或禁用此服务。

### 更新 Vaultwarden <a href="#updating-bitwarden_rs" id="updating-bitwarden_rs"></a>

编译新版本的 Vaultwarden 之后，您可以复制已编译的（新的）二进制文件并替换现有的（旧的）二进制文件，然后重新启动服务：

```shell
$ sudo systemctl restart vaultwarden.service
```

### 卸载 Vaultwarden <a href="#uninstalling-bitwarden_rs" id="uninstalling-bitwarden_rs"></a>

在执行其他操作之前，应先停止并禁用该服务：

```shell
$ sudo systemctl disable --now vaultwarden.service
```

然后，您可以删除二进制、环境文件、web-vault 文件夹（如果已安装）以及用户数据（如果需要）。请记住，还要删除专门创建的用户、群组和防火墙规则（如果需要）和 systemd 文件。

删除 systemd 文件后，您应该通过下面的方式使 systemd 意识到这一点：

```shell
$ sudo systemctl daemon-reload
```

### 查看日志和状态 <a href="#logging-and-status-view" id="logging-and-status-view"></a>

如果要查看日志输出，请运行：

```bash
$ journalctl -u vaultwarden.service
```

或查看此服务的更简洁的状态，请运行：

```shell
$ systemctl status vaultwarden.service
```

## 故障排除 <a href="#troubleshooting" id="troubleshooting"></a>

### 旧版 systemd 的沙盒选项 <a href="#sandboxing-options-with-older-systemd-versions" id="sandboxing-options-with-older-systemd-versions"></a>

在 RHEL 7（以及 debian 8）中，使用的 systemd 不支持某些隔离选项 ([#445](https://github.com/dani-garcia/bitwarden_rs/issues/445), [#363](https://github.com/dani-garcia/bitwarden_rs/issues/363))。这可能导致出现如下错误：

```
Failed at step NAMESPACE spawning /home/vaultwarden/vaultwarden: Permission denied
```

或者：

```
Failed to parse protect system value
```

要解决这一点，您可以在包含有 `PrivateTmp`、`PrivateDevices`、`ProtectHome`、`ProtectSystem` 和 `ReadWritePaths` 的部分或全部行前面放置 `#` 符号来将其注释掉。尽管将所有这些行注释掉可能会起作用，但不建议这样做，因为这些都是很好的安全措施。要查看您的 systemd 支持哪些选项，请运行以下命令来查看其输出：

```shell
$ systemctl --version
```

检查您的 systemd 版本并与 [systemd/NEWS.md](https://github.com/systemd/systemd/blob/master/NEWS) 进行比较。

编辑 `.service` 文件后，请不要忘记在启动（或重启）服务之前运行如下命令：

```shell
$ sudo systemctl daemon-reload
```

### 服务无法启动 <a href="#service-fails-to-start" id="service-fails-to-start"></a>

systemd journal (`journalctl -eu vaultwarden.service`) 中显示以下错误：

```
Feb 18 05:29:10 staging-bitwarden systemd[1]: Started Vaultwarden Server (Rust Edition).
Feb 18 05:29:10 staging-bitwarden systemd[49506]: vaultwarden.service: Failed to execute command: Resource temporarily unavailable
Feb 18 05:29:10 staging-bitwarden systemd[49506]: vaultwarden.service: Failed at step EXEC spawning /usr/bin/vaultwarden: Resource temporarily unavailable
Feb 18 05:29:10 staging-bitwarden systemd[1]: vaultwarden.service: Main process exited, code=exited, status=203/EXEC
Feb 18 05:29:10 staging-bitwarden systemd[1]: vaultwarden.service: Failed with result 'exit-code'.
```

已知当 Vaultwarden 在容器（LXC 等）内部或本地运行时，会出现这种情况。服务文件中的参数 `LimitNPROC=64` 使服务无法启动。注释掉此参数后，服务可以正常启动。

**注意**：systemd 覆盖文件不起作用，必须注释/删除该行。最简单的方法是通过

```shell
# systemctl edit --full vaultwarden.service
```

然后重新加载守护程序并重新启动。

### 环境变量未被加载 <a href="#environment-variable-its-not-loaded" id="environment-variable-its-not-loaded"></a>

请注意，systemd 不支持 `EnvironmentFile=/etc/vaultwarden.env` 文件中的注释与变量在同一行中（参阅 [#1607](https://github.com/dani-garcia/vaultwarden/issues/1607)）。比如下面这个环境文件示例中，变量 `WEBSOCKET_ENABLED` 将不会被加载：

```systemd
ROCKET_PORT=8080
WEBSOCKET_ENABLED=true # enable websocket
```

如果您想要使用同行注释，请考虑改用 `/var/lib/vaultwarden/.env`（这也将避免启动时提示 [.env 文件缺失](https://github.com/dani-garcia/vaultwarden/wiki/FAQs#why-does-vaultwarden-say-info-no-env-file-found-even-though-i-provided-one)的 INFO 错误）。

## 更多信息 <a href="#more-information" id="more-information"></a>

有关 `.service` 文件的更多信息，请参阅 [systemd.service](https://www.freedesktop.org/software/systemd/man/systemd.service.html) 和 [systemd.exec](https://www.freedesktop.org/software/systemd/man/systemd.exec.html)（用于安全性配置）手册页。


# 3.第三方包

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Third-party-packages)
{% endhint %}

{% hint style="danger" %}
本页面是一个第三方 Vaultwarden 包的索引。

由于这些包不是由 Vaultwarden 维护或控制的，因此它们可能会比官方的发行版本滞后，有时甚至会滞后很多。如果您依赖这些包，您可能需要为新的 Vaultwarden 发行版本[启用监视](https://docs.github.com/en/github/managing-subscriptions-and-notifications-on-github/viewing-your-subscriptions#configuring-your-watch-settings-for-an-individual-repository)功能，并告诉维护者该包未保持最新。
{% endhint %}

***

## 非官方包状态

<table data-full-width="false"><thead><tr><th>Server</th><th>Web-Vault</th></tr></thead><tbody><tr><td><a href="https://repology.org/project/vaultwarden/versions"><img src="https://repology.org/badge/vertical-allrepos/vaultwarden.svg" alt="Packaging status"></a></td><td><a href="https://repology.org/project/vaultwarden-web/versions"><img src="https://repology.org/badge/vertical-allrepos/vaultwarden-web.svg" alt="Packaging status" data-size="original"></a></td></tr></tbody></table>

{% hint style="danger" %}
请注意，最新的 Vaultwarden 版本并不总是与最新的 web-vault 版本前向兼容，因此您可能需要[使用旧版本](https://github.com/dani-garcia/bw_web_builds/releases)的 vaultwarden-web 以确保兼容性。
{% endhint %}

## Arch Linux

可在[官方仓库](https://archlinux.org/packages/community/x86_64/vaultwarden)中获取，同时包含了[网页版密码库](https://archlinux.org/packages/extra/any/vaultwarden-web/)。

## Debian

一个基于 docker 的工具链，可用于构建 debian 包：<https://github.com/greizgh/vaultwarden-debian>。它捆绑了服务器和网页版密码库。

带有纯编译工具链的 Debian 源（无 docker）：<https://github.com/dionysius/vaultwarden-deb>。适用于多种可用发行版和架构的预构建包和 apt 存储库。

## DietPi（高度优化的最小化 Debian 操作系统） <a href="#dietpi-highly-optimised-minimal-debian-os" id="dietpi-highly-optimised-minimal-debian-os"></a>

[DietPi](https://dietpi.com/) 是一个基于 Debian 的轻量级发行版（镜像），适用于各种设备，如 Raspberry Pi、Odroid、NanoPi 等。它提供了一个用于安装包括 Vaultwarden 在内的各种程序的软件脚本。这使用户无需了解安装命令。

要在 DietPi 上安装 Vaultwarden，只需在命令行中键入 `dietpi-software install 183`。有关安装过程和首次访问 DietPi 上的 Vaultwarden 的更多信息，请访问 <https://dietpi.com/docs/software/cloud/#vaultwarden>。

## CentOS 8 / RHEL 8（已弃用）

一个使用 SQLite 的 hacky 包。它还不包含密码库，并且在很明显的地方仍然使用旧的名称。

<https://github.com/alexpdp7/vaultwarden-rpm>

我不再维护这个软件包了，我现在使用 EPEL 9 软件包。

## Fedora (current release, x86\_64)

此 Vaultwarden 包被构建为一个通用二进制文件，其用于 SQLite、MySQL 和 PostgreSQL。它还创建一个 `vaultwarden` 用户/组和一个 systemd 服务。

```sh
dnf config-manager --add-repo https://evermeet.cx/pub/repo/fedora/evermeet.repo
dnf install vaultwarden vaultwarden-webvault
```

## Gentoo

用户可以自定义（是否使用 mysql/sqlite/postgresql 或者 web/cli）使用 USE 标记构建 Vaultwarden。使用 `equery uses vaultwarden` 查看 Vaultwarden 可用的 USE 标记。

```sh
echo "app-admin/vaultwarden <your USE flags here>" >> /etc/portage/package.use/vaultwarden
emerge app-admin/vaultwarden
```

## Nix (OS)

此 Vaultwarden 被同时打包包含 mysql、sqlite、postgresql，以及包含 Vault。还有一个用于声明式配置的 NixOS 模块（请参阅 `services.vaultwarden`）

## Cloudron

[Cloudron](https://cloudron.io/) 是一个帮助您在服务器上运行 Web 应用程序的平台。使用 Cloudron，你可以从 [App Library](https://cloudron.io/store/com.github.bitwardenrs.html) 中轻松地安装自定义域名的 Vaultwarden。该应用包与上游网页密码库捆绑在一起，安装后不需要任何进一步的配置即可开始使用。Cloudron 团队会保持发行版跟踪并提供自动更新。

包代码和话题跟踪器可以在这里找到：[https://git.cloudron.io/cloudron/bitwardenrs-app](https://git.cloudron.io/cloudron/vaultwarden-app)。

## Home Assistant <a href="#home-assistant" id="home-assistant"></a>

[Home Assistant](https://www.home-assistant.io/) 是一个开源的家庭自动化平台。在这里可找到 Vaultwarden 社区插件：<https://github.com/hassio-addons/addon-bitwarden>。

## 用于 Ubuntu 20.04 的构建脚本 <a href="#build-script-for-ubuntu-20-04" id="build-script-for-ubuntu-20-04"></a>

Dinger1986 创建了一个在 Ubuntu 20.04 上从源代码安装 Vaultwarden 的脚本，参阅：<https://github.com/dinger1986/bitwardenrs_install_script>

## FreeBSD

在 [FreeBSD 端口树](https://www.freshports.org/security/vaultwarden/)中可用，并在 FreeBSD pkg 仓库中作为二进制包提供：`pkg install vaultwarden`

`/usr/local/etc/rc.conf.d/vaultwarden.sample` 是示例配置文件。将此文件复制到 `/usr/local/etc/rc.conf.d/vaultwarden` 并编辑其内容以[配置 Vaultwarden](/configuration/configuration-overview#configuration-options)。然后就可以像平常那样（`service(8)` 等）启动 `vaultwarden` 服务了。

## Syncloud

[Syncloud](https://syncloud.org/) 是一个自托管平台，可以帮助没有设备管理经验的人在他们的设备上运行流行的服务。

Bitwarden 可在设备上的应用商店中安装，并且无需配置。

## 用于最常见发行版的 RPM 和 DEB 包 <a href="#rpm-and-deb-packages-for-most-common-distributions" id="rpm-and-deb-packages-for-most-common-distributions"></a>

openSUSE 构建服务项目，支持：

> \[**译者注**]：[什么是 openSUSE 构建服务](https://zh.wikipedia.org/wiki/Open_Build_Service)

| RPM    | 版本                           |
| ------ | ---------------------------- |
| SUSE   | 15.4; 15.5; 15.6; Tumbleweed |
| RHEL   | 8                            |
| CentOS | 7; 8; 8\_Stream; 9\_Stream   |
| Fedora | 36; 37; 38; 39               |

| DEB    | 版本                         |
| ------ | -------------------------- |
| Debian | 10; 11; 12; Testing        |
| Ubuntu | 18.04; 20.04; 22.04; 23.04 |

您可以直接下载包或使用可用的仓库。

[vaultwarden](https://build.opensuse.org/package/show/home:Masgalor:Vaultwarden/vaultwarden)、[vaultwarden-webvault](https://build.opensuse.org/package/show/home:Masgalor:Vaultwarden/vaultwarden-webvault)、[vaultwarden-webvault-dark](https://build.opensuse.org/package/show/home:Masgalor:Vaultwarden/vaultwarden-webvault-dark)

## CentOS 9 / RHEL 9

从 Masgalor 包中为 EL9 构建的包：

<https://rpm.awx.wiki/vaultwarden/>

每晚自动构建新版本。

## Void Linux

在 void-packages 中作为 [vaultwarden](https://github.com/void-linux/void-packages/tree/master/srcpkgs/vaultwarden) 可用：`xbps-install vaultwarden`\
还可以选择安装网页密码库 ([vaultwarden-web](https://github.com/void-linux/void-packages/tree/master/srcpkgs/vaultwarden-web))：`xbps-install vaultwarden-web`

## Snap

Vaultwarden 通过 [Snap Store](https://snapcraft.io/vaultwarden) 以 [snap](https://github.com/DownThePark/snapcraft-vaultwarden) 形式提供。可以使用以下命令从命令行安装 Vaultwarden：

```bash
sudo snap install vaultwarden
```

配置文件位置：`/var/snap/vaultwarden/current/vaultwarden.conf`。


# 4.部署示例

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Deployment-examples)
{% endhint %}

本页面是独立部署示例的索引。如果要添加新的示例，请酌情创建一个新的类别，并保持总体有序。

{% hint style="danger" %}
本页面上的示例由社区贡献。Vaultwarden 维护者不会对这些示例进行主动审核或提供支持。请自行评估并使用，风险自负。
{% endhint %}

## 自托管 <a href="#self-hosted" id="self-hosted"></a>

本节介绍了在您**自己的硬件**或主要**由您自己管理**的任何基础设施上托管 Vaultwarden 的不同选项。

### 使用 Ansible 进行高可用性 Vaultwarden 部署 <a href="#highly-available-vaultwarden-deployment-with-ansible" id="highly-available-vaultwarden-deployment-with-ansible"></a>

* <https://github.com/InfraArtists/vaultwarden-ansible>

此 Ansible 部署使用以下组件设置高可用的 Vaultwarden 集群：

**主要特点：**

* **Nginx**：处理 SSL 卸载和负载平衡，以获得最佳性能和安全性。
* **Certbot**：自动生成和管理 SSL 证书以实现安全通信。
* **Vaultwarden**：作为密码管理的主要后端。
* **Keepalived**：提供虚拟IP和冗余以实现高可用性。
* **PostgreSQL**：使用外部数据库来存储数据。
* **Docker** 和 **Docker Compose**：使用 docker compose 部署所有服务。

### Ansible

* <https://github.com/guerzon/ansible-role-vaultwarden>

目前支持 EL8 和 EL9 发行版的 Ansible 角色。在积极开发和支持下，已经有一个可用的 MVP 版本。

### Raspberry Pi

* <https://github.com/martient/vaultwarden-ansible>

Raspberry Pi 上的 Vaultwarden Ansible 部署。要从以前的配置迁移，请按照页面上链接的指南进行操作。

* <https://dietpi.com/>

[DietPi](https://dietpi.com/) 是一个轻量级的基于 Debian 的发行版（镜像），适用于各种设备，例如 Raspberry Pi、Odroid、NanoPi 等。它提供了一个软件脚本，用于安装包括 Vaultwarden 在内的各种程序。这样可以让用户免去对安装命令的苦恼。

要在 DietPi 上安装 Vaultwarden，只需在命令行中键入 `dietpi-software install 183` 即可。有关在 DietPi 上的安装步骤和首次访问 Vaultwarden 的更多信息，请访问 <https://dietpi.com/docs/software/cloud/#vaultwarden>

* <https://mijo.remotenode.io/posts/tailscale-caddy-docker/>

使用 Tailscale 和 Caddy 确保安全访问 Vaultwarden 的演练指南。所有服务均使用 Docker Compose 进行容器化管理，并托管在 Raspberry Pi 上。

* <https://github.com/Alphan-Aksoyoglu/vaultwarden-rpi>

基于 docker-compose 的、模块化的、自托管的 Vaultwarden 部署。

选项：

* 仅 LAN，或 LAN + Tailscale（通过 VPN 从任何地方访问）
* 您的域名 (Cloudflare) 或 DuckDNS 域名
* 可选的不依赖第三方容器的备份服务
* 可选的 UFW 和 IPTABLES 强化

配有方便的安装程序：

* 只需运行 `install.sh --init` 和 `install.sh --install`

还有一个广泛的自述文件。

### 共享主机 <a href="#shared-hosting" id="shared-hosting"></a>

* <https://github.com/jjlin/vaultwarden-shared-hosting>

在 [DreamHost](https://www.dreamhost.com/) 上运行 Vaultwarden 的配置示例，但应该也适用于许多其他共享主机服务。

* <https://lab.uberspace.de/guide_vaultwarden.html?highlight=bitwarden>

如何从源代码安装以及如何在 [Uberspace](https://uberspace.de/en/) 共享托管服务提供商上运行的说明。

### NixOS (by tklitschi)

这里是一个针对 NixOS 上的 Vaultwarden 配置的示例。它不是很复杂，有您想使用的数据库类型的后端选项、用于系统服务专用备份的备份目录、启用它的选项以及配置选项。对于配置选项，你只需[从 .env 模板](https://github.com/dani-garcia/bitwarden_rs/blob/1.13.1/.env.template)传递 .env 变量到 nix 语法中即可。密码 (SMTP\_PASSWORD,... ) 存储在 /nix/store 之外的另一个 .env 文件中，并被 [services.vaultwarden.environmentFile](https://search.nixos.org/options?channel=21.11\&show=services.vaultwarden.environmentFile\&from=0\&size=50\&sort=relevance\&type=packages\&query=vaultw) 包含。请参阅[代理示例](/reverse-proxy/proxy-examples)以了解 nixos-nginx 的配置示例。

<details>

<summary>配置示例</summary>

```nginx
{ pkgs, ... }:
{
  services.bitwarden_rs = {
    enable = true;
    backupDir = "/mnt/bitwarden";
    config = {
      WEB_VAULT_FOLDER = "${pkgs.bitwarden_rs-vault}/share/bitwarden_rs/vault";
      WEB_VAULT_ENABLED = true;
      LOG_FILE = "/var/log/bitwarden";
      WEBSOCKET_ENABLED = true;
      WEBSOCKET_ADDRESS = "0.0.0.0";
      WEBSOCKET_PORT = 3012;
      SIGNUPS_VERIFY = true;
#     ADMIN_TOKEN = (import /etc/nixos/secret/bitwarden.nix).ADMIN_TOKEN;
      DOMAIN = "https://exmaple.com";
#     YUBICO_CLIENT_ID = (import /etc/nixos/secret/bitwarden.nix).YUBICO_CLIENT_ID;
#     YUBICO_SECRET_KEY = (import /etc/nixos/secret/bitwarden.nix).YUBICO_SECRET_KEY;
      YUBICO_SERVER = "https://api.yubico.com/wsapi/2.0/verify";
      SMTP_HOST = "mx.example.com";
      SMTP_FROM = "bitwarden@example.com";
      SMTP_FROM_NAME = "Bitwarden_RS";
      SMTP_PORT = 587;
      SMTP_SECURITY = starttls;
#     SMTP_USERNAME = (import /etc/nixos/secret/bitwarden.nix).SMTP_USERNAME;
#     SMTP_PASSWORD = (import /etc/nixos/secret/bitwarden.nix).SMTP_PASSWORD;
      SMTP_TIMEOUT = 15;
      ROCKET_PORT = 8812;
    };
    environmentFile = "/etc/nixos/secret/bitwarden.env";
  };
}
```

如果您有任何关于这部分的问题，请随时联系我。我在 matrix 的 @litschi:litschi.xyz 、以及 IRC（hackint 和 freenode）的 litschi，或简单地在 matrix.org 的 Vaultwarden 频道中询咨询我。

</details>

### QNAP NAS (ARM 和 x86) <a href="#qnap-nas-arm-and-x-86" id="qnap-nas-arm-and-x-86"></a>

* <https://github.com/umireon/vaultwarden-qnap>

您可以使用 Let's Encrypt 将 Vaultwarden 安装到您的安全网络附加存储 (NAS) 中。但由于 QNAP 内置的 HTTP(S) 服务器，您不能在标准的 HTTP(S) 端口 (80/443) 上发布 Vaultwarden。

### Kubernetes Manifests

* <https://github.com/icicimov/kubernetes-bitwarden_rs>

在 Kubernetes 上以 [nginx-ingress-controller](https://github.com/kubernetes/ingress-nginx) 和 AWS [ELBv1](https://aws.amazon.com/elasticloadbalancing/features/#Details_for_Elastic_Load_Balancing_Products) 作为后端设置一个功能齐全且安全的 Vaultwarden 应用程序。它提供的不仅仅是简单的部署，还可以根据您的需要和设置使用全部或部分功能。

### Helm charts

* <https://github.com/Skeen/helm-bitwarden_rs>

在 Kubernetes 上以您选择的 nginx 控制器作为后端设置一个功能齐全且安全的 Vaultwarden 应用程序。它运行良好，并已使用 [microk8s](https://microk8s.io/) 设置进行了测试。而且支持通过 [cert-manager](https://github.com/jetstack/cert-manager) 生成 SSL 证书。

* <https://github.com/guerzon/vaultwarden>

使用 [Helm](https://helm.sh/zh/docs/) 将 Vaultwarden 部署到 Kubernetes 集群。它支持重要的自定义，例如提供图像标签和自定义注册表值、使用​​外部 MySQL 或 PostgreSQL 数据库、使用入口控制器（如 [nginx-ingress](https://kubernetes.github.io/ingress-nginx/deploy/) 和 [AWS LB 入口控制器](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/deploy/installation/)）、使用服务账户、配置 SMTP，以及配置存储选项。

此 Helm chart 目前正在积极开发和支持中。

## PaaS 托管 <a href="#paas-hosting" id="paas-hosting"></a>

本节介绍了**在云端**或使用平台即服务 (PaaS) 提供商托管 Vaultwarden 的不同选项。

> \[**译者注**]：[PaaS](https://cloud.google.com/learn/what-is-paas?hl=zh-cn)：Platform as a Service，平台即服务。PaaS 是一种云计算服务模型，提供灵活的可扩缩云平台来开发、部署、运行和管理应用。PaaS 为开发者提供了开发应用所需的所有功能，而不必费心考虑操作系统和开发工具更新或者硬件维护。整个 PaaS 环境（或平台）而是由第三方服务提供商通过云提供。

### AWS EKS

* <https://medium.com/@sreafterhours/deploy-vaultwarden-to-amazon-eks-using-terraform-terragrunt-and-helm-69a0a7396625>

使用 Terraform 和 Infrastructure-as-Code 在亚马逊 EKS 中部署 Vaultwarden。

### Zenith

[![Deploy with Zenith](https://cdn.zenith.hosting/buttons/deploy-with-zenith.svg)](https://zenith.hosting/host/vaultwarden?ref=gh)

一键在 Zenith 上部署 Vaultwarden。

### Sealos

[![Deploy on Sealos](https://raw.githubusercontent.com/labring-actions/templates/main/Deploy-on-Sealos.svg)](https://template.sealos.io/deploy?templateName=vaultwarden)

使用完全免费的插件在 Sealos 上安装 Vaultwarden。安装大约需要 1 分钟。优雅地处理高并发并提供动态可扩展性。

### Google Cloud

* <https://github.com/dadatuputi/bitwarden_gcloud>

针对 Google Cloud 的「永远免费」的 f1-micro 计算实例进行了优化的 Vaultwarden 安装。

* [~~https://medium.com/@sreafterhours/terraform-helm-external-dns-cert-manager-nginx-and-vaultwarden-on-gke-5080f3b4909f~~](https://medium.com/@sreafterhours/terraform-helm-external-dns-cert-manager-nginx-and-vaultwarden-on-gke-5080f3b4909f)

~~针对 Google Kubernetes Engine 的详细的 Vaultwarden 安装，包括基础设施和集群配置。~~

### Heroku

* <https://github.com/davidjameshowell/vaultwarden_heroku>

使用完全免费的插件在 Heroku 上安装 Vaultwarden。安装大约需要 15 分钟。

### Fly.io

* <https://github.com/nosovk/vaultwarden-fly-io/blob/main/fly.toml>

使用 SQLite 数据库安装 Vaultwarden。但是您需要为数据库创建卷：`flyctl volumes create vaultwarden_data -a [your app name] -s 1`

* <https://github.com/arthurgeek/vaultwarden-fly-template>

在 Fly.io 上部署 Vaultwarden 的模板，具有 websockets 支持（带有 caddy）和使用 Restic 的 sqlite 每小时备份功能。

### Dokku

这是一个脚本，使用上传到 DockerHub 的 docker 镜像自动设置 Vaultwarden，并创建一个 Dokku 应用程序。该脚本假设您已经设置了一个全局域名（即存在 `/home/dokku/VHOST` 文件）。遵循提示进行设置。

```sh
#!/usr/bin/env bash

set -euo pipefail

APPNAME=""

read -rp "Enter the name of the app: " APPNAME

# 检查应用名称是否为空
if [ -z "$APPNAME" ]; then
    echo "App name empty. Using default name: vaultwarden"
    APPNAME="vaultwarden"
fi

# 检查 dokku 插件是否存在
if ! dokku plugin:list | grep letsencrypt; then
    sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git
fi
# 检查是否设置了用于 letsencrypt 的全局电子邮件
if ! dokku config:get --global DOKKU_LETSENCRYPT_EMAIL; then
    read -rp "Enter email address for letsencrypt: " EMAIL
    dokku config:set --global DOKKU_LETSENCRYPT_EMAIL="$EMAIL"
fi

# 拉取最新版的镜像
IMAGE_NAME="vaultwarden/server"
docker pull $IMAGE_NAME
image_sha="$(docker inspect --format='{{index .RepoDigests 0}}' $IMAGE_NAME)"
echo "Calculated image sha: $image_sha"
dokku apps:create "$APPNAME"
dokku storage:ensure-directory "$APPNAME"
dokku storage:mount "$APPNAME" /var/lib/dokku/data/storage/"$APPNAME":/data
dokku domains:add $APPNAME $APPNAME."$(cat /home/dokku/VHOST)"
dokku letsencrypt:enable "$APPNAME"
dokku proxy:ports-add "$APPNAME" http:80:80
dokku proxy:ports-add "$APPNAME" https:443:80
dokku proxy:ports-remove "$APPNAME" http:80:5000
dokku proxy:ports-remove "$APPNAME" https:443:5000
dokku git:from-image "$APPNAME" "$image_sha"
```

将上面的脚本复制到您的 Dokku 主机然后运行它。脚本运行成功后，即可通过 `https://$APPNAME.dokku.me` 访问网页密码库。

要更新您的 Vaultwarden 服务器，请运行以下命令（记得将 `$APP_NAME` 替换为您的应用程序的名称）：

```batch
docker rmi -f vaultwarden/server
docker pull vaultwarden/server:latest
image_sha="$(docker inspect --format='{{index .RepoDigests 0}}' vaultwarden/server)"
dokku git:from-image $APP_NAME $image_sha
```

### Azure

* <https://github.com/adamhnat/vaultwarden-azure>

针对具有数据文件共享的 Azure 容器应用程序服务进行了优化的 Vaultwarden 安装。

### Digital Ocean

* <https://github.com/HarrisonLeach1/vaultwarden_digitalocean>

Digital Ocean 最便宜的 Droplet 的 Vaultwarden 安装。通过 Terraform 设置资源。

***

{% hint style="info" %}
2023-09-25：我们不认可这种托管 Vaultwarden 的方式，因此移除了代管式托管部分。
{% endhint %}

## ~~代管式托管~~ <a href="#managed-hosting" id="managed-hosting"></a>

~~最后，本节展示了代管式 Vaultwarden 托管的不同提供商和选项，如果您根本不想自己去关心配置和管理的话。~~

### ~~Server.Camp~~

* [~~https://server.camp/product/vaultwarden~~](https://server.camp/product/vaultwarden)

~~为开发人员、初创公司和中小型企业提供的基于欧盟且符合 GDPR 的 Vaultwarden 托管。15% 的收入将捐赠给开源社区。~~


# 5.Kubernetes 部署

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Kubernetes-deployment)
{% endhint %}

在 Kubernetes 上部署有两种方式：

* 本地部署
* 通过 [Helm](https://helm.sh/) 部署

## 本地部署： <a href="#natively" id="natively"></a>

请查看 [kubernetes-bitwarden\_rs](https://github.com/icicimov/kubernetes-bitwarden_rs) 存储库，以获取在 Kubernetes 中部署的示例。

它将在 Kubernetes 中的 [nginx-ingress-controller](https://github.com/kubernetes/ingress-nginx) 和 AWS [ELBv1](https://aws.amazon.com/elasticloadbalancing/features/#Details_for_Elastic_Load_Balancing_Products) 后面设置一个功能完整且安全的 `vaultwarden` 应用程序。它提供的不仅仅是简单的部署，您可以根据自身需求和环境，选择使用全部或部分配置文件。

## 通过 Helm 部署： <a href="#via-helm" id="via-helm"></a>

请查看 [guerzon/vaultwarden](https://github.com/guerzon/vaultwarden/tree/main/charts/vaultwarden) 存储库，以获取在 Kubernetes 中部署的示例。

另一个具有同等甚至更高灵活性的选项是：<https://github.com/gissilabs/charts/tree/master/vaultwarden>


# 6.禁用管理令牌

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Disable-admin-token)
{% endhint %}

{% hint style="info" %}
任何人都将可以访问管理页面。
{% endhint %}

如果您有其他方式对 `/admin` 页面进行身份验证，则可以将 `DISABLE_ADMIN_TOKEN` 变量设置为 `true`。这将禁用内置的 `ADMIN_TOKEN` 身份验证功能，同时启用管理面板。可以访问此 URL 的任何人都可以访问管理面板。您需要采取额外的步骤（包括外部和本地）来对它提供保护。

```shell
docker run -d --name vaultwarden \
  -e DISABLE_ADMIN_TOKEN=true \
  -v /vw-data/:/data/ \
  -p 80:80 \
  vaultwarden/server:latest
```


# 其他


# 1.从 Keepass 或 KeepassX 导入数据

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Importing-data-from-Keepass-or-KeepassX)
{% endhint %}

## 介绍 <a href="#introduction" id="introduction"></a>

Bitwarden 可以导入来自许多[应用程序](https://help.ppgg.in/import-export/import-data-to-your-vault)的数据。

当前的导入器让您只需选择导入文件的格式即可，而不用去管它是如何将数据转换为 Bitwarden 的。

## Keepass 和 KeepassX 有不同的导入结果 <a href="#different-import-results-for-keepass-and-keepassx" id="different-import-results-for-keepass-and-keepassx"></a>

从 Keepass 或 KeepassX 导入会产生完全不同的结果，尽管它们使用相同的 Keepass 2.x kbdx 数据库：

* Keepass CSV 文件是在**组织**级别（每个条目的所有者）导入，Keepass 的群组将转换为 Bitwarden 的**集合**。
* Keepass XML 文件是在**用户**级别（每个条目的所有者）导入，Keepass 的群组将转换为 Bitwarden 的**文件夹**，其主文件夹为 Keepass 数据库的名称。

做导入操作时，Bitwarden 自己会自动做很多工作：比如将「集合」更改为「文件夹」以及转换所有条目的所有权等。因此，根据您的需要选择合适的方式！

一种替代方法是使用 [KP2BW - Python based KeePass to Bitwarden converter](https://github.com/kjanat/kp2bw) 执行导入，该转换器支持更多的 Keepass 功能，如文件附件，引用等等！

## 示例 <a href="#example" id="example"></a>

### 名称为「MyVault」的 Keepass 数据库 <a href="#keepass-database-with-name-myvault" id="keepass-database-with-name-myvault"></a>

**群组为:**

* Group1
  * Group1Sub1
  * Group2Sub2
* Group2

### 通过 Keepass (CSV) 导入后 <a href="#import-via-keepass-csv" id="import-via-keepass-csv"></a>

**所有者** = 组织

**集合为:**

* Group1
  * Group1Sub1
  * Group2Sub2
* Group2

### 通过 Keepass (XML) 导入后 <a href="#import-via-keepass-xml" id="import-via-keepass-xml"></a>

**所有者** = 已登录的用户

**文件夹为:**

* MyVault
  * Group1
    * Group1Sub1
    * Group2Sub2
  * Group2

**注意 1**：您必须手动创建主文件夹，否则导入后会将 MyVault/Group1 和 MyVault/Group2 显示为文件夹（因为没有上级 MyVault 文件夹）。创建 MyVault 文件夹后才会在 MMI 中显示子文件夹。

> \[**译者注**]：Bitwarden 文件夹规则：[官方 Help](https://help.bitwarden.com/article/folders/)，[中文版](https://help.ppgg.in/your-vault/folders)。

**注意 2**：在导入 Bitwarden 之前，您可以编辑文件夹以删除主文件夹「MyVault」，或编辑导出的 CSV 文件并删除每个条目中的「MyVault/」字符串。


# 2.更改持久性数据位置

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Changing-persistent-data-location)
{% endhint %}

## /data 前缀 <a href="#data-prefix" id="data-prefix"></a>

默认情况下，所有持久性数据都保存在 `/data` 下，您可以通过设置 `DATA_FOLDER` 环境变量来覆盖此路径：

```shell
docker run -d --name vaultwarden \
  -e DATA_FOLDER=/persistent \
  -v /vw-data/:/persistent/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，您需要相应地调整您的卷挂载。

## 数据库名称和位置 <a href="#database-name-and-location" id="database-name-and-location"></a>

默认值为 `$DATA_FOLDER/db.sqlite3`，您可以使用 `DATABASE_URL` 变量专门为数据库更改路径：

```shell
docker run -d --name vaultwarden \
  -e DATABASE_URL=/database/vaultwarden.sqlite3 \
  -v /vw-data/:/data/ \
  -v /vw-database/:/database/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，如果数据库和其他持久性数据在不同的位置，记得为他们挂载卷。

## 附件位置 <a href="#attachments-location" id="attachments-location"></a>

默认值为 `$DATA_FOLDER/attachments`，您可以使用 `ATTACHMENTS_FOLDER` 变量更改路径：

```shell
docker run -d --name vaultwarden \
  -e ATTACHMENTS_FOLDER=/attachments \
  -v /vw-data/:/data/ \
  -v /vw-attachments/:/attachments/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，如果附件和其他持久性数据在不同的位置，记得为他们挂载卷。

## 图标缓存位置 <a href="#icons-cache" id="icons-cache"></a>

默认值为 `$DATA_FOLDER/icon_cache`，您可以使用 `ICON_CACHE_FOLDER` 变量更改路径：

```shell
docker run -d --name vaultwarden \
  -e ICON_CACHE_FOLDER=/icon_cache \
  -v /vw-data/:/data/ \
  -v /icon_cache/ \
  -p 80:80 \
  vaultwarden/server:latest
```

请注意，在上面的示例中，我们没有在本地挂载该卷，这意味着在升级过程中将不会保留该卷，除非您用 `--volumes-from` 使用中间数据容器。这会影响性能，因为 Vaultwarden 在重新启动时必须重新下载图标。但由于图标不会被自动清除，因此可避免在缓存中保留过时的图标。


# 3.从 LDAP 同步用户

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Syncing-users-from-LDAP)
{% endhint %}

LDAP 集成使用一个小型服务来执行，该小型服务用于查询 LDAP 并邀请用户加入您的 Vaultwarden 实例。该服务的名称被非正式地命名为 [bitwarden\_rs\_ldap](https://github.com/ViViDboarder/bitwarden_rs_ldap)。

由于 Vaultwarden 的零信任架构，此服务不提供密码同步，只提供对新 LDAP 成员的邀请。

它尚未以二进制形式分发，但是有可用的 Docker 镜像 [vividboarder/vaultwarden\_ldap](https://hub.docker.com/r/vividboarder/vaultwarden_ldap)。

部署之前，您必须[启用 Vaultwarden 管理页面](/configuration/enabling-admin-page)，这将启用 API，以便 LDAP 同步服务使用 API 来邀请用户。配置 LDAP 同步服务时，将使用您设置的 `ADMIN_TOKEN`。您还必须确保**未禁用**邀请功能。请再次检查环境变量 `INVITATIONS_ALLOWED` 未被设置为 `false`。

另外也建议在您的 Vaultwarden 实例中[启用电子邮件发送功能](/configuration/smtp-configuration)，以便通知您的用户注册他们的账户。如果不这样做，虽然他们也可以使用他们的 LDAP 电子邮箱地址注册，但是您必须自己通知他们。

完成这些步骤后，您就可以配置和部署 LDAP 同步服务了。最新的说明文档可在它的[自述文件](https://github.com/ViViDboarder/vaultwarden_ldap)中找到，此文档也涉及了使用 Vaultwarden 实例、LDAP 实例以及您用于查找用户的 LDAP 查询等连接信息来创建 `config.toml` 文件的说明。


# 4.Cloudflare DNS Caddy 2.x

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Caddy-2.x-with-Cloudflare-DNS)
{% endhint %}

Dockerfile（Caddy 构建器）：

```docker
FROM caddy:builder AS builder
RUN xcaddy build --with github.com/caddy-dns/cloudflare

FROM caddy:latest
COPY --from=builder /usr/bin/caddy /usr/bin/caddy
```

构建命令：

```shell
docker build -t [YOUR-NAME]/caddycfdns .
```

Caddyfile（作为反向代理）：

```nginx
[YOUR-DOMAIN] {

  tls {
        dns cloudflare [API-KEY]
  }

#  encode gzip

#  header / {
#       # 启用 HTTP Strict Transport Security (HSTS)
#       Strict-Transport-Security "max-age=31536000;"
#       # 启用 cross-site filter (XSS) 并告诉浏览器阻止检测到的攻击
#       X-XSS-Protection "0"
#       # 禁止在框架内呈现网站 (clickjacking protection)
#       X-Frame-Options "DENY"
#       # 阻止搜索引擎编制索引（可选）
#       X-Robots-Tag "noindex, nofollow"
#       # 禁止嗅探 X-Content-Type-Options
#       X-Content-Type-Options "nosniff"
#       # 服务器名称移除
#       -Server
#       # 移除 X-Powered-By 应该不会引起问题，但最好移除 opsec
#       -X-Powered-By
#       # 移除 Last-Modified 因为 etag 具有相同的效果
#       -Last-Modified
#   }
#  # 代理到 Rocket
#  reverse_proxy vaultwarden:80 {
#       # 将真正的远程 IP 发送给 Rocket，以便 vaultwarden 可以将其
#       # 放入日志，以便 fail2ban 可以禁止正确的 IP。
#       header_up X-Real-IP {remote_host}
#  }

#  其余配置，请参阅 ”代理示例“ 部分
}
```

docker-compose.yml：

```yaml
version: '3'

services:
  vaultwarden:
    image: vaultwarden/server
    restart: always
    volumes:
      - $PWD/vw-data:/data
    environment:
      SIGNUPS_ALLOWED: 'false'   # 设置为 false 以禁用注册
      DOMAIN: 'https://[DOMAIN]'
      SMTP_HOST: '[MAIL-SERVER]'
      SMTP_FROM: '[E-MAIL]'
      SMTP_PORT: '587'
      SMTP_SECURITY: 'starttls'
      SMTP_USERNAME: '[E-MAIL]'
      SMTP_PASSWORD: '[SMTP-PASS]'
#      ADMIN_TOKEN: '[RAND. GENERATE]'
#      YUBICO_CLIENT_ID: '[OPTIONAL]'
#      YUBICO_SECRET_KEY: '[OPTIONAL]'

  caddy:
    image: [YOUR-NAME]/caddycfdns
    restart: always
    volumes:
      - $PWD/Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
      - caddy_log:/logs
    ports:
      - [PRIVATE-IP]:443:443
    environment:
      ACME_AGREE: 'true'
      CLOUDFLARE_EMAIL: '[YOUR-EMAIL]'
      CLOUDFLARE_API_TOKEN: '[YOUR-TOKEN]'
      DOMAIN: '[DOMAIN]'

volumes:
  caddy_data:
  caddy_config:
  caddy_log:
```


# 5.转储示例

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Logrotate-example)
{% endhint %}

随着时间增长，Vaultwarden 日志文件的大小可能会增长到很大。使用 logrotate，我们可以定期转储日志。

```shell
sudo nano /etc/logrotate.d/vaultwarden
```

```systemd
/var/log/vaultwarden/*.log {
    # 以 vaultwarden 用户和群组的身份执行转储
    su vaultwarden vaultwarden
    # 每天转储
    daily
    # 当大小大于 5M 时转储
    size 5M
    # 压缩旧的日志文件
    compress
    # 在删除或邮寄到 mail 指令中指定的地址之前，保留 4 个转储的日志文件
    rotate 4
    # 把当前日志备份并截断
    copytruncate
    # 如果日志文件不存在，继续下一个操作
    missingok
    # 如果日志文件为空则不进行转储
    notifempty
    # 在转储的日志文件中添加数字格式的日期
    dateext
    # dateext 的日期格式
    dateformat -%Y-%m-%d-%s
}
```

无需手动解压缩而查看压缩的日志文件：

```sh
zcat logfile.gz
zless logfile.gz
zgrep -i keyword_search logfile.gz
```


# \*使用非 root 用户运行 docker 容器

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Running-docker-container-with-non-root-user)
{% endhint %}

默认情况下，`vaultwarden/server` 使用 root 用户在容器内运行服务。如果您想以非 root 用户身份运行容器，则需要进行一些设置：

1、确保您在容器内挂载的目录可供用户写入。例如，如果您决定以 `nobody` 身份运行，那么此目录就必须是 id 为 `65534` 的用户可以写入的。有关在容器内指定用户的其他方法，请参阅 [docker 文档](https://docs.docker.com/engine/reference/run/#user)。这里的示例中，我们将使用 `nobody`。

```bash
# 在主机上创建目录，将其更改为您的首选路径
sudo mkdir /vw-data

# 使用用户 ID 设置所有者。
# 请注意，所有权必须与容器内的 /etc/passwd 中的用户一致，而不是主机上的用户
sudo chown 65534 /vw-data

# 授予所有者对该文件夹的全部权限
sudo chmod u+rwx /vw-data
```

2、使用合适的参数启动容器。定义用户并确保启动时端口设置为 `1024` 或更高。

```bash
docker run -d \
  --name vaultwarden \
  --user nobody \
  -e ROCKET_PORT=1024 \
  -v /vw-data/:/data/ \
  -p 80:1024 \
  vaultwarden/server:latest
```

请注意，端口映射 (`-p 80:1024`) 反映了 `ROCKET_PORT` 设置。

另一种方法可能是 `CAP_NET_BIND_SERVICE`，它允许以非 root 用户身份绑定到低于 `1024` 的端口。

```batch
cap_add:
  - CAP_NET_BIND_SERVICE
user: nobody
```


# \*使私有 CA 和自签名证书兼容 Chrome

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Private-CA-and-self-signed-certs-that-work-with-Chrome)
{% endhint %}

{% hint style="danger" %}
⚠️ 💩 ⚠️此方法仅用于测试和开发。绝大多数用户不应该使用这种方法，因为它需要在您的每台设备上加载证书，这既容易出错，又需要后期的维护。相反，应把精力集中在通过 [Let's Encrypt](https://letsencrypt.org/getting-started/) 获取的真实证书上。如果您的 Vaultwarden 实例不处于公共互联网中，此方法甚至也可以工作（[示例](/reverse-proxy/https/running-a-private-vaultwarden-instance-with-lets-encrypt-certs)）。⚠️ 💩 ⚠️
{% endhint %}

{% hint style="danger" %}
☠️ ☠️ ☠️ **此方法不受支持。请不要开启 GitHub 话题，也不要在讨论区发帖询问如何让这个方法能正常工作。**☠️ ☠️ ☠️
{% endhint %}

***

为了使 Vaultwarden 能够正常地使用自签名证书，Chrome 要求该证书在证书的备用名称字段中包含域名。

创建 CA 密钥（您自己的小型本地证书颁发机构）：

```sh
openssl genpkey -algorithm RSA -aes128 -out private-ca.key -outform PEM -pkeyopt rsa_keygen_bits:2048
```

> 您也可以使用较旧的 `-des3` 来代替 `-aes128`。

创建 CA 证书：

```sh
openssl req -x509 -new -nodes -sha256 -days 3650 -key private-ca.key -out self-signed-ca-cert.crt
```

> `-nodes` 参数用于阻止在测试/安全环境中为私钥（密钥对）设置密码短语，否则每次启动/重启服务器时都必须输入密码短语。

创建一个 Vaultwarden 密钥：

```sh
openssl genpkey -algorithm RSA -out vaultwarden.key -outform PEM -pkeyopt rsa_keygen_bits:2048
```

创建 Vaultwarden 证书请求文件：

```sh
openssl req -new -key vaultwarden.key -out vaultwarden.csr
```

使用以下内容创建文本文件 `vaultwarden.ext`，请将域名更改为您设置的域名：

```systemd
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:TRUE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1 = vaultwarden.local
DNS.2 = www.vaultwarden.local
# 如果不使用 DNS 名称，也可选择添加 IP
IP.1 = 192.168.1.3
```

创建从根 CA 签名的 Vaultwarden 证书：

```sh
openssl x509 -req -in vaultwarden.csr -CA self-signed-ca-cert.crt -CAkey private-ca.key -CAcreateserial -out vaultwarden.crt -days 365 -sha256 -extfile vaultwarden.ext
```

> **注意**：自 2019 年 4 月起，iOS 13+ 和 macOS 15+ 的服务器证书的有效期不能大于 825 天，并且必须包含 ExtendedKeyUsage (EKU) 扩展。详见 <https://support.apple.com/zh-cn/HT210176>。

> **注意**：从 Android 11 开始，`basicConstraints` 值必须设置为 `CA:TRUE` 才能通过 「设置」 应用程序导入。

将根证书和 Vaultwarden 证书添加到客户端计算机。

更多参考，请参阅这里：<https://deliciousbrains.com/ssl-certificate-authority-for-local-https-development/>。


# \*测试 SSO

{% hint style="success" %}
对应的[官方页面地址](https://github.com/dani-garcia/vaultwarden/wiki/Testing-SSO/)
{% endhint %}

## 用于测试 SSO 的开发设置 <a href="#development-setup-to-test-sso" id="development-setup-to-test-sso"></a>

Vaultwarden 的 SSO 支持目前[正在开发中](https://github.com/dani-garcia/vaultwarden/pull/3154)。以下内容描述了基于 docker-compose 的用于本地测试这些更改的设置。

{% hint style="danger" %}
**仅用于测试 SSO，这些设置并不安全！**
{% endhint %}

## 设置 <a href="#setup" id="setup"></a>

* 查看 SSO 分支
* 使用以下内容创建 `docker-compose.yml`：

  ```yaml
  services:
    vaultwarden:
      build: .
      environment:
        DOMAIN: "http://localhost:8000"
        I_REALLY_WANT_VOLATILE_STORAGE: "true"
        SSO_ENABLED: "true"
        SSO_CLIENT_ID: "client"
        SSO_CLIENT_SECRET: "clientsecret"
        SSO_AUTHORITY: "http://auth.test:8080/mock"
      ports:
        - 127.0.0.1:8000:80

    mock-oauth2:
      image: ghcr.io/navikt/mock-oauth2-server:0.5.10
      hostname: "auth.test"
      ports:
        - 127.0.0.1:8080:8080
  ```
* 将 `auth.test` 添加到您的系统 host 文件中：`echo "127.0.0.1 auth.test" | sudo tee -a /etc/hosts`
* 构建 Vaultwarden：`docker compose build`

## 测试 <a href="#testing" id="testing"></a>

* 启动服务：`docker compose up`
* 转到 <http://localhost:8000/#/sso>，输入任意字符串作为标识符，点击「登录」
* 在模拟 Auth2 服务器登录页面上，输入任意字符串作为用户/主题，并在声明字段中添加要测试的电子邮件，像这样：`{"email": "user@example.com"}`
* 如果一切按计划进行，您将会被要求输入主密码


# \*使用 systemd docker 运行

{% hint style="success" %}
对应的官方页面地址（Vaultwarden WiKi 已移除此页面）
{% endhint %}

这部分的内容允许您使用 systemd 来管理 Docker 容器的生命周期，若您喜欢的话。

首先，使用系统包管理器安装 `systemd-docker` 包。这是一个用于改进 docker 与 systemd 集成的封装器。

有关完整介绍和配置选项，请参阅 [Github 仓库](https://github.com/ibuildthecloud/systemd-docker)。

以 root 身份，使用您喜欢的编辑器用以下内容创建 `/etc/systemd/system/vaultwarden.service` 文件：

```systemd
[Unit]
Description=Vaultwarden
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker pull vaultwarden/server:latest
ExecStartPre=-/usr/bin/docker stop vaultwarden
ExecStartPre=-/usr/bin/docker rm vaultwarden
ExecStart=/usr/bin/docker run \
  -p 8080:80 \
  -p 8081:3012 \
  --env-file /opt/.vaultwarden.env \
  -v /opt/vw-data:/data/ \
  --rm --name vaultwardenvaultwarden/server:latest
ExecStopPost=-/usr/bin/docker rm vaultwarden
Restart=Always
RestartSec=30s
Type=notify
NotifyAccess=all

[Install]
WantedBy=multi-user.target
```

根据需要调整上述示例。特别要注意 `-p` 和 `-v` 选项，因为它们控制着容器和主机之间的端口和卷绑定。另外，请确保为您的配置提供一个 `--env-file`，或者直接通过 `-e KEY=VALUE` 输入您的所有配置。

对上述选项的解释：

* `TimeoutStartSec` 的值 `0`：等待默认启动时间后，认为服务已经失败，将停止 systemd。此为必选项，因为 `ExecStartPre` 中的 `docker pull` 命令需要一段时间来完成。
* `ExecStartPre`：在运行之前拉取 docker 标签。
* `ExecStopPost`：删除容器（以确保我们下次可以重新启动）。我们这样做的原因是 systemd 监控的是 docker 服务而不是单个容器。因此，我们使用 `unless-stopped` 告诉 docker 服务重启容器。这基本上就像 `--restart=Always`，但不包括 docker 服务停止的时候（或者容器被挂起）。当 docker 服务停止时，这允许我们使用 `Restart=Always` 让 systemd 仅重启服务。
* `Type` 的值 `notify`：告诉 systemd 从已准备就绪的服务中获取通知。
* `NotifyAccess` 的值 `all`：是由 `systemd-docker` 请求的。

## 设置环境变量 <a href="#setting-environment-variables" id="setting-environment-variables"></a>

可以通过两种方式在单元文件中直接指定环境变量：

* 在 `[Service]` 块中使用 `Environment` 指令。
* 使用 `docker` 的 `-e` 选项。此时，您可以省略上面示例中显示的 `--env` 选项。

要验证是否正确设置了环境变量，请检查 `systemctl show vaultwarden.service` 的输出中是否存在 `Environment` 行。

也可以在单元文件中使用 `EnvironmentFile` 指令将环境变量存储在单独的文件中。在这种情况下，请如上面示例中所示在 docker 命令行中设置 `--env` 选项，否则将不会处理环境文件。

systemd 可以获取以下格式的文件：

```systemd
Key="Value"
```

您可以在此[环境示例模版](https://github.com/dani-garcia/bitwarden_rs/blob/21325b7523a68ab3ae8d435ab5b73176db6155ff/.env.template)中找到更多关于环境设置和语法的说明。

但是，systemd 项目并没有规定该文件的存储位置。有关此文件的最佳存储位置，请查阅发行版文档。例如，基于 RedHat 的发行版通常将这些文件放在 `/etc/sysconfig/` 中。

如果您不确定，只需使用 root 权限在 `/etc/` 中创建一个文件即可，比如 `/etc/vaultwarden.service.conf`。

在您的单元文件中的 `[Service]` 块中添加一个 `EnvironmentFile` 指令，其值是上面创建的文件的完整路径。例如：

```systemd
[Unit]
Description=Vaultwarden
After=docker.service
Requires=docker.service

[Service]
EnvironmentFile=/etc/vaultwarden.service.conf
TimeoutStartSec=0
-snip-
```

## 运行服务 <a href="#running-the-service" id="running-the-service"></a>

完成上述安装和配置后，使用 `sudo systemctl daemon-reload` 命令重新加载 systemd 。然后，使用 `sudo systemctl start vaultwarden` 命令启动 Vaultwarden 服务。

要使服务跟随系统启动，请使用 `sudo systemctl enable vaultwarden`。

使用 `systemctl status vaultwarden` 来验证容器是否已经启动。

如果在启动服务时遇到 `json: cannot unmarshal object into Go value of type string` 错误，则应使用最新版本的 Go 来自己编译 systemd-docker 二进制，请参阅此[话题](https://github.com/ibuildthecloud/systemd-docker/issues/50)。


