set :nginx_configuration, fetch(:nginx_configuration, {}) set :base_domain, ->{fetch(:base_domain,ask(:base_domain,nil))} set :prelaunch_domain, ->{fetch(:prelaunch_domain,ask(:prelaunch_domain,nil))} set :site_domains, ->{fetch(:site_domains,ask(:site_domains,nil))} set :basic_auth_required, fetch(:basic_auth_required, false) set :ssl_required, fetch(:ssl_required, false) set :deploy_domain, ->{fetch(:deploy_domain,ask(:deploy_domain,nil))}
namespace :nginx do
desc "Check the config exists, and generate if it doesn't" task :check_config do set :nginx_sites_available, "/etc/nginx/sites-available/#{fetch(:deploy_domain)}" set :nginx_sites_enabled, "/etc/nginx/sites-enabled/#{fetch(:deploy_domain)}" on roles(:web) do unless test("[ -f #{"/etc/nginx/sites-enabled/#{fetch(:deploy_domain)}"} ]") invoke "nginx:generate_config" end end end desc "Generate an Nginx config from a template, with a few prerequisite tasks" task :generate_config => [ :generate_ssl, :generate_cloudflare_real_ips, :generate_php, :generate_upstream_proxy, :generate_redirects, :add_basic_auth, :generate_rewrites, :generate_custom_rules, :generate_custom_aliases, :generate_cors, :generate_path_redirects, :generate_proxy_cache ] do file = File.join(File.dirname(__FILE__), "templates","nginx", "nginx_vhost.conf.erb") buffer = ERB.new(File.read(file)).result(binding) on roles(:web) do upload! StringIO.new(buffer), "#{shared_path}/#{fetch(:deploy_domain)}" execute "mv #{shared_path}/#{fetch(:deploy_domain)} #{"/etc/nginx/sites-available/#{fetch(:deploy_domain)}"}" execute "ln -nfs #{"/etc/nginx/sites-available/#{fetch(:deploy_domain)}"} #{"/etc/nginx/sites-enabled/#{fetch(:deploy_domain)}"}" invoke 'nginx:reload' end end desc "Add basic auth to the nginx config" task :add_basic_auth do #set up the basic auth if the vars are defined if fetch(:basic_auth_required, false) set :basic_auth_realm, "Your username and password are required" # set :basic_auth_username, ->{fetch(:basic_auth_username,ask(:basic_auth_username,nil))} # set :basic_auth_password, ->{fetch(:basic_auth_password,ask(:basic_auth_password,nil))} on roles :web do encrypted_password = `openssl passwd -apr1 #{fetch(:basic_auth_password)}` execute :echo, "'#{fetch(:basic_auth_username)}:#{encrypted_password.chomp}'", "> #{shared_path}/.htpasswd" end file = File.join(File.dirname(__FILE__), "templates","nginx", "basic_auth.erb") basic_auth = {basic_auth: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration).merge(basic_auth) invoke "deploy:set_ownership" end end desc "Reload Nginx" task :reload do on roles(:web) do sudo "/usr/sbin/invoke-rc.d nginx reload" end end desc "Generate CORS headers for nginx" task :generate_cors do if fetch(:include_nginx_cors, false) file = File.join(File.dirname(__FILE__), "templates","nginx", "cors.erb") # generate a hash which is the content of the nginx redirects, with a key cors = {cors: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration).merge(cors) end end desc "Generate custom rules from a hash of rules. NB this is inside the main server block" task :generate_custom_rules do file = File.join(File.dirname(__FILE__), "templates","nginx", "custom_rules.erb") # generate a hash which is the content of the nginx redirects, with a key rules = {custom_rules: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration).merge(rules) end desc "Generate custom aliases from a hash. NB this is inside the main server block" task :generate_custom_aliases do file = File.join(File.dirname(__FILE__), "templates","nginx", "custom_aliases.erb") # generate a hash which is the content of the nginx redirects, with a key aliases = {custom_aliases: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration).merge(aliases) end desc "Generate 301 path redirects from a hash. NB this is inside the main server block" task :generate_path_redirects do file = File.join(File.dirname(__FILE__), "templates","nginx", "path_redirects.erb") # generate a hash which is the content of the nginx redirects, with a key aliases = {path_redirects: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration).merge(aliases) end desc "Generate PHP-FPM proxy and headers" task :generate_php => :generate_ssl do if fetch(:php_required, false) file = File.join(File.dirname(__FILE__), "templates","nginx", "php.erb") php = {php: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(php) end end desc "Generate upstream proxy and headers" task :generate_upstream_proxy => :generate_ssl do if fetch(:upstream_proxy_required, false) file = File.join(File.dirname(__FILE__), "templates","nginx", "upstream_proxy.erb") upstream = {upstream: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(upstream) end end desc "Generate proxy cache settings" task :generate_proxy_cache => :generate_upstream_proxy do if fetch(:upstream_proxy_cache, false) set :cache_zone, "#{fetch(:application)}_#{fetch(:stage)}" file = File.join(File.dirname(__FILE__), "templates","nginx", "proxy_cache_path.erb") cache_path = {proxy_cache_path: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(cache_path) file = File.join(File.dirname(__FILE__), "templates","nginx", "location_proxy_cache.erb") location_proxy_cache = {location_proxy_cache: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(location_proxy_cache) end end desc "Generate redirects in separate server blocks" task :generate_redirects => :generate_ssl do file = File.join(File.dirname(__FILE__), "templates","nginx", "redirects.erb") # generate a hash which is the content of the nginx redirects, with a key redirects = {domain_redirects: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(redirects) end desc "Generate rewrites" task :generate_rewrites do file = File.join(File.dirname(__FILE__), "templates","nginx", "rewrites.erb") rewrites = {url_rewrites: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(rewrites) end desc "Generate SSL settings from files in a specified location" task :generate_ssl do if fetch(:ssl_required, false) set :ip_address, ->{fetch(:ip_address, ask(:ip_address,nil))} set :ssl_cert_path, File.join(fetch(:ssl_dir), fetch(:ssl_cert)) set :ssl_key_path, File.join(fetch(:ssl_dir), fetch(:ssl_key)) set :ssl_dh_path, File.join(fetch(:ssl_dir), fetch(:ssl_dh)) unless File.exists?(fetch(:ssl_cert_path)) && File.exists?(fetch(:ssl_key_path)) & File.exists?(fetch(:ssl_dh_path)) puts "You need to put your SSL GPG-encrypted key, DH params and cert in the locations you've specified" exit end set :gpg_phrase, ask("GPG passphrase for SSL key and DH:",nil) set :ssl_path, "/etc/nginx/ssl" key = `echo #{fetch(:gpg_phrase)} | gpg -d -q --batch --passphrase-fd 0 --no-mdc-warning #{fetch(:ssl_key_path)}` dh = `echo #{fetch(:gpg_phrase)} | gpg -d -q --batch --passphrase-fd 0 --no-mdc-warning #{fetch(:ssl_dh_path)}` set :certificate_sha256, `openssl x509 -in #{fetch(:ssl_cert_path)} -pubkey -noout | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -binary | openssl enc -base64` if $?.success? on roles(:web) do upload! fetch(:ssl_cert_path), "#{fetch(:ssl_path)}/#{fetch(:deploy_domain)}.crt" upload! StringIO.new(key), "#{fetch(:ssl_path)}/#{fetch(:deploy_domain)}.key" upload! StringIO.new(dh), "#{fetch(:ssl_path)}/#{fetch(:deploy_domain)}.pem" end else puts "Incorrect GPG passphrase" exit end file = File.join(File.dirname(__FILE__), "templates","nginx", "ssl_settings.erb") ssl_settings = {ssl_settings: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(ssl_settings) end end desc "Get a list of Cloudflare IPs, and set real ip from the header" task :generate_cloudflare_real_ips do ips = open("https://www.cloudflare.com/ips-v4/").read set :cloudflare_real_ips, ips.gsub(/\<.*>/,"").split("\n") file = File.join(File.dirname(__FILE__), "templates","nginx", "cloudflare_real_ips.erb") cloudflare_ips = {cloudflare_real_ips: ERB.new(File.read(file)).result(binding)} set :nginx_configuration, fetch(:nginx_configuration,{}).merge(cloudflare_ips) end
end
after “deploy:check”, “nginx:check_config” after “nginx:generate_config”, “nginx:reload”