Capistrano appserver as service without sudo - ruby-on-rails

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'

Related

Capistrano rename a file task

I am working on an Opensourced project I want to create, deploying to a VPS.
I'm working with Rails 4 and Capistrano 3 on Ubuntu, both on the local machine and the server.
I have a configuration file named "application.yml" that includes basic information about the application, as a Google Analytics script, the application name, Mailer configurations and such.
I want to create a task that would rename "application.example.yml" to "application.yml" before Capistrano runs deploy:migrate.
I wrote the task below and put it in config/deploy.rb:
before "deploy:migrate", "configure:application"
namespace :configure do
task :application do
run "#{try_sudo} cp #{current_path}/config/application.example.yml #{current_path}/config/application.yml"
end
end
(I know cp copies the file but it also renames so it is fine.)
It does not seem to work. How can I rename "application.example.yml" before deploy:migrate runs?
GitHub Repository and deploy.rb
Also as I am moving forward with my App I seem to find more and more stuff I know little or nothing about, and would love it if someone experienced with Rails would be willing to become my "Mentor" by sharing with me his Skype (or any other communication service) so I could occasionally ask him my questions.

Better Rails 3 Asset Handling for `cap deploy`

I notice the default "deploy" task does the asset precompilation on the remote machine, which has these ill effects:
Weird glitchy assets during the time it's precompiling (on the live site)
Errors in the config cause downtime with a 500 response code
The task to take a long time
I've seen this, which mitigates the problem a tiny bit by not causing you to precompile when you don't have anything to precompile: Speed up assets:precompile with Rails 3.1/3.2 Capistrano deployment
But there must be a better solution.
Has anyone tried these:
Always deploy to a "staging" location, where you can test everything out, then add some kind of cap enliven task that somehow tells the web server frontend to start using the other port? (I could manually manage this with editing the nginx upstream and restarting it, then I could automate that a bit with an include in the nginx.conf and a cap task to tie it together.)
Precompile locally then simply push the files over via rsync. I prefer #1, but this would be a smaller step that would probably work as a better default than the current behavior.
Am I missing something obvious? I'm am new to Rails assets + Capistrano deployment, but it seems like the best practices of deployment aren't available right out of the box on this one.
You can:
precompile assets before deploy
compile it server-side in background
leave it to delayed_job or another queue management system

How to Restart Rails Production Servers After Code Deployment w/o Downtime

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

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

What's the best way to deploy a JRuby on Rails application to Tomcat?

I'm looking at ways to deploy a Ruby on Rails app (running on JRuby) to a Tomcat instance for testing.
The tomcat instance is running on a Solaris server that I can SSH to. I've looked at using Capistrano, but there doesn't seem to be a lot out there about using it to deploy to Tomcat, or even about running it under JRuby, and I keep hitting bugs in Capistrano due to the Windows/JRuby environment my PC is running (yeah, it's corporate - not my choice, but I've got to live with it).
I'm using warble to build the .war file, and the app deploys and runs fine once I manually copy it up and deploy it. I'm wanting something easier and more automated to actually get it there.
Anyone done this before? Documentation on the web seems pretty thin.
I am running a Rails project using JRuby and deploying to a Tomcat server. I have chosen to deploy with Capistrano because it automates just about everything. I had to make a few minor modifications to Capistrano's deployment lifecycle in order to get it to run on Tomcat:
Step 1: I created a warble task to be run on the server after Capistrano updates the code:
desc "Run the warble command to deploy the site"
namespace(:deploy) do
task :warble do
run ". ~/.profile;cd #{release_path};warble"
end
end
And hooked it into Capistrano lifecycle using:
after 'deploy:update_code', 'deploy:warble'
My Tomcat server has a symlink pointing to the #{release_path}/tmp/war directory created by warble. If you don't like this, you can easily modify the warble task to move the war file into the Tomcat directory instead.
Step 2: I overrode the deploy:start and deploy:stop tasks so that they kick off the Tomcat server instead of a Mongrel server:
desc "Starts the Tomcat Server"
namespace(:deploy) do
task :start do
sudo "#{tomcat_home}/bin/startup.sh"
end
end
desc "Shutdown the Tomcat Server"
namespace(:deploy) do
task :stop do
sudo "#{tomcat_home}/bin/shutdown.sh"
end
end
I run Capistrano tasks using MRI rather than the JRuby interpreter.
I don't have much experience on this, so I don't know if I can give you the BEST way, but if Capistrano doesn't work, and you can't have a separate MRI install just to run it, you have just a few alternatives left:
Try running plain Rake and write your own deployment target:
http://www.gra2.com/article.php/deploy-ruby-on-rails-applications-rake
Or use Ant or Maven.
Or if it just ONE server you have to deploy to, you could just hack together two Ruby scripts - one that listens on the server for shutdown/startup requests, and one local that you run to: Send shutdown, scp over the file, send startup.
By the way, have you submitted any integration bugs you find with Capistrano to the JRuby team? I'm sure they'd be happy to have any contribution.
:)
Might be worth looking at 'Vlad the deployer' it adds remote_task to Rake allowing you to run tasks on a remote server. Personally however I prefer to have a standard Rake task on the server, ssh in and run that task - which would then do an svn checkout, make the WAR file, whatever...
I would probably use Ant for this. After all, it's just another WAR file, right? I don't know which version of Tomcat you're using but version 4.1x comes with an Ant task for deploying to Tomcat.
There's a few Capistrano recipes for deploying to Tomcat -- I built one into a gem called capistrano-tomcat. It takes a WAR you've built (probably with Warbler) and deploys and starts a Tomcat instance on a remote server.
The source is up on Github: http://github.com/rhunter/capistrano-tomcat

Resources