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
Related
Im using Settingslogic gem as alternative to Environment Variables, and I found it more convenient. But, how to deploy the application to Heroku if my file with configs is out of the repo? I mean, all configs I save in application.yml, which is included in .gitignore file (because there is sensitive data). And when I push it to heroku, server can't find this file and can't complete deploy.
I've tried to create the file from heroku bash, but after git push heroku master command, created file disappears, and deploy failes with the same error.
How can I implement this deploy with one config file, and how can I force heroku to read this file or store it if I have no it in Git? Thanks a lot!
I'm new to Rails and Heroku as well.
Following tutorials I succeed to upload my app to Heroku.
My app is enable us to upload csv file to uploads folder in public.
So I can upload file in heroku deployed app and show table as I want.
But after 30 mins or so those files are removed automatically and showing error that no such file in public/uploads folder.
It is properly working on my local which is using sqlite3.
But heroku want to use psql for production mode so I changed production mode to use psql.
So if I upload csv file then it is stored in 'public/uploads' folder.
I think heroku app is automatically update to github repo even I didn't execute 'git push heroku master' command.
In my local repository files are stored but they are run on development mode.
How can I make upload functionality fully working?
Any help would be appreciate.
Ephemeral filesystem is just the way heroku works, as explained in the article - uploaded files will be removed when the instance is restarted.
What you should do is to upload those files for example to S3 (https://devcenter.heroku.com/articles/s3), you can achieve this with CarrierWave gem with Fog gem but there are other possibilities as explained in this thread here: https://www.reddit.com/r/rails/comments/2k9sq4/heroku_any_files_you_upload_will_not_be_saved/
I am totally new to rails deployment. After googling, I still find it hard to understand how to deploy rails apps.
So, my questions are:
After setting up the VPS with all rails dependencies, where do I store my codebase? The root directory of the VPS or some specific locations e.g. www/ or public/?
Should I upload the whole rails app folder or just part of it? I have paperclip in my rails app, and paperclip creates a system/ directory in the public/ folder, so should I upload system/?
In Capistrano 3, there is a repo_url field, I know they support file://, https://, ssh://, or svn+ssh://, but most of the articles about capistrano put github repositories into that. However, I do not have such a github repo. What should I input then?
Thank you for your attention.
Answers to the specific questions raised:
After setting up the VPS with all rails dependencies, where do I store
my codebase? The root directory of the VPS or some specific locations
e.g. www/ or public/?
It will be deployed to the folder pointed by :deploy_to parameter. If not specified, :deploy_to defaults to /var/www/#{fetch(:application) See: https://github.com/capistrano/capistrano/blob/05f63f5f333bb261f2a4c4497174361c48143252/lib/capistrano/defaults.rb#L3
Should I upload the whole rails app folder or just part of it? I have
paperclip in my rails app, and paperclip creates a system/ directory
in the public/ folder, so should I upload system/?
Paperclip system folder is specific to the environment; each environment (development, production,...) will have its own system folder which will store the files uploaded on that specific environment. This folder should not be part of the code being deployed.
The recommended way of handing such folders is the keep them in a shared folder on the server, and create symlinks in the current version of the code so that the same folder is used for storing/retrieving attachments. See Section 3. Update custom links section in http://robmclarty.com/blog/how-to-deploy-a-rails-4-app-with-git-and-capistrano for more details about this.
As mentioned there, the same applies to config/database.yml file, and any other file containing environment specific configurations.
In Capistrano 3, there is a repo_url field, I know they support
file://, https://, ssh://, or svn+ssh://, but most of the articles
about capistrano put github repositories into that. However, I do not
have such a github repo. What should I input then?
Depends on where the code you are deploying is stored. If it is in a local folder, use the file::// format to specify where the files are located.
You can set up your own private git server, then in deploy.rb you can put something like
set :repo_url, 'ssh://user#server_ip/path/to/your_git_repo.git'
When you commit your changes to the git repo, you do not have to upload the app to the server. Capistrano will upload the app for you when you deploy.
where do i put my code base? This is determined by what you put in deploy.rb e.g
set :deploy_to, '/path/to/my_codebase'
Whether to upload the /system directory will depend on whether you want the paperclip images on your version control. If not you can add the directory to gitignore. Here is a tutorial on how to deploy on ubuntu 14.04 passenger and NGINX. if you are not using Passenger and Nginx you can skip to how to configure capistrano and make adjustments depending on your setup.
EDIT
You need to install git on your development machine and set up a git server on your VPS as explained on the link above, add your remote server to your local machine using
git remote add origin <server>
where 'server' is the url to your git repo in the VPS e.g.
ssh://VPS_user#VPS_ip/path/to/your_git_repo.git
Now when you commit and push your changes to the server, capistrano will deploy the latest version on your git server.
Here is a link with a guide on how to get started with git
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
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)