I'm using GitHub for code and Heroku for the deployment platform for my rails app.
I don't want to have sensitive data under Git. Such data include database file settings (database.yml) and some other files that have secret API keys.
When I deploy to heroku, how can I deal with files that are not under revision control.
When I use Capistrano, I can write some hook methods, but I don't know what to do with Heroku.
For Heroku, you'll need to have database.yml under Git because Heroku will automatically read it and create a PostgreSQL configuration from it.
For other sensitive information such as API keys, Heroku provide config vars which are effectively environment variables. You can add them using:
heroku config:add KEY=value
—and access them from within your application using:
ENV['KEY']
Note that config vars can be listed, added and removed using the heroku command-line program and that once set they are persistent.
Heroku Config Vars documentation
I would create a local branch, let's call it SECRET, and make the 'secret' modifications there. Commit them and DO NOT push them to github.
Now just checkout and keep working on the master branch till ready to release.
To prepare the release checkout the SECRET branch, merge the master branch into it, and push it to heroku as usual.
(BTW : I always forget to switch back to the work branch, git stash is your friend in this case)
Related
I have an app being developed on github. I want to opensource it. Currently we use a capistrano script to deploy to our staging & production servers.
I am trying to figure out how we can put our config files in a separate repo, and still use capistrano to execute one touch deploys. The goal is that we can open up our repo for anyone to use.
You have some options.
Use environment variables: You can set environment variables at both your local and production machines. In your app you'll read these vars by doing: <%= ENV['my_var'] %>. Doing this you can commit your app to a public repo without worrying about expose sensitive information like passwords and keys. For example, set a db_password environment var to store your database password and in your database.yml you could read it doing: password: <%= ENV['db_password'] %>
You can use gems link dotenv (https://github.com/bkeepers/dotenv) or figaro (https://github.com/laserlemon/figaro): By using these gems you won't need to set environment variables manually on your machines, you will define them in a .env file instead. You'll be able to read them the same way using <%= ENV['my_var'] %>. You will have to ignore your .env files at your .gitignore and tell capistrano to create the environment variables at your production server reading from your .env file.
Another alternative would be make different config files for development and production and ignore them in your .gitignore. You can store your config production files in a different repo and have it updated on your machine at the time of your deploy. You'll just need to copy your config files from your local machine to the production server (https://coderwall.com/p/wgs6gw/copy-local-files-to-remote-server-using-capistrano-3) after updating the app repo on your production server.
The last alternative is the one I use most (in my case I use ansible in place of capistrano).
If you wanna see an example I have an application and a deployment task currently running in production that you can checkout:
Application: https://github.com/josuelima/bolao
Provisoning and Deployment: https://github.com/josuelima/ansible-sandbox
Hope I made myself clear and you got the idea.
I am trying to deploy a rails app to heroku, and I know that their file system is read only, and it only contains the latest code. I am using a git repository, via this guide. I have a config file, holding passwords and other stuff that I don't want to track on git, but I have to upload them to heroku. How can I accomplish that?
Rather than store the confidential info in the app files, set them up as environment variables on heroku using config vars
Ref: https://stackoverflow.com/a/7832040/429758
I have a Rails 3 app I'm developing with a team using Git/Github and deploying to a Heroku cedar stack. Our Github respository has 2 main branches Master and Development.
I would like to push our Development branch regularly to a different server on Heroku as a development/staging environment.
What's the cleanest simplest way to push our Development branch to a different app than Master without disrupting our Git flow much?
Thanks a lot!
You'll want to add a second git remote i.e. your second application's heroku git repo url to your app to be able to push to that from a single codebase.
At the moment you probably have the default remote origin named 'heroku' which is pushing to your production application.
You'll want to add a second remote origin pointing at your new heroku app that you intend to use for staging, eg
git remote add staging <git repo url from 'my apps' page on heroku>
once you have the new git origin set up you can push to it via;
git push staging <branch to deploy>:master
Simple. Heroku always uses the master branch, but using Git will allow you to push /your/ development branch, to /their/ master
For instance:
git push heroku development:master
where heroku is your origin for your heroku development env, and development is your local development branch. You might also want to override the RACK_ENV var on Heroku too if you don't want your dev branch running in production mode (although, personally I would create a staging environment in your code which does caching etc, but not send email to production addresses etc)
heroku_san is a Gem which allows complex deploy configurations when using Heroku, without the need to constantly specify which Heroku app you wish to push to on the command line. It would allow you to do exactly what you describe above.
I've configured the keys to my heroku, and I've gotten far enough to be able to commit and push onto my heroku server. But for some reason, commands like "heroku logs" or "heroku rake" or "heroku restart" bring up "no such file or directory" errors. Similarly, heroku restart -app "" bring up an "app not found!" even though I'd typed everything correctly.
I think this may have to do with my Github repo being stored and written on an external hard drive. Is this possible?
Thanks in advance!
An external hard drive will have nothing to do with this problem.
Make sure you are in your app.
cd myap
Then you need to create a repo and add your project to it:
git init
git add.
git commit -m 'master'
Then you need to create a heroku project:
heroku create
heroku rename myapp
git push heroku master
Make sure you have done all of that in that order.
Are you sure you are in the project folder that your application lives in. It doesn't matter where the project is as git and the project git config (including remotes) will all be local to the project folder iteself.
Also, you don't actually need to be in the project folder if you explicitly pass the application name,
eg;
heroku rake db:migrate --app myappnamehere
This also arises if you don't have your heroku remote not named heroku. Eg, I typically call my heroku remotes based off the environment eg, production, development. So my typical push looks like;
git push production mybranch:master
In this scenario when you issue a heroku command it is unable to locate the application name which is does by inspecting the git config for a 'heroku' remote so it will always say application not specified which is why you then need to pass it in explicitly via --app attribute.
I have a number of Rails apps hosted on GitHub. They are all currently private, and I often will deploy them from their GitHub repository. I'd like to be able to make some of them open source, just like the ones you can find on http://opensourcerails.com.
My question is: How can I make these repositories public without giving away super secret credentials?
For example, I can look in /config/initializers/cookie_verification_secret.rb and see the cookie secret for nearly every one of them. I don't understand how this is acceptable. Are these users all changing these values in their deploy environments somehow?
Some users even expose their AWS secret and key! Others will instead set their AWS secret to something like:
ENV['aws-secret']
although I'm not sure at what point they're setting that value.
So, what are the best practices for open sourcing your Rails app without compromising your app's security.
I recently went through this with one of my own apps. My solution was to store anything secret in a git-ignored YAML config file, and then to access that file using a simple class in the initializers directory. The config file is stored in the 'shared' folder for the Capistrano deployment and copied to config at each deploy.
Config store: http://github.com/tsigo/jugglf/blob/master/config/initializers/juggernaut.rb
Example usage: https://github.com/tsigo/jugglf/blob/6b91baae72fbe4b1f7efa2759bb472541546f7cf/config/initializers/session_store.rb
You may also want to remove from source control all history of the file that used these secret values. Here's a guide for doing this in Git that I used: http://help.github.com/removing-sensitive-data/
If you're using foreman, put an .env file in the root of your app. (foreman docs)
.env will have
AWS_SECRET=xxx
AWS_ACCESS=yyy
Then when you need to use the keys, insert:
ENV['AWS_SECRET']
ENV['AWS_ACCESS']
Though it's important that you don't commit this .env to your version control. So if you're using git, add the .env to your .gitignore.
Bonus round! - Heroku
If deploying to Heroku, these environment variables need to be configured in the Heroku environment, too. There are two options:
Manually add the keys through the heroku config:add command
Use the heroku-config gem to synchronize your local environment variables, both ways.
Not storing any secret value at all. At any point in the history of a Git repo.
Those values should be stored elsewhere, leaving only template config files versioned, along with a script able:
to read the right values from the external repo
and build the final config file complete (with the secret values in it)
By keeping the tow set of data separate (sources on one side, secret values on the other), you can then open source the sources repo without comprising any secrets.
I actually took a hint from your question, using ENV.
I had three different secret values that I didn't want made available. They're the app's secret token of course, and Twitter's consumer key and secret. In my secret token initializer:
KinTwit::Application.config.secret_token = ENV['SECRET_TOKEN']
Twitter.consumer_key = ENV['CONSUMER_KEY']
Twitter.consumer_secret = ENV['CONSUMER_SECRET']
I'm hosting my project on Heroku, so I added these as configuration variables to Heroku.
[03:07:48] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_KEY=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v7
CONSUMER_KEY => ub3rs3cr3tk3y
[03:08:40] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add CONSUMER_SECRET=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v8
CONSUMER_SECRET => ub3rs3cr3tk3y
[03:08:57] [william#enterprise ~/dev/rwc/kintwit]$ heroku config:add SECRET_TOKEN=ub3rs3cr3tk3y
Adding config vars and restarting app... done, v9
SECRET_TOKEN => ub3rs3cr3tk3y
Now, the values are ready on my next push. But, what if you aren't using Heroku? I'm obviously not an expert on every single rails deployment (jeesh, not even a Heroku pro), but an example of this would be doing a db:migrate for testing.
$ RAILS_ENV=test rake db:migrate
The KEY=value pair before the command sets the environment variable, so running this command, echo ENV['RAILS_ENV'] would print test. So however this is set up in your environment is how you would do it. But, the environment variables aren't in your code, so that's the trick.
[EDIT - The following method has the annoyance of having to switch to the Production branch to run "rails server" in order to include necessary cookies. Thus, making edits while the server is difficult... and I'm still looking for a good solution]
After further investigation, I think the solution I was looking for was to exclude anything that stored a secret value from my Git repo's master branch (just as #VonC said). But instead of then reading from those files in a separate repo, I simply create a new "production" branch and add them to that.
This way they're excluded from Master and I can push that to Github or some other public repo just fine. When I'm ready to deploy, I can checkout the Production branch and merge Master into it and deploy Production.
I need to be able to do this because Heroku and other hosts require a single git repo to be pushed to their servers.
More information here:
http://groups.google.com/group/heroku/browse_thread/thread/d7b1aecb42696568/26d5249204c70574