### DigitalOcean Ubuntu 14.04 x64 + Rails 4 + Nginx + Unicorn + PostgreSQL + Capistrano 3 #### [Create a Droplet](https://www.digitalocean.com/community/tutorials/how-to-create-your-first-digitalocean-droplet-virtual-server) SSH into Root $ ssh root@123.123.123.123 Change Root Password $ passwd Add Deploy User $ adduser deployer Update Sudo Privileges $ visudo username ALL=(ALL:ALL) ALL Configure SSH $ vi /etc/ssh/sshd_config Port 22 # Change (1025..65536) Protocol 2 # Change PermitRootLogin no # Change UseDNS no # Add AllowUsers deployer # Add Reload SSH $ reload ssh SSH with Deploy User (Don't close root) $ ssh -p 1026 deployer@123.123.123.123 Install Curl $ sudo apt-get update $ sudo apt-get install curl Install RVM $ curl -L get.rvm.io | bash -s stable $ source ~/.rvm/scripts/rvm $ rvm requirements $ rvm install 2.2.0 $ rvm use 2.2.0 --default $ rvm rubygems current Install PostgreSQL $ sudo apt-get install postgresql postgresql-server-dev-9.3 $ gem install pg -- --with-pg-config=/usr/bin/pg_config Create Postgres User $ sudo -u postgres psql create user deployer with password 'password'; alter role deployer superuser createrole createdb replication; create database MYAPP_production owner deployer; Install GIT $ sudo apt-get install git-core Install Bundler $ gem install bundler Setup Nginx $ sudo apt-get install nginx $ nginx -h $ cat /etc/init.d/nginx $ /etc/init.d/nginx -h $ sudo service nginx start $ sudo vim /etc/nginx/sites-enabled/default upstream unicorn { server unix:/tmp/unicorn.MYAPP.sock fail_timeout=0; } server { listen 80 default deferred; # server_name example.com; root /home/deployer/apps/MYAPP/current/public; location ^~ /assets/ { gzip_static on; expires max; add_header Cache-Control public; } location ~ ^/(robots.txt|sitemap.xml.gz)/ { root /home/deployer/apps/MYAPP/current/public; } try_files $uri/index.html $uri @unicorn; location @unicorn { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_redirect off; proxy_pass http://unicorn; } error_page 500 502 503 504 /500.html; client_max_body_size 4G; keepalive_timeout 10; } Add Unicorn $ vim Gemfile gem 'unicorn' Update Unicorn Config $ vim config/unicorn/production.rb root = "/home/deployer/apps/MYAPP/current" working_directory root pid "#{root}/tmp/pids/unicorn.pid" stderr_path "#{root}/log/unicorn.log" stdout_path "#{root}/log/unicorn.log" worker_processes Integer(ENV['WEB_CONCURRENCY']) timeout 30 preload_app true listen '/tmp/unicorn.spui.sock', backlog: 64 before_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn master intercepting TERM and sending myself QUIT instead' Process.kill 'QUIT', Process.pid end defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect! end after_fork do |server, worker| Signal.trap 'TERM' do puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT' end defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection end # Force the bundler gemfile environment variable to # reference the capistrano "current" symlink before_exec do |_| ENV['BUNDLE_GEMFILE'] = File.join(root, 'Gemfile') end Add Capistrano $ vim Gemfile group :development do gem 'capistrano-rails' gem 'capistrano-rvm' gem 'capistrano3-unicorn' end Install Capistrano $ bundle exec cap install Update Capistrano Capfile $ vim Capfile require 'capistrano/setup' require 'capistrano/deploy' require 'capistrano/rvm' require 'capistrano/bundler' require 'capistrano/rails/assets' require 'capistrano/rails/migrations' require 'capistrano3/unicorn' # Load custom tasks from `lib/capistrano/tasks' if you have any defined Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r } Update Capistrano Deploy Config $ vim config/deploy.rb lock '3.3.5' set :application, 'spui' set :repo_url, 'git@github.com:MYGITHUB/MYAPP.git' ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call set :use_sudo, false set :bundle_binstubs, nil set :linked_files, fetch(:linked_files, []).push('config/database.yml') set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system') after 'deploy:publishing', 'deploy:restart' namespace :deploy do task :restart do invoke 'unicorn:reload' end end Update Production Deploy Config $ vim config/deploy/production.rb set :port, 22 set :user, 'deployer' set :deploy_via, :remote_cache set :use_sudo, false server '123.333.333.333', roles: [:web, :app, :db], port: fetch(:port), user: fetch(:user), primary: true set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}" set :ssh_options, { forward_agent: true, auth_methods: %w(publickey), user: 'deployer', } set :rails_env, :production set :conditionally_migrate, true Add SSH Key to DigitalOcean $ cat ~/.ssh/id_rsa.pub | ssh -p 22 username@123.123.123.123 'cat >> ~/.ssh/authorized_keys' Say Hi to Github # follow the steps in this guide if receive permission denied(public key) # https://help.github.com/articles/error-permission-denied-publickey $ ssh github@github.com Check Deployment (Commit and Push) $ cap production deploy:check Deploy $ cap production deploy Thanks to [James Dullaghan](https://gist.github.com/JamesDullaghan/5941259) for his help.