lldap 日常运维手册
lldap 0.6.3 日常运维闭环手册:日常巡检与告警白名单核对、备份与恢复(users.db 与 key_seed 成对原则)、监控告警、与 Authelia 对接 LDAP 认证最小实测、扩容缩容、升级与回滚、故障排查手册(WorkingDirectory 资源加载失败等实录)与常见问题,全部命令与回显实测照抄。
lldap 日常运维手册
目标:为 lldap 0.6.3 建立完整的日常运维闭环——巡检、备份恢复、监控告警、升级回滚、故障排查——并以端到端实测验证《Authelia 4.39 介绍与选型指南》对接 lldap 的 LDAP 认证链路。 实测声明:本文全部命令与回显均来自 2026-10-19 真实环境,逐字照抄。安装与参数细节见《lldap 0.6.3 配置参数详解》。
一、环境信息
- 操作系统:Ubuntu 24.04 LTS(x86_64),主机名
lldap-server - 软件版本:lldap 0.6.3(systemd 托管,二进制
/opt/lldap/lldap) - 配置:
/etc/lldap/lldap_config.toml(base_dndc=example,dc=com,LDAP 3890 / Web 17170) - 数据:
/var/lib/lldap/users.db(SQLite) - 服务账号:系统用户
lldap - 测试账号:管理员
admin/q1w2e3r4,普通用户jsmith/q1w2e3r4(组developers,测试环境值) - 对接端:另一台已部署的《Authelia 4.39 介绍与选型指南》服务器(IP
10.89.40.4,部署形态见《Authelia Docker Compose 部署指南》),lldap 服务器地址10.89.40.3 - 工具依赖:
curl、ldap-utils(ldapsearch/ldapwhoami)、sqlite3、ss(iproute2)
服务基态确认(实测回显):
# systemctl is-active lldap
active
# ss -ltn | grep -E ':3890|:17170'
LISTEN 0 2048 0.0.0.0:3890 0.0.0.0:*
LISTEN 0 2048 0.0.0.0:17170 0.0.0.0:*
二、日常巡检
2.1 巡检清单与口径
| 序号 | 巡检项 | 命令口径 | 正常判据 |
|---|---|---|---|
| 1 | 服务状态 | systemctl is-active lldap | 输出 active |
| 2 | 端口探活 | `ss -ltn | grep -E ':3890 |
| 3 | Web 可用性 | curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:17170/health | 200 |
| 4 | LDAP 绑定探活 | ldapwhoami(admin 凭据绑定) | 返回 dn:cn=admin,ou=people,... |
| 5 | 日志异常 | `journalctl -u lldap --since "24 hours ago" | grep -c ERROR` |
| 6 | 数据目录 | ls -la /var/lib/lldap/users.db | 文件存在、大小无异常跳变 |
2.2 巡检脚本
落地 /usr/local/lldap-scripts/lldap-check.sh:
#!/bin/bash
# lldap 日常巡检脚本:服务状态/端口探活/Web 可用性/LDAP 绑定/日志异常
echo "==== lldap 巡检 $(date '+%F %T') ===="
echo "-- 1. 服务状态 --"
systemctl is-active lldap
echo "-- 2. 端口探活 --"
ss -ltn | grep -E ":3890|:17170" || echo "ALERT: 端口未监听"
echo "-- 3. Web /health --"
curl -s -o /dev/null -w "health HTTP:%{http_code}\n" http://127.0.0.1:17170/health
echo "-- 4. LDAP 绑定探活 --"
ldapwhoami -x -H ldap://127.0.0.1:3890 -D "cn=admin,ou=people,dc=example,dc=com" -w q1w2e3r4 >/dev/null 2>&1 && echo "LDAP bind: OK" || echo "ALERT: LDAP bind 失败"
echo "-- 5. 近 24h ERROR 日志条数 --"
journalctl -u lldap --since "24 hours ago" | grep -c "ERROR"
echo "-- 6. 数据目录 --"
ls -la /var/lib/lldap/users.db | awk '{print $5, $9}'
执行结果(实测回显):
# chmod +x /usr/local/lldap-scripts/lldap-check.sh
# /usr/local/lldap-scripts/lldap-check.sh
==== lldap 巡检 2026-10-19 05:33:28 ====
-- 1. 服务状态 --
active
-- 2. 端口探活 --
LISTEN 0 2048 0.0.0.0:3890 0.0.0.0:*
LISTEN 0 2048 0.0.0.0:17170 0.0.0.0:*
-- 3. Web /health --
health HTTP:200
-- 4. LDAP 绑定探活 --
LDAP bind: OK
-- 5. 近 24h ERROR 日志条数 --
13
-- 6. 数据目录 --
139264 /var/lib/lldap/users.db
第 5 项的 13 条 ERROR 均为当日 SMTP 项实验留下的已知错误(见 8.3 节),属"已知告警白名单"情形;稳态环境该值应为 0,非 0 时按第八章逐条核对。
2.3 cron 化巡检
# apt-get install -y cron 2>&1 | tail -1
# systemctl enable --now cron
Synchronizing state of cron.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing /usr/lib/systemd/systemd-sysv-install enable cron
# (crontab -l 2>/dev/null; echo "30 8 * * * /usr/local/lldap-scripts/lldap-check.sh >> /var/log/lldap-check.log 2>&1") | crontab -
# crontab -l | tail -1
30 8 * * * /usr/local/lldap-scripts/lldap-check.sh >> /var/log/lldap-check.log 2>&1
2.4 内置健康检查命令
lldap 自带 healthcheck 子命令(对 LDAP 与 GraphQL 双端口做真实探测):
# /opt/lldap/lldap healthcheck --config-file /etc/lldap/lldap_config.toml
2026-10-19T05:35:19.231040080+00:00 INFO ┝━ i [info]: Testing LDAP
2026-10-19T05:35:19.231691204+00:00 INFO ┕━ i [info]: Testing GraphQL
退出码 0 即双端口正常;巡检脚本第 3/4 项可整体替换为该命令。
三、备份与恢复
3.1 备份策略
| 对象 | 方式 | 频率建议 |
|---|---|---|
users.db(用户/组/会话库) | sqlite3 .backup 在线热备 | 每日 |
private_key(服务端密钥,若未用 key_seed) | 文件拷贝,与库成对 | 变更时 + 每日 |
/etc/lldap/lldap_config.toml(含口令密钥,注意保管) | 文件拷贝 | 变更时 |
在线热备实测:
# mkdir -p /var/backups/lldap
# sqlite3 /var/lib/lldap/users.db ".backup /var/backups/lldap/users-$(date +%Y%m%d).db"
# ls -la /var/backups/lldap/
total 144
drwxr-xr-x 2 root root 4096 Oct 19 05:24 .
drwxr-xr-x 1 root root 4096 Oct 19 05:24 ..
-rw-r--r-- 1 root root 139264 Oct 19 05:24 users-20261019.db
成对原则:口令 blob 以服务端密钥加密(本文环境用
key_seed派生,种子值须同步备份);只备库不备密钥,恢复后所有用户将无法登录(详见《lldap 0.6.3 配置参数详解》5.4)。
3.2 恢复演练(删除 → 恢复 → 验证)
① 模拟数据丢失(删除用户 jsmith,实测回显):
# curl -s -X POST http://127.0.0.1:17170/api/graphql -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" -d '{"query":"mutation { deleteUser(userId: \"jsmith\") { ok } }"}'
{"data":{"deleteUser":{"ok":true}}}
# ldapsearch -x -H ldap://127.0.0.1:3890 -D "cn=admin,ou=people,dc=example,dc=com" -w q1w2e3r4 -b "dc=example,dc=com" "(uid=jsmith)" dn
# 0 个匹配条目(search result: success,无 dn 输出)
② 停服 → 还原 → 起服:
# systemctl stop lldap
# cp /var/backups/lldap/users-20261019.db /var/lib/lldap/users.db && chown lldap:lldap /var/lib/lldap/users.db
# systemctl start lldap
# systemctl is-active lldap
active
③ 恢复后验证(用户、组关系、口令全部还原,实测回显):
# ldapsearch -x -H ldap://127.0.0.1:3890 -D "cn=admin,ou=people,dc=example,dc=com" -w q1w2e3r4 -b "dc=example,dc=com" "(uid=jsmith)" dn memberOf 2>&1 | grep -E "dn:|memberOf"
dn: uid=jsmith,ou=people,dc=example,dc=com
memberOf: cn=developers,ou=groups,dc=example,dc=com
# curl -s -X POST http://127.0.0.1:17170/auth/simple/login -H "Content-Type: application/json" -d '{"username":"jsmith","password":"q1w2e3r4"}' | head -c 80
{"token":"eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3OTIzODA5...
演练结论:SQLite 文件级恢复完整还原用户/组/口令,RTO ≈ 秒级(停服+拷文件+起服)。
四、监控告警
4.1 指标口径与告警阈值
| 指标 | 采集口径 | 告警阈值(建议) | 处置指引 |
|---|---|---|---|
| 服务活性 | systemctl is-active lldap | ≠ active 持续 1 个周期 | 第八章 8.1/8.2 |
| LDAP 可用性 | 3890 端口 TCP 探活 + ldapwhoami 绑定 | 失败 2 个周期 | 第八章 8.1 |
| Web 可用性 | GET /health 返回码 | ≠ 200 持续 2 个周期 | 第八章 8.1 |
| ERROR 日志增量 | journalctl --since 时间窗 grep 计数 | 新增 > 0 且非白名单 | 第八章 8.2–8.4 |
| 数据库体积 | stat -c %s users.db | 环比跳变 > 50% | 排查异常写入 |
| 常态内存 | ps -o rss= -C lldap | > 256 MiB(实测基线 16 MiB,见 6.1) | 排查异常 |
4.2 告警实现建议
最小闭环:直接复用 2.2 节巡检脚本,把 ALERT: 行与 ERROR 计数接 webhook(钉钉/企飞书机器人均可),cron 密度可调到每 5 分钟。想要可视化与独立探测点时,推荐用既有监控栈对 lldap 做 HTTP 探测(http://10.89.40.3:17170/health)与 TCP 探测(3890)双探针,具体部署与告警配置见《Gatus 介绍与选型指南》专栏文档。注意:探针应至少覆盖内网 LDAP 3890 与 Web 17170 两路,二者故障域不同(LDAP 故障通常只影响下游应用认证,Web 故障影响管理入口)。
五、与 Authelia 对接 LDAP 认证最小实测
目标:验证下游认证组件《Authelia 4.39 介绍与选型指南》能否以 lldap 为用户源完成端到端登录认证(用户检索 → LDAP 绑定 → 组读取)。
5.1 对接前提
- lldap 侧:admin 绑定 DN
cn=admin,ou=people,dc=example,dc=com;测试用户jsmith(组developers); - Authelia 侧(IP
10.89.40.4,启用自签 TLS)configuration.yml关键段:
authentication_backend:
ldap:
implementation: 'lldap'
address: 'ldap://10.89.40.3:3890'
timeout: '5s'
start_tls: false
base_dn: 'DC=example,DC=com'
additional_users_dn: 'OU=people'
users_filter: '(&({username_attribute}={input})(objectClass=person))'
additional_groups_dn: 'OU=groups'
groups_filter: '(member={dn})'
attributes:
display_name: 'displayName'
mail: 'mail'
member_of: 'memberOf'
group_name: 'cn'
user: 'CN=admin,OU=people,DC=example,DC=com'
password: 'q1w2e3r4'
implementation: 'lldap'会让 Authelia 采用与 lldap 目录约定匹配的默认属性映射;cookie 域配置须与实际访问地址一致(踩坑记录见 8.4 节)。
5.2 认证实测(正向 + 反向)
① 正向:jsmith 正确口令(实测回显)
$ curl -sk -w "\nHTTP:%{http_code}\n" -X POST https://10.89.40.4:9091/api/firstfactor \
-H "Content-Type: application/json" \
-d '{"username":"jsmith","password":"q1w2e3r4","targetURL":"https://example.com","keepMeLoggedIn":false}'
{"status":"OK"}
HTTP:200
② 反向:jsmith 错误口令(实测回显)
$ curl -sk -w "\nHTTP:%{http_code}\n" -X POST https://10.89.40.4:9091/api/firstfactor \
-H "Content-Type: application/json" \
-d '{"username":"jsmith","password":"wrongpass","targetURL":"https://example.com","keepMeLoggedIn":false}'
{"status":"KO","message":"Authentication failed. Check your credentials."}
HTTP:401
③ 管理员账号认证(实测回显)
$ curl -sk -w "\nHTTP:%{http_code}\n" -X POST https://10.89.40.4:9091/api/firstfactor \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"q1w2e3r4","targetURL":"https://example.com","keepMeLoggedIn":false}'
{"status":"OK"}
HTTP:200
5.3 两侧证据链
- lldap 侧日志(
verbose = true)可见 Authelia 的完整 LDAP 行为:先以 admin DN 成功绑定检索用户(passwords_match succeeded for user admin→list_users返回 jsmith 及其组developers),再以用户 DN(uid=jsmith,ou=people,dc=example,dc=com)完成绑定; - Authelia 侧日志记录失败路径的原始错误(实测回显):
time="2026-10-19T05:28:03Z" level=error msg="Unsuccessful 1FA authentication attempt by user 'jsmith'" error="authentication failed. Cause: error occurred performing bind: LDAP Result Code 49 \"Invalid Credentials\": " method=POST path=/api/firstfactor remote_ip=10.89.40.1
结论:三态(正确/错误/管理员)全部符合预期,lldap 可直接作为《Authelia 4.39 介绍与选型指南》的 LDAP 用户源;《Authentik 介绍与选型指南》《ZITADEL v4.19.5 介绍与选型指南》《Keycloak 介绍与选型指南》等以 LDAP 方式消费 lldap 的对接参数可参考 5.1 的 DN 与过滤器形态。
六、扩容缩容
6.1 资源基线(实测)
# systemctl status lldap --no-pager | grep Memory
Memory: 2.3M
# ps -o rss=,comm= -C lldap | awk '{print $1/1024 " MiB"}'
16.2656 MiB
# du -h /var/lib/lldap/users.db
136K /var/lib/lldap/users.db
- 内存:启动态 ≈2.3 MiB,持续运行带活跃会话后 ≈16 MiB(均为实测值);
- 磁盘:3 用户 + 4 组的库文件 136 KB,用户量级到数千时仍为个位数 MB(SQLite 行存);
- 带宽:LDAP 查询为短连接小报文,千级用户每日登录的负载远低于单核上限。
6.2 扩缩容结论
- 纵向:当前基线远低于任何节点瓶颈,无需扩容动作;
- 横向:lldap 为单写者模型(单库单实例),不支持多实例共写;"扩容"的正确路径是把
database_url切到 MySQL/PostgreSQL 并按官方docs/database_migration.md迁移,或维持单实例——其资源占用决定了这几乎不会被触发; - 下游弹性:下游应用(《Authelia 4.39 介绍与选型指南》等)数量增长不影响 lldap 形态,只需保证网络可达与绑定 DN 配额。
七、升级与回滚
7.1 版本核验
# /opt/lldap/lldap --version
lldap 0.6.3
# curl -s -o /dev/null -w '%{redirect_url}\n' https://github.com/lldap/lldap/releases/latest
https://github.com/lldap/lldap/releases/tag/v0.6.3
(当前已为最新稳定版;Pre-release 不纳入升级目标。)
7.2 升级演练(v0.6.2 → v0.6.3 实测)
lldap 升级即"换二进制 + 重启",schema 由服务自动迁移。真实演练:用 v0.6.2 初始化一份独立数据目录(schema 从 v1 建到 v10),再以 v0.6.3 接管同一目录——
v0.6.2 初始化(实测回显节选):
2026-10-19T05:42:25.078639675+00:00 INFO ┝━ i [info]: Starting LLDAP version 0.6.2
2026-10-19T05:42:25.087738532+00:00 INFO ┝━ i [info]: Upgrading DB schema from version 1
2026-10-19T05:42:25.087740167+00:00 INFO ┝━ i [info]: Upgrading DB schema to version 2
2026-10-19T05:42:25.090003051+00:00 INFO ┝━ i [info]: Upgrading DB schema to version 3
...
v0.6.3 接管同数据目录(实测回显):
2026-10-19T05:43:01.698842968+00:00 INFO ┝━ i [info]: Starting LLDAP version 0.6.3
2026-10-19T05:43:01.699669362+00:00 INFO ┝━ i [info]: Upgrading DB schema from version 10
2026-10-19T05:43:01.699670445+00:00 INFO ┝━ i [info]: Upgrading DB schema to version 11
# curl -s -o /dev/null -w "0.6.3 health HTTP:%{http_code}\n" http://127.0.0.1:17171/health
0.6.3 health HTTP:200
# curl -s -X POST http://127.0.0.1:17171/auth/simple/login -H "Content-Type: application/json" -d '{"username":"admin","password":"q1w2e3r4"}' | head -c 60
{"token":"eyJhbGciOiJIUzUxMiJ9.eyJleHAiOjE3OTI0NzQ5ODYsImlh
演练结论:跨版本 schema 自动迁移(10 → 11),数据与口令完好;服务端密钥(key_seed)跨版本保持一致是登录成功的前提。
7.3 标准升级流程(生产)
# 1. 全量备份(第三章)
sqlite3 /var/lib/lldap/users.db ".backup /var/backups/lldap/users-pre-upgrade.db"
# 2. 下载新版二进制并解压到新目录
curl -LO https://github.com/lldap/lldap/releases/download/v0.6.4/amd64-lldap.tar.gz
tar xzf amd64-lldap.tar.gz -C /opt/lldap-new --strip-components=1
# 3. 换二进制并重启
systemctl stop lldap && mv /opt/lldap /opt/lldap.old && mv /opt/lldap-new /opt/lldap
systemctl start lldap
# 4. 验证(巡检脚本 6 项 + 下游应用登录)
/usr/local/lldap-scripts/lldap-check.sh
7.4 回滚
只回滚二进制(schema 已升级,旧版无法读新库):恢复方式是"还原备份库 + 旧版二进制"成对回滚——systemctl stop lldap → 还原 users-pre-upgrade.db → 恢复 /opt/lldap.old → systemctl start lldap。这也是升级前必须备份的原因。
八、故障排查手册
8.1 服务无法启动 / 端口未监听
先看实时日志:
# journalctl -u lldap -f --no-pager
常见两类:配置错误(如 8.2 的 jwt_secret 缺失,日志有明确 Configuration error)与端口占用(ss -ltnp | grep -E '3890|17170' 查占用进程)。
8.2 Web UI 打不开但服务 active(assets 路径问题)
现象:服务 active、LDAP 正常,浏览器访问 Web UI 样式/页面异常。日志原始报错(实测):
Oct 19 05:13:02 lldap-server lldap[1417]: 2026-10-19T05:13:02.532969106+00:00 WARN ┝━ w [warn]: Cannot find ./app, please ensure that assets_path is set correctly!
Oct 19 05:13:02 lldap-server lldap[1417]: 2026-10-19T05:13:02.533031862+00:00 WARN ┕━ w [warn]: The LLDAP admin UI will not be accessible!
Oct 19 05:13:02 lldap-server lldap[1417]: 2026-10-19T05:13:02.534165399+00:00 ERROR ┝━ e [error]: Failed serving the index page: Request error: IO error: No such file or directory (os error 2)
根因:systemd 未设置 WorkingDirectory,Web 前端资源默认按相对路径 ./app 查找。修复:单元文件 [Service] 段补 WorkingDirectory=/opt/lldap → systemctl daemon-reload && systemctl restart lldap。复验(实测):
# journalctl -u lldap --no-pager -n 12 | grep -E 'Cannot find|listening'
(无告警输出)
# curl -s -o /dev/null -w 'GET / -> %{http_code}\n' http://127.0.0.1:17170/
GET / -> 200
8.3 邮件类:连接拒绝 / 认证机制不兼容(原始报错实测)
① SMTP 服务器不可达(server=127.0.0.1、port=2525、无监听,触发找回邮件):
# curl -s -w "\nHTTP:%{http_code}\n" -X POST "http://127.0.0.1:17170/auth/reset/step1/jsmith@example.com"
Internal server error: `Could not send email: Error sending email: Connection error: Connection refused (os error 111)`
HTTP:500
服务端 DEBUG 明细(verbose = true,实测):
DEBUG ┝━ i [info]: Sending email to 'jsmith@example.com' as 'LLDAP Admin <noreply@example.com>' via 'noreply@example.com'@'127.0.0.1':'2525'
DEBUG ┝━ 🐛 [debug]: Error sending email: lettre::transport::smtp::Error { kind: Connection, source: Os { code: 111, kind: ConnectionRefused, message: "Connection refused" } }
WARN ┕━ 🚧 [warn]: Error sending email: "Error sending email: Connection error: Connection refused (os error 111)"
② smtp_encryption = "NONE" 时配置了 user/password(服务端拒绝明文认证,实测):
Internal server error: `Could not send email: error response to `AUTH` command: 535 5.7.8 Error: authentication failed: No compatible authentication mechanism was found (os error 335)`
HTTP:500
处置:NONE 模式去掉凭据(匿名中继);或改 STARTTLS/TLS + 凭据。修复后复验返回 HTTP:200 且收件器收到主题为 [LLDAP] Password reset requested 的邮件(全文样例见《lldap 0.6.3 配置参数详解》5.6)。
8.4 下游应用认证失败三连(Authelia 实例,原始报错实测)
① 请求地址与会话 cookie 域不匹配(LDAP 链路已通,但 Authelia 拒绝响应):
time="2026-10-19T05:28:02Z" level=error msg="Failed to get session provider during 1FA attempt" error="unable to retrieve session cookie domain provider: no configured session cookie domain matches the url 'https://127.0.0.1:19091/api/firstfactor'" method=POST path=/api/firstfactor remote_ip=10.89.40.1
处置:session.cookies[].domain 必须覆盖实际访问主机名(本例改为 10.89.40.4 后恢复)。
② 口令错误(LDAP Result Code 49,实测见 5.3)——属正常拒绝,非故障。
③ 绑定 DN 形态错误:lldap 用户 DN 固定为 uid=<ID>,ou=people,<base_dn>、组为 cn=<组名>,ou=groups,<base_dn>,过滤器和管理员 DN 均按此书写。
8.5 GraphQL 入参错误(原始报错实测)
addUserToGroup 旧参数形态会得到 schema 明示报错:
{"errors":[{"message":"Unknown argument \"group\" on field \"Mutation.addUserToGroup\".","locations":[{"line":1,"column":45}]}],"data":null}
处置:改用 userId/groupId(正确用法与完整回显见《lldap 0.6.3 配置参数详解》6.3)。
九、常见问题
Q1:巡检脚本第 5 项 ERROR 计数长期非 0?
对照 8.3 的两类 SMTP 错误与 8.2 的 assets 告警排除已知项;verbose = true 期间 DEBUG 不计入 ERROR。稳态下应为 0。
Q2:备份能否只拷 users.db 文件?
运行中直接拷贝有读到半事务的风险,必须用 sqlite3 .backup(3.1 节实测)或停服拷贝;且必须与 key_seed/private_key 成对保管。
Q3:升级后旧版能直接跑新库吗? 不能。schema 版本单调上升(实测 10 → 11),回滚须按 7.4 成对回滚(旧库 + 旧二进制)。
Q4:lldap 挂了,下游应用会立刻瘫痪吗? 已认证用户不受影响(下游持有有效 token/session);新登录/认证失败。按 4.1 阈值告警并重启即可,RTO 极小(单二进制秒级启动)。
Q5:如何确认下游应用使用的绑定 DN 是否正确?
在 lldap 侧 verbose = true 后观察 journalctl -u lldap 的 BindRequest 行(5.3 节证据链),可直接看到下游使用的 DN 与检索结果。
十、参考链接
- 官方文档(database_migration/faq 等):https://github.com/lldap/lldap/tree/main/docs
- lldap v0.6.3 Release:https://github.com/lldap/lldap/releases/tag/v0.6.3
- SQLite 在线备份(.backup):https://www.sqlite.org/backup.html
- Authelia LDAP 认证文档:https://www.authelia.com/authentication/ldap/
- 本系列文档:《lldap 0.6.3 介绍与选型指南》《lldap Docker Compose 部署指南》《lldap 0.6.3 配置参数详解》