These are the steps I go through to configure a new server for use with a Rails app.
- Either create a new one or rebuild an existing one.
- Select Ubuntu 14 LTS
SSH into the server:
ssh root@[IP]
Add a user with the same name as your local user (whoami
).
sudo addgroup application
sudo adduser [username] --ingroup application
Don't forget to store your password somewhere.
sudo visudo
Add this rule:
# Members of the group application may gain root privileges
%application ALL=(ALL) ALL
sudo vi /etc/hostname # Change this to be example.com
sudo vi /etc/hosts # Append [appname] to first line
sudo reboot
# On your local machine
ssh-copy-id [local-username]@[ip]
ssh [username]@[ip]
ssh git@github.com
ssh bitbucket.org
sudo apt-add-repository -y ppa:brightbox/ruby-ng
sudo apt-get update
sudo apt-get install -y ruby2.1 # Install ruby 2.1.
sudo apt-get install -y ruby2.1-dev # Also need development headers for some gems
sudo apt-get install postgresql
sudo apt-get install libxslt-dev
sudo apt-get install libxml2-dev
sudo apt-get install nginx
sudo service nginx start
sudo apt-get install git
gem 'recap' # dev group only
gem 'unicorn'
gem 'foreman'
Procfile:
web: unicorn_rails -p 3000
Procfile.production --- replace with your app name:
web: bundle exec unicorn -c /home/[appname]/app/config/unicorn-production.rb -E production >> /home/[appname]/app/log/web.log 2>&1
You'll need to change [appname] throughout:
# Some config taken from gist: https://gist.github.com/534668
# Our own variable where we deploy this app to
deploy_to = "/home/[appname]/app"
# Use at least one worker per core if you're on a dedicated server,
# more will usually help for _short_ waits on databases/caches.
worker_processes 2
# Help ensure your application will always spawn in the symlinked
# "current" directory that Capistrano sets up.
working_directory deploy_to
# Listen on a TCP port
listen 8080
# Restart any workers that haven't responded in 120 seconds (there are some long running requests, eg. reporting)
timeout 120
# feel free to point this anywhere accessible on the filesystem
pid "#{deploy_to}/tmp/[appname].pid"
# By default, the Unicorn logger will write to stderr.
# Additionally, some applications/frameworks log to stderr or stdout,
# so prevent them from going to /dev/null when daemonized here:
# stderr_path "#{shared_path}/log/unicorn.stderr.log"
# stdout_path "#{shared_path}/log/unicorn.stdout.log"
#
# combine REE with "preload_app true" for memory savings
# http://rubyenterpriseedition.com/faq.html#adapt_apps_for_cow
preload_app false
GC.respond_to?(:copy_on_write_friendly=) and
GC.copy_on_write_friendly = true
before_fork do |server, worker|
# the following is highly recomended for Rails + "preload_app true"
# as there's no need for the master process to hold a connection
# defined?(ActiveRecord::Base) and
# ActiveRecord::Base.connection.disconnect!
# The following is only recommended for memory/DB-constrained
# installations. It is not needed if your system can house
# twice as many worker_processes as you have configured.
#
# # This allows a new master process to incrementally
# # phase out the old master process with SIGTTOU to avoid a
# # thundering herd (especially in the "preload_app false" case)
# # when doing a transparent upgrade. The last worker spawned
# # will then kill off the old master process with a SIGQUIT.
old_pid = "#{server.config[:pid]}.oldbin"
if old_pid != server.pid
begin
sig = (worker.nr + 1) >= server.worker_processes ? :QUIT : :TTOU
Process.kill(sig, File.read(old_pid).to_i)
rescue Errno::ENOENT, Errno::ESRCH
end
end
# # *optionally* throttle the master from forking too quickly by sleeping
# sleep 1
#log_env(:before_fork, server)
end
after_fork do |server, worker|
# worker.user('deployer', 'deployer') if Process.euid == 0
# per-process listener ports for debugging/admin/migrations
# addr = "127.0.0.1:#{9293 + worker.nr}"
# server.listen(addr, :tries => -1, :delay => 5, :tcp_nopush => true)
# the following is *required* for Rails + "preload_app true",
defined?(ActiveRecord::Base) and
ActiveRecord::Base.establish_connection
# if preload_app is true, then you may also want to check and
# restart any other shared sockets/descriptors such as Memcached,
# and Redis. TokyoCabinet file handles are safe to reuse
# between any number of forked children (assuming your kernel
# correctly implements pread()/pwrite() system calls)
# Reconnect memcached
#Rails.cache.reset
end
# before_exec do |server|
# paths = (ENV["PATH"] || "").split(File::PATH_SEPARATOR)
# paths.unshift "#{shared_bundler_gems_path}/bin"
# ENV["PATH"] = paths.uniq.join(File::PATH_SEPARATOR)
# ENV['GEM_HOME'] = ENV['GEM_PATH'] = shared_bundler_gems_path
# ENV['BUNDLE_GEMFILE'] = "#{deploy_to}/Gemfile"
# end
recap setup # creates a Capfile
- Update the server address
bundle exec cap bootstrap
sudo gem install bundler
Add this line to the end:
set(:procfile) { "#{deploy_to}/Procfile.production" }
We are currently using this hack – add this to the Capfile:
# TODO: hack. Foreman now takes a --run option, which recap doesn't have a configuration option for
# https://github.com/tomafro/recap/blob/master/lib/recap/tasks/foreman.rb#L22
set(:foreman_export_command) { "./bin/foreman export #{foreman_export_format} #{foreman_tmp_location} --procfile #{procfile} --app #{application} --user #{application_user} --log #{deploy_to}/log --run #{deploy_to}" }
Whoosh.
sudo apt-get install libpq-dev
sudo apt-get install build-essential
See here for instructions.
Edit database.yml
production:
adapter: postgresql
encoding: unicode
database: [appname]_production
pool: 5
username: [appname]
Then commit and push.
Switch to the postgres user:
sudo su postgres
Create the db:
createdb [appname]_production
Create the user:
psql
create user [appname] with superuser;
bundle exec cap deploy:setup
bundle exec cap foreman:export
bundle exec cap deploy
- You might need to gitkeep some folders to keep sprockets happy
bundle exec unicorn -c /home/[appname]/app/config/unicorn-production.rb -E production
rake secret
Push as prod env var
cap -vT
Config nginx to proxy any requests to that domain to port 80 to 8080.