Heroku:私有存储库中的Python依赖项,而无需存储我的密码
我的问题就像我如何为Python Heroku项目安装内部要求?和规范答案,由Heroku自己的
My problem is exactly like How do I install in-house requirements for Python Heroku projects? and How to customize pip's requirements.txt in Heroku on deployment?. Namely, I have a private repo from which I need a Python dependency installed into my Heroku app. The canonical answer, given by Heroku's own Kenneth Reitz, is to put something like
-e git+https://username:password@github.com/kennethreitz/requests.git@v0.10.0#egg=requests
在您的requirements.txt
文件中.
出于安全考虑,我无法将密码存储在存储库中.(我也不希望将依赖项放入应用程序存储库中;它们是独立的软件,需要放在单独的软件中我只能将密码(或者最好是GitHub OAuth令牌或部署密钥)提供给Heroku的位置是在环境变量中,例如
My security needs prevent my storing my password in a repo. (I also do not want to put the dependency inside my app's repo; they're separate pieces of software and need to be in separate repos.) The only place I can give my password (or, preferably, a GitHub OAuth token or deployment key) to Heroku, is in an environment variable like
heroku config:add GITHUB_OAUTH_TOKEN=12312312312313
尝试的解决方案
我可以在应用的存储库中使用自定义的.profile
,但是每次 我将下载并安装依赖项时,进程(Web,Worker等)将重新启动.
Attempted Solutions
I could use a custom .profile
in my app's repo, but then I'd be downloading and installing my dependency each time a process (web, worker, etc) restarts.
这将使用自定义buildpack和 Heroku Labs插件在buildpack编译之前公开我的heroku config
环境.我在.buildpacks
文件,它首先下载常规的Heroku Python buildpack,然后下载我的自定义版本.
This leaves using a custom buildpack and the Heroku Labs addon that exposes my heroku config
environment before the buildpack compiles. I tried building one on top of Buildpack Multi. The idea is Buildpack Multi is the primary buildpack, and using the .buildpacks
file in my app's repo, it first downloads the normal Heroku Python buildpack, then my custom one.
问题甚至在于Buildpack Multi成功运行Python buildpack之后,
The trouble is even after Buildpack Multi successfully runs the Python buildpack, the Python binary and Pip package are not visible to my buildpack once Buildpack Multi runs. So the custom buildpack just fails outright. (In my tests, the GITHUB_OAUTH_TOKEN
environment variable was correctly exposed to the buildpacks.)
我想尝试尝试的另一件事是制作自己的Python buildpack分支,该分支在安装requirements.txt
中的所有内容时会安装我的依赖项,甚至直接重写requirements.txt
.对于我认为这是一个非常普遍的问题,这两种方法似乎都是沉重的解决方案.
The only other thing I can think to try is to make my own fork of the Python buildpack that installs my dependency when it installs everything from requirements.txt
, or even rewrites requirements.txt
directly. Both of these seem like really heavy solutions to what I would think is a very common problem.
我的自定义buildpack(上面链接)现在下载并将我的封闭源代码依赖项("foo")保存到geos buildpack使用的供应商目录中.我将foo本身对应用程序requirements.txt
的依赖项提交到我的应用程序中.因此,Pip通过我的应用程序的requirements.txt
安装foo的依赖项,并且buildpack将foo的供应商副本添加到我的应用程序的环境PYTHONPATH
(因此foo的setup.py install
永远不会运行).
My custom buildpack (linked above) now downloads and saves my closed-source dependency ("foo") into the vendor directory that the geos buildpack uses. I committed into my app the dependencies that foo itself has into my app's requirements.txt
. Thus Pip installs foo's dependencies through my app's requirements.txt
and the buildpack adds the vendored copy of foo to my app's environment's PYTHONPATH
(so foo's setup.py install
never runs).
这种方法的最大问题是将我的(公认的写得不好)buildpack与我的应用程序耦合在一起.第二个问题是我的应用程序的requirements.txt
应该仅将foo列为依赖项,并将foo的依赖项留给foo来确定.最后,从现在起的六个月内,如果忘记设置GITHUB_OAUTH_TOKEN环境变量(或者,如果生成令牌到期,环境变量仍然存在,但不再有效.
The biggest problem with this approach is coupling my (admittedly badly written) buildpack with my app. The second problem is that my app's requirements.txt
should just list foo as a dependency and leave foo's dependencies to foo to determine. Lastly, there isn't a good way to give myself in six months from now when I forget how I did all this an error message if I forget to set my GITHUB_OAUTH_TOKEN environment variable (or, producing even less useful error feedback would be if the token expires and the environment variable still exists but is no longer valid).
我缺少什么(可能很明显)?您如何在应用程序中解决此问题?关于使我的构建包正常工作的任何建议,还是希望有一个更简单的解决方案?
What (likely obvious) thing am I missing? How have you solved this problem in your apps? Any suggestions on getting my build pack to work, or hopefully an even simpler solution?
我创建了一个buildpack,用于使用存储为环境变量的自定义ssh密钥来解决此问题.由于buildpack与技术无关,因此可以使用任何工具(如php的composer,ruby的bundler,javascript的npm)来下载依赖项:
I created a buildpack to solve this problem using a custom ssh key stored as an environment variable. As the buildpack is technology agnostic, it can be used to download dependencies using any tool like composer for php, bundler for ruby, npm for javascript, etc: https://github.com/simon0191/custom-ssh-key-buildpack
-
将构建包添加到您的应用中:
Add the buildpack to your app:
$ heroku buildpacks:add --index 1 https://github.com/simon0191/custom-ssh-key-buildpack
生成一个新的SSH密钥(假设您将其命名为deploy_key)
Generate a new SSH key (lets say you named it deploy_key)
将公钥添加到您的私有存储库帐户.例如:
Add the public key to your private repository account. For example:
Bitbucket: https://confluence.atlassian.com/bitbucket/add-an-ssh-key-to-an-account-302811853.html
Bitbucket: https://confluence.atlassian.com/bitbucket/add-an-ssh-key-to-an-account-302811853.html
将私钥编码为base64字符串,并将其添加为heroku应用程序的CUSTOM_SSH_KEY
环境变量.
Encode the private key as a base64 string and add it as the CUSTOM_SSH_KEY
environment variable of the heroku app.
用逗号分隔列出要使用ssh密钥的主机列表,并将其添加为heroku应用程序的CUSTOM_SSH_KEY_HOSTS
环境变量.
Make a comma separated list of the hosts for which the ssh key should be used and add it as the CUSTOM_SSH_KEY_HOSTS
environment variable of the heroku app.
# 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