登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  文章 >  linux

Linux systemd.exec LoadCredential 怎样向服务传入文件凭据

来源:17golang原创

时间:2026-10-27 14:03:12 304浏览 收藏

如果 Linux 服务需要读取一个不适合写进环境变量的文件凭据,可以在 [Service] 中使用 LoadCredential=ID:绝对路径。systemd 会在服务启动时读取源文件,并把内容放进该单元专用的只读凭据目录;服务进程通过 $CREDENTIALS_DIRECTORY/ID 读取,而不是把主机上的原始路径直接暴露给应用。

官方文档:https://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html

最小可用做法是:把凭据源文件交给 systemd,在单元里用一个短 ID 绑定它,再让启动命令读取 ${CREDENTIALS_DIRECTORY}/ID。源文件必须能被服务管理器读取,服务进程本身只需要访问 systemd 准备好的只读副本。
  • 配置格式:LoadCredential=client-token:/etc/myapp/client-token。
  • 服务侧路径:优先使用 $CREDENTIALS_DIRECTORY/client-token,不要硬编码运行时目录。
  • 权限边界:凭据目录只对单元的 User= 或 DynamicUser= 对应用户和超级用户可见。
  • 大小边界:同一单元的凭据累计大小目前限制为 1 MB,适合密钥、证书和小型身份文件。

为什么 LoadCredential 比 Environment 更适合文件凭据

环境变量看起来很方便,但 systemd 官方文档明确提醒:单元环境可通过 D-Bus 暴露给非特权客户端,也会沿进程树传播,可能越过 setuid/setgid 等安全边界。因此,密码、密钥材料和证书这类内容不要直接写进 Environment= 或把文件内容展开到命令行。

LoadCredential= 面向的是“有限大小的二进制或文本对象”。systemd 读取源文件后,以单元专用目录中的只读文件交给服务;如果系统支持且条件允许,这个目录还会使用不可换出的内存后端。应用只需要知道凭据 ID,不必知道主机上的秘密文件布局。

systemd LoadCredential 从主机源文件到服务只读凭据目录的边界结构图
图1:LoadCredential 的输入文件、systemd 单元与服务只读凭据目录关系,这是静态结构说明图,不是运行截图。

用 ID 和绝对路径声明一个文件凭据

先准备一个仅允许服务管理器读取的源文件,例如 /etc/myapp/client-token。下面的单元片段只表达凭据绑定和读取方式,路径、用户与启动命令应替换成你的实际服务信息。

[Unit]
Description=读取文件凭据的示例服务

[Service]
# 用短 ASCII ID 作为服务侧文件名,冒号后是主机上的源文件
LoadCredential=client-token:/etc/myapp/client-token
# 服务进程以普通用户运行,凭据副本按该用户的访问边界提供
User=myapp
# %d 在 Environment= 中代表本单元的凭据目录
Environment=TOKEN_FILE=%d/client-token
# ExecStart 中可直接使用 CREDENTIALS_DIRECTORY 展开运行时路径
ExecStart=/usr/local/bin/myapp --token-file=${CREDENTIALS_DIRECTORY}/client-token

[Install]
WantedBy=multi-user.target

这里的 client-token 是凭据 ID,不要求和源文件同名;它必须是适合作为文件名的短 ASCII 字符串。绝对路径表示 systemd 直接打开一个普通文件并读取其内容。凭据内容可以包含换行或 NUL 字节,不应假设它一定是单行 UTF-8 文本。

如果启动程序已经支持从文件读取秘密,直接传入 --token-file 往往比把秘密改写成命令行参数更稳妥。若程序只接受配置路径,可以把 %d/client-token 写到 Environment= 中,但要传的是路径,不是秘密本身。

服务进程怎样找到凭据文件

服务进程最应该依赖 $CREDENTIALS_DIRECTORY。systemd 会把它导出为当前单元的凭据目录;在 ExecStart= 中可以用 ${CREDENTIALS_DIRECTORY}/client-token,在 Environment= 中则可用 %d/client-token。systemd 文档还说明,系统服务在无法插值的配置场景下可能使用 /run/credentials/UNITNAME,但应用接口优先选择环境变量。

#!/bin/sh
# 只把凭据文件交给应用,不把文件内容打印到日志
set -eu

token_file="${CREDENTIALS_DIRECTORY:?凭据目录未由 systemd 提供}/client-token"
# 让应用自行读取文件;不要用 cat 把秘密写入标准输出
exec /usr/local/bin/myapp --token-file "$token_file"

凭据源文件不一定需要对服务运行用户直接可读:systemd 先由服务管理器读取,再复制成单元专用的只读副本。这一点对 DynamicUser= 很有用,因为应用可以使用动态 UID,而不必让所有可能的 UID 都能读取主机源文件。

服务通过 CREDENTIALS_DIRECTORY 读取 LoadCredential 凭据的路径说明图
图2:服务只通过 CREDENTIALS_DIRECTORY 和凭据 ID 读取副本,源文件权限与应用运行用户是两层边界,这是静态操作示意图。

重载单元后怎样处理常见边界

单元文件修改后,先让 systemd 重新加载配置,再重启服务使新的凭据副本生成。下面命令中的注释说明每一步用途,命令输出不应包含凭据内容。

# 重新读取单元文件,避免继续使用旧配置
sudo systemctl daemon-reload
# 重启服务,让 systemd 重新装载凭据副本
sudo systemctl restart myapp.service
# 只查看服务状态和错误,不把凭据文件内容写入日志
sudo systemctl status myapp.service --no-pager
# 查看单元最终配置中的凭据声明,确认绑定的是预期源路径
sudo systemctl cat myapp.service

如果源路径是绝对文件且打不开,启动通常会失败;如果省略路径,或使用一个合法的凭据 ID 去继承管理器已收到的凭据,缺失凭据不一定被视为致命错误。因此,排查时先确认配置到底是“读取主机文件”还是“继承同名凭据”。

LoadCredential= 可以重复使用以传入多个凭据,但每个 ID 都应保持清晰且不重复。若需要传入目录,systemd 会递归装载其中的文件,并把每个凭据命名为给定 ID 加下划线和文件名;目录中的符号链接会被忽略。所有凭据加起来仍受单元级 1 MB 限制。

LoadCredential、加密凭据和 SetCredential 怎么选

普通 LoadCredential= 适合源文件已经由主机权限保护、需要在启动时以只读形式提供给服务的场景。若磁盘上不希望保存明文凭据,可以考虑 LoadCredentialEncrypted=:它读取由 systemd-creds 生成的加密凭据,在交给进程前完成解密和认证。

SetCredential= 是把字面值直接写进单元配置,不适合密码等秘密,因为这类值可能通过 IPC 被非特权进程看到。它更适合用户 ID、公钥材料等非敏感默认值;真正的秘密应优先放在受保护的源文件或加密凭据中。

需求更合适的方式注意点
主机上已有受保护文件LoadCredential=ID:/绝对路径服务管理器需能读取源文件
不想以明文落盘LoadCredentialEncrypted=需用匹配目标的 systemd-creds 加密
非敏感小型默认值SetCredential=不要把秘密直接写进单元

常见问题

LoadCredential 的 ID 可以写成任意字符串吗?

不能。ID 应是短 ASCII 字符串,并且适合作为文件名;不要使用空格、路径分隔符或含义不清的长字符串。

服务用户必须直接读取 /etc 下的源文件吗?

不必。源文件需要能被服务管理器读取,systemd 会准备单元专用的只读副本,再按 User= 或 DynamicUser= 的边界提供给进程。

为什么服务里没有 CREDENTIALS_DIRECTORY?

先确认进程确实由 systemd 单元启动,并检查 LoadCredential= 是否写在正确的 [Service] 段。随后执行 daemon-reload 和重启,避免仍在运行旧的单元配置。

可以把大文件当作凭据传入吗?

不适合。当前文档说明单元凭据累计大小限制为 1 MB;大文件应采用专门的文件访问或挂载方案,凭据机制更适合密钥、证书和小型身份信息。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>