Liwan 1.8 运维实操指南

Liwan 1.8 运维实操手册:systemd 服务管理、CLI 账号管理、冷备恢复、版本升级、Nginx 反代与真实 IP 透传、prune 数据治理与故障排查。

LiwanLiwanRust隐私安全2026/10/30

Liwan 1.8 运维实操指南

Liwan 装好之后,日常要面对的运维事项其实只有五类:进程管理(systemd)、账号管理(CLI)、数据治理(备份、保留策略、prune)、版本升级、以及放在最前面的反向代理接入。本文全部操作在 Ubuntu 22.04.5 LTS + Liwan v1.8.2 环境实测完成,命令与回显均为实际执行结果。安装与初始化流程见《Ubuntu 22.04 安装 Liwan 1.8 指南》,所有配置项的语义与默认值见《Liwan 1.8 配置参数详解》,产品定位与竞品对比见《Liwan 1.8 介绍与选型指南》。

💡 技术拓展:嵌入式数据库的运维心智模型与「外部数据库服务」不同。DuckDB/SQLite 是库文件而不是常驻服务,没有连接池要调、没有慢查询日志要看,运维重心从「调优服务」转移到「管好文件」:文件属主与权限、磁盘水位、备份窗口(必须在服务停止时做一致性备份)、以及单写者约束带来的「CLI 与服务互斥」。理解了这一层,本文的操作清单基本可以自行推导。

一、服务管理(systemd)

1.1 单元文件与开关机

按安装篇创建的 /etc/systemd/system/liwan.service 如下(按需调整 ExecStart 与 User):

[Unit]
Description=liwan web analytics
After=network.target

[Service]
ExecStart=/root/.local/bin/liwan
Restart=on-failure
User=root

[Install]
WantedBy=multi-user.target

日常操作速查:

sudo systemctl daemon-reload      # 改过单元文件后执行
sudo systemctl enable liwan       # 开机自启
sudo systemctl start liwan        # 启动
sudo systemctl restart liwan      # 重启(改配置、升级后)
sudo systemctl stop liwan         # 停止(执行 CLI、备份前)
systemctl is-active liwan         # 健康检查,返回 active
systemctl is-enabled liwan        # 自启检查,返回 enabled

enable 实测回显:

Created symlink /etc/systemd/system/multi-user.target.wants/liwan.service -> /etc/systemd/system/liwan.service.

1.2 状态与资源观测

systemctl status liwan --no-pager -n 0

实测回显:

* liwan.service - liwan web analytics
     Loaded: loaded (/etc/systemd/system/liwan.service; enabled; vendor preset: enabled)
     Active: active (running) since Fri 2026-10-30 02:13:39 UTC; 4s ago
   Main PID: 3511 (liwan)
      Tasks: 20 (limit: 2266)
     Memory: 28.1M

稳态内存占用 28 MB 量级(cgroup 口径;ps -eo rss,comm 进程 RSS 约 57 MB),20 个线程。中小流量站点 1 核 1 GB 机型绰绰有余,容量瓶颈一般先出现在磁盘(事件库文件随流量线性增长)。

1.3 日志查看与级别调整

journalctl -u liwan --no-pager -n 4      # 最近 4 行
journalctl -u liwan -f                   # 实时跟踪
journalctl -u liwan --since "2026-10-30 10:00" --until "2026-10-30 11:00"

实测回显(启动段):

Oct 30 02:13:39 liwan-server systemd[1]: Started liwan web analytics.
Oct 30 02:13:39 liwan-server liwan[3511]: 2026-10-30T02:13:39.093545Z  WARN liwan::config: Base URL is not using HTTPS
Oct 30 02:13:39 liwan-server liwan[3511]: 2026-10-30T02:13:39.110625Z  INFO liwan::web: Liwan is running on http://localhost:9042 (0.0.0.0:9042)

日志分 WARN/INFO 两级常驻输出。需要更细的排障信息时,用全局参数 --log-level 调高(该参数来自 liwan --help,默认 INFO)。改单元文件示例:

ExecStart=/root/.local/bin/liwan --log-level DEBUG

改完 daemon-reload && restart,排障完记得改回,DEBUG 级别日志量大。

二、账号管理(CLI)

Liwan 的用户管理有一组专用 CLI:add-user、users、update-password(liwan --help 可见全部 5 个子命令)。关键约束:这些命令与常驻服务互斥——服务持有 DuckDB 写锁时,CLI 会重试 10 次后失败退出,实测报错:

Error: Failed to load DuckDB Database after 10 attempts

Caused by:
    0: IO Error: Could not set lock on file "/root/.local/share/liwan/data/liwan-events.duckdb": Conflicting lock is held in /root/.local/bin/liwan (PID 2674). See also https://duckdb.org/docs/stable/connect/concurrency
    1: Error code 1: Unknown error code

标准操作序列:先 systemctl stop liwan,执行 CLI,再 start。

2.1 新建用户与列表

sudo systemctl stop liwan
liwan add-user --admin true ops q1w2e3r4
liwan users
sudo systemctl start liwan

add-user 实测回显:

2026-10-30T02:03:30.598451Z  WARN liwan::config: Base URL is not using HTTPS
User admin created

users 实测回显:

2026-10-30T02:03:30.631287Z  WARN liwan::config: Base URL is not using HTTPS
Users:
 - admin (admin)

括号内是角色(admin/普通用户)。两个语法要点:--admin 是带值参数必须写 --admin true;用户名仅限 3 位以上字母数字(与初始化向导的 pattern 一致)。注意 add-user 不带 --admin 创建的是普通用户,其可见项目由团队分配(Settings → Teams)决定。

2.2 重置密码

liwan update-password --help

实测回显:

Usage: liwan update-password [--] <username> <password>

Update a user's password

Positional Arguments:
  username          the username of the user to update
  password          the new password

Options:
  --help, help      display usage information

按 liwan update-password <用户名> <新密码> 执行即可,同样需先停服务。忘记管理员密码的场景下,这是唯一的自助恢复通道。

2.3 SSO 场景说明

接入 Google Workspace、Microsoft Entra ID 或 OIDC(Keycloak、Dex 等)后,日常账号增删走身份提供商,CLI 只保留本地账号兜底。SSO 的配置入口在看板 Settings 中,具体指引见官方文档 liwan.dev/guides/authentication/。

三、数据备份与恢复

3.1 备份对象

默认数据目录 $HOME/.local/share/liwan/data(可用 data_dir 改移),内含:

文件内容备份必要性
liwan-app.sqlite用户、项目、实体、看板设置必须
liwan-app.sqlite-shm / -walSQLite 读写伴生文件服务停止后消失,无需单独备
liwan-events.duckdb全部访问事件必须
liwan-events.duckdb.walDuckDB 预写日志服务停止后合并,无需单独备
GeoLite2-*.mmdb(如启用)自动下载的 MaxMind 库可不备(可重新下载)

3.2 冷备实测

一致性备份的正确姿势是「停服 → 打包 → 起服」:

sudo systemctl stop liwan
tar -czf /root/liwan-data-backup-$(date +%F).tar.gz -C ~/.local/share/liwan data
ls -la /root/liwan-data-backup-*.tar.gz
sudo systemctl start liwan

实测回显(打包与归档内容核验):

-rw-r--r-- 1 root root 10994 Oct 30 02:25 liwan-data-backup.tar.gz
data/
data/liwan-events.duckdb
data/liwan-app.sqlite

一个值得注意的实测细节:干净停止服务后,两个库的 WAL/SHM 伴生文件自动消失(检查点已合并落盘),所以归档里只有两个主库文件,天然一致。

3.3 恢复流程

目标机上先完成一次全新安装(保证二进制在位),然后:

sudo systemctl stop liwan
rm -rf ~/.local/share/liwan/data
tar -xzf liwan-data-backup-2026-10-30.tar.gz -C ~/.local/share/liwan/
sudo systemctl start liwan
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9042/   # 期望 200

启动日志不再出现 Applied migration 序列(库结构已存在)即恢复成功。注意恢复会连带还原所有账号密码,若原库密码已泄露应改走「全新初始化 + 重新配站点」路线。

3.4 磁盘水位

事件库增长速度取决于流量与采集项(会话指标、UTM、地理位置都显著增大行宽)。巡检建议:

du -sh ~/.local/share/liwan/data/
df -h ~/.local/share/liwan/

磁盘吃紧时优先按《Liwan 1.8 配置参数详解》4.2 节收紧保留周期与采集粒度,再用 liwan prune 清理历史。

四、版本升级

4.1 标准升级流程

Liwan 没有包管理器渠道,升级 = 换二进制 + 重启:

curl -JLO 'https://github.com/explodingcamera/liwan/releases/latest/download/liwan-x86_64-unknown-linux-musl.tar.gz'
tar -xzf liwan-x86_64-unknown-linux-musl.tar.gz -C ~/.local/bin liwan
sudo systemctl restart liwan
journalctl -u liwan --no-pager -n 5

升级后重点看两处:Liwan is running on ... 正常出现、无 ERROR 级日志。若版本跨越了库结构变更,启动日志会再次打印 Applied migration: Vx__xxx 序列,属于预期行为。

4.2 升级前检查

  1. 读 Releases 说明:v1.8.0 的先例——私有项目从「用户直授」改为「团队制」,升级后需把原直授用户重新分配进团队;追踪 npm 包从 liwan-tracker 改名 @liwan.dev/tracker,前端如有引用需同步改;
  2. 冷备一次(3.2 节流程),迁移不可逆时用于回退;
  3. 低峰执行:迁移在启动时同步进行,大库会拉长重启窗口。

追踪脚本托管在 Liwan 自身(/script.js),服务端升级后脚本自动同步,站内嵌入代码无需改动;仅当使用 npm 包 @liwan.dev/tracker 时需要随服务端一起升级(来源:liwan.dev/guides/tracking/)。

五、反向代理与真实客户端 IP

5.1 Nginx 实测配置

生产环境推荐「Nginx 80/443 对外 + Liwan 只听本机」,先把 listen 收紧为 127.0.0.1:9042(配置方法见《Liwan 1.8 配置参数详解》2.2 节),再配 Nginx 站点:

server {
    listen 80;
    server_name analytics.example.com;
    location / {
        proxy_pass http://127.0.0.1:9042;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

语法校验、启动与连通性实测:

nginx -t
systemctl start nginx
curl -s -X POST http://127.0.0.1:8080/api/event \
  -H "Content-Type: text/plain;charset=UTF-8" \
  -H "X-Forwarded-For: 203.0.113.77" \
  -d '{"name":"pageview","url":"https://blog.example.com/via-nginx","entity_id":"blog"}'

实测回显:

nginx: configuration file /etc/nginx/nginx.conf test is successful
{"status":"OK"}

Liwan 默认信任回环代理(trusted_proxies = ["127.0.0.1/8", "::1/128"]),同机 Nginx 无需改 Liwan 侧配置,注入的 X-Forwarded-For 即被采信为访客 IP。HTTPS 终结建议交给 Certbot(certbot --nginx -d analytics.example.com),证书就绪后把 base_url 改为 https 地址,启动日志的 HTTPS 警告随之消失。

5.2 Caddy 与容器网络场景

官方文档(liwan.dev/guides/reverse-proxy/)给出的 Caddy 配置仅三行,证书自动管理:

liwan.example.com {
    reverse_proxy localhost:9042
}

反向代理跑在独立网络/主机上时,必须把代理的实际来源网段加进 trusted_proxies(如容器网桥 172.17.0.0/16,用 docker network inspect 查实值),否则 Liwan 会把转发头当不可信输入丢弃,导致访客分组、GeoIP、退出信号、限流全部退化。多层 CDN 场景改用厂商预设头(cloudflare/akamai 等),写法见《Liwan 1.8 配置参数详解》3.1 节。

六、数据治理:保留、裁剪与清洗

6.1 prune 实测

prune 按「当前看板采集设置」清理历史数据,先预览后执行:

sudo systemctl stop liwan
liwan prune --dry-run
sudo systemctl start liwan

实测回显(4 条测试事件、未收紧任何设置):

2026-10-30T02:15:15.826926Z  WARN liwan::config: Base URL is not using HTTPS
blog: total=4, delete=0, clear_utm=0, clear_geo=0, clear_sessions=0
total: total=4, delete=0, clear_utm=0, clear_geo=0, clear_sessions=0
Dry run only. Re-run without --dry-run to apply changes.

逐实体输出五列:事件总数、将删除数、将清除 UTM 字段数、将清除地理字段数、将清除会话指标数。确认后去掉 --dry-run 真正执行。典型用途:把 UTM 采集关掉后清洗历史归因字段、缩短保留期后清掉过期事件、把地理精度从「国家+城市」降到「仅国家」后抹掉历史城市字段。

6.2 保留策略与 Drop rules

  • 保留周期在实体设置中按周期裁剪过期事件,建议按合规要求设定(如 6/12 个月);
  • Drop rules 在入库前丢弃匹配流量,适合过滤内部访问、测试环境来源、爬虫类 UA,比事后过滤省存储;
  • 两者都属于实体级设置(Settings → Entities),配置项语义见《Liwan 1.8 配置参数详解》4.2 节。

七、故障排查手册

现象原因处置
CLI 报 Failed to load DuckDB Database after 10 attempts服务在运行,写锁被占停服执行 CLI 后再起服(见第二节)
add-user 报 provided string was not 'true' or 'false'--admin 被当成开关写 --admin true
启动有 WARN Base URL is not using HTTPSbase_url 仍为 http套 TLS 后改 base_url(正常提示,非故障)
端口被占用启动失败9042 被其他进程占用`ss -ltnp
看板能看到访问但国家全是 Unknown未配 MaxMind 且无代理头来源按《Liwan 1.8 配置参数详解》4.1 节配置 geoip
经反代后访客分组异常、限流失效trusted_proxies 未含代理网段补网段(见 5.2 节)
嵌入脚本后无数据script 域名不可达 / data-entity 错误 / 实体 ID 不符先 curl /script.js 验 200,再核对 data-entity 与实体 ID
磁盘持续增长事件库随流量累积收紧保留期 + liwan prune(见 6.1 节)

八、日常巡检清单

建议纳入周巡检的低成本动作:

  1. systemctl is-active liwan 与 journalctl -u liwan --since "7 days ago" | grep -i error(应无输出);
  2. du -sh ~/.local/share/liwan/data/ 观察事件库增速,异常陡增时核对是否有突发流量或采集项变更;
  3. 备份任务在跑且归档可解(定期抽一份做恢复演练);
  4. curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9042/script.js 应为 200,确认追踪面健康;
  5. 关注 GitHub Releases,安全补丁版(如 v1.8.1 的证书更新)应及时跟进。

同类方案的运维侧对照阅读:《Offen 1.4.2 常用 CLI 命令与工具详解》(同为单二进制形态的账号与数据管理),多容器栈的运维差异可对比《Plausible Docker Compose 部署指南》与《Umami Docker Compose 部署指南》。