docs: 添加一键部署脚本说明与脚本文件

这个提交包含在:
2026-08-26 11:24:42 +08:00
父节点 45f6f08195
当前提交 038be408d0
共修改 4 个文件,包含 215 行新增和 33 行删除
+27
查看文件
@@ -54,6 +54,33 @@ npm start
## 部署(Docker) ## 部署(Docker)
### 一键部署脚本
仓库提供一键部署脚本,自动完成「拉取 git 代码 → 校验/生成 `.env` → 准备挂载目录 → `docker compose` 构建并启动」:
- **Linux / macOS**:`deploy.sh`
```bash
chmod +x deploy.sh
./deploy.sh # 默认仓库与 ./kdbx-viewer 目录
./deploy.sh /opt/kdbx # 指定部署目录
REPO=https://... ./deploy.sh # 指定 git 仓库地址
```
- **Windows(cmd)**:`deploy.bat`
```bat
deploy.bat # 默认仓库与 kdbx-viewer 目录
deploy.bat D:\kdbx # 指定部署目录
set REPO=https://... && deploy.bat # 指定 git 仓库地址
```
脚本行为:
1. 目录已存在 git 仓库则 `git pull`,否则 `git clone`(仓库地址见脚本顶部 `REPO`,可被环境变量覆盖)。
2. 无 `.env` 时从 `.env.example` 复制,并**中断提示填写敏感项**(`APP_PW_DYNAMIC` / `APP_PW_STATIC` / `SESSION_SECRET`);若仍为占位值也会拒绝启动。
3. 创建 `vault/`、`logs/`、`ssl/` 挂载目录。
4. 检查 `docker` 与 `docker compose v2` 是否可用。
5. `docker compose up -d --build` 启动,并打印访问地址。
### 手动部署
所有配置通过**同目录的 `.env` 文件注入**,无需在 `docker-compose.yml` 中写死(`compose` 会自动读取 `.env` 并用 `${VAR}` 替换)。 所有配置通过**同目录的 `.env` 文件注入**,无需在 `docker-compose.yml` 中写死(`compose` 会自动读取 `.env` 并用 `${VAR}` 替换)。
```bash ```bash
-33
查看文件
@@ -1,33 +0,0 @@
'use strict';
// 验证 IP 封锁逻辑修复:必须用字符串 IP 作 key,而非对象
const ipFails = new Map();
const IP_WINDOW = 30 * 60 * 1000, IP_MAX_FAIL = 5;
function recordIpFail(ip) {
const now = Date.now();
let r = ipFails.get(ip);
if (!r || now - r.first > IP_WINDOW) r = { count: 0, first: now };
r.count++; ipFails.set(ip, r);
return r.count >= IP_MAX_FAIL;
}
function isIpBlocked(ip) {
const r = ipFails.get(ip);
if (!r) return false;
if (Date.now() - r.first > IP_WINDOW) { ipFails.delete(ip); return false; }
return r.count >= IP_MAX_FAIL;
}
// 旧 bug:传入对象 {ip:'1.2.3.4'} 作 key
const ipObj = { ip: '1.2.3.4' };
let blockedOld = false;
for (let i = 0; i < 5; i++) recordIpFail(ipObj);
blockedOld = isIpBlocked(ipObj); // 每次都是新对象 -> 永远 false
// 修复后:传入字符串 '1.2.3.4'
const ipStr = '1.2.3.4';
let blockedNew = false;
for (let i = 0; i < 5; i++) recordIpFail(ipStr);
blockedNew = isIpBlocked(ipStr);
console.log('修复前(对象key)是否封锁:', blockedOld, '-> 期望 false(bug 表现)');
console.log('修复后(字符串key)是否封锁:', blockedNew, '-> 期望 true');
process.exit(blockedNew === true ? 0 : 1);
+98
查看文件
@@ -0,0 +1,98 @@
@echo off
REM ============================================================
REM kdbx-viewer 一键部署脚本(Windows / cmd)
REM 功能:拉取 git 代码 -> 生成/校验 .env -> 准备目录 -> docker compose 构建并启动
REM
REM 用法:
REM deploy.bat 使用默认仓库与当前目录
REM deploy.bat D:\kdbx 指定部署目录
REM set REPO=https://... && deploy.bat 指定 git 仓库地址
REM ============================================================
setlocal EnableDelayedExpansion
REM 默认仓库地址(可被环境变量 REPO 覆盖)
if not defined REPO set "REPO=http://git.iwali.top/wangchuanli/kdbx-viewer.git"
REM 部署目录(第一个参数,默认当前目录下的 kdbx-viewer)
if "%~1"=="" (set "DEPLOY_DIR=kdbx-viewer") else (set "DEPLOY_DIR=%~1")
echo ============================================
echo kdbx-viewer 一键部署
echo 仓库: %REPO%
echo 目录: %DEPLOY_DIR%
echo ============================================
REM ---------- 1. 拉取代码 ----------
if exist "%DEPLOY_DIR%\.git" (
echo [1/5] 已存在仓库,执行 git pull ...
git -C "%DEPLOY_DIR%" pull --ff-only || git -C "%DEPLOY_DIR%" pull
) else (
echo [1/5] 克隆仓库 %REPO% ...
git clone "%REPO%" "%DEPLOY_DIR%"
)
cd /d "%DEPLOY_DIR%"
REM ---------- 2. 校验/生成 .env ----------
echo [2/5] 检查 .env ...
if not exist ".env" (
if not exist ".env.example" (
echo 缺少 .env.example,无法生成 .env,请手动创建。 1>&2
exit /b 1
)
copy .env.example .env >nul
echo 已生成 .env(基于 .env.example)。
echo !!! 请先编辑 .env 填写敏感项,再重新运行本脚本:
findstr /b "APP_PW_DYNAMIC= APP_PW_STATIC= SESSION_SECRET=" .env
echo (将占位值替换为真实强口令/随机串)
exit /b 1
)
REM 校验关键敏感项是否仍为占位/空
set "NEED_EDIT=0"
for %%K in (APP_PW_DYNAMIC APP_PW_STATIC SESSION_SECRET) do (
for /f "tokens=2* delims==" %%V in ('findstr /b "%%K=" .env') do (
set "VAL=%%V"
if "!VAL!"=="" set "NEED_EDIT=1"
if "!VAL!"=="你的固定部分" set "NEED_EDIT=1"
if "!VAL!"=="改成你的强口令" set "NEED_EDIT=1"
if "!VAL!"=="改成随机长字符串" set "NEED_EDIT=1"
)
)
if "!NEED_EDIT!"=="1" (
echo .env 中仍存在未设置的占位项,请编辑补全后重新运行 deploy.bat
exit /b 1
)
REM ---------- 3. 准备挂载目录 ----------
echo [3/5] 准备挂载目录 vault/ logs/ ssl/ ...
if not exist vault mkdir vault
if not exist logs mkdir logs
if not exist ssl mkdir ssl
REM ---------- 4. 环境前置检查 ----------
echo [4/5] 检查 docker / docker compose ...
where docker >nul 2>nul
if errorlevel 1 (
echo 未检测到 docker,请先安装 Docker Desktop:https://www.docker.com/products/docker-desktop/
exit /b 1
)
docker compose version >nul 2>nul
if errorlevel 1 (
echo 未检测到 docker compose v2,请升级 Docker Desktop 或安装 compose 插件。
exit /b 1
)
REM ---------- 5. 构建并启动 ----------
echo [5/5] docker compose 构建并启动(后台)...
docker compose up -d --build
echo.
echo 部署完成。访问地址(默认 HTTPS,证书缺失时自动生成自签):
for /f "tokens=2* delims==" %%P in ('findstr /b "PORT=" .env') do set "PORT=%%P"
if not defined PORT set "PORT=3000"
echo https://localhost:!PORT!
echo.
echo 常用命令:
echo 查看日志: docker compose logs -f
echo 停止服务: docker compose down
echo 更新代码: deploy.bat
endlocal
+90
查看文件
@@ -0,0 +1,90 @@
#!/usr/bin/env bash
#
# kdbx-viewer 一键部署脚本(Linux / macOS)
# 功能:拉取 git 代码 -> 生成/校验 .env -> 准备挂载目录 -> docker compose 构建并启动
#
# 用法:
# ./deploy.sh # 使用默认仓库与当前目录
# ./deploy.sh /opt/kdbx # 指定部署目录
# REPO=https://... ./deploy.sh # 指定 git 仓库地址
#
set -euo pipefail
# 默认仓库地址(可被环境变量 REPO 覆盖)
REPO="${REPO:-http://git.iwali.top/wangchuanli/kdbx-viewer.git}"
# 部署目录(第一个参数,默认 ./kdbx-viewer)
DEPLOY_DIR="${1:-kdbx-viewer}"
echo "============================================"
echo " kdbx-viewer 一键部署"
echo " 仓库: $REPO"
echo " 目录: $DEPLOY_DIR"
echo "============================================"
# ---------- 1. 拉取代码 ----------
if [ -d "$DEPLOY_DIR/.git" ]; then
echo "[1/5] 已存在仓库,执行 git pull ..."
git -C "$DEPLOY_DIR" pull --ff-only || git -C "$DEPLOY_DIR" pull
else
echo "[1/5] 克隆仓库 $REPO ..."
git clone "$REPO" "$DEPLOY_DIR"
fi
cd "$DEPLOY_DIR"
# ---------- 2. 校验/生成 .env ----------
echo "[2/5] 检查 .env ..."
if [ ! -f .env ]; then
if [ ! -f .env.example ]; then
echo "缺少 .env.example,无法生成 .env,请手动创建。" >&2
exit 1
fi
cp .env.example .env
echo "已生成 .env(基于 .env.example)。"
echo "!!! 请先编辑 .env 填写以下敏感项,再重新运行本脚本:"
grep -nE '^APP_PW_DYNAMIC=|^APP_PW_STATIC=|^SESSION_SECRET=' .env || true
echo "(将占位值替换为真实强口令/随机串)"
exit 1
fi
# 校验关键敏感项是否为空或仍为占位
need_edit=0
for key in APP_PW_DYNAMIC APP_PW_STATIC SESSION_SECRET; do
val="$(grep -E "^${key}=" .env | tail -1 | cut -d= -f2-)"
if [ -z "${val:-}" ] || [ "${val}" = "你的固定部分" ] || [ "${val}" = "改成你的强口令" ] || [ "${val}" = "改成随机长字符串" ]; then
echo " [警告] .env 中 $key 未正确设置($val)"
need_edit=1
fi
done
if [ "$need_edit" -eq 1 ]; then
echo "请编辑 .env 补全敏感项后重新运行 ./deploy.sh"
exit 1
fi
# ---------- 3. 准备挂载目录 ----------
echo "[3/5] 准备挂载目录 vault/ logs/ ssl/ ..."
mkdir -p vault logs ssl
# ---------- 4. 环境前置检查 ----------
echo "[4/5] 检查 docker / docker compose ..."
if ! command -v docker >/dev/null 2>&1; then
echo "未检测到 docker,请先安装 Docker:https://docs.docker.com/get-docker/" >&2
exit 1
fi
if ! docker compose version >/dev/null 2>&1; then
echo "未检测到 docker compose v2,请升级 Docker Desktop 或安装 compose 插件。" >&2
exit 1
fi
# ---------- 5. 构建并启动 ----------
echo "[5/5] docker compose 构建并启动(后台)..."
docker compose up -d --build
echo ""
echo "部署完成。访问地址(默认 HTTPS,证书缺失时自动生成自签):"
PORT="$(grep -E '^PORT=' .env | tail -1 | cut -d= -f2-)"
PORT="${PORT:-3000}"
echo " https://localhost:${PORT}"
echo ""
echo "常用命令:"
echo " 查看日志: docker compose logs -f"
echo " 停止服务: docker compose down"
echo " 更新代码: ./deploy.sh"