2016 年 3 月 26 日更新
如果您使用的是 npm3,则所描述的方法将不再有效,因为 npm3 在运行 preinstall 脚本之前会获取 package.json 中描述的所有模块。这个has been confirmed as a bug。
官方的node.js Heroku buildpack 现在包含heroku-prebuild 和heroku-postbuild,它们将分别在npm install 之前和之后运行。在所有情况下,您都应该使用这些脚本而不是 preinstall 和 postinstall,以同时支持 npm2 和 npm3。
换句话说,您的package.json 应该类似于:
"scripts": {
"heroku-prebuild": "bash preinstall.sh",
"heroku-postbuild": "bash postinstall.sh"
}
我想出了 Michael 的答案的替代方案,保留了 (IMO) 有利的要求,即使您的凭据不受源代码控制,同时不需要自定义 buildpack。这是因为buildpack linked by Michael 已经过时了。
解决方案是在 npm 的 preinstall 和 postinstall 脚本中设置和拆除 SSH 环境,而不是在 buildpack 中。
按照以下说明进行操作:
- 在您的存储库中创建两个脚本,我们称它们为
preinstall.sh 和 postinstall.sh。
- 使它们可执行 (
chmod +x *.sh)。
- 将以下内容添加到
preinstall.sh:
#!/bin/bash
# Generates an SSH config file for connections if a config var exists.
if [ "$GIT_SSH_KEY" != "" ]; then
echo "Detected SSH key for git. Adding SSH config" >&1
echo "" >&1
# Ensure we have an ssh folder
if [ ! -d ~/.ssh ]; then
mkdir -p ~/.ssh
chmod 700 ~/.ssh
fi
# Load the private key into a file.
echo $GIT_SSH_KEY | base64 --decode > ~/.ssh/deploy_key
# Change the permissions on the file to
# be read-only for this user.
chmod 400 ~/.ssh/deploy_key
# Setup the ssh config file.
echo -e "Host github.com\n"\
" IdentityFile ~/.ssh/deploy_key\n"\
" IdentitiesOnly yes\n"\
" UserKnownHostsFile=/dev/null\n"\
" StrictHostKeyChecking no"\
> ~/.ssh/config
fi
#!/bin/bash
if [ "$GIT_SSH_KEY" != "" ]; then
echo "Cleaning up SSH config" >&1
echo "" >&1
# Now that npm has finished running, we shouldn't need the ssh key/config anymore.
# Remove the files that we created.
rm -f ~/.ssh/config
rm -f ~/.ssh/deploy_key
# Clear that sensitive key data from the environment
export GIT_SSH_KEY=0
fi
当 Heroku 构建您的应用程序时,在 npm 安装您的依赖项之前,preinstall.sh 脚本会运行。这将根据GIT_SSH_KEY 环境变量的解码内容创建一个私钥文件,并创建一个 SSH 配置文件来告诉 SSH 在连接到github.com 时使用该文件。 (如果您改为连接到 Bitbucket,则将 preinstall.sh 中的 Host 条目更新为 bitbucket.org)。然后 npm 使用这个 SSH 配置安装模块。安装后,私钥被删除,配置被擦除。
这允许 Heroku 通过 SSH 拉下您的私有模块,同时将私钥保留在代码库之外。如果您的私钥被泄露,因为它只是部署密钥的一半,您可以在 GitHub 中撤销公钥并重新生成密钥对。
顺便说一句,由于 GitHub 部署密钥具有读/写权限,如果您在 GitHub 组织中托管模块,则可以改为创建只读团队并为其分配“部署”用户。然后可以使用密钥对的公共部分配置部署用户。这为您的模块增加了一层额外的安全性。