Last active
August 9, 2019 05:02
-
-
Save sudhirsb2003/f578e72f91a7bf60ad33fc561eaf74f4 to your computer and use it in GitHub Desktop.
Ubuntu 14.04 x64 + Rails 4 + Nginx + Unicorn + PostgreSQL + Capistrano 3 Setup Instructions
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
### Ubuntu 14.04 x64 + Rails 4 + Nginx + Unicorn + PostgreSQL + Capistrano 3 | |
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 | |
Create Unicorn Init Script | |
Let's create an init script so we can easily start and stop Unicorn, and ensure that it will start on boot. | |
Create a script and open it for editing with this command (replace the unicorn_app part with your application name, if you wish): | |
sudo vi /etc/init.d/unicorn_appname | |
Copy and paste the following code block into it, and be sure to substitute USER and APP_NAME with the appropriate values | |
#!/bin/sh | |
### BEGIN INIT INFO | |
# Provides: unicorn | |
# Required-Start: $all | |
# Required-Stop: $all | |
# Default-Start: 2 3 4 5 | |
# Default-Stop: 0 1 6 | |
# Short-Description: starts the unicorn app server | |
# Description: starts unicorn using start-stop-daemon | |
### END INIT INFO | |
set -e | |
USAGE="Usage: $0 <start|stop|restart|upgrade|rotate|force-stop>" | |
# app settings | |
USER="deploy" | |
APP_NAME="appname" | |
APP_ROOT="/home/$USER/$APP_NAME" | |
ENV="production" | |
# environment settings | |
PATH="/home/$USER/.rbenv/shims:/home/$USER/.rbenv/bin:$PATH" | |
CMD="cd $APP_ROOT && bundle exec unicorn -c config/unicorn.rb -E $ENV -D" | |
PID="$APP_ROOT/shared/pids/unicorn.pid" | |
OLD_PID="$PID.oldbin" | |
# make sure the app exists | |
cd $APP_ROOT || exit 1 | |
sig () { | |
test -s "$PID" && kill -$1 `cat $PID` | |
} | |
oldsig () { | |
test -s $OLD_PID && kill -$1 `cat $OLD_PID` | |
} | |
case $1 in | |
start) | |
sig 0 && echo >&2 "Already running" && exit 0 | |
echo "Starting $APP_NAME" | |
su - $USER -c "$CMD" | |
;; | |
stop) | |
echo "Stopping $APP_NAME" | |
sig QUIT && exit 0 | |
echo >&2 "Not running" | |
;; | |
force-stop) | |
echo "Force stopping $APP_NAME" | |
sig TERM && exit 0 | |
echo >&2 "Not running" | |
;; | |
restart|reload|upgrade) | |
sig USR2 && echo "reloaded $APP_NAME" && exit 0 | |
echo >&2 "Couldn't reload, starting '$CMD' instead" | |
$CMD | |
;; | |
rotate) | |
sig USR1 && echo rotated logs OK && exit 0 | |
echo >&2 "Couldn't rotate logs" && exit 1 | |
;; | |
*) | |
echo >&2 $USAGE | |
exit 1 | |
;; | |
esac | |
Save and exit. This will allow you to use service unicorn_appname to start and stop your Unicorn and your Rails application. | |
Update the script's permissions and enable Unicorn to start on boot: | |
sudo chmod 755 /etc/init.d/unicorn_appname | |
sudo update-rc.d unicorn_appname defaults | |
Let's start it now: | |
sudo service unicorn_appname start | |
Now your Rails application's production environment is running under Unicorn, and it's listening on the shared/sockets/unicorn.sock socket. | |
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. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment