{"id":1642,"date":"2011-05-04T11:07:39","date_gmt":"2011-05-04T03:07:39","guid":{"rendered":"http:\/\/hazelong.com\/?p=1642"},"modified":"2011-05-04T16:51:25","modified_gmt":"2011-05-04T08:51:25","slug":"deploying-rails-centos-capistrano","status":"publish","type":"post","link":"https:\/\/musenmaker.com\/hazelong\/?p=1642","title":{"rendered":"Deploying Rails to Centos : Capistrano"},"content":{"rendered":"<p>Thank you for following this series, this will be the last part of the series where we actually bring our development app to our remote server. Learning Rails has been a tremendous journey for me, the learning curve is not steep at all and it allows me to experiment and also to learn how to set up my own server to house it. Thanks to all the people that wrote tutorials and made <a href=\"http:\/\/railscasts.com\">railscasts<\/a> out there I have learnt so much but this is just the beginning. This would not have been possible if I wasn&#8217;t introduced to the language itself by the_empty from <a href=\"http:\/\/webdevrefinery.com\">webdevrefinery. <\/a><\/p>\n<p><strong>Deploying Rails to Centos 5<\/strong><\/p>\n<ul>\n<li><a href=\"http:\/\/hazelong.com\/?p=1618\"><strong>Part 1 \/\/ Apache<\/strong><\/a><\/li>\n<li><a href=\"http:\/\/hazelong.com\/?p=1622\"><strong>Part 2 \/\/ mySQL<\/strong><\/a><\/li>\n<li><a href=\"http:\/\/hazelong.com\/?p=1625\"><strong>Part 3 \/\/ Git<\/strong><\/a><\/li>\n<li><a href=\"http:\/\/hazelong.com\/?p=1631\"><strong>Part 4 \/\/ Ruby, Gems &amp; Rails<\/strong><\/a><\/li>\n<li><a href=\"http:\/\/hazelong.com\/?p=1634\"><strong>Part 5 \/\/ Passenger<\/strong><\/a><\/li>\n<li><strong><a href=\"http:\/\/hazelong.com\/?p=1637\">Part 6 \/\/ Gitosis<\/a><\/strong><\/li>\n<li><strong>You are here!<\/strong><\/li>\n<\/ul>\n<p>Right, before deploying with Capistrano we should make sure our application is fully prepared for deployment. The first thing we should do is strengthen our local&#8217;s <code>.gitignore<\/code> file. It should have the following lines :<br \/>\n[text]<br \/>\nlog\/*.log<br \/>\n*.log<br \/>\ntmp\/**\/*<br \/>\ntmp\/*<br \/>\ndoc\/api<br \/>\ndoc\/app<br \/>\nconfig\/database.yml.sample[\/text]<\/p>\n<p>Next, we should rename the <code>database.yml<\/code> file so that it doesn&#8217;t clash with other developer&#8217;s copy since they might differ from yours. Renaming it to <code>database.yml.sample<\/code> ensures that the production&#8217;s copy remain intact and the file doesnt clashes with other developers on your team. There is a <a href=\"http:\/\/www.simonecarletti.com\/blog\/2009\/06\/capistrano-and-database-yml\/\">great post by Simone Carletti about this issu<\/a>e that you should definitely check out.<\/p>\n<p>You should also make sure that you have a root path pointing to some controller, meaning your index page should be properly routed and the public folder&#8217;s index.html is removed.<\/p>\n<p>If you are on a shared host, you should mind your gems cuz they might upgrade their pack of gems without notifying you. To prevent anything from breaking you should unpack each gem to the <code>vendor<\/code> folder.<br \/>\n[shell]local $ cd vendor<br \/>\nlocal $ gem unpack money[\/shell]<\/p>\n<p>To enable the gems to have version control, you just need to copy the contents of the <code>lib<\/code> folder to <code>vendor<\/code><br \/>\n[shell]$ cp -R money-1.5.9\/lib\/* .<br \/>\n$ cp money-1.5.9\/MIT-LICENSE LICENSE-money<br \/>\n$ rm -Rf money-1.5.9\/<br \/>\n$ ls<br \/>\n[\/shell]<br \/>\nMake sure you copy in the license depending on the gem&#8217;s license agreements.<\/p>\n<p>In the future when you have upgraded your gems you can follow the same procedure again :[shell]$ gem unpack money<br \/>\nUnpacked gem: &#8216;money-1.7.1&#8217;<br \/>\n$ cp -Rf money-1.7.1\/lib\/* .<br \/>\n$ cp -f money-1.7.1\/MIT-LICENSE LICENSE-money<br \/>\n$ rm -Rf money-1.7.1 [\/shell]<\/p>\n<p>Remember to update your <code>database.yml<\/code> file to include your remote server&#8217;s database for the production database and make sure that it is using the <code>mysql2<\/code> for the production database.<\/p>\n<p>There are also some things you can tighten up when it comes to security. You can read more about it in <a href=\"http:\/\/pragprog.com\/titles\/fr_deploy\/deploying-rails-applications\">this book.<\/a> Important things to note are the following:<\/p>\n<ul>\n<li>Never evaluate user input<\/li>\n<li>Never evaluate SQL input<\/li>\n<\/ul>\n<p>One last thing to check is to make sure you have eager associations for all your active records so that you can have the best optimal database performance.<\/p>\n<p>If your remote server is using mySQL but your local machine is running SQLite for your app, you might also want a copy of the mySQL gem in your local machine. [shell]gem install mysql2[\/shell] Remember to include all this in the Gemfile [ruby]group :development, :test do<br \/>\ngem &#8216;sqlite3-ruby&#8217;, &#8216;1.2.5&#8217;, :require =&gt; &#8216;sqlite3&#8217;<br \/>\nend<br \/>\ngroup :production do<br \/>\ngem &#8216;mysql2&#8217;<br \/>\nend[\/ruby] Run one last time after you are done.[shell] bundle install[\/shell]<\/p>\n<p>When you are done, remember to push your changes up to the gitosis server. [shell] git commit -am &#8220;for deploy&#8221;<br \/>\ngit push origin master[\/shell]<\/p>\n<p>Alright. Capistrano. Yay!<\/p>\n<p>First thing to do is to install Capistrano locally in your development machine. Capistrano only runs in the local machine and it uses SSH or SFTP to connect to your remote server. You do not need to install Capistrano in your remote server.[shell] local $ gem install capistrano[\/shell] Check if it is working by doing : [shell] cap[\/shell]<\/p>\n<p>If it shows you an error of not being able to find your Ruby Gems, then you need to install the &lt;code&gt;echoe&lt;\/code&gt; gem. [shell]gem install echoe[\/shell] Then you can see a list of capistrano tasks. [shell] cap -T[\/shell]<\/p>\n<p>Now that it&#8217;s installed and working we can start. \ud83d\ude42 Finally. CD into your working directory. [shell] capify .[\/shell] Remember the dot after capify.<\/p>\n<p>This will create a &lt;code&gt;Capify&lt;\/code&gt; file in your working directory and a <code>deploy.rb<\/code> in your config folder. To deploy, we just need to ammed the <code>deploy.rb<\/code> file. [ruby]<br \/>\nrequire &#8216;bundler\/capistrano&#8217;<br \/>\nset :application, &#8220;demoappname&#8221;<br \/>\nset :deploy_to,  &#8220;\/home\/#{application}&#8221;<\/p>\n<p>server &#8220;yourdomain.com&#8221;, :app, :web, :db, :primary =&gt; true<\/p>\n<p>default_run_options[:ptr] = true # Ensure password prompt is prompt true<br \/>\nset :repository, &#8216;git@yourdomain.com:demoappname.git&#8217; # your private\/public url and user<\/p>\n<p>set :scm, &#8216;git&#8217; #scm utility name<br \/>\nset :branch, &#8216;master&#8217; #remote branch to push<br \/>\nset :deploy_via, :copy # If you have public like github.com then use :remote_cache<br \/>\nset :user, &#8216;root&#8217;<br \/>\nset :admin_runner, &#8216;root&#8217;<br \/>\n#set :use_sudo, false #to avoid tty error[\/ruby]<\/p>\n<p>And also add the following lines for Passenger to work.[ruby] namespace :deploy do<br \/>\ndesc &#8216;Restart Application&#8217;<br \/>\ntask :restart, :roles =&gt; :app do<br \/>\nrun &#8220;#{current_path}\/tmp\/restart.txt&#8221; #tells passenger to restart app<br \/>\nend<br \/>\ndesc &#8216;Start Application &#8212; not needed for Passenger&#8217;<br \/>\ntask :start, :roles =&gt; :app do<br \/>\n#empty since using passenger<br \/>\nend<br \/>\nend<br \/>\n[\/ruby]<\/p>\n<p>Now you can prepare your server for deployment.[shell]cap deploy:setup[\/shell] You may need to enter your password and if you get a <code>tty<\/code> error just uncomment this line from your<code>deploy.rb<\/code>[ruby]set :use_sudo, false #to avoid tty error[\/ruby]<br \/>\nIf all goes well, your application directory in your remote server should have 2 new folders, <code>releases<\/code> and <code>current<\/code> Now, go back and edit your apache config file in your remote server in the VirtualHosts chunk section. This is your current chunk [text]DocumentRoot \/home\/demoapp\/public<\/p>\n<p>[\/text]<br \/>\nChange it to this and you should be all set to go after you restart your apache server. \ud83d\ude42<br \/>\n[text]DocumentRoot \/home\/demoapp\/current\/public<br \/>\n[\/text]<\/p>\n<p>Check your deployment dependencies. [shell]cap deploy:check[\/shell]<\/p>\n<p>Ok. Time for deployment. For the first deployment, you can do this. [shell]cap deploy:update[\/shell]<br \/>\nNow, errors may pop up now an then.. for my first deploy, I spent the whole night figuring out what I did wrong only to realize I forgot to push my app to gitosis first. lol.<\/p>\n<p>Another error would be the bundle install error where they say that I changed my <code>Gemfile<\/code> without adding <code>Gemfile.lock<\/code> to git. Hmm. I couldn&#8217;t fix it but a fresh deploy on an empty folder fixed it. I cleared out my demo app and deleted the demoapp folder.<\/p>\n<p>After that, ssh into your remote server and CD into your app&#8217;s directory. [shell]rake RAILS_ENV=production db:schema:load[\/shell] This will create all the nessecary tables for your application. The reason why the deployment is separated into this 2 steps, <code>update<\/code> and <code>rake<\/code> is to enable you to debug errors faster instead of doing one whole chunk of deploying to realize that the last step does not work and you have to redo the whole thing.<\/p>\n<p>If you run into errors saying that you do not have mysql2 gem then you probably installed the wrong gem. It should be mysql2 gem not mysql gem, the mysql gem is now stale and no longer supported. You need to install this gem and also define it in Gemfile PLUS ensure that database.yml uses mysql2, not mysql.<\/p>\n<p>If all goes well, all tables would be created, then you can run a test of whether anything works or not by doing [shell] rails console [production][\/shell] [shell]&gt;&gt; app.get(&#8220;\/&#8221;)[\/shell]If it returns 200 or 302 (or any other 2xx or 3xx code, or even 4xx if you haven\u2019t configured the \u201d\/\u201d url for your application), you\u2019re probably set. If it returns something in the 500\u2019s, you\u2019ll want to check your log\/production.log and see why it blew up.<\/p>\n<p>Next, try to access any static asset in your public folder by pointing your browser to <code>http:\/\/yourdomain.com\/javascripts\/prototype.js <\/code><br \/>\nIt should display the javascript file. If it doesn&#8217;t you probably have some issues with apache. Make sure your VirtualHosts is pointing to <code>demoapp\/current\/public folder<\/code><\/p>\n<p>When it works, it is time to start the magic. [shell] cap deploy:start[\/shell]<\/p>\n<p>I need to cry now. Thanks for reading. Peace out.<\/p>\n<p>After that, for every subsequent release you can just issue this command. [shell] cap deploy[\/shell]<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Thank you for following this series, this will be the last part of the series where we actually bring our development app to our remote server. Learning Rails has been a tremendous journey for me, the learning curve&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1776],"tags":[1845,1836,1835,1841,1844,1843,1788,1842],"class_list":["post-1642","post","type-post","status-publish","format-standard","hentry","category-coding-tutorials","tag-capistrano","tag-centos","tag-deploying","tag-git","tag-gitosis","tag-passenger","tag-rails","tag-ruby"],"acf":[],"_links":{"self":[{"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=\/wp\/v2\/posts\/1642","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1642"}],"version-history":[{"count":0,"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=\/wp\/v2\/posts\/1642\/revisions"}],"wp:attachment":[{"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1642"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1642"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/musenmaker.com\/hazelong\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1642"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}