How should I give the repo url in production environment - ruby-on-rails

I am using capistrano for deployment of my rails application. In my config/deploy.rb file how should I give the repo url.
I am following this tutorial:
https://gorails.com/deploy/ubuntu/14.04
Instead of
set :repo_url, 'git#github.com:excid3/myapp.git'
what should be given there if I am using bitbucket

For bitbucket, you would use:
git#bitbucket.org:accountname/reponame.git
or
ssh://git#bitbucket.org/accountname/reponame.git
See "Use the SSH protocol with Bitbucket"
Note: the comments of the tutorial mentioned in the question add:
Your local key in ~/.ssh/id_rsa will be tried against the server's /home/deploy/authorized_keys file.
Capistrano won't allow password authentication, so you must make sure you ran the ssh-copy-id to add your pub key to the server deploy user's authorized_keys file.

Related

How to store secret variables in capistrano

I am writing a Rails app with automated deployment using Capistrano. In the deploy.rb script I have:
set :deploy_to, '/my/deploy/path/'
And in production.rb I have:
server 'example.com', user: 'secret_user_name', roles: %w{web app db}
Currently the app is private. But assume I wanted an open source app like this. Then I wouldn't want secret_user_name and /my/deploy/path to be stored in the repo. In the Rails project if I encountered an issue like this I would store the secret values in secrets.yml and access them from there. However I don't have access to secrets.yml from Capistrano. So I could manually load the secrets file but I'm sure there is a better way to do this.
So my question is: How can I have an automated deployment process without exposing server information using Capistrano? Is there a recommended way to store secrets like there is in Rails?
If your intention is to maintain your own deployment environment (which you keep secret) but open source the code of the application itself, then I would simply move the Capistrano-related files to a separate private repository. Then you can open source the app itself, but keep the Capistrano config private.
There is no need for Capistrano's deploy.rb, etc. to live in the same directory structure or even the same repository as the app that is being deployed. After all, Capistrano deploys based on the :repo_url, which can be anything. It doesn't have to match repo where Capistrano's files are kept.
If you want to give other people (i.e. those that fork/clone the app) the ability to deploy to their own infrastructure, perhaps the easiest solution is to write up a wiki page explaining how they can set up their own Capistrano config. Deployment environments can vary widely and therefore it is probably not something you can do simply with environment variables or encrypted secrets.
In any case make sure you audit and rewrite your Git history if necessary to make sure you won't be leaking any sensitive config when you make the repo public.
Environment variables might help you.
You can put export SSH_PROD_USER=secret_user_name; in your preferred shell profile. For example if you use bash then it would be ~.bash_profile. Then use it in production.rb like this:
server 'example.com', user: ENV['SSH_PROD_USER'], roles: %w{web app db}
So basically ruby will have all your environment variables
Use something like Figaro gem: https://github.com/laserlemon/figaro
and don't push to your repo your application.yml
Or use an encrypted repo with credentials.

Changing remote of git does not work on digital ocean

I'm deploying a rails app on digital ocean, following this link. When I followed the exact steps, it worked perfectly. But then I realized the github repository is public. I should have it as private. I create a private repository and changed the remote origin in my local. I put the ssh keys in the new private repository. Removed the old apps folder in the server. And then tried to clone from the remote repository but it asks for password. (It should have taken the ssh key??).
Also I changed the deploy.rb and nginx.conf to reflect the changes of the remote repository and then gave this command, cap production deploy:initial, but it fails, due to authentication failure in git.
Why does it fail? Why is the ssh key not taking effect?
Maybe it is because you have not enabled ssh forwarding for digital ocean? To verify, first edit the $HOME/.ssh/config on your local pc:
host *
ForwardAgent yes
Now try to run cap production deploy:initial. If it works without a password now, then you should change the host * to actually match the hostname of your ssh host, so ForwardAgent is only set for digital ocean:
host digitalocean.com
ForwardAgent yes
For your use case: ForwardAgent enables the server to use your local ssh keys, so your deploy user has the same "ssh rights" like your local user.
This looks like capistrano is still using the old git remote address. When you change the remote url, it is not enough to do this inside deploy.rb etc, but you have to manually change the file repo/config inside the deployment dir of capistrono on the server when you already deployed it with an old remote url before.
So, if you have the following inside your deploy.rb (or deploy/production.rb)
set :deploy_to, '/var/www/path/to/deploy'
You have to manually edit the file on the server
/var/www/path/to/deploy/repo/config
and amend the url = XXX entry of your remote to match the new one.

Intercity chef-repo Capistrano asking for deploy password

I have set up a vps everything according to the https://github.com/intercity/chef-repo instructions. I have set up Capistrano but when i try cap production deploy:check
it keeps asking for deploy password. But i don't have one because it is generated through the intercity node. I have the public key of my server in the node file.
Check that you can log in via normal SSH manually. Guessing you didn't get the SSH keys installed correctly.

Heroku Config Secret Key Base Error

Just pushed my first app to Heroku using Git and straight away got an Interanl Server Error.
You must set config.secret_key_base in your app's config.
This is because on my .gitignore file the following file is included:
config/initializers/secret_token.rb
I am using a standard template for my .gitignore file found here: https://github.com/github/gitignore/blob/master/Rails.gitignore
My Question: Should I set this key via Heroku directly for added security and if so how?
OR
should I just remove this line from my .gitignore file?
In addition to setting the secret token as an ENV variable on Heroku, as outlined by Nick Ginanto, you also need the following to make this work.
Remove the config/initializers/secret_token.rb from .gitignore
Change the line in this file to:
MyApp::Application.config.secret_token = ENV['SECRET_TOKEN']
This will then pick up the secret token you have set with Heroku's config vars.
In order for the token to be picked up in your local environment you will need to add it. There are a number of options here but the one closest to Heroku is to use the foreman gem along with a .env file in your project root. The .env will need to have the secret_token
SECRET_TOKEN=NKUd7gisd7fueAISDfg....
You can use the rake secret command to generate tokens. Make sure your .env file is added to .gitignore.
With all this in place you will have different tokens for Heroku and local and your token will not be in your source control.
Set it as a Heroku environment variable, & provide a fallback for development
Remove the hardcoded secret, check the secret initialiser into version control, set an environment variable on Heroku, and provide a fallback for development and stage.
1. Remove the hardcoded secret, and optionally provide a fallback:
Edit your config/initializers/secure_random.rb to remove the hardcoded secret for production. Optionally include a fallback for non-production environments if you'd rather not change the way you start your server.
secret = Rails.env.production? ? ENV['SECRET_TOKEN'] : "top_secret_token"
YourApp::Application.config.secret_key_base = secret
2. Check config/initializers/secure_random.rb into git
Edit .gitignore and remove the line:
config/initializers/secret_token.rb
Now commit the file.
3. Set the secret key for Heroku
Run:
rake secret
to generate a random alphanumeric string. I like to make doubly sure by mixing the key up a little by hand as well, just in case a future weakness is discovered in the key generation algorithm, as happened for Debian not so long ago. Probably this is unnecessary.
Next run:
heroku config:set SECRET_TOKEN=paste_random_string_here
to set the secret as a Heroku environment variable. Deploy to Heroku and you're done.
Its best to use an ENV variable for this..
This way you can invalidate all the cookies quickly if needed, have a separate secret per environment and no need to deal with the file in a special way
heroku config:set SECRET_TOKEN=ertbs45tnsb3aw5bsxdrt54...
if you duplicated the app or have another app setup in heroku, each app will have its own secret_token.
on your localmachine just setup the same variable

How do I open source my Rails' apps without giving away the app's secret keys and credentials

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

Resources