Deploying rails application to multiple environments - ruby-on-rails

I am getting ready to deploy to a true production environment. When I say true I mean that my current production environment will now be staging because there is other crap on the server and I am creating a new larger slice for what will actually be my production machine.
The capistrano-ext gem has made separating the deploy recipes quite easy. However, one issue I run into is getting my code from one slice to another. I have a git repo set up on my staging slice that I will be using for production. The flow will be:
Develop locally
Test locally
Push from local to stage
Test on stage
Push from stage to production
...
Therefore I obviously need a way to establish a secure connection between staging and production. When deploying to production, I get a "Permission denied (publickey)." error because this is not set up. How can I establish this connection? Do I need to generate keys on my production server and put the public on my staging? How do I know what user on my production server is trying to connect to my staging server?

Branches and capistrano multistage are your friends.
To solve the production not having access to the git repo issue, try…
set :deploy_via, :copy
…this deploys by checking out locally, and pushing a tar ball.

I find that branching or version tagging works much better for differentiating staging vs. production when using Capistrano.
For example, set up a 'staging' and 'production' branch for your application and use your source control tools to manage migrating changes from one to the next. During deployment simply deploy as you usually would, but with a particular branch instead of the main one.
It's not necessary to promote directly from staging to production, and in fact, this may be considered a bad idea since anyone with access to the staging machine potentially has access to the production server. In most environments a staging server is treated much more casually than the production site, so the security profile is usually quite different.

Do I need to generate keys on my production server and put the public on my staging?
Yes.
How do I know what user on my production server is trying to connect to my staging server?
The productionuser will be whatever user you connect with (see :user). The staginguser will be from the git url (see :repository).
When you use
set :deploy_via, :remote_cache
(which is the default), two ssh connections are actually occurring. The first one is from your local machine to production, and it uses the 'user' as configured in your recipe.
set :user, 'www-data'
The second ssh connection is made by that user, on production, to your git origin. So if git origin is on staging, the production user is trying to connect back to staging to pull code from git.
set :repository, "staginguser#staging.com:project.git"
Try this: ssh to production as the user. Then run the failing command by hand. You'll see the "permission denied" and maybe a prompt for a password. Add the public key of the staging server user to the production box and things should work better.

There's also:
set :gateway, 'staging server ip'
which should allow you to tunnel all the way through to your firewalled production box. But if you're deploying from staging you need to set up keys on the staging box if you're going to go through it that way.
On a side note, it's important to be able to do this whole process from your home box, staging really shouldn't need to have a capistrano gem, the hope is that you can do the whole process without ever having to actually log into a server. That includes logging in to your staging server. :)
If there's an issue of data pushing between the two this could easily be added onto just the production config so that it automatically takes data from staging and rsync's it over.

Related

What repository should be set in set :repo_url "" in deploy.rb for capistrano?

According to this description I have to set a repository in the deploy.rb file.
set :application, "my_app_name"
set :repo_url, "git#example.com:me/my_repo.git"
I assume this is the source code of my app, is that correct? At the moment I have my app repository on a cloud9 server. To deploy the app I type cap production deploy on the development system. So, do I have to put in the url and path of the cloud9 server? That seems weird, because I deploy from that server. Or is this file transferred to the production system that then pulls the data from the development environment? Does this mean, I need a passwordless ssh connection from a cloud 9 server to the production server or vice versa? Or do I need to push my data to a third system?
According to the docs, repo_url must be set appropriately and the deployed server must be able to connect to it. The reason is that by defaut, capistrano will try to pull code from the repo to the deployed server instead of pushing your code directly.

What does the data communication flow look like during a Capistrano deployment? Is there a diagram somewhere that explains this?

I couldn't find any information regarding how information flows during a Capistrano deployment, and I can't make out the log information when running the deployment.
I currently have the following setup:
Development code on my laptop
Local Git server
Staging web server
I push my code to the local Git server with the Capistrano repo_url set to the repository on this server. The code is then deployed to the staging web server. During the deployment, does the communication go like this:
1 --> 2 --> 3?
Or is there any communication from 1 (the development laptop) to 3 (the web server)?
this could help :
https://github.com/mattbrictson/airbrussh
It's cleaning cap log while you're deploying, let you follow up capistrano work flow
"When you run cap, Capistrano dutifully connects to your server(s) via SSH and executes the steps necessary to deploy your project." This that your local code has nothing to do with it.
When you use cap staging deploy (for example). Capistrano will look about a staging.rb file for settings. Connect to your server and pull code from your github.
As I assume you're new with capistrano, take a look at :
https://github.com/sgruhier/capistrano-db-tasks
I'll help you to manage your db and staging/prod db for any tests/bug solving.
I hope this help :)

How do I work on my Rails app in development mode, but push it in production mode?

Simple question, I do all my work on my local at home computer and then I git push to my repo on github, and then on my Ubuntu Server I do a git pull to get the content, but this causes inconsistencies because it pulls in development mode which I always have to go in and change. Is there a way to make it so I can work in development mode but push it to the repo production mode? Thanks.
This isn't a git problem. Rails environments ('production', 'development', 'test') affect how the code runs, but the code isn't changed.
When you run rails server on your development machine, the application starts in development mode because that is the default for that command.
You probably aren't using the same command to host your site on WEBrick on your server, but rather using something like Phusion Passenger, which can (should) be configured to boot your application in Production mode.
If the environment is set correctly, the config/environments/#[RAILS_ENV}.rb file is correctly selected upon loading the app, and the correct database sources are selected from config/database.yml.
Rails apps default to development unless you set the RAILS_ENV variable to production. Git doesn't really factor in to this. On your production machine, you'll want to set RAILS_ENV.
Where to do this depends on your production deployment environment, and how your server is configured. Things like Passenger default to production mode, and configuring that depends on your server (Apache, nginx). If you're manually starting the server from the command line (via rails s thin or something along those lines), then you can configure it in your shell's startup file (.profile or something similar, depending on your shell). thin also optionally takes an environment argument like -e production.
If you provide more details on how your production environment works, you might get a more specific answer for where to set RAILS_ENV.

Rails: Reasonable to deploy to both internal server AND Heroku?

Considering migrating an app to Heroku. Currently we build & test locally before deploying to our own server for hosting...But the application is growing and now wondering if it's reasonable to have, say, 3 versions of our app. One local to developer's machines. A second (testing) deployed via Capistrano to an internal server. And then finally a third on Heroku (production). Databases would not need to be shared.
Any problems or advice for this sort of scenario?
I think it's a good thing to have a staging server with the same environment as your production. So instead of internal server, wouldn't it be better to test on heroku?
For this purpose I've created another app on heroku and before updating my production app, I push my app to the staging one.
I would highly recommend the heroku_san gem which simplifies pushing app to heroku to just rake staging deploy.
I do this. I have development on developer's machines, staging, and production.
Staging is our test sandbox and sometimes also shares user databases with production so I can let users beta test, etc.
Whether or not you use Heroku for production really doesn't matter does it?

Deploying Rails app over VPN

You'll have to bear with me as I'm not a Ruby dev, but have inherited a Ruby system.
I need to deploy some changes to the app from my repository to the server. I've been instructed to run cap deploy and told that that script will get the latest code from my repository and deploy it to the server.
My problem is that I have to VPN to get to the production server and the VPN client then blocks access to my local network, cutting off the repository. So my question is, how can I change my deploy.rb so that I can deploy from my local machine instead? Or is there a better way.
If you need to see the deploy.rb, please let me know.
Thanks
Dave
The solution I've used before means adding:
set :deploy_via, :copy
However, it may be better to read more about this at:
http://www.capify.org/index.php/Understanding_Deployment_Strategies#Deploy_Strategy_:copy

Resources