How to Restart Rails Production Servers After Code Deployment w/o Downtime - ruby-on-rails

In Rails, what is the best strategy to restarting app servers like Thin after a code deployment through a Capistrano script. I would like to be able to deploy code to production servers without fearing that a user might see the 500.html page.

I found this question while looking for an answer. Because I wanted to stick with Thin, none of the answers here suited my needs. This fixed it for me:
thin restart -e production --servers 3 --onebyone --wait 30

Unicorn is supposed to have rolling restarts built in. I have not setup a unicorn stack yet but http://sirupsen.com/setting-up-unicorn-with-nginx/ looks like a good start.

The way I used to do the production servers are with apache and passenger. thats a industry standard setup and will allow you to deploy new versions with out a down time
Once everything is correctly setup all you have to do is, go to app directory
create a file called restart.txt in /tmp dir.
Ex: touch tmp/restart.txt
read more here http://www.modrails.com/
http://jimneath.org/2008/05/10/using-capistrano-with-passenger-mod_rails.html
http://www.zorched.net/2008/06/17/capistrano-deploy-with-git-and-passenger/
http://snippets.dzone.com/posts/show/5466
HTH
sameera

Related

Capistrano appserver as service without sudo

Does anyone have a good way to manage the appserver with capistrano?. This seems to be a leave it to your own devices situation, and I've yet to see a good example of it.
There is basically two trains of thoughts I see.
1) Daemonize it as the deploy user. Pros, no system service etc, so no permissions issues. However this wreaks as if the machine is rebooted, blam the system goes down.
2) Init scripts. Installing a init script and using that to manage the server. This would survive reboots, and allow for say /etc/init.d/myapp restart/stop/start control if you ssh'd in. This is decent apart from two reasons
Most people manage it from capistrano with sudo (I feel like capistrano 3 discourages this)
I've yet to see a good upstart or the like script that works with unicorn for it.
I'm experimenting with using nginx+unicorn. Nginx I have set perfectly. I've added a site to sites-available and pointed upstream to /appserver/public. This works great, asset precompilation works fantastic and all is well, I can redeploy and be served new assets. It's simple, works with the OS init process. However I've lucked out as the nginx config is basically static, and nginx only has to serve static files.
The appserver.. unicorn/thin/puma/ whatever is the part thats tripping me. I would like it to reload the application on cap deploy, but I'm struggling to find a good enough example of this.
In summary. What is a simple way of having a rails application survive reboots, and reload when cap deploy is called
If you use Passenger with your nginx and unicorn or thin... you can restart after deployment by touching tmp/restart.txt file:
task :restart do
on roles(:app), in: :sequence, wait: 5 do
execute :touch, release_path.join('tmp/restart.txt')
end
end
To reload a puma server after deploy use capistrano3-puma:
Gemfile:
gem 'capistrano3-puma'
Capfile:
require 'capistrano/puma'

Want to develop rails site offline then move to server

Is there an issue with developing my site on my macbook and then moving to a server when done? Will there be issues I need to plan ahead for? DB or ruby related maybe? Dependencies or something a server could have different from my dev environment that could cause a nightmare later? I'd rather develop it offline since it'd be faster and wouldn't require an internet connection but in the past I've always done everything with live sites so this would be a first, and I am new to ruby on rails.
Developing locally and then deploying to your server(s) via something like capistrano is standard practise.
It's a good idea to keep your development environment as close as possible to your production environment (ruby versions, database versions etc). Bundler makes keeping your gems in sync easy
I used Heroku for some projects. The deployment was as easy as it could be. I just did a git push and it worked without problems... I really like bundler and rake :-)
Your Question embodies THE way to develop in Rails. Your development environment is an offline representation of what you're production site will be.
A quick workflow analysis for you could be:
rails new ~/my_app -d postgresql; cd ~/my_app; rm public/index.html
Next, create the database:
bundle exec rake db:create:all
Now you'll have the db and app all set up, let's set up your main pages:
bundle exec rails generate controller Site index about_us contact_us
Now you'll have something to see on the site, so run:
bundle exec rails server
This server acts as your offline connection and will handle the rendering of any text, images, html etc you want to serve in your rails app. Now you can join in the debates of TDD, to TATFT or JITT, rspec vs test::unit. Welcome.
Developing locally is definitely the way to go. However, I would look into getting it on production as soon as possible and pushing often. This way you can see changes happen as you make them and are aware of any possible breaking changes.
I use heroku a lot and when I start a new project I push it to heroku almost immediately. While developing, I can publish new changes simply by git push heroku master. Everyone has to find their own workflow, but this has always worked well for me.
If you are interested in Heroku here is a good link to get you started:
https://devcenter.heroku.com/articles/rails3

Running a Rails site: development vs production

I'm learning Ruby on Rails. At the moment I'm just running my site locally with rails server in the OS X Terminal. What changes when a Rails site is run on a production box?
Is the site still started with rails server?
Any differences with how the db is setup?
Note: I'm running Rails 3.
A rails app can be run in production calling rails server -e production, although 99% of the time you'll be serving on something like passenger or thin instead of WEBrick, which means there's a different command to start the server. (thin start -e production for instance)
This is a complicated question, but the best place to start learning about the differences would be to look at the specific environment.rb files. When rails boots up it starts with the environment file that matches the called environment, ie if you start it in development it begins by loading your development.rb file, or if you're in production it will load the production.rb file. The differences in environments are mostly the result of these differences in the various environment config files.
Basically if a Rails 3.1 app is in production mode, then by default it is not going to be compiling assets on the fly, and a lot of caching will be going on that isn't happening in development. Also, when you get error messages they will be logged but not rendered to the user, instead the static error page from your public directory will be used.
To get more insight into this, I would suggest reading the relevant rails guides:
Rails Initialization Guide: http://guides.rubyonrails.org/initialization.html
Rails Configuration Guide: http://guides.rubyonrails.org/configuring.html
There are two contexts you can use the word "production" here. One of them is running the server in production mode. You can do this locally by,
RAILS_ENV=production ./script/server
The configuration for this is picked up from config/environments/production.rb. Try comparing this file with config/environments/development.rb. There are only subtle differences like caching classes. Development mode makes it easier so that it will respond to any changes you make instantly. Plus there are two different databases (by default) will be used namely yourproject_development and yourproject_production if you choose to run your server in either of these modes.
On the other hand, rails deployment to a production box is something different. You will need to pick your server carefully. You may have to deal with a deployment script may be capistrano. You may also need a load balancer such as netgear. The database also may require a deep consideration like size expectation, master/slave clustering etc.,
Note: I have never used Rails 3. This answer is biased towards 2.3.x.

How to deploy resque workers in production?

The GitHub guys recently released their background processing app which uses Redis:
http://github.com/defunkt/resque
http://github.com/blog/542-introducing-resque
I have it working locally, but I'm struggling to get it working in production. Has anyone got a:
Capistrano recipe to deploy workers (control number of workers, restarting them, etc)
Deployed workers to separate machine(s) from where the main app is running, what settings were needed here?
gotten redis to survive a reboot on the server (I tried putting it in cron but no luck)
how did you work resque-web (their excellent monitoring app) into your deploy?
Thanks!
P.S. I posted an issue on Github about this but no response yet. Hoping some SO gurus can help on this one as I'm not very experienced in deployments. Thank you!
I'm a little late to the party, but thought I'd post what worked for me. Essentially, I have god setup to monitor redis and resque. If they aren't running anymore, god starts them back up. Then, I have a rake task that gets run after a capistrano deploy that quits my resque workers. Once the workers are quit, god will start new workers up so that they're running the latest codebase.
Here is my full writeup of how I use resque in production:
http://thomasmango.com/2010/05/27/resque-in-production
I just figured this out last night, for Capistrano you should use san_juan, then I like the use of God to manage deployment of workers. As for surviving a reboot, I am not sure, but I reboot every 6 months so I am not too worried.
Although he suggest different ways of starting it, this is what worked easiest for me. (Within your deploy.rb)
require 'san_juan'
after "deploy:symlink", "god:app:reload"
after "deploy:symlink", "god:app:start"
To manage where it runs, on another server, etc, he covers that in the configuration section of the README.
I use Passenger on my slice, so it was relatively easy, I just needed to have a config.ru file like so:
require 'resque/server'
run Rack::URLMap.new \
"/" => Resque::Server.new
For my VirtualHost file I have:
<VirtualHost *:80>
ServerName resque.server.com
DocumentRoot /var/www/server.com/current/resque/public
<Location />
AuthType Basic
AuthName "Resque Workers"
AuthUserFile /var/www/server.com/current/resque/.htpasswd
Require valid-user
</Location>
</VirtualHost>
Also, a quick note. Make sure you overide the resque:setup rake task, it will save you lots of time for spawning new workers with God.
I ran into a lot of trouble, so if you need any more help, just post a comment.
Garrett's answer really helped, just wanted to post a few more details. It took a lot of tinkering to get it right...
I'm using passenger also, but nginx instead of apache.
First, don't forget you need to install sinatra, this threw me for a while.
sudo gem install sinatra
Then you need to make a directory for the thing to run, and it has to have a public and tmp folder. They can be empty but the problem is that git won't save an empty directory in the repo. The directory has to have at least one file in it, so I made some junk files as placeholders. This is a weird feature/bug in git.
I'm using the resque plugin, so I made the directory there (where the default config.ru is). It looks like Garrett made a new 'resque' directory in his rails_root. Either one should work. For me...
cd MY_RAILS_APP/vendor/plugins/resque/
mkdir public
mkdir tmp
touch public/placeholder.txt
touch tmp/placeholder.txt
Then I edited MY_RAILS_APP/vendor/plugins/resque/config.ru so it looks like this:
#!/usr/bin/env ruby
require 'logger'
$LOAD_PATH.unshift File.expand_path(File.dirname(__FILE__) + '/lib')
require 'resque/server'
use Rack::ShowExceptions
# Set the AUTH env variable to your basic auth password to protect Resque.
AUTH_PASSWORD = "ADD_SOME_PASSWORD_HERE"
if AUTH_PASSWORD
Resque::Server.use Rack::Auth::Basic do |username, password|
password == AUTH_PASSWORD
end
end
run Resque::Server.new
Don't forget to change ADD_SOME_PASSWORD_HERE to the password you want to use to protect the app.
Finally, I'm using Nginx so here is what I added to my nginx.conf
server {
listen 80;
server_name resque.seoaholic.com;
root /home/admin/public_html/seoaholic/current/vendor/plugins/resque/public;
passenger_enabled on;
}
And so it gets restarted on your deploys, probably something like this in your deploy.rb
run "touch #{current_path}/vendor/plugins/resque/tmp/restart.txt"
I'm not really sure if this is the best way, I've never setup rack/sinatra apps before. But it works.
This is just to get the monitoring app going. Next I need to figure out the god part.
Use these steps instead of making configuration with web server level and editing plugin:
#The steps need to be performed to use resque-web with in your application
#In routes.rb
ApplicationName::Application.routes.draw do
resources :some_controller_name
mount Resque::Server, :at=> "/resque"
end
#That's it now you can access it from within your application i.e
#http://localhost:3000/resque
#To be insured that that Resque::Server is loaded add its requirement condition in Gemfile
gem 'resque', :require=>"resque/server"
#To add basic http authentication add resque_auth.rb file in initializers folder and add these lines for the security
Resque::Server.use(Rack::Auth::Basic) do |user, password|
password == "secret"
end
#That's It !!!!! :)
#Thanks to Ryan from RailsCasts for this valuable information.
#http://railscasts.com/episodes/271-resque?autoplay=true
https://gist.github.com/1060167

How do I force Capistrano deployed app to use my development database?

I have a app that I'm deploying to a development server using Capistrano. I'd like to force this deployment to use the development database. So far the only way I've managed to do it is to make my production database info in database.yml equal to the development info. But this is a complete hack.
I've tried setting rails_env to development in deploy.rb but that hasn't worked.
Thoughts?
I ended up using the solution over here. Basically a recipe to replace a line in environment.rb after deploy but before restart.
The problems seems to be with DreamHost's Passenger config. It assumes you're running in production mode.
I'd use Capistrano Ext in order to define multiple deployment environments. I have used this in the past to deply staging and production installations of my apps, so I think it'd work well for you.
Jamis Buck has a writeup if you'd like an overview on how to use it.

Resources