我正在尝试将我的应用程序部署到 Heroku,但是我依赖于使用一些私有 git 存储库作为模块。我这样做是为了项目之间的代码重用,例如,我有一个在多个应用程序中使用的自定义记录器。
"logger":"git+ssh://git@bitbucket.org..............#master"
问题是 Heroku 显然没有 ssh 访问此代码的权限。我在这个问题上找不到任何东西。理想情况下,Heroku 有一个公钥,我可以将其添加到模块中。
GitHub 支持基本身份验证:
"dependencies" : {
"my-module" : "git+https://my_username:my_password@github.com/my_github_account/my_repo.git"
}
和 BitBucket 一样:
"dependencies" : {
"my-module": "git+https://my_username:my_password@bitbucket.org/my_bitbucket_account/my_repo.git"
}
package.json
但是可能不需要在您的密码中使用纯密码。
为了使这个答案更加最新,我现在建议在 GitHub 上使用个人访问令牌,而不是用户名/密码组合。
您现在应该使用:
"dependencies" : {
"my-module" : "git+https://<username>:<token>@github.com/my_github_account/my_repo.git"
}
对于 Github,您可以在此处生成新令牌:
https://github.com/settings/tokens
应用程序密码主要用于提供与不支持双重身份验证的应用程序的兼容性,您也可以将它们用于此目的。首先,创建一个应用密码,然后像这样指定您的依赖项:
"dependencies" : {
"my-module": "git+https://<username>:<app-password>@bitbucket.org/my_bitbucket_account/my_repo.git"
}
对于 BitBucket,您可以在管理团队页面上生成一个 API 密钥,然后使用此 URL:
"dependencies" : {
"my-module" : "git+https://<teamname>:<api-key>@bitbucket.org/team_name/repo_name.git"
}
2016-03-26 更新
如果您使用的是 npm3,则所描述的方法不再有效,因为 npm3package.json
在运行preinstall
脚本之前会获取中描述的所有模块。这已被确认为一个错误。
官方的 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"
}
我提出了迈克尔的答案的替代方案,保留了(IMO)将您的凭据排除在源代码控制之外的有利要求,同时不需要自定义构建包。这是由于 Michael 链接的 buildpack已经过时而感到沮丧。
preinstall
解决方案是在 npm和脚本中设置和拆除 SSH 环境postinstall
,而不是在 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
postinstall.sh
: #!/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
将以下内容添加到您的package.json
:
"scripts": {
"preinstall": "bash preinstall.sh",
"postinstall": "bash postinstall.sh"
}
使用 生成私钥/公钥对ssh-agent
。
GIT_SSH_KEY
。当 Heroku 构建您的应用程序时,在 npm 安装您的依赖项之前,preinstall.sh
脚本会运行。这会根据环境变量的解码内容创建一个私钥文件GIT_SSH_KEY
,并创建一个 SSH 配置文件来告诉 SSH 在连接到github.com
. (如果您改为连接到 Bitbucket,则将Host
条目更新preinstall.sh
为bitbucket.org
)。然后 npm 使用这个 SSH 配置安装模块。安装后,删除私钥并擦除配置。
这允许 Heroku 通过 SSH 拉下您的私有模块,同时将私钥保留在代码库之外。如果您的私钥被泄露,因为它只是部署密钥的一半,您可以在 GitHub 中撤销公钥并重新生成密钥对。
顺便说一句,由于 GitHub 部署密钥具有读/写权限,如果您在 GitHub 组织中托管模块,则可以改为创建只读团队并为其分配“部署”用户。然后可以使用密钥对的公共部分配置部署用户。这为您的模块增加了一层额外的安全性。
在你的 git repo 中使用纯文本密码是一个非常糟糕的主意,使用访问令牌更好,但你仍然需要非常小心。
"my_module": "git+https://ACCESS_TOKEN:x-oauth-basic@github.com/me/my_module.git"
我创建了一个自定义 nodeJS buildpack,它允许您指定一个 SSH 密钥,该密钥在 ssh-agent 中注册并在首次设置 dynos 时由 npm 使用。它允许您无缝地将模块指定为 ssh url,package.json
如下所示:
"private_module": "git+ssh://git@github.com:me/my_module.git"
要设置您的应用程序以使用您的私钥:
ssh-keygen -t rsa -C "your_email@example.com"
不输入密码。buildpack 不支持带密码的密钥)pbcopy < ~/.ssh/id_rsa.pub
在 OS X 中)并将结果粘贴到 github admincat id_rsa | base64 | pbcopy
中,然后heroku config:set GIT_SSH_KEY=<paste_here> --app your-app-name
我的自定义 buildpack 可以在这里找到:https ://github.com/thirdiron/heroku-buildpack-nodejs它适用于我的系统。非常欢迎评论和拉取请求。
根据@fiznool 的回答,我创建了一个 buildpack 来使用存储为环境变量的自定义 ssh 密钥来解决这个问题。由于 buildpack 与技术无关,它可用于使用任何工具下载依赖项,如 php 的 composer、ruby 的 bundler、javascript 的 npm 等:https ://github.com/simon0191/custom-ssh-key-buildpack
将 buildpack 添加到您的应用程序:
$ heroku buildpacks:add --index 1 https://github.com/simon0191/custom-ssh-key-buildpack
生成一个没有密码的新 SSH 密钥(假设您将其命名为 deploy_key)
将公钥添加到您的私有存储库帐户。例如:
将私钥编码为 base64 字符串,并将其添加为CUSTOM_SSH_KEY
heroku 应用程序的环境变量。
制作应使用 ssh 密钥的主机的逗号分隔列表,并将其添加为CUSTOM_SSH_KEY_HOSTS
heroku 应用程序的环境变量。
# MacOS
$ heroku config:set CUSTOM_SSH_KEY=$(base64 --input ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
# Ubuntu
$ heroku config:set CUSTOM_SSH_KEY=$(base64 ~/.ssh/deploy_key) CUSTOM_SSH_KEY_HOSTS=bitbucket.org,github.com
我能够通过个人访问令牌在 Heroku 构建中设置 Github 私有存储库的解析。
heroku config:set GITHUB_TOKEN=<paste_here> --app your-app-name
或通过 Heroku Dashboard添加heroku-prebuild.sh
脚本:
#!/bin/bash
if [ "$GITHUB_TOKEN" != "" ]; then
echo "Detected GITHUB_TOKEN. Setting git config to use the security token" >&1
git config --global url."https://${GITHUB_TOKEN}@github.com/".insteadOf git@github.com:
fi
将预构建脚本添加到package.json
:
"scripts": {
"heroku-prebuild": "bash heroku-prebuild.sh"
}
对于本地环境,我们也可以使用git config ...
或者我们可以将访问令牌添加到~/.netrc
文件中:
machine github.com
login PASTE_GITHUB_USERNAME_HERE
password PASTE_GITHUB_TOKEN_HERE
并且安装私有 github 存储库应该可以工作。
npm install OWNER/REPO --save
将显示package.json
为:"REPO": "github:OWNER/REPO"
并在 Heroku 构建中解决私人回购也应该有效。可选地,您可以设置一个 postbuild 脚本来取消设置GITHUB_TOKEN
.
这个答案很好https://stackoverflow.com/a/29677091/6135922,但我改变了一点预安装脚本。希望这会对某人有所帮助。
#!/bin/bash
# Generates an SSH config file for connections if a config var exists.
echo "Preinstall"
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 o-w ~/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/deploy_key
# Setup the ssh config file.
echo -e "Host bitbucket.org\n"\
" IdentityFile ~/.ssh/deploy_key\n"\
" HostName bitbucket.org\n" \
" IdentitiesOnly yes\n"\
" UserKnownHostsFile=/dev/null\n"\
" StrictHostKeyChecking no"\
> ~/.ssh/config
echo "eval `ssh-agent -s`"
eval `ssh-agent -s`
echo "ssh-add -l"
ssh-add -l
echo "ssh-add ~/.ssh/deploy_key"
ssh-add ~/.ssh/deploy_key
# uncomment to check that everything works just fine
# ssh -v git@bitbucket.org
fi
您可以在 package.json 私有存储库中使用以下身份验证示例:
https://usernamegit:passwordgit@github.com/reponame/web/tarball/branchname
简而言之,这是不可能的。我想出的这个问题的最佳解决方案是使用新的git subtree。在撰写本文时,它们不在官方 git 源中,因此需要手动安装,但它们将包含在 v1.7.11 中。目前它可以在 homebrew 和 apt-get 上使用。然后就是这样做的情况
git subtree add -P /node_modules/someprivatemodue git@github.......someprivatemodule {master|tag|commit}
这会扩大 repo 的大小,但是通过使用 gitsubtree pull 执行上面的命令可以轻松进行更新。
我之前使用来自 github 的模块完成了此操作。Npm 当前接受包的名称或tar.gz
包含该包的文件的链接。
例如,如果您想直接从 Github 使用 express.js(通过下载部分获取链接),您可以这样做:
"dependencies" : {
"express" : "https://github.com/visionmedia/express/tarball/2.5.9"
}
tar.gz
因此,您需要找到一种通过 http(s)将存储库作为文件访问的方法。