systemd 245 配置 LoadCredential 后找不到凭据文件
先核对systemd 245不支持凭据的版本边界,再检查支持版本的ID、源文件与服务副本。
unit 写了 LoadCredential=credentials.json:/path/to/credentials.json,程序启动参数却变成 --credentials=/credentials.json。如果 ${CREDENTIALS_DIRECTORY} 展开为空,先核对服务管理器版本:systemd 245 尚不支持这套凭据功能,LoadCredential= 从 247 引入。
这不是把变量写成 $CREDENTIALS_DIRECTORY 就能解决的问题。源文件存在、服务用户在终端能读它,也不能让旧管理器生成凭据目录。
查版本,同时看配置解析日志
在实际管理这个服务的环境中检查,容器里的命令结果不能代替宿主机管理器:
systemctl --version
systemctl cat example-app.service
journalctl -u example-app.service -b -n 80 --no-pager
服务名换成实际名称,日志读取需要对应权限。查看 LoadCredential 是否被当成未知配置,以及最早的加载、启动错误。用户级服务则要使用所属用户的管理器和日志范围。
确认为 245 时,继续增加 Environment= 或 PassEnvironment= 不能补上这项功能。也不要硬编码 /run/credentials/... 来假装目录已经存在。
支持凭据的管理器怎样提供文件
在支持这项设置的环境中,管理器读取源文件,把凭据复制到该 unit 的只读目录,再将目录路径通过 CREDENTIALS_DIRECTORY 提供给进程。源文件需要管理器能读取;服务读取的是副本,不要求对原秘密文件开放同样权限。
以下只展示现有服务中相关设置,程序和参数都是占位示例:
[Service]
LoadCredential=credentials.json:/etc/example-app/credentials.json
ExecStart=
ExecStart=/usr/local/bin/example-app --credentials=${CREDENTIALS_DIRECTORY}/credentials.json
空的 ExecStart= 清除原命令,下一行应保留真实应用的全部必要参数。credentials.json 是凭据 ID,必须与访问副本的文件名一致;原有 User=、沙箱、环境和服务类型也要保留,不能用这个片段覆盖整个 unit。
变量在这里位于参数中。把变量放到程序名位置还有另一项限制,详见ExecStart 的程序名不能使用环境变量。当前文档在 Environment= 中引用凭据路径使用 %d/凭据ID,也不能机械照搬 shell 的变量展开方式;具体写法须以已安装版本支持的规则为准。
旧系统的迁移与支持版本的排错分开做
需要升级时,按发行版支持的系统升级流程安排,保存原 unit、源凭据保护设置和应用配置,在隔离环境验证服务启动。不要单独替换系统管理器二进制,也不要在升级尚未完成时删除原应用仍依赖的配置。
已经支持 LoadCredential,仍没有预期文件时,应重新核对有效 unit、凭据 ID、源路径和加载错误;不能继续把故障归给 245。应用的根目录或沙箱视图也应按实际情况检查,ProtectHome 隐藏家目录不等于源凭据必须对所有用户开放。
配置加载完成后,在允许中断的窗口重启目标服务。重启前保存需要保留的工作;daemon-reload 只重读定义,不会让原进程重新获得凭据。验收要看到应用以原定身份读到对应副本并完成正常请求,不要把打印秘密内容当作检查方法。回退应恢复应用和 unit 的原配置,保留凭据文件的受控权限。


