From 0721bab031470053ee5087edbcd7ab9f4364efe6 Mon Sep 17 00:00:00 2001 From: LiuShen <3162475700@qq.com> Date: Wed, 25 Jun 2025 17:29:21 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=99=82=E6=B7=BB=E5=8A=A0vaultwarden-mysql?= =?UTF-8?q?=E7=89=88=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- vaultwarden-mysql/1.34.1/data.yml | 143 ++++++++++++++++++++ vaultwarden-mysql/1.34.1/docker-compose.yml | 22 +++ vaultwarden-mysql/README.md | 61 +++++++++ vaultwarden-mysql/data.yml | 32 +++++ vaultwarden-mysql/logo.png | Bin 0 -> 7787 bytes 5 files changed, 258 insertions(+) create mode 100644 vaultwarden-mysql/1.34.1/data.yml create mode 100644 vaultwarden-mysql/1.34.1/docker-compose.yml create mode 100644 vaultwarden-mysql/README.md create mode 100644 vaultwarden-mysql/data.yml create mode 100644 vaultwarden-mysql/logo.png diff --git a/vaultwarden-mysql/1.34.1/data.yml b/vaultwarden-mysql/1.34.1/data.yml new file mode 100644 index 000000000..a54c987cd --- /dev/null +++ b/vaultwarden-mysql/1.34.1/data.yml @@ -0,0 +1,143 @@ +additionalProperties: + formFields: + - child: + default: "" + envKey: PANEL_VW_DB_HOST + required: true + type: service + default: mysql + envKey: PANEL_VW_DB_TYPE + labelEn: Database Service + labelZh: 数据库服务 + label: + en: Database Service + ja: データベースサービス + ms: Perkhidmatan Pangkalan Data + pt-br: Serviço de Banco de Dados + ru: Сервис базы данных + ko: 데이터베이스 서비스 + zh: 数据库服务 + zh-Hant: 數據庫 服務 + required: true + type: apps + values: + - label: MySQL + value: mysql + - label: MariaDB + value: mariadb + + - default: vaultwarden + envKey: PANEL_VW_DB_NAME + labelEn: Database Name + labelZh: 数据库名 + label: + en: Database Name + ja: データベース名 + ms: Nama Pangkalan Data + pt-br: Nome do Banco de Dados + ru: Имя базы данных + ko: 데이터베이스 이름 + zh: 数据库名 + zh-Hant: 數據庫名 + required: true + rule: paramCommon + type: text + + - default: vaultwarden + envKey: PANEL_VW_DB_USER + labelEn: Database User + labelZh: 数据库用户 + label: + en: Database User + ja: データベースユーザー + ms: Pengguna Pangkalan Data + pt-br: Usuário do Banco de Dados + ru: Пользователь базы данных + ko: 데이터베이스 사용자 + zh: 数据库用户 + zh-Hant: 數據庫用戶 + required: true + rule: paramCommon + type: text + + - default: "" + envKey: PANEL_VW_DB_PASSWORD + labelEn: Database Password + labelZh: 数据库密码 + label: + en: Database Password + ja: データベースパスワード + ms: Kata Laluan Pangkalan Data + pt-br: Senha do Banco de Dados + ru: Пароль базы данных + ko: 데이터베이스 비밀번호 + zh: 数据库密码 + zh-Hant: 數據庫密碼 + required: true + type: password + + - default: 3306 + envKey: PANEL_VW_DB_PORT + labelEn: Database Port + labelZh: 数据库端口 + label: + en: Database Port + ja: データベースポート + ms: Pelabuhan Pangkalan Data + pt-br: Porta do Banco de Dados + ru: Порт базы данных + ko: 데이터베이스 포트 + zh: 数据库端口 + zh-Hant: 數據庫連接埠 + required: true + rule: paramPort + type: number + + - default: "https://vw.example.com/" + envKey: PANEL_VW_DOMAIN + labelEn: Domain + labelZh: 域名 (反向代理时必填) + label: + en: Domain (Required if using reverse proxy) + ja: ドメイン(リバースプロキシ使用時に必須) + ms: Domain (Diperlukan jika menggunakan reverse proxy) + pt-br: Domínio (obrigatório se usar proxy reverso) + ru: Домен (обязательно при использовании обратного прокси) + ko: 도메인 (리버스 프록시 사용 시 필수) + zh: 域名 (反向代理时必填) + zh-Hant: 域名 (反向代理時必填) + required: false + type: text + + - default: "" + envKey: PANEL_VW_ADMIN_TOKEN + labelEn: Admin Token + labelZh: 管理员令牌 + label: + en: Admin Token + ja: 管理者トークン + ms: Token Pentadbir + pt-br: Token do Administrador + ru: Токен администратора + ko: 관리자 토큰 + zh: 管理员令牌 + zh-Hant: 管理員令牌 + required: false + type: password + + - default: 80 + envKey: PANEL_APP_PORT_HTTP + labelEn: HTTP Port + labelZh: HTTP 端口 + label: + en: HTTP Port + ja: ポート + ms: Port + pt-br: Porta HTTP + ru: HTTP Порт + ko: HTTP 포트 + zh: HTTP 端口 + zh-Hant: HTTP 連接埠 + required: true + rule: paramPort + type: number diff --git a/vaultwarden-mysql/1.34.1/docker-compose.yml b/vaultwarden-mysql/1.34.1/docker-compose.yml new file mode 100644 index 000000000..7180a5d56 --- /dev/null +++ b/vaultwarden-mysql/1.34.1/docker-compose.yml @@ -0,0 +1,22 @@ +version: '3.8' +services: + vaultwarden: + image: vaultwarden/server:1.34.1 + container_name: ${CONTAINER_NAME} + restart: always + environment: + DOMAIN: ${PANEL_VW_DOMAIN} + ADMIN_TOKEN: ${PANEL_VW_ADMIN_TOKEN} + DATABASE_URL: mysql://${PANEL_VW_DB_USER}:${PANEL_VW_DB_PASSWORD}@${PANEL_VW_DB_HOST}:${PANEL_VW_DB_PORT}/${PANEL_VW_DB_NAME} + volumes: + - ./data:/data + ports: + - "${PANEL_APP_PORT_HTTP}:80" + labels: + createdBy: "Apps" + networks: + - 1panel-network + +networks: + 1panel-network: + external: true diff --git a/vaultwarden-mysql/README.md b/vaultwarden-mysql/README.md new file mode 100644 index 000000000..6f2031508 --- /dev/null +++ b/vaultwarden-mysql/README.md @@ -0,0 +1,61 @@ +# Vaultwarden + +Vaultwarden 是一个轻量、开源的 Bitwarden 服务端实现,适用于资源有限的自托管环境。它提供密码管理、TOTP、密码生成器、附件上传等核心功能,并支持 Web、移动和浏览器扩展客户端。 + +------ + +## ✨ 特性 + +- ✅ 兼容 [Bitwarden 官方客户端](https://bitwarden.com/) +- 🧠 支持 TOTP 两步验证、密码生成器、密码分享等功能 +- 🪶 轻量级,仅需极少系统资源 +- 📁 支持附件存储与文件上传 +- 🔐 多用户支持、组织功能、审计日志(可选启用) +- 📦 支持 SQLite、MySQL、PostgreSQL 后端 + +------ + +## 🚀 快速开始(Docker 部署) + +``` +bash复制编辑docker run -d \ + --name vaultwarden \ + -e ADMIN_TOKEN='your_admin_token' \ + -v ./vw-data:/data \ + -p 8222:80 \ + vaultwarden/server:latest +``` + +- 默认 Web 服务端口:`80` +- 持久化数据存储路径:`/data` +- 设置 `ADMIN_TOKEN` 后访问 `/admin` 管理面板 + +------ + +## 📦 支持环境变量(示例) + +| 变量名 | 描述 | 是否必填 | +| ----------------- | -------------------------- | ------------------- | +| `ADMIN_TOKEN` | 后台管理口令 | 否(建议设置) | +| `DOMAIN` | 自定义访问域名 | 否 | +| `ROCKET_PORT` | HTTP 服务端口 | 否,默认 `80` | +| `DATABASE_URL` | 数据库连接地址 | 否,默认使用 SQLite | +| `SIGNUPS_ALLOWED` | 是否允许注册(true/false) | 否 | + + + +------ + +## 🔐 访问地址 + +部署完成后,请访问: + +``` +cpp + + +复制编辑 +http://<服务器地址>:端口 +``` + +如果设置了 `ADMIN_TOKEN`,可通过 `http://<服务器地址>:端口/admin` 访问管理后台。 \ No newline at end of file diff --git a/vaultwarden-mysql/data.yml b/vaultwarden-mysql/data.yml new file mode 100644 index 000000000..66239758b --- /dev/null +++ b/vaultwarden-mysql/data.yml @@ -0,0 +1,32 @@ +name: Vaultwarden-mysql +tags: + - 密码管理 + - 自托管 + - 安全 +title: 轻量、安全、兼容 Bitwarden 的密码管理服务 +description: 一个轻量级、自托管的密码管理服务,兼容 Bitwarden 客户端,适合个人或小团队使用,该版本为mysql版本应用 +additionalProperties: + key: vaultwarden-mysql + name: Vaultwarden-mysql + tags: + - Tool + - Security + shortDescZh: Bitwarden 的轻量开源替代方案 + shortDescEn: Lightweight, self-hosted alternative to Bitwarden + type: Tool + crossVersionUpdate: true + limit: 0 + website: https://github.com/dani-garcia/vaultwarden + github: https://github.com/dani-garcia/vaultwarden + document: https://github.com/dani-garcia/vaultwarden/wiki + description: + en: A lightweight, secure, and self-hosted password manager compatible with Bitwarden clients. + zh: 一个轻量、安全、可自托管的密码管理服务,兼容 Bitwarden 客户端。 + zh-Hant: 一個輕量、安全、自託管的密碼管理工具,兼容 Bitwarden。 + ja: Bitwarden クライアントと互換性のある軽量なセルフホスティング型パスワードマネージャー。 + ms: Pengurus kata laluan yang ringan dan selamat serta boleh dihoskan sendiri, serasi dengan Bitwarden. + pt-br: Um gerenciador de senhas leve, seguro e auto-hospedado compatível com clientes Bitwarden. + ru: Лёгкий, безопасный и самодостаточный менеджер паролей, совместимый с клиентами Bitwarden. + ko: Bitwarden 클라이언트와 호환되는 가볍고 안전한 셀프 호스팅 비밀번호 관리자입니다. + architectures: + - amd64 diff --git a/vaultwarden-mysql/logo.png b/vaultwarden-mysql/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..346f2a841b28974aae1c57e421ca5035bb3319e7 GIT binary patch literal 7787 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