如何安全向PM2管理的Node.js应用传递密码?
最优解决方案
方案1:权限受限临时文件方案(最高安全等级)
该方案完全避免敏感数据出现在进程环境变量中,从根源解决ps命令可读取的问题:
- 调整bash启动脚本,密码输入后写入当前用户专属的tmpfs路径(内存存储,系统重启自动清除),设置严格访问权限:
get_password () { read -s -p "Enter password:" if [[ -z $REPLY ]]; then get_password else echo $REPLY fi } PASSWORD=$(get_password) || exit 1 # 写入当前用户的运行时目录,属于内存文件系统,无落盘风险 PASS_FILE="/run/user/$UID/pm2_app_pass.tmp" echo -n "$PASSWORD" > "$PASS_FILE" chmod 0400 "$PASS_FILE" # 直接启动PM2,不需要传递敏感环境变量 pm2 start ecosystem.config.js
如果你的系统没有/run/user/$UID目录,可以替换为PASS_FILE=$(mktemp),mktemp会自动创建权限为0600的临时文件,仅当前用户可读写。
- 在Node应用入口最顶部读取密码,读取后立即清除痕迹:
const fs = require('fs') const PASSWORD = fs.readFileSync(`/run/user/${process.getuid()}/pm2_app_pass.tmp`, 'utf8') // 读取完成后可选择立即删除临时文件,不需要支持实例重启的场景建议开启 // fs.unlinkSync(`/run/user/${process.getuid()}/pm2_app_pass.tmp`)
业务代码直接使用PASSWORD变量即可,无需挂载到process.env上。
方案2:优化现有环境变量方案(改动最小)
如果不想大幅调整现有逻辑,仅优化现有代码即可大幅提升安全性:
- 首先删除原有代码中的
eval语句,该语句完全多余还会引入命令注入风险,直接传递环境变量即可:
# 替换原有的eval行 PASSWORD="$PASSWORD" pm2 start ecosystem.config.js
- 目前主流Linux发行版默认对
/proc/<pid>/environ做了权限限制,仅进程所有者和root可以读取,只要你的服务器没有其他不可信普通用户,该方案本身风险极低。 - 额外加固建议:在Node应用入口拿到密码后,立即删除环境变量中的敏感字段,成本极低但效果显著:
const PASSWORD = process.env.PASSWORD delete process.env.PASSWORD
操作后后续任何进程枚举、核心转储都无法获取到密码,完全不影响业务正常使用。
方案3:PM2全局环境注入
你也可以把密码注入到PM2的全局环境中,所有从该PM2实例启动的进程都能继承配置,同样仅需要输入一次密码:
PASSWORD="$PASSWORD" pm2 set env:PASSWORD "$PASSWORD" pm2 start ecosystem.config.js # 不需要使用密码时可删除配置 # pm2 delete env:PASSWORD
注意该方案会将密码保存在PM2的配置文件中,如果你不需要持久存储密码,使用完要及时删除配置项。
内容的提问来源于stack exchange,提问作者manidos
相关产品推荐
相关产品推荐

