VPS Ubuntu 14.04(update to 16.04) x64 + Rails 4 + Nginx + Unicorn + MySQL + PostgreSQL + Capistrano 3
SSH into Root
local$ ssh root@123.123.123.123
Step 01 - Upgrade to Ubuntu 16.04 LTS
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
$ sudo apt-get install update-manager-core
$ sudo do-release-upgrade
Change Root Password
$ sudo passwd
Add Deploy User
$ sudo adduser deployer
Update Sudo Privileges (don't forget remove it after installing all you need)
$ sudo visudo
deployer ALL=(ALL:ALL) ALL
Configure SSH
$ sudo nano /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
Login with Deploy User
local$ ssh deployer@123.123.123.123
Add SSH Key to DigitalOcean
$ mkdir ~/.ssh
$ touch ~/.ssh/authorized_keys
local$ 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
Install Curl
$ sudo apt-get update
$ sudo apt-get install curl
Step 02 - Install RVM
$ curl -L get.rvm.io | bash -s stable
$ source ~/.rvm/scripts/rvm
$ rvm requirements
$ rvm install 2.3.0
$ rvm use 2.3.0 --default
$ rvm rubygems current
Install Bundler
$ gem install bundler
Step 03 - Install MySQL
$ sudo apt-get install mysql-server libmysql-ruby libmysqlclient-dev
$ gem install mysql2
# If you need import your DB:
# copy db file from your machine
$ scp ~/Path/database-name.sql deployer@123.123.123.123:/home/deployer/dest-folder
$ scp -r ~/Path/source-folder deployer@123.123.123.123:/home/deployer/dest-folder
# and import it into db (on server)
$ mysql
CREATE DATABASE database_name;
$ mysql -u username -p database_name < /home/deployer/dest-folder/database_name.sql
Step 04 - Install PostgreSQL
$ sudo apt-get install postgresql postgresql-server-dev-9.5
$ 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;
Step 05 - Install GIT
$ sudo apt-get install git-core
Step 06 - Install Sendmail
$ sudo nano /etc/hosts
127.0.0.1 localhost localhost.localdomain yourhostnamehere
$ sudo nano /etc/hostname
localhost
123.123.123.123
$ /etc/init.d/networking stop
$ /etc/init.d/networking start
$ sudo apt-get install sendmail
$ sudo sendmailconfig
$ echo "Subject: test" | sendmail yourname@gmail.com
Step 07 - Setup Nginx
$ sudo apt-get install nginx
$ nginx -h
$ cat /etc/init.d/nginx
$ /etc/init.d/nginx -h
$ sudo service nginx start
$ sudo nano /etc/nginx/sites-enabled/default
upstream YOURAPP{
server 127.0.0.1:4000 fail_timeout=0;
}
server {
listen 80 default deferred;
#server_name YOURAPP.org.ua;
root /var/www/current/public;
#root /home/deployer/apps/YOURAPP/current/public
location / {
proxy_pass http://YOURAPP;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 100m;
client_body_buffer_size 128k;
proxy_connect_timeout 90;
proxy_send_timeout 90;
proxy_read_timeout 90;
proxy_buffer_size 4k;
proxy_buffers 4 32k;
proxy_busy_buffers_size 64k;
proxy_temp_file_write_size 64k;
}
location ~ ^/(assets)/ {
root /home/deployer/apps/YOURAPP/current/public;
gzip_static on; # to serve pre-gzipped version
expires max;
add_header Cache-Control public;
}
}
$ sudo service nginx restart
Step 08 - Add Puma
$ nano Gemfile
gem 'puma'
Step 09 - Add Capistrano
$ nano Gemfile
group :development do
gem 'capistrano'#, '~> 3.6'
gem 'capistrano-rails'#, '~> 1.2'
gem 'capistrano-rvm'
gem 'capistrano3-puma', require: false
gem 'steps', git: 'git@github.com:roman-franko/gem-steps.git'
end
Install Capistrano
$ bundle exec cap install
Update Capistrano Capfile
$ nano Capfile
require 'capistrano/setup'
require 'capistrano/deploy'
require 'capistrano/rvm'
require 'capistrano/bundler'
require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/puma'
require 'capistrano/scm/git'
require 'whenever/capistrano'
# require 'capistrano/rails/db'
install_plugin Capistrano::SCM::Git
# Load custom tasks from `lib/capistrano/tasks' if you have any defined
Dir.glob('lib/capistrano/tasks/*.cap').sort.each { |r| import r }
Update Capistrano Deploy Config
$ vim config/deploy.rb
# lock '3.4.0'
set :application, "YOURAPP"
# set :scm, :git
set :repo_url, 'git@bitbucket.org:REPO/YOURAPP.git'
set :branch, ENV['BRANCH'] ? ENV['BRANCH'] : "master"
# ask :branch, proc { `git rev-parse --abbrev-ref HEAD`.chomp }.call
set :ssh_options, { forward_agent: true, auth_methods: %w(publickey) }
set :linked_files, %w{ config/database.yml
config/secrets.yml
config/mailer.yml }
set :linked_dirs, %w{ bin
db/sphinx/demo/extracted_page_core
log
public/system
public/uploads
public/assets
tmp/pids
tmp/cache
tmp/sockets
tmp/binlog/demo
vendor/bundle }
set :assets_roles, [:web, :app]
set :rails_env, "#{fetch(:stage)}"
set :bundle_binstubs, -> { shared_path.join('bin') }
set :puma_worker_timeout, nil
set :puma_init_active_record, true
set :puma_preload_app, true
# set :format, ENV['DEBUG'] ? :pretty : :black_hole
set :log_level, ENV['DEBUG'] ? :debug : :warn
Update Demo Deploy Config
$ nano config/deploy/demo.rb
set :user, 'deployer'
set :stage, :demo
set :branch, ENV['BRANCH'] || "master"
set :deploy_to, "/home/#{fetch(:user)}/apps/#{fetch(:application)}"
server "123.123.123.123", user: "deployer", roles: %w{app db resque_worker}
# set :workers, { email: 1, carrierwave: 1 }
set :puma_bind, 'tcp://0.0.0.0:4000'
set :puma_threads, [1, 32]
set :puma_workers, 2
namespace :deploy do
desc "Start application"
task :start do
# invoke 'resque:start'
end
desc "Stop application"
task :stop do
# invoke 'resque:stop'
end
desc "Restart application"
task :restart do
# invoke 'resque:restart'
end
after :publishing, :restart
# after 'deploy:updated', 'deploy:db:migrate'
after :finishing, 'deploy:cleanup'
end
Check Deployment (Commit and Push)
$ cap demo deploy:check
Step 10 - Deploy
$ cap demo deploy
$ cap demo puma:start
$ cap demo puma:restart
$ cap demo puma:stop
Step 11 - Extra settings: Basic Firewal, Timezones, Swap File
- Close all you need portswith ufw
- Check ports with: nmap / zenmap netstat -tuna
- If need protection from DDos install 'fail2ban'
Step 12 - Remove Sudo Privileges
$ visudo
#deployer ALL=(ALL:ALL) ALL
Step 13 - Add helpful tools
- slap - text editor (like Sublime, for terminal)
Thanks to JHardy for his help.