server/DEPLOY_SYNOLOGY.md
Rama main · réplica de lectura del repositorio original.
# TapLedger 服务端部署教程 — 群晖 DS224+(DSM 7 / Container Manager)
> 把「一点账本」的家庭共享后端跑在你的群晖 DS224+ 上。全程图形化操作,无需 SSH、无需命令,数据只存在你的 NAS 本地。
## 0. 事前准备
- 一台 **DS224+**,系统 **DSM 7.x** 或更高
- 已安装 **Container Manager**(套件中心 → 可直接装上;若没有,先去「套件中心」安装)
- NAS 能访问外网(首次要拉取镜像)
- 知道你的 **局域网 IP**(例如 `192.168.1.200`,在「控制面板 → 网络 → 网络接口」可查到)
> 本教程用的是镜像 `ghcr.io/sctale/tapledger-server`(公共镜像,`latest` 标签,无需登录即可拉取)。
---
## 1. 获取 docker-compose.yml
我们直接在 Container Manager 里新建,不碰命令行。需要用以下内容创建一份 `docker-compose.yml`:
1. 打开 **File Station**,进入共享文件夹 **`docker`**,新建文件夹 `tapledger`(本文以下均以实际路径 `/volume1/docker/tapledger` 为准)。
2. 在 `tapledger` 文件夹里新建文本文件 `docker-compose.yml`,内容照抄下面这段:
```yaml
services:
tapledger:
image: ghcr.io/sctale/tapledger-server:latest
container_name: tapledger-server
restart: unless-stopped
ports:
- "8420:8420"
environment:
- PORT=8420
- TZ=Asia/Shanghai
# JWT_SECRET 从同级 .env 读取(首次部署前在同文件夹放一个 .env)
env_file:
- .env
volumes:
# 持久化:NAS 上的 /volume1/docker/tapledger/data ↔ 容器内 /app/data
# 数据库、用户、家庭、账本全部存在这里,备份/迁移只需带走这个文件夹
- /volume1/docker/tapledger/data:/app/data
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost:8420/api/health"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
```
然后在**同一个 `/volume1/docker/tapledger` 文件夹**里再建一个 `.env` 文件(不要提交到任何 git),内容:
```
JWT_SECRET=这里填你的随机长字符串(至少32位)
# 可选:配置后可浏览器打开 http://NAS_IP:8420/admin 在线开关「注册/加入家庭」;不填则无面板
ADMIN_TOKEN=另一个随机长字符串(可留空注释掉本行)
```
> `JWT_SECRET` 必填:生产环境镜像 `NODE_ENV=production`,若缺失/过短/沿用默认值,容器会**拒绝启动**(防 token 伪造)。`ADMIN_TOKEN` 可先注释掉,需要面板时再取消注释并重启一次。
### 持久化文件夹说明(重要)
- 数据库文件为 **`/volume1/docker/tapledger/data/tapledger.db`**(SQLite 单文件,WAL 模式运行时同目录还会有 `tapledger.db-wal` / `tapledger.db-shm` 两个临时文件,属正常现象)。
- **首次启动时容器会自动创建** `data` 文件夹和数据库,无需手动新建;之后所有记账数据(用户/家庭/账本/记录)都只落在这里,容器删了重建数据也不丢。
- **备份**:容器**每天自动热备份**数据库到 `/volume1/docker/tapledger/data/backups/`(保留最近 7 份,v0.4.3 起内置);再配合 DSM「Hyper Backup」定期整包备份 `data/` 文件夹即可双保险。
- **迁移到新 NAS**:把整个 `/volume1/docker/tapledger` 文件夹(含 `docker-compose.yml`、`.env`、`data/`)原样复制过去,照第 2 节重新建项目即可,数据完整保留。
- ⚠️ `.env` 里的 `JWT_SECRET` 是登录凭证的签名密钥,**换库/迁移时必须保持同一个值**,否则所有用户需要重新登录;也不要把它放到任何仓库/网盘里。
> 「示范计划」:如果你只会 File Station 新增空文件,可以用「右键 → 用 Notepad 编辑」,粘贴后保存。确保文件名是 `docker-compose.yml`(不是 `docker-compose.yml.txt`)。
---
## 2. 在 Container Manager 里创建项目
1. 打开 **Container Manager**(桌面图标)。
2. 左侧选 **项目(Project)** → 右上点 **新建(Create Project)**。
3. 填:
- **名称**:`tapledger`
- **路径**:`/volume1/docker/tapledger`(含 `docker-compose.yml` 的那一层)
- **来源**:选用「提供 docker-compose.yml 的内容」或「从文件夹读取」均可,指向这份 yml
4. 点击 **下一步 → 创建(Apply)**。
5. Container Manager 会自动从 GHCR 拉取镜像并启动容器。等它显示 **运行中(Running)**。
> 第一次拉镜像约几十 MB,视网速等 1~3 分钟;状态栏变「运行中」即成功。
---
## 3. 打开防火墙端口(可选)
默认 APP 走 `http://NAS_IP:8420`。若只在家里局域网用,不需要这步。
要开放公网/其他设备访问,到 **控制面板 → 安全性 → 防火墙**,为 `8420` 端口 **允许**(TCP),并设置好路由器端口转发。
> ⚠️ 想从外网访问强烈建议加 HTTPS 反向代理,不要让明文 8420 裸露在公网。
---
## 4. 验证部署成功
在电脑浏览器打开(把 IP 换成你的):
```
http://192.168.1.200:8420/api/health
```
出现类似输出即成功:
```json
{"ok":true,"time":1720000000000}
```
也可打开 **Container Manager → 项目 → tapledger → 日志**,应能看到 Node 服务启动、无报错。
---
## 5. 在「一点账本」APP 里连接
1. 打开 APP → 我的 → 家庭同步(或设置里的同步)。
2. 服务器地址填:`http://192.168.1.200:8420`
3. 注册账号(第一位成员)→ 创建「我们家」家庭 → 其余家人用邀请码加入。
连接后即可多人共享同一个家庭账本,数据全部存在你的 NAS(`/volume1/docker/tapledger/data/`)。
---
## 6. 常见问题(FAQ)
| 现象 | 原因 / 解决 |
|---|---|
| 一直是「拉取中」,状态不运行 | 外网不通或镜像名写错;检查 Container Manager 网络设置,确认能访问 ghcr.io |
| `/api/health` 打不开 | 端口 8420 没映射或防火墙挡了;核对 yml 的 `ports` 与 DSM 防火墙 |
| APP 提示连接失败 | IP/端口填错,或在非局域网环境没做端口转发/HTTPS |
| 重启 NAS 后容器没起来 | 确认 yml 里有 `restart: unless-stopped`;Container Manager 项目需已启用 |
| 想换新版本 | 镜像在**开发者本地构建发布**到 GHCR(版本号 + latest 双标签)。你只需进项目 → **更新**:重新拉取 latest 再「重新创建」即可,或手动在上面的 yml 里指定 `image: ...:具体版本号` 更稳定 |
| 数据会不会丢 | 不会。数据库在 `/volume1/docker/tapledger/data/tapledger.db`,容器每天自动热备份到 `data/backups/`(留 7 份);再用 Hyper Backup 整包备份 `data/` 即双保险 |
| 升级到 v0.4.2+ 后容器立刻退出/反复重启,日志有 `[fatal] 生产环境必须配置 JWT_SECRET` | 不是镜像坏了:新版生产环境**拒绝用不安全密钥启动**。编辑 `.env` 填入 ≥16 位随机串(建议 32 位,`openssl rand -hex 32` 生成),再「重新创建」容器即可 |
| APP 注册报 403「服务器已关闭注册」 | 你在 `/admin` 面板关过「允许新用户注册」。家人老账号登录不受影响;要加新成员时开回即可 |
| 加入家庭报 429 | 正常保护:同一 IP 每分钟限 5 次尝试,或同一邀请码被连错 10 次锁定 10 分钟。核对邀请码(家庭管理里可重新生成),稍后再试 |
---
## 7. 升级 / 备份要点
- **升级**:项目 → 更新(拉取 latest)→ 重新创建;或改 yml 里 `image: ghcr.io/sctale/tapledger-server:新版本号` → 重新创建。数据保留在 `/volume1/docker/tapledger/data/`,升级不丢。
- ⚠️ **升级到 v0.4.2+ 前先查 `.env`**:`JWT_SECRET` 必须是真实强随机串(≥16 位,建议 32 位),不能留示例值——新版生产环境密钥不安全会**拒绝启动**(见第 6 节 FAQ)。想启用管理面板,顺手加一行 `ADMIN_TOKEN=<强随机串>`(可先不加,之后要用再取消注释并重启一次)。
- **升级后自查**:容器状态为“健康”;`curl http://NAS_IP:8420/api/health` 有 `{"ok":true}`;日志出现一行 `[backup] wrote tapledger-日期.db` 说明自动备份正常。
- **想回退旧版**:把 yml 里 `image:` 改回旧版本号 tag → 重新创建即可,数据卷不动。
- **备份**:容器每天自动热备份到 `/volume1/docker/tapledger/data/backups/tapledger-日期.db`(保留 7 份,可用 `.env` 里 `BACKUP_KEEP` 调整、`BACKUP_DISABLED=1` 关闭)。需回滚时:停止容器 → 删除 `data/` 下 `tapledger.db-wal`、`tapledger.db-shm` → 把目标备份复制为 `tapledger.db` → 启动容器。另建议 DSM Hyper Backup 整包备份 `data/` 做双保险。
- 强烈建议把 `JWT_SECRET` 记到安全的地方——换库/迁移时保持同一个值,已登录的用户才不需重新登录。
---
> 遇到任何一步报错,把 Container Manager 项目日志贴出来,我可以帮你排查。