Skip to content

Instantly share code, notes, and snippets.

@rajeevkannav
Created December 1, 2017 05:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rajeevkannav/ddf1ba7aee971710b5cc52e1b190a7b4 to your computer and use it in GitHub Desktop.
Save rajeevkannav/ddf1ba7aee971710b5cc52e1b190a7b4 to your computer and use it in GitHub Desktop.
Mina Deploy Ubuntu 17.10-From Scratch-Rails-Ruby-Mysql-Nginx-Puma and all possible option
require 'mina/rails'
require 'mina/git'
require 'mina/puma'
require 'mina/rvm'
require 'yaml'
set :user, 'deploy'
set :port, '22'
set :forward_agent, true
set :term, :system
set :execution_mode, :system
set :ruby_version, "#{File.readlines(File.join(__dir__, '..', '.ruby-version')).first.strip}"
set :gemset, "#{File.readlines(File.join(__dir__, '..', '.ruby-gemset')).first.strip}"
set :ssl_enabled, false
set :application_name, 'app_name'
set :deploy_to, 'deploy_to_path'
set :repository, "https://GITLAB_USERNAME:GITLAB_PASSWORD@gitlab.com/URL.git"
set :branch, 'master'
set :shared_dirs, fetch(:shared_dirs, []).push(
'log',
'tmp/pids',
'tmp/sockets',
'public/uploads'
)
set :shared_files, fetch(:shared_files, []).push(
'config/database.yml',
'config/cable.yml',
'config/secrets.yml',
'config/puma.rb'
)
##########################################################################
#
# TODO: Something meaning full should be here.
#
##########################################################################
task :remote_environment do
unless ENV['env']
print_error "Task 'test' needs a valid environment name as an argument. e.g. mina test env=trunk"
exit
end
unless ['staging', 'production'].include? ENV['env'].to_s
puts "Task 'test' needs a valid environment name as an argument. e.g. mina test env=trunk"
exit 1
end
case ENV['env']
when 'production'
set :rails_env, 'production'
set :domain, 'PRODUCTION_IP_ADDRESS'
set :db_password, 'MYSQL_DB_PASSWROD'
set :db_name, 'MYSQL_DB_NAME'
when 'staging'
set :rails_env, 'staging'
set :domain, 'PRODUCTION_IP_ADDRESS'
set :db_password, 'MYSQL_DB_PASSWROD'
set :db_name, 'MYSQL_DB_NAME'
else
set :domain, 'localhost'
end
end
##########################################################################
#
# Tasks below are related to code-deploy only. just clone/migrate/
# assets precompile assuming all dependencies are installed and
# in-place and configured.
#
##########################################################################
desc 'Deploys the current version to the server.'
task :deploy => :remote_environment do
invoke :'rvm:use', "#{fetch(:ruby_version)}@#{fetch(:gemset)}"
deploy do
comment "Deploying #{fetch(:application_name)} to #{fetch(:domain)}:#{fetch(:deploy_to)}"
invoke :'git:clone'
invoke :'deploy:link_shared_paths'
# invoke :'rvm:load_env_vars' #FIXME: Why this is commented.
invoke :'bundle:install'
invoke :'rails:db_migrate'
command %{#{fetch(:rails)} db:seed}
invoke :'rails:assets_precompile'
invoke :'deploy:cleanup'
on :launch do
invoke :'puma:phased_restart'
end
end
end
##########################################################################
#
# Tasks below are related to setup, sym-linking, configurations once
# install done.
#
##########################################################################
desc 'Setup everything symlinking/yamls/database/nginx'
task :'setup:all' => :remote_environment do
comment %{ Setup folder structure on server }
invoke :setup
comment %{ defining VirtualHost configurations for nginx }
invoke :'setup:nginx'
end
task :setup do
command %{ mkdir -p #{fetch(:deploy_to)}/shared/log }
command %{ chmod g+rx,u+rwx #{fetch(:deploy_to)}/shared/log }
command %{mkdir -p #{fetch(:deploy_to)}/shared/config}
command %{chmod g+rx,u+rwx #{fetch(:deploy_to)}/shared/config}
command %{touch "#{fetch(:deploy_to)}/shared/config/database.yml"}
invoke :'setup:config:database_yml'
command %{touch "#{fetch(:deploy_to)}/shared/config/cable.yml"}
invoke :'setup:config:cable_yml'
command %{touch "#{fetch(:deploy_to)}/shared/config/secrets.yml"}
invoke :'setup:config:secrets_yml'
command %{mkdir -p "#{fetch(:deploy_to)}/shared/tmp/sockets" }
command %{chmod g+rx,u+rwx "#{fetch(:deploy_to)}/shared/tmp/sockets" }
command %{mkdir -p "#{fetch(:deploy_to)}/shared/tmp/pids" }
command %{chmod g+rx,u+rwx "#{fetch(:deploy_to)}/shared/tmp/pids" }
command %{touch "#{fetch(:deploy_to)}/shared/config/puma.rb"}
invoke :'setup:config:puma'
end
desc 'Populate database.yml'
task :'setup:config:database_yml' do
database_yml = <<-DATABASE.dedent
#{fetch(:rails_env)}:
adapter: mysql2
pool: 15
username: #{fetch(:db_user_name)}
password: #{fetch(:db_password)}
encoding: utf8mb4
collation: utf8mb4_unicode_ci
reconnect: true
reaping_frequency: 25
database: #{fetch(:db_name)}
host: localhost
DATABASE
comment %{ Populating database.yml }
command %{ echo '#{database_yml}' > #{fetch(:deploy_to)}/shared/config/database.yml }
comment %{ database.yml populated. }
end
desc 'Populate cable.yml'
task :'setup:config:cable_yml' do
channel_prefix = 'HoneycrispApple-web_production' #STDIN.gets.chomp
cable_yml = <<-CABLE.dedent
#{fetch(:rails_env)}:
adapter: redis
url: redis://localhost:6379/1
channel_prefix: #{channel_prefix}
CABLE
comment %{ Populating cable.yml }
command %{ echo '#{cable_yml}' > #{fetch(:deploy_to)}/shared/config/cable.yml }
comment %{ cable.yml populated. }
end
desc 'Populate secrets.yml'
task :'setup:config:secrets_yml' do
secret_key_base = 'SECRETS_KEYS' #STDIN.gets.chomp
secrets_yml = <<-SECRETS.dedent
#{fetch(:rails_env)}:
secret_key_base: #{secret_key_base}
SECRETS
comment %{ Populating secrets.yml }
command %{ echo '#{secrets_yml}' > #{fetch(:deploy_to)}/shared/config/secrets.yml }
comment %{ secrets.yml populated.}
end
desc 'Populate Puma.rb'
task :'setup:config:puma' do
puma_rb = <<-PUMA.dedent
environment "#{fetch(:rails_env)}"
bind "unix://#{fetch(:deploy_to)}/shared/tmp/sockets/puma.sock"
pidfile "#{fetch(:deploy_to)}/shared/tmp/pids/puma.pid"
state_path "#{fetch(:deploy_to)}/shared/tmp/sockets/puma.state"
directory "#{fetch(:deploy_to)}/current"
workers 2
threads 1,2
daemonize true
activate_control_app
prune_bundler
PUMA
comment %{ Populating secrets.yml }
command %{ echo '#{puma_rb}' > #{fetch(:deploy_to)}/shared/config/puma.rb }
comment %{ puma.rb populated.}
end
desc "TODO: Something should be here"
task :'setup:nginx' do
if fetch(:ssl_enabled)
#Todo: SSL configurations
else
vhost_content = <<-HOSTFILE.dedent
upstream puma {
server unix://#{fetch(:deploy_to)}/shared/tmp/sockets/puma.sock fail_timeout=0;
}
server {
listen 80;
listen [::]:80;
root #{fetch(:deploy_to)}/current/public;
location ~ ^/assets/ {
expires max;
gzip_static on;
gzip_vary on;
add_header Cache-Control public;
break;
}
location / {
proxy_pass http://puma;
proxy_set_header Host \$host;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
location ~ ^/(500|404|422).html {
root #{fetch(:deploy_to)}/current/public;
}
error_page 500 502 503 504 /500.html;
error_page 404 /404.html;
error_page 422 /422.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
HOSTFILE
end
command %{ echo "#{vhost_content}" > #{fetch(:application_name)}.tmp }
command %{ sudo cp #{fetch(:application_name)}.tmp /etc/nginx/sites-available/#{fetch(:application_name)}}
command %{ rm #{fetch(:application_name)}.tmp }
command %{ sudo ln -s -f /etc/nginx/sites-available/#{fetch(:application_name)} /etc/nginx/sites-enabled/#{fetch(:application_name)} }
command %[sudo -A rm -f /etc/nginx/sites-enabled/default]
comment %{ nginx configurations updated.}
end
##########################################################################
#
# Tasks below are related to installing required stuff required on server
# This include installation of general requirements, nginx, rvm_ruby
#
##########################################################################
desc 'Install everything from the scratch to an ubuntu 17.10 requirements/nodejs/rvm/ruby/rails/nginx/mysql'
task :'install:all' do
invoke :sys_update
invoke :requirements_install
invoke :invoke_nodejs_install
invoke :rvm_ruby_rails_install
invoke :memcached_install
invoke :redis_install
invoke :nginx_install
end
task :sys_update do
comment %{ Running sudo apt-get update }
command %{ sudo apt-get update }
comment %{ sudo apt-get update completed. }
end
task :requirements_install do
comment %{ Installing general requirements ... }
command %{ sudo apt-get install -y git-core curl zlib1g-dev build-essential
libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3
libxml2-dev libxslt1-dev libcurl4-openssl-dev python-software-properties
libffi-dev libmagickwand-dev imagemagick mysql-client libmysqlclient-dev
}
comment %{ General requirements installed. }
end
task :rvm_ruby_rails_install do
comment %{ Installing RVM ... }
command %{ sudo apt-get install -y libgdbm-dev libncurses5-dev automake libtool bison libffi-dev }
command %{ gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 }
command %{ curl -sSL https://get.rvm.io | bash -s stable }
command %{ source ~/.rvm/scripts/rvm }
comment %{ Installing ruby ... }
command %{ rvm install #{fetch(:ruby_version)} }
command %{ rvm use #{fetch(:ruby_version)}@#{fetch(:gemset)} --create }
comment %{ Checking ruby version ... }
command %{ ruby -v }
comment %{ Installing bundler ... }
command %{ gem install bundler }
end
task :invoke_nodejs_install do
comment %{ installing nodejs }
command %{ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash - }
command %{ sudo apt-get install -y nodejs }
comment %{ nodejs installed. }
end
task :memcached_install do
comment %{ installing memcached }
command %{ sudo apt-get install -y memcached }
comment %{ memcached installed. }
end
task :redis_install do
comment %{ installing redis }
command %{ wget -P /tmp http://download.redis.io/redis-stable.tar.gz }
command %{ tar xvfz /tmp/redis-stable.tar.gz -C /tmp/ }
command %{ cd '/tmp/redis-stable' }
command %{ make }
command %{ sudo -A make install }
command %{ cd ~ }
command %{ rm -rf /tmp/redis-* }
comment %{ redis installed. }
end
task :nginx_install do
comment %{ installing nginx }
command %{ sudo apt-get install -y nginx }
comment %{ nginx installed. }
end
#########################################################################
#
# Libraries
#
##########################################################################
#
# See https://github.com/cespare/ruby-dedent/blob/master/lib/dedent.rb
#
class String
def dedent
lines = split "\n"
return self if lines.empty?
indents = lines.map do |line|
line =~ /\S/ ? (line.start_with?(" ") ? line.match(/^ +/).offset(0)[1] : 0) : nil
end
min_indent = indents.compact.min
return self if min_indent.zero?
lines.map {|line| line =~ /\S/ ? line.gsub(/^ {#{min_indent}}/, "") : line}.join "\n"
end
end
######
### Pending Items
# 1.) MYSQL
# a.) Ask mysql password install mysql-server.
# b.) Ask mysql password/database name and Create Database.
# c.) Ask mysql password/database name and write them to database.yml.
# 2.) Restart PUMA
# 3.) Install libmagickwand-dev imagemagick mysql-client libmysqlclient-dev
# 4.) nginx $host issue
# 5.) Gitlab ask username password
# 6.) comments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment