Liwan 1.8 运维实操指南
Liwan 1.8 运维实操手册:systemd 服务管理、CLI 账号管理、冷备恢复、版本升级、Nginx 反代与真实 IP 透传、prune 数据治理与故障排查。
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 / -wal | SQLite 读写伴生文件 | 服务停止后消失,无需单独备 |
| liwan-events.duckdb | 全部访问事件 | 必须 |
| liwan-events.duckdb.wal | DuckDB 预写日志 | 服务停止后合并,无需单独备 |
| 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 升级前检查
- 读 Releases 说明:v1.8.0 的先例——私有项目从「用户直授」改为「团队制」,升级后需把原直授用户重新分配进团队;追踪 npm 包从
liwan-tracker改名@liwan.dev/tracker,前端如有引用需同步改; - 冷备一次(3.2 节流程),迁移不可逆时用于回退;
- 低峰执行:迁移在启动时同步进行,大库会拉长重启窗口。
追踪脚本托管在 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 HTTPS | base_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 节) |
八、日常巡检清单
建议纳入周巡检的低成本动作:
systemctl is-active liwan与journalctl -u liwan --since "7 days ago" | grep -i error(应无输出);du -sh ~/.local/share/liwan/data/观察事件库增速,异常陡增时核对是否有突发流量或采集项变更;- 备份任务在跑且归档可解(定期抽一份做恢复演练);
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:9042/script.js应为 200,确认追踪面健康;- 关注 GitHub Releases,安全补丁版(如 v1.8.1 的证书更新)应及时跟进。
同类方案的运维侧对照阅读:《Offen 1.4.2 常用 CLI 命令与工具详解》(同为单二进制形态的账号与数据管理),多容器栈的运维差异可对比《Plausible Docker Compose 部署指南》与《Umami Docker Compose 部署指南》。