How to deploy a Rails app to a VPS (or dedicated server)?

ruby-on-rails, ruby-on-rails-3, vps

Solution

I have successfully deployed a heavy Rails application to Linode or Digital Ocean, using these technologies:

- rbenv for Ruby installation

- nginx + Passenger for the application server

- PostgreSQL for the database server

- Capistrano to automate deploys (configure this first on your dev machine with your server IP and settings, I will not cover it here)

These are the steps that work for me:

Setting up the virtual machine

Create a new virtual machine

Follow the setup instructions of your hosting, being Linode or Digital Ocean, to create the node and set it up.

Set up date

- dpkg-reconfigure tzdata

Update packages

- apt-get update

- apt-get upgrade

Security

Create user

- adduser deploy

- usermod -a -G sudo deploy

- logout

Set up SSH key-authentication

On local:

- ssh-keygen

- copy the public key:

- scp ~/.ssh/id_rsa.pub deploy@example.com:~

On the server:

- ssh deploy@example.com

- enable the alias to list files:

- vim ~/.bashrc

- uncomment all aliases

- mkdir .ssh

- mv id_rsa.pub .ssh/authorized_keys

- chown -R deploy:deploy .ssh

- chmod 700 .ssh

- chmod 600 .ssh/authorized_keys

- logout (test the new authentication)

Set up SSH

- sudo vim /etc/ssh/sshd_config

- Switch PermitRootLogin to no

- sudo service ssh restart

Set up firewall

- sudo iptables -L (it should show a void table)

- sudo vim /etc/iptables.firewall.rules

- Paste this: https://gist.github.com/davidmles/89fc88e48e17cf8252bfca374e46355f#file-iptables-firewall-rules

- sudo iptables-restore < /etc/iptables.firewall.rules

- sudo iptables -L (now it should show the configured rules)

- sudo vim /etc/network/if-pre-up.d/firewall

- Paste this: https://gist.github.com/davidmles/89fc88e48e17cf8252bfca374e46355f#file-firewall

- sudo chmod +x /etc/network/if-pre-up.d/firewall

Set up fail2ban

Set up if you have enough free memory, as it tends to eat it.

- sudo apt-get install -y fail2ban

Setup Ruby

Install Git

- sudo apt-get install -y git

Install rbenv

- git clone https://github.com/sstephenson/rbenv.git ~/.rbenv

- echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc

- echo 'eval "$(rbenv init -)"' >> ~/.bashrc

- source ~/.bashrc

- git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build

Install Ruby

- sudo apt-get install -y curl gnupg build-essential

- rbenv install -l (look for the latest version)

- rbenv install 2.3.3 (or the latest available version at this moment)

- rbenv global 2.3.3

- rbenv rehash

- vim .gemrc

- Paste this: gem: --no-document

Setup servers

Install nginx + Passenger

- Install following the documentation:

- https://www.phusionpassenger.com/library/install/nginx/install/oss/jessie/

Install PostgreSQL

- Install following the documentation:

- https://wiki.postgresql.org/wiki/Apt#PostgreSQL_packages_for_Debian_and_Ubuntu

Setup libraries

Install node.js

Needed to pre-compile assets.

- sudo apt-get install -y nodejs

Install bundler

- get install bundler

- rbenv rehash

Setup the application

Create the user in PostgreSQL

- createuser username --pwprompt

- createdb -Ousername -Eutf8 db_name

- Test it:

- psql db_name --user username --password

Deploy the code * On the server: * sudo mkdir -p /srv/yoursite.com * sudo chown deploy:deploy /srv/yoursite.com * On your dev machine: * bundle exec cap production deploy:check (it will throw an error because it doesn't find the database) * On the server: * cd /srv/yoursite.com/shared/config * vim database.yml (paste your database config) * vim secrets.yml (paste your secrets config) * On your dev machine: * bundle exec cap production deploy * bundle exec cap production whenever:update_crontab

Configure logrotate

- Follow this guide: * https://gorails.com/guides/rotating-rails-production-logs-with-logrotate

Problem

How can I deploy a Rails app to a VPS (virtual private server) or a dedicated server? It would be nice to have an easy to follow guide. I know about scripts to automate the process, but I think it's better to have everything under control, in order to understand better the process.

Original source