lldap 日常运维手册

lldap 0.6.3 日常运维闭环手册:日常巡检与告警白名单核对、备份与恢复(users.db 与 key_seed 成对原则)、监控告警、与 Authelia 对接 LDAP 认证最小实测、扩容缩容、升级与回滚、故障排查手册(WorkingDirectory 资源加载失败等实录)与常见问题,全部命令与回显实测照抄。

lldapIAM监控2026/10/19

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_dn dc=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 -ltngrep -E ':3890
3Web 可用性curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:17170/health200
4LDAP 绑定探活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 与检索结果。

十、参考链接

  1. 官方文档(database_migration/faq 等):https://github.com/lldap/lldap/tree/main/docs
  2. lldap v0.6.3 Release:https://github.com/lldap/lldap/releases/tag/v0.6.3
  3. SQLite 在线备份(.backup):https://www.sqlite.org/backup.html
  4. Authelia LDAP 认证文档:https://www.authelia.com/authentication/ldap/
  5. 本系列文档:《lldap 0.6.3 介绍与选型指南》《lldap Docker Compose 部署指南》《lldap 0.6.3 配置参数详解》