First draft/installment of my new Ruby deployment book now out

I’ve always thought that Rails’s “Deploy” page is one of the weakest parts of the Rails website – it’s just a bunch of links with no explanation unlike, say, the Active Job guide. Online tutorials also don’t help, most of them rely only on Heroku (which recently changed the behavior of their free tier to require 6 hours of sleep per day).

Beginners are left with:

  • Buy a book like Agile Web Development With Rails 4 or Rails 4 in Action which have chapters on deployment.
  • Read through the docs of the links on the “Deploy” page and do everything by trial and error.
  • Scour through the countless tutorials online and hope the one you’re working on is correct.

In short, newbies are pretty much screwed.

So I decided to give my own take on the “Ruby deployment for Dummies”. Unlike your usual tutorial, I wouldn’t just focus on the “How to” but also the “Why”. I’ll also look at the various alternatives for the different components of your Ruby server.

And here’s the first draft/installment: A Beginner’s Guide to Deploying Rails.

Early draft of book cover

It’s only the first part so it’s free to read and download. I expect to finish this book by late August.

Please buy the book so I can get out of mini-writer’s blocks and push it out earlier. LOL

Notes on Setting up a Rails Server in 2015 (Ubuntu 14.04, Nginx, Passenger, Ruby 2.1, PostgreSQL)

I spent a decent amount of time last month playing around with scripts for setting up a Rails server from scratch. Turns out that the whole process is simpler than what I had to go through 7 years ago when I was learning how to install LAMP from scratch.

Here’s the basic set of commands to install Nginx + Passenger + Ruby 2.1 + PostgreSQL on an Ubuntu 14.04 Server:

$ sudo su

# apt-add-repository ppa:brightbox/ruby-ng
# apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
# vim /etc/apt/sources.list.d/passenger.list
 
# apt-get update
 
# apt-get install git-core build-essential ruby2.1 ruby2.1-dev \
    libruby2.1 nodejs nginx-extras passenger postgresql libpq-dev
 
# vim /etc/nginx/nginx.conf
 
# adduser deploy --shell /bin/bash --disabled-password
# sudo -u postgres createuser --superuser deploy
# sudo -u postgres createdb deploy
 
# gem2.1 install bundler --no-ri --no-rdoc

($ prompt means user, # means root)

There are a bunch of other stuff that you need to setup like ssh/sshd/firewall and mail/postfix settings but these commands pretty much covers all the software you need to install before you setup a production app. For example, here’s the rest of the commands for setting up Redmine:

# su -l deploy

$ wget http://www.redmine.org/releases/redmine-2.6.0.tar.gz
$ tar -xf redmine-2.6.0.tar.gz
$ cd redmine-2.6.0/
$ vim config/database.yml
$ createdb redmine
$ bundle install --binstubs bin --path bundle --without development test rmagick
$ bin/rake generate_secret_token
$ RAILS_ENV=production bin/rake db:migrate
$ RAILS_ENV=production bin/rake redmine:load_default_data
$ exit

# vim /etc/nginx/sites-available/default
# service nginx restart

Other tutorials already cover most of the commands above. Instead of repeating them, I’ll just be going through some quick notes about the process, explaining my approach and mentioning some gotchas.

Why install Passenger and Ruby from apt repositories?

It’s much faster than installing from source.

It’s also easier to update via apt-get upgrade.

Why Passenger instead of Nginx + Unicorn/Puma/etc?

Aside from the reasons above, it requires less configuration and it’s good enough for most cases.

The only way I’d consider other setups is if you need rolling restarts or more control over your memory usage.

Why use BrightBox’s repo instead of RVM/rbenv or install from source?

Most production servers only need one version of Ruby installed so I don’t see a reason for using version managers. They might make sense in staging servers for testing multiple versions, but not in prod.

Gem installation isn’t a problem since you’re going to use Bundler anyway i.e. after installing and having bundle available system-wide, you can have it install gems locally via --path like in the example above.

So that leaves us with manually installing from source. However, as mentioned above, installing via apt is just more convenient. The BrightBox packages may sometimes not be up-to-date (DevCon is running in preview 2.2 right now), but they tend to update a few weeks after a major release.

Bonus: Why are we using an older version of NodeJS?

We’re not using a more up-to-date apt repository for NodeJS because we’re only using it for asset precompilation.

There’s a gotcha related to this that we’ll talk about later.

Security: why allow root login via ssh?

Just like the “use rvm in prod” advice, it feels like a lot of people go by “PermitRootLogin no” when my script instead uses PermitRootLogin without-password.

For newbies, this makes sense: preventing people from logging in as root is a great way to prevent hacking attempts. In reality, we’re not totally preventing remote “root” log-ins – we’re prevent logging in as root because we want our SysAds to log in as a sudo user so all of their actions can be logged.

For simpler systems, it may be better to just allow remote root login as long as public keys are used, hence “PermitRootLogin without-password“.

Why is the deploy user not a sudo user?

It’s not really for security reasons. Yes, having a basic pasword-less user does make our apps secure, considering that Passenger automatically switches the user to the owner of the app, but my main reason for not making deploy a sudo user is because it doesn’t need it.

It doesn’t need sudo to install gems, bundle install --path installs to a local folder.
It doesn’t need sudo to restart the app server, touch tmp/restart.txt does that.

It’s just a simple constraint I added to make sure I’m isolating the deploy user to deployment tasks.

And besides, some of you might notice how insecure deploy is when it comes to…

Why is the deploy user a superuser for PostgreSQL? Why use Ident/Peer auth instead of a password?

Same reason as root login: personal server, no need for extra security than needed. If the attacker somehow logs in as deploy, the DB is screwed either way.

In other words superuser + peer auth is about as secure as the usual password approach while also easier to setup (by just a few commands LOL).

Config files

There’s nothing special about most of the config files edited via vim in the scripts above. The apt source and default nginx site config file would just contain the recommended settings. The database config can just contain three lines: the environment (production:), the adapter (adapter: postgresql), and the database name.

As for the main nginx config file, apart from being edited as recommended by the docs, there’s also one big gotcha that will prevent your app from running in Passenger:

execjs gotcha

If your app is using sprockets and you’re using an external JS runtime like NodeJS, your app may not run because Passenger can’t find a valid JS runtime via execjs.

Reason? Execjs looks for NodeJS with the PATH, and environment variables like PATH are not automatically used by Passenger.

While there are a couple of ways to solve this, my current preferred method is to use env PATH;.

There you have it, my quick guide to Rails server setup.

I could write a part 2 about deployment, but I’m afraid the tl;dr to that would be “just use Mina“.

On “Career”

It’s graduation season again and kids fresh out of college are out there looking for or choosing jobs. One of them posted a question over at the PhRUG Facebook Group last week and I replied a lengthy series of comments.

I just thought it would be timely to repost them here and make a blog post out of them.

Original question:

Good morning mga sir/ma’am! Tell me if this topic isn’t welcome in this group. :)

I’m a computer engineering student, graduating this april 24.

I need to choose between Accenture and X-Company (private name :) ). This X-Company uses Ruby on Rails. Later at 8PM I’ll be having my Final Assessment in Accenture for Associate Software Engineer position. At 3PM, I have an appointment (probably Job Offer too) in X-company. I need to submit my very very very first web app (is this the right term?) made in Ruby on Rails to them. The bosses there instructed me to do a basic web app made in RoR for me to get hired.

My question is: Are there lots of companies in the Philippines which use RoR? Naiinspired (let’s just say, medyo naiinggit na naiinspired) ako sa ibang tao na nakikita ko na 6-digits ang sahod nila as Senior Software Engineers. I can’t go into that position kapag sa web ako, diba? Although in that X-Company, the possibility na maging pioneer ako is very high. Kasi starting company palang ito dito sa Pilipinas. Ang orig branch niya ay nasa Canada.

I think the misconception here is that web developers are not software engineers.

Yes, some people who setup WordPress and pirate themes can be considered “web developers”. But there are also enterprise web developers that build web applications for large companies (e.g. government and financial institutions), and they are also called “software engineers”. Even this site you’re on right now is being built and maintained by highly paid web developer software engineers.

And here comes the reality check: hindi ka makakapili ng “magandang career”. It’s what you make of what life gives you that will determine if your career will be successful or not.

Maybe if you accept the Accenture gig, you’ll be on the fast track to being a senior dev in a few years. Or maybe you’ll be unlucky and get assigned to a horrible team and a death-march project then get burned out in a shorter span of time.

Maybe if you push on with learning Rails, it will finally click into your head and you’ll get a 6 digit salary by your second year from your day job and freelance work combined. Or maybe you just won’t get it and decide to move on to something different like mobile development.

Point here is that either way is good. No one can predict where life can take you, so please don’t think of this choice as a “do-or-die” one. As long as you invest a good portion your time to personal growth (e.g. studying technology/business/finance, expanding your personal and professional network, keeping yourself healthy, etc), and in turn, significantly increase the opportunities available to you, you do not need to worry about the outcome of this decision.

someone else’s response:

IMHO, don’t let the $alary be your driver for your career.. but, your passion.

Passion is great, and passionate people get far in this industry.

However, keep in mind that many people will try to abuse your passion. It’s no surprise that overtime (paid or unpaid) is very common in this industry.

As for salary, I’d say it’s also important – but you must quickly learn how to manage your finances. A person earning 40k (net) but spends all of it on stuff that fails to make him happy is obviously worse off than a person earning 20k who saves 8k (or more) after spending only on necessities and stuff that she really enjoys. Then there are other stuff like credit cards, investments, avoiding scams, etc BUT THIS IS A RUBY GROUP, DAMMIT! so I won’t talk about them.

One thing that’s definitely more important than salary is TRAINING. Being paid well as a junior developer doesn’t matter if you don’t have good mentors around to show you the ropes and teach you good practices early on.

a side comment to close things out:

Bryan Bibat ibang level talaga ang advice mo *bow*

*shrugs*

It’s not rocket science, people who have gotten out of the rat race will give you pretty much the same advice (most people don’t get out of the rat race, though). I just wish someone would’ve given me that type of advice in my first years of work rather than learning them the hard way. Would’ve spared me years of suicidal depression.

So You Want to Teach Ruby and Rails…

RubyConf Philippines was a blast. I still can’t decide which of the following was the best thing I did in the event:

So yeah, I did a talk on the first day about teaching. Here are my slides:

I recorded an “extended podcast-version” earlier today. Here it is in all it’s crappy one-take glory:

Some quick links for further reading:

Free Rails Book at Leanpub + RailsFTW update

A month and a half to go to build up my street cred for RubyConf PH

Seriously, though, I’ve spent the past month working on stuff related to my upcoming talk, namely, about teaching Rails. At the top of the list was converting and formatting my old outdated Rails 3.0 book to Leanpub‘s markdown dialect.

Long story short, the book is now available there for online viewing. I’ve also gone the Humble Bundle-esque “Pay-what-you-want” for e-books scheme for people interested in giving me money to support my other writing endeavors.

In other news, I’ve finally updated RailsFTW to Rails 4.0.2 and Ruby 2.0 (2.1 is still unstable for Windows). Head over to the site and grab it while it’s hot.