Skip to content

Instantly share code, notes, and snippets.

@jesperronn
Forked from troelskn/Capfile
Created January 26, 2016 11:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jesperronn/ebc945796138163b216d to your computer and use it in GitHub Desktop.
Save jesperronn/ebc945796138163b216d to your computer and use it in GitHub Desktop.
Sample cap setup
# Load DSL and set up stages
require 'capistrano/setup'
# Include default deployment tasks
require 'capistrano/deploy'
# Include tasks from other gems included in your Gemfile
#
# For documentation on these, see for example:
#
# https://github.com/capistrano/rvm
# https://github.com/capistrano/rbenv
# https://github.com/capistrano/chruby
# https://github.com/capistrano/bundler
# https://github.com/capistrano/rails
# https://github.com/capistrano/passenger
#
# require 'capistrano/rvm'
# require 'capistrano/rbenv'
# require 'capistrano/chruby'
require 'capistrano/bundler'
# require 'capistrano/rails/assets'
require 'capistrano/rails/migrations'
require 'capistrano/git-submodule-strategy'
require 'capistrano/puma'
require 'capistrano/puma/workers' # if you want to control the workers (in cluster mode)
require 'capistrano/puma/jungle' # if you need the jungle tasks
# require 'capistrano/puma/monit' # if you need the monit tasks
require 'capistrano/puma/nginx' # if you want to upload a nginx site template
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
# config valid only for current version of Capistrano
lock '3.4.0'
set :application, 'xxx'
set :repo_url, 'git@github.com:troelskn/xxx.git'
set :ssh_options, {
user: "ubuntu",
forward_agent: true,
keys: "~/.ssh/aws-xxx.pem"
}
# To see verbose output from bundler
# set :bundle_flags, '--deployment'
# Default branch is :master
# ask :branch, `git rev-parse --abbrev-ref HEAD`.chomp
# Default deploy_to directory is /var/www/my_app_name
# set :deploy_to, '/var/www/my_app_name'
# Default value for :scm is :git
# set :scm, :git
set :git_strategy, Capistrano::Git::SubmoduleStrategy
# Default value for :format is :pretty
# set :format, :pretty
# Default value for :log_level is :debug
# set :log_level, :debug
# Default value for :pty is false
# set :pty, true
# Default value for :linked_files is []
# set :linked_files, fetch(:linked_files, []).push('config/database.yml', 'config/secrets.yml')
# Default value for linked_dirs is []
# set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
set :linked_dirs, fetch(:linked_dirs, []).push('log', 'tmp/pids', 'tmp/cache', 'tmp/sockets', 'vendor/bundle', 'public/system')
# Default value for default_env is {}
# set :default_env, { path: "/opt/ruby/bin:$PATH" }
# Default value for keep_releases is 5
# set :keep_releases, 5
task :setup do ; end
after 'deploy:finished', 'puma:jungle:restart'
before 'setup', 'setup:apt:upgrade'
before 'setup', 'setup:apt:install'
before 'setup', 'setup:ruby'
before 'setup', 'setup:nginx:install'
before 'setup', 'puma:jungle:install'
before 'setup', 'puma:jungle:add'
before 'setup', 'puma:nginx_config'
after 'puma:nginx_config', :puma_post_setup do
on roles(fetch(:puma_nginx)) do
execute "mkdir -p #{shared_path}/tmp/pids"
execute "mkdir -p #{shared_path}/tmp/sockets"
execute "mkdir -p #{shared_path}/log"
end
invoke 'setup:nginx:restart'
end
before 'setup', 'git:check'
set_if_empty :setup_roles, :app
set :apt_packages, %w(build-essential openssl libmysqlclient-dev libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev autoconf libc6-dev libncurses5-dev automake libtool bison nodejs subversion)
set :puma_user, -> { fetch(:ssh_options)[:user] }
set :puma_nginx, -> { fetch(:setup_roles) }
set :nginx_server_name, -> { fetch(:domain) }
set :nginx_cache_path, "/var/cache/nginx"
# TODO Need a letsencrypt task first
# set :nginx_use_ssl, true
source 'https://rubygems.org'
gem 'rails', '>= 5.0.0.beta1.1', '< 5.1'
gem 'mysql2', '>= 0.3.18', '< 0.5'
gem 'puma'
group :development do
gem 'spring'
gem 'capistrano'
gem 'capistrano-git-submodule-strategy'
gem 'capistrano-rails'
gem 'capistrano3-puma'
end
require 'setup_helpers'
namespace :setup do
# TODO: Not currently used, but probably should be
namespace :user do
desc "Create deploy user"
task :create do
on roles(fetch(:setup_roles)) do
name = 'deploy'
deploy_keys = Dir.glob("config/deploy/keys/*.pub")
groups = ['www-data', 'sudo'].join(",")
unless test :sudo, "id -u #{name} > /dev/null"
execute :sudo, "useradd --create-home --shell /bin/bash --user-group --groups #{groups} #{name}"
end
if deploy_keys.any?
sudo "mkdir -p /home/#{name}/.ssh"
sudo "touch /home/#{name}/.ssh/authorized_keys"
sudo "chmod 0700 /home/#{name}/.ssh"
sudo "chown -R #{name}:#{name} /home/#{name}/.ssh"
sudo "chmod 0700 /home/#{name}/.ssh/authorized_keys"
path = "/home/#{name}/.ssh/authorized_keys"
[deploy_keys].flatten.each do |keyname|
key = File.open(keyname).read.strip
execute "echo #{key.shellescape}|sudo tee -a #{path}" unless file_contains?(path, key, sudo: true)
end
end
# passwdless sudo
execute :echo, "#{name} ALL=(ALL) NOPASSWD:ALL\n".shellescape, "|sudo tee /etc/sudoers.d/90-#{name}-user"
end
end
end
namespace :apt do
desc "Updates apt index"
task :update do
on roles(fetch(:setup_roles)) do
sudo "apt-get update -y -qq"
end
end
desc "Upgrades apt-installed packages"
task upgrade: :update do
on roles(fetch(:setup_roles)) do
noninteractive = "env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive"
sudo "#{noninteractive} apt-get upgrade --assume-yes --force-yes"
end
end
desc "Installs system level packages with apt"
task install: :update do
on roles(fetch(:setup_roles)) do
apt_install fetch(:apt_packages)
end
end # task :install_apt
end # namespace :apt
desc "Installs ruby from source"
task :ruby do
on roles(fetch(:setup_roles)) do
version = fetch(:ruby_version, "2.3.0")
major_version = version.gsub(/(\d+\.\d+)\.\d+/, "\\1")
unless capture("which ruby && ruby -v ; echo ''").match(version)
within "/usr/src/" do
sudo :wget, "https://cache.ruby-lang.org/pub/ruby/#{major_version}/ruby-#{version}.tar.gz"
sudo :tar, "xvfz", "ruby-#{version}.tar.gz"
within "ruby-#{version}" do
sudo "./configure"
sudo :make
sudo :make, "install"
end
end
sudo "gem update --system"
sudo "gem install bundler"
end
end
end # task :ruby
namespace :nginx do
desc "Installs nginx server"
task :install do
on roles(fetch(:setup_roles)) do
apt_install "nginx"
["/var/www", fetch(:nginx_cache_path, "/var/cache/nginx")].each do |path|
unless test "[ -d #{path.shellescape} ]"
sudo :mkdir, "-p #{path.shellescape}"
sudo :chown, "www-data:www-data #{path.shellescape}"
end
end
if test "[ -L '/etc/nginx/sites-enabled/default' ]"
sudo :rm, "/etc/nginx/sites-enabled/default"
end
end
end # task :install
desc "Restarts nginx service"
task :restart do
on roles(fetch(:setup_roles)) do
# TODO: This fails silently - verify
sudo "service nginx restart"
end
end
end # namespace :nginx
end
module SetupHelpers
def template(from, to)
[
"config/deploy/assets/#{from}.#{fetch(:stage)}.erb",
"config/deploy/assets/#{from}.erb",
].each do |path|
if File.file?(path)
erb = File.read(path)
upload! StringIO.new(ERB.new(erb).result(binding)), to
break
end
end
end
def file_contains?(path, text, options = {})
options = {:mode => :text}.merge(options)
if options[:mode] == :text
command = Array(text.strip.split("\n")).flatten.map {|line| "grep --fixed-strings #{line.shellescape} #{path.shellescape}" }.join(" && ")
elsif options[:mode] == :perl
command = [:grep, "--perl-regexp #{text.shellescape} #{path.shellescape}"]
else
command = [:grep, "grep --basic-regexp #{text.shellescape} #{path.shellescape}"]
end
if options[:sudo]
test(:sudo, *command)
else
test(*command)
end
end
def apt_install(packages)
[packages].flatten.each do |package_name|
unless test(:sudo, "dpkg --status #{package_name.to_s.shellescape} | grep 'ok installed'")
noninteractive = "env DEBCONF_TERSE='yes' DEBIAN_PRIORITY='critical' DEBIAN_FRONTEND=noninteractive"
execute :sudo, "#{noninteractive} apt-get --assume-yes --force-yes --show-upgraded --quiet install #{package_name.to_s.shellescape}"
end
end
end
def with_verbosity(verbosity, &block)
old_output_verbosity = SSHKit.config.output_verbosity
SSHKit.config.output_verbosity = verbosity
yield
ensure
SSHKit.config.output_verbosity = old_output_verbosity if old_output_verbosity
end
end
SSHKit::Backend::Abstract.send :include, SetupHelpers
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment