Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Installing a Gem on Heroku from a Private GitHub Repo

Installing a Gem on Heroku from a Private GitHub Repo

Sometimes you want to use a gem on Heroku that is in a private repository on GitHub.

Using git over http you can authenticate to GitHub using basic authentication. However, we don't want to embed usernames and passwords in Gemfiles. Instead, we can use authentication tokens.

  1. Get an OAuth Token from GitHub

First you will need to get an OAuth Token from GitHub using your own username and "note"

$ curl -u 'masonforest' -d '{"scopes":["repo"],"note":"Ventana Example App"}' https://api.github.com/authorizations
  1. Authenticate bundler to GitHub via OAuth Token

Add this line to your Gemfile replacing "your_token" with the token you got from step 1. In this example we are installing the 'ventana' gem:

gem 'ventana', git: "https://your_token:x-oauth-basic@github.com/thoughtbot/ventana.git"

EXPERIMENTAL ALTERNATIVE: Storing the OAuth token in an environment variable (more secure)

For additional security you can store your OAuth token in an environment variable. This way your token is not included in your codebase which is insecure. However this technique relies on on a Heroku labs feature which can change/be revoked at any time.

Change the line in your Gemfile to

gem 'ventana', git: "https://#{ENV['GITHUB_TOKEN']}:x-oauth-basic@github.com/thoughtbot/ventana.git"

Then set the your access token locally using the token you got from above:

$ export GITHUB_TOKEN=your_token

Now bundle and if everything works locally you are ready to deploy to Heroku!

Environment variables such as GITHUB_TOKEN are not available at build time to Heroku by default.

To make them available, you will need to enable the "user-env-compile" feature

$ heroku labs:enable user-env-compile -a ventana-demo

Finally add the GITHUB_TOKEN to your Heroku environment

$ heroku config:add GITHUB_TOKEN=your_token

You now have a private gem installed on Heroku!

@JonRowe

This comment has been minimized.

Copy link

JonRowe commented Jan 20, 2013

Awesome!

I tried using ENV variables in the past with a "deploy user" but it's much easier (and user specific) to create deploy tokens!

Sneaky hint for those on OS X, if you use .rvmrc files you can export the token in there meaning it can be app specific, or you can use .env and foreman...

@Agowan

This comment has been minimized.

Copy link

Agowan commented Feb 26, 2013

Hi,
this is a great way of bundle from private repositories at github. And the use of the environment variable is a great idea.

But if I'm not mistaken the token will be stored in the Gemfile.lock which basically will store the oauth token in your version control. Maybe I'm missing something, but whats the purpose of the environmental variables if it's stored in the lock file anyway?

@anagri

This comment has been minimized.

Copy link

anagri commented Mar 22, 2013

+1 to Agowan, I am facing the same issue. Will bundler in future support environment variables in Gemfile.lock ?

@ejholmes

This comment has been minimized.

Copy link

ejholmes commented Apr 14, 2013

I just opened a PR on the ruby buildpack to get better support for this: heroku/heroku-buildpack-ruby#85

@iainbeeston

This comment has been minimized.

Copy link

iainbeeston commented Mar 11, 2014

I've made a gem that solves this problem by vendoring the code in your source repo rather than using an oath token. My concern with the oath approach is not just that committing the token into source control is dangerous but that a github ouath token anywhere can give access to all your repositories. It's a question of which is the lesser of two evils.

https://github.com/new-bamboo/vendorise

@JoshCheek

This comment has been minimized.

Copy link

JoshCheek commented May 6, 2014

I think @iainbeeston's criticism of this approach is very valid, but I didn't need a gem to do it, just used bundle package --all

@icem

This comment has been minimized.

Copy link

icem commented May 28, 2014

Expirimental method don't work. This what we get when pushing to heroku

   Running: bundle install --without development:test --path vendor/bundle --binstubs vendor/bundle/bin -j4 --deployment
   You are trying to install in deployment mode after changing
   your Gemfile. Run `bundle install` elsewhere and add the
   updated Gemfile.lock to version control.

The problem is that Gemfile.lock don't have oauth token (because it's stored in git, that would be not secure to commit token). And because Gemfile.lock changes during bundle install, it refuses to continue.

@postmodern

This comment has been minimized.

Copy link

postmodern commented Jul 28, 2014

Storing the OAuth token in the ENV variable is NOT more secure. When you run bundle install it will save the fully qualified repository URLs into Gemfile.lock, which will then be committed and pushed to heroku. Also the repo OAuth scope is read-write, not read-only.

@siassaj

This comment has been minimized.

Copy link

siassaj commented May 6, 2015

I've built an alternative, today it's rough around the edges but we're gonna use it in production for a while so it should evolve.
https://github.com/siassaj/heroku-buildpack-git-deploy-keys

@adis-io

This comment has been minimized.

Copy link

adis-io commented May 26, 2015

Created separate user and gave read-only access.

@sebboh

This comment has been minimized.

Copy link

sebboh commented Jun 16, 2016

I've forked this gist with instructions on how to do this without committing your OAuth token to source control:
https://gist.github.com/sebboh/f1dfe4f096746c45f3e9ea06a09743a0

@simon0191

This comment has been minimized.

Copy link

simon0191 commented Feb 24, 2017

I created a buildpack to solve this problem using a custom ssh key stored as an environment variable: https://github.com/simon0191/custom-ssh-key-buildpack

Feedback is welcome :)

@esampaio

This comment has been minimized.

@nfedyashev

This comment has been minimized.

Copy link

nfedyashev commented Jan 8, 2019

@esampaio thanks for the link! Much easier indeed

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.