diff --git a/.overcommit.yml b/.overcommit.yml index 0fc245be..5cfa04e0 100644 --- a/.overcommit.yml +++ b/.overcommit.yml @@ -6,13 +6,6 @@ PreCommit: enabled: true BundleAudit: enabled: true - description: 'Run bundle-audit' - required_executable: './bin/bundle-audit' - flags: ['check', '--update'] - install_command: 'gem install bundler-audit' - include: - - 'Gemfile' - - 'Gemfile.lock' BundleCheck: enabled: true CaseConflicts: diff --git a/Berksfile b/Berksfile index 0656a996..30c95447 100644 --- a/Berksfile +++ b/Berksfile @@ -1,4 +1,5 @@ # frozen_string_literal: true source 'https://supermarket.chef.io' +solver :ruby, :required metadata diff --git a/Gemfile.lock b/Gemfile.lock index 0e893fe5..afbb881c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -194,7 +194,7 @@ GEM plist (~> 3.1) systemu (~> 2.6.4) wmi-lite (~> 1.0) - overcommit (0.34.2) + overcommit (0.36.0) childprocess (~> 0.5.8) iniparse (~> 1.4) parser (2.3.1.2) diff --git a/README.md b/README.md index 39bc8a76..a7669923 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ then [add recipes to the corresponding OpsWorks actions](#recipes). * Unicorn * Web server * Null (no webserver) + * Apache2 * nginx * Worker * Null (no worker) @@ -41,7 +42,6 @@ then [add recipes to the corresponding OpsWorks actions](#recipes). ### Cookbooks -* [build-essential (~> 2.0)](https://supermarket.chef.io/cookbooks/build-essential) * [deployer](https://supermarket.chef.io/cookbooks/deployer) * [ruby-ng](https://supermarket.chef.io/cookbooks/ruby-ng) * [nginx (~> 2.7)](https://supermarket.chef.io/cookbooks/nginx) @@ -234,14 +234,49 @@ and `Puma` are supported. ### webserver Webserver configuration. Proxy passing to application is handled out-of-the-box. -Currently only nginx is supported. +Currently Apache2 and nginx is supported. * `app['webserver']['adapter']` * **Default:** `nginx` - * **Supported values:** `nginx`, `null` + * **Supported values:** `apache2`, `nginx`, `null` * Webserver in front of the instance. It runs on port 80, and receives all requests from Load Balancer/Internet. `null` means no webserver enabled. +* `app['webserver']['dhparams']` + * If you wish to use custom generated DH primes, instead of common ones + (which is a very good practice), put the contents (not file name) of the + `dhparams.pem` file into this attribute. [Read more here.](https://weakdh.org/sysadmin.html) +* `app['webserver']['ssl_for_legacy_browsers']` + * **Supported values:** `true`, `false` + * **Default:** `false` + * By default webserver is configured to follow strict SSL security standards, + [covered in this article](https://cipherli.st/). However, old browsers + (like IE < 9 or Android < 2.2) wouldn't work with this configuration very + well. If your application needs a support for those browsers, set this + parameter to `true`. + +#### apache + +* `app['webserver']['extra_config']` + * Raw Apache2 configuration, which will be inserted into `` + section of the application. +* `app['webserver']['extra_config_ssl']` + * Raw Apache2 configuration, which will be inserted into `` + section of the application. If set to `true`, the `extra_config` will be copied. +* [`app['webserver']['limit_request_body']`](https://httpd.apache.org/docs/2.4/mod/core.html#limitrequestbody) + * **Default**: `1048576` +* [`app['webserver']['keepalive_timeout']`](https://httpd.apache.org/docs/2.4/mod/core.html#keepalivetimeout) + * **Default**: `15` +* [`app['webserver']['log_level']`](https://httpd.apache.org/docs/2.4/mod/core.html#loglevel) + * **Default**: `info` +* `app['webserver']['log_dir']` + * **Default**: `/var/log/apache2` (debian) or `/var/log/httpd` (rhel) + * A place to store application-related Apache2 logs. +* [`app['webserver']['proxy_timeout']`](https://httpd.apache.org/docs/current/mod/mod_proxy.html#proxytimeout) + * **Default**: `60` + +#### nginx + * `app['webserver']['build_type']` * **Supported values:** `default` or `source` * **Default:** `default` @@ -255,35 +290,23 @@ Currently only nginx is supported. * **Default:** `12` * [`app['webserver']['client_max_body_size']`](http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size) * **Default:** `10m` -* `app['webserver']['dhparams']` - * If you wish to use custom generated DH primes, instead of common ones - (which is a very good practice), put the contents (not file name) of the - `dhparams.pem` file into this attribute. [Read more here.](https://weakdh.org/sysadmin.html) * `app['webserver']['extra_config']` * Raw nginx configuration, which will be inserted into `server` section of the application for HTTP port. * `app['webserver']['extra_config_ssl']` * Raw nginx configuration, which will be inserted into `server` section of the application for HTTPS port. If set to `true`, the `extra_config` will be copied. -* [`app['webserver']['keepalive_timeout']`](http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout) - * **Default**: `15` * `app['webserver']['log_dir']` * **Default**: `/var/log/nginx` * A place to store application-related nginx logs. +* [`app['webserver']['keepalive_timeout']`](http://nginx.org/en/docs/http/ngx_http_core_module.html#keepalive_timeout) + * **Default**: `15` * [`app['webserver']['proxy_read_timeout']`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_read_timeout) * **Default**: `60` * [`app['webserver']['proxy_send_timeout']`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_send_timeout) * **Default**: `60` * [`app['webserver']['send_timeout']`](http://nginx.org/en/docs/http/ngx_http_core_module.html#send_timeout) * **Default**: `10` -* `app['webserver']['ssl_for_legacy_browsers']` - * **Supported values:** `true`, `false` - * **Default:** `false` - * By default nginx is configured to follow strict SSL security standards, - [covered in this article](https://cipherli.st/). However, old browsers - (like IE < 9 or Android < 2.2) wouldn't work with this configuration very - well. If your application needs a support for those browsers, set this - parameter to `true`. Since this driver is basically a wrapper for [nginx cookbook](https://github.com/miketheman/nginx/tree/2.7.x), you can also configure [`node['nginx']` attributes](https://github.com/miketheman/nginx/tree/2.7.x#attributes) diff --git a/attributes/default.rb b/attributes/default.rb index 43f1c575..14effc4b 100644 --- a/attributes/default.rb +++ b/attributes/default.rb @@ -70,19 +70,26 @@ default['defaults']['webserver']['ssl_for_legacy_browsers'] = false default['defaults']['webserver']['extra_config'] = '' default['defaults']['webserver']['extra_config_ssl'] = '' +default['defaults']['webserver']['keepalive_timeout'] = '15' + +## apache2 + +default['defaults']['webserver']['limit_request_body'] = '1048576' +default['defaults']['webserver']['log_level'] = 'info' +default['defaults']['webserver']['proxy_timeout'] = '60' ## nginx +# These are parameters, directly for the `nginx` cookbook, not the `webserver` part! +default['nginx']['build_type'] = 'default' default['nginx']['default_site_enabled'] = false -default['defaults']['webserver']['build_type'] = 'default' -default['nginx']['client_body_timeout'] = default['defaults']['webserver']['client_body_timeout'] = '12' -default['nginx']['client_header_timeout'] = default['defaults']['webserver']['client_header_timeout'] = '12' -default['nginx']['client_max_body_size'] = default['defaults']['webserver']['client_max_body_size'] = '10m' -default['nginx']['keepalive_timeout'] = default['defaults']['webserver']['keepalive_timeout'] = '15' -default['nginx']['log_dir'] = default['defaults']['webserver']['log_dir'] = '/var/log/nginx' -default['nginx']['proxy_read_timeout'] = default['defaults']['webserver']['proxy_read_timeout'] = '60' -default['nginx']['proxy_send_timeout'] = default['defaults']['webserver']['proxy_send_timeout'] = '60' -default['nginx']['send_timeout'] = default['defaults']['webserver']['send_timeout'] = '10' +default['nginx']['client_body_timeout'] = '12' +default['nginx']['client_header_timeout'] = '12' +default['nginx']['client_max_body_size'] = '10m' +default['nginx']['log_dir'] = '/var/log/nginx' +default['nginx']['proxy_read_timeout'] = '60' +default['nginx']['proxy_send_timeout'] = '60' +default['nginx']['send_timeout'] = '10' # framework ## common diff --git a/libraries/drivers_appserver_puma.rb b/libraries/drivers_appserver_puma.rb index b4d7e1af..607c0304 100644 --- a/libraries/drivers_appserver_puma.rb +++ b/libraries/drivers_appserver_puma.rb @@ -7,7 +7,8 @@ class Puma < Drivers::Appserver::Base output filter: [:log_requests, :preload_app, :thread_max, :thread_min, :timeout, :worker_processes] def add_appserver_config(context) - opts = { deploy_dir: deploy_dir(app), out: out, deploy_env: globals[:environment] } + opts = { deploy_dir: deploy_dir(app), out: out, deploy_env: globals[:environment], + webserver: Drivers::Webserver::Factory.build(app, node).adapter } context.template File.join(opts[:deploy_dir], File.join('shared', 'config', 'puma.rb')) do owner node['deployer']['user'] diff --git a/libraries/drivers_appserver_thin.rb b/libraries/drivers_appserver_thin.rb index 89a1b4ef..df5447b7 100644 --- a/libraries/drivers_appserver_thin.rb +++ b/libraries/drivers_appserver_thin.rb @@ -7,7 +7,8 @@ class Thin < Drivers::Appserver::Base output filter: [:max_connections, :max_persistent_connections, :timeout, :worker_processes] def add_appserver_config(context) - opts = { deploy_dir: deploy_dir(app), out: out, deploy_env: globals[:environment] } + opts = { deploy_dir: deploy_dir(app), out: out, deploy_env: globals[:environment], + webserver: Drivers::Webserver::Factory.build(app, node).adapter } context.template File.join(opts[:deploy_dir], File.join('shared', 'config', 'thin.yml')) do owner node['deployer']['user'] diff --git a/libraries/drivers_appserver_unicorn.rb b/libraries/drivers_appserver_unicorn.rb index 05418b5e..8ddcc295 100644 --- a/libraries/drivers_appserver_unicorn.rb +++ b/libraries/drivers_appserver_unicorn.rb @@ -11,13 +11,14 @@ class Unicorn < Drivers::Appserver::Base def add_appserver_config(context) deploy_to = deploy_dir(app) output = out + webserver = Drivers::Webserver::Factory.build(app, node).adapter context.template File.join(deploy_to, File.join('shared', 'config', 'unicorn.conf')) do owner node['deployer']['user'] group www_group mode '0644' source 'unicorn.conf.erb' - variables deploy_dir: deploy_to, out: output + variables deploy_dir: deploy_to, out: output, webserver: webserver end end diff --git a/libraries/drivers_dsl_notifies.rb b/libraries/drivers_dsl_notifies.rb index 0326d839..c7c81e05 100644 --- a/libraries/drivers_dsl_notifies.rb +++ b/libraries/drivers_dsl_notifies.rb @@ -14,9 +14,22 @@ def notifies(*options) end end + # rubocop:disable Metrics/LineLength def notifies - self.class.notifies.presence || (self.class.superclass.respond_to?(:notifies) && self.class.superclass.notifies) + notifier = self.class.notifies.presence || (self.class.superclass.respond_to?(:notifies) && self.class.superclass.notifies) + parsed_notifier = {} + + notifier.each_pair do |action, options| + parsed_notifier[action] = options.map do |option| + option.merge( + resource: option[:resource].is_a?(Hash) ? option[:resource][node['platform_family'].to_sym] : option[:resource] + ) + end + end + + parsed_notifier end + # rubocop:enable Metrics/LineLength end end end diff --git a/libraries/drivers_webserver_apache2.rb b/libraries/drivers_webserver_apache2.rb new file mode 100644 index 00000000..09666d49 --- /dev/null +++ b/libraries/drivers_webserver_apache2.rb @@ -0,0 +1,94 @@ +# frozen_string_literal: true +module Drivers + module Webserver + class Apache2 < Drivers::Webserver::Base + adapter :apache2 + allowed_engines :apache2 + packages debian: 'apache2', rhel: %w(httpd24 mod24_ssl) + output filter: [ + :dhparams, :keepalive_timeout, :limit_request_body, :log_dir, :log_level, :proxy_timeout, + :ssl_for_legacy_browsers, :extra_config, :extra_config_ssl + ] + notifies :deploy, + action: :restart, resource: { debian: 'service[apache2]', rhel: 'service[httpd]' }, timer: :delayed + notifies :undeploy, + action: :restart, resource: { debian: 'service[apache2]', rhel: 'service[httpd]' }, timer: :delayed + + def raw_out + output = node['defaults']['webserver'].merge( + node['deploy'][app['shortname']]['webserver'] || {} + ).symbolize_keys + output[:log_dir] = node['deploy'][app['shortname']]['webserver']['log_dir'] || "/var/log/#{service_name}" + output[:extra_config_ssl] = output[:extra_config] if output[:extra_config_ssl] == true + output + end + + def setup(context) + handle_packages(context) + enable_modules(context, %w(expires headers lbmethod_byrequests proxy proxy_balancer proxy_http rewrite ssl)) + add_sites_available_enabled(context) + define_service(context, :start) + end + + def configure(context) + add_ssl_directory(context) + add_ssl_item(context, :private_key) + add_ssl_item(context, :certificate) + add_ssl_item(context, :chain) + add_dhparams(context) + + remove_defaults(context) + add_appserver_config(context) + enable_appserver_config(context) + end + + def before_deploy(context) + define_service(context) + end + alias before_undeploy before_deploy + + def conf_dir + File.join('/', 'etc', node['platform_family'] == 'debian' ? 'apache2' : 'httpd') + end + + def service_name + node['platform_family'] == 'debian' ? 'apache2' : 'httpd' + end + + private + + def remove_defaults(context) + conf_path = conf_dir + + context.execute 'Remove default sites' do + command "find #{conf_path}/sites-enabled -maxdepth 1 -mindepth 1 -exec rm -rf {} \\;" + user 'root' + group 'root' + end + end + + def add_sites_available_enabled(context) + return if node['platform_family'] == 'debian' + + context.directory "#{conf_dir}/sites-available" do + mode '0755' + end + context.directory "#{conf_dir}/sites-enabled" do + mode '0755' + end + + context.execute 'echo "IncludeOptional sites-enabled/*.conf" >> /etc/httpd/conf/httpd.conf' + end + + def enable_modules(context, modules = []) + return unless node['platform_family'] == 'debian' + + context.execute 'Enable modules' do + command "a2enmod #{modules.join(' ')}" + user 'root' + group 'root' + end + end + end + end +end diff --git a/libraries/drivers_webserver_base.rb b/libraries/drivers_webserver_base.rb index 23ab35ef..81b4b107 100644 --- a/libraries/drivers_webserver_base.rb +++ b/libraries/drivers_webserver_base.rb @@ -4,6 +4,7 @@ module Webserver class Base < Drivers::Base include Drivers::Dsl::Notifies include Drivers::Dsl::Output + include Drivers::Dsl::Packages def out handle_output(raw_out) @@ -17,6 +18,81 @@ def raw_out def validate_app_engine end + + protected + + def conf_dir + raise NotImplementedError + end + + def service_name + raise NotImplementedError + end + + def define_service(context, default_action = :nothing) + context.service service_name do + supports status: true, restart: true, reload: true + action default_action + end + end + + def add_ssl_item(context, name) + key_data = app[:ssl_configuration].try(:[], name) + return if key_data.blank? + extensions = { private_key: 'key', certificate: 'crt', chain: 'ca' } + + context.template "#{conf_dir}/ssl/#{app[:domains].first}.#{extensions[name]}" do + owner 'root' + group 'root' + mode name == :private_key ? '0600' : '0644' + source 'ssl_key.erb' + variables key_data: key_data + end + end + + def add_ssl_directory(context) + context.directory "#{conf_dir}/ssl" do + owner 'root' + group 'root' + mode '0700' + end + end + + def add_dhparams(context) + dhparams = out[:dhparams] + return if dhparams.blank? + + context.template "#{conf_dir}/ssl/#{app[:domains].first}.dhparams.pem" do + owner 'root' + group 'root' + mode '0600' + source 'ssl_key.erb' + variables key_data: dhparams + end + end + + def add_appserver_config(context) + opts = { application: app, deploy_dir: deploy_dir(app), out: out, conf_dir: conf_dir, adapter: adapter, + name: Drivers::Appserver::Factory.build(app, node).adapter } + return unless Drivers::Appserver::Base.adapters.include?(opts[:name]) + + context.template "#{opts[:conf_dir]}/sites-available/#{app['shortname']}.conf" do + owner 'root' + group 'root' + mode '0644' + source "appserver.#{opts[:adapter]}.conf.erb" + variables opts + end + end + + def enable_appserver_config(context) + application = app + conf_path = conf_dir + + context.link "#{conf_path}/sites-enabled/#{application['shortname']}.conf" do + to "#{conf_path}/sites-available/#{application['shortname']}.conf" + end + end end end end diff --git a/libraries/drivers_webserver_nginx.rb b/libraries/drivers_webserver_nginx.rb index 720028be..00694440 100644 --- a/libraries/drivers_webserver_nginx.rb +++ b/libraries/drivers_webserver_nginx.rb @@ -43,69 +43,12 @@ def before_deploy(context) end alias before_undeploy before_deploy - private - - def define_service(context, default_action = :nothing) - context.service 'nginx' do - supports status: true, restart: true, reload: true - action default_action - end - end - - def add_ssl_directory(context) - context.directory '/etc/nginx/ssl' do - owner 'root' - group 'root' - mode '0700' - end - end - - def add_ssl_item(context, name) - key_data = app[:ssl_configuration].try(:[], name) - return if key_data.blank? - extensions = { private_key: 'key', certificate: 'crt', chain: 'ca' } - - context.template "/etc/nginx/ssl/#{app[:domains].first}.#{extensions[name]}" do - owner 'root' - group 'root' - mode name == :private_key ? '0600' : '0644' - source 'ssl_key.erb' - variables key_data: key_data - end - end - - def add_dhparams(context) - dhparams = out[:dhparams] - return if dhparams.blank? - - context.template "/etc/nginx/ssl/#{app[:domains].first}.dhparams.pem" do - owner 'root' - group 'root' - mode '0600' - source 'ssl_key.erb' - variables key_data: dhparams - end - end - - def add_appserver_config(context) - opts = { application: app, deploy_dir: deploy_dir(app), out: out, - name: Drivers::Appserver::Factory.build(app, node).adapter } - return unless Drivers::Appserver::Base.adapters.include?(opts[:name]) - - context.template "/etc/nginx/sites-available/#{app['shortname']}" do - owner 'root' - group 'root' - mode '0644' - source 'appserver.nginx.conf.erb' - variables opts - end + def conf_dir + File.join('/', 'etc', 'nginx') end - def enable_appserver_config(context) - application = app - context.link "/etc/nginx/sites-enabled/#{application['shortname']}" do - to "/etc/nginx/sites-available/#{application['shortname']}" - end + def service_name + 'nginx' end end end diff --git a/metadata.rb b/metadata.rb index 103d8db4..f19fb18f 100644 --- a/metadata.rb +++ b/metadata.rb @@ -7,7 +7,6 @@ long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) version '0.8.0' -depends 'build-essential', '~> 2.0' depends 'deployer' depends 'ruby-ng' depends 'nginx', '~> 2.7' diff --git a/spec/fixtures/node.rb b/spec/fixtures/node.rb index c030e4cb..c470017e 100644 --- a/spec/fixtures/node.rb +++ b/spec/fixtures/node.rb @@ -42,6 +42,7 @@ def node(override = {}) webserver: { adapter: 'nginx', client_max_body_size: '125m', + limit_request_body: '131072000', dhparams: '--- DH PARAMS ---', extra_config: 'extra_config {}' }, @@ -79,7 +80,7 @@ def node(override = {}) }, webserver: { adapter: 'nginx', - keepalive_timeout: '15', + keepalive_timeout: '65', extra_config_ssl: 'extra_config_ssl {}' }, framework: { diff --git a/spec/unit/libraries/drivers_webserver_apache2_spec.rb b/spec/unit/libraries/drivers_webserver_apache2_spec.rb new file mode 100644 index 00000000..dc0a72b0 --- /dev/null +++ b/spec/unit/libraries/drivers_webserver_apache2_spec.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true +require 'spec_helper' + +describe Drivers::Webserver::Apache2 do + it 'receives and exposes app and node' do + driver = described_class.new(aws_opsworks_app, node) + + expect(driver.app).to eq aws_opsworks_app + expect(driver.node).to eq node + expect(driver.options).to eq({}) + end + + it 'returns proper out data' do + expect(described_class.new(aws_opsworks_app, node).out).to eq( + dhparams: '--- DH PARAMS ---', + keepalive_timeout: '65', + limit_request_body: '131072000', + extra_config: 'extra_config {}', + extra_config_ssl: 'extra_config_ssl {}', + log_dir: '/var/log/httpd' + ) + end + + it 'copies extra_config to extra_config_ssl if extra_config_ssl is set to true' do + expect(described_class.new(aws_opsworks_app, node(defaults: { webserver: { extra_config_ssl: true } })).out).to eq( + dhparams: '--- DH PARAMS ---', + limit_request_body: '131072000', + extra_config: 'extra_config {}', + extra_config_ssl: 'extra_config {}', + log_dir: '/var/log/httpd' + ) + end +end diff --git a/spec/unit/libraries/drivers_webserver_nginx_spec.rb b/spec/unit/libraries/drivers_webserver_nginx_spec.rb index d244283e..221bd858 100644 --- a/spec/unit/libraries/drivers_webserver_nginx_spec.rb +++ b/spec/unit/libraries/drivers_webserver_nginx_spec.rb @@ -15,7 +15,7 @@ client_max_body_size: '125m', client_body_timeout: '30', dhparams: '--- DH PARAMS ---', - keepalive_timeout: '15', + keepalive_timeout: '65', extra_config: 'extra_config {}', extra_config_ssl: 'extra_config_ssl {}' ) diff --git a/spec/unit/recipes/configure_spec.rb b/spec/unit/recipes/configure_spec.rb index d66f390c..84b5acc1 100644 --- a/spec/unit/recipes/configure_spec.rb +++ b/spec/unit/recipes/configure_spec.rb @@ -65,6 +65,9 @@ end it 'creates proper unicorn.conf file' do + expect(chef_run) + .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/unicorn.conf") + .with_content("listen \"/srv/www/#{aws_opsworks_app['shortname']}/shared/sockets/unicorn.sock\",") expect(chef_run) .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/unicorn.conf") .with_content('worker_processes 4') @@ -106,42 +109,42 @@ it 'creates nginx unicorn proxy handler config' do expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('upstream unicorn_dummy-project.example.com {') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('client_max_body_size 125m;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('client_body_timeout 30;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('keepalive_timeout 15;') + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('keepalive_timeout 65;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_certificate_key /etc/nginx/ssl/dummy-project.example.com.key;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_dhparam /etc/nginx/ssl/dummy-project.example.com.dhparams.pem;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_ecdh_curve secp384r1;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_stapling on;') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_session_tickets off;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('extra_config {}') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('extra_config_ssl {}') - expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}") + expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}.conf") end it 'enables ssl rules for legacy browsers in nginx config' do @@ -151,7 +154,7 @@ solo_node.set['deploy'] = deploy solo_node.set['nginx'] = node['nginx'] end.converge(described_recipe) - expect(chef_run).to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}").with_content( + expect(chef_run).to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf").with_content( 'ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:' \ 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:' \ 'DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:' \ @@ -160,7 +163,7 @@ 'AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4";' ) expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_ecdh_curve secp384r1;') end @@ -298,13 +301,14 @@ end end - context 'Mysql + Puma' do + context 'Mysql + Puma + Apache2' do let(:chef_run) do ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node| deploy = node['deploy'] deploy['dummy_project']['appserver']['adapter'] = 'puma' + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + deploy['dummy_project']['webserver']['keepalive_timeout'] = '65' solo_node.set['deploy'] = deploy - solo_node.set['nginx'] = node['nginx'] end.converge(described_recipe) end @@ -326,6 +330,9 @@ expect(chef_run) .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/puma.rb") .with_content('workers 4') + expect(chef_run) + .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/puma.rb") + .with_content('bind "tcp://127.0.0.1:3000"') expect(chef_run) .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/puma.rb") .with_content('environment "staging"') @@ -368,44 +375,97 @@ .to eq "/srv/www/#{aws_opsworks_app['shortname']}/shared/scripts/puma.service status" end - it 'creates nginx puma proxy handler config' do + it 'creates apache2 puma proxy handler config' do expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('upstream puma_dummy-project.example.com {') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('client_max_body_size 125m;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('LimitRequestBody 131072000') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('client_body_timeout 30;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('KeepAliveTimeout 65') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('keepalive_timeout 15;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('SSLCertificateKeyFile /etc/apache2/ssl/dummy-project.example.com.key') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_certificate_key /etc/nginx/ssl/dummy-project.example.com.key;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('SSLOpenSSLConfCmd DHParameters "/etc/apache2/ssl/dummy-project.example.com.dhparams.pem"') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_dhparam /etc/nginx/ssl/dummy-project.example.com.dhparams.pem;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('SSLUseStapling on') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_ecdh_curve secp384r1;') + .to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('extra_config {}') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_stapling on;') + .not_to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('extra_config_ssl {}') + expect(chef_run).to create_link("/etc/apache2/sites-enabled/#{aws_opsworks_app['shortname']}.conf") + end + + it 'enables ssl rules for legacy browsers in apache2 config' do + chefrun = ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node| + deploy = node['deploy'] + deploy[aws_opsworks_app['shortname']]['webserver']['adapter'] = 'apache2' + deploy[aws_opsworks_app['shortname']]['webserver']['ssl_for_legacy_browsers'] = true + solo_node.set['deploy'] = deploy + end.converge(described_recipe) + + expect(chefrun).to render_file("/etc/apache2/sites-available/#{aws_opsworks_app['shortname']}.conf").with_content( + 'SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:' \ + 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:' \ + 'DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:' \ + 'ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:' \ + 'ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:' \ + 'AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4' + ) + end + + it 'creates SSL keys for apache2' do + expect(chef_run).to create_directory('/etc/apache2/ssl') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('ssl_session_tickets off;') + .to render_file("/etc/apache2/ssl/#{aws_opsworks_app['domains'].first}.key") + .with_content('--- SSL PRIVATE KEY ---') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('extra_config {}') + .to render_file("/etc/apache2/ssl/#{aws_opsworks_app['domains'].first}.crt") + .with_content('--- SSL CERTIFICATE ---') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('extra_config_ssl {}') - expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/apache2/ssl/#{aws_opsworks_app['domains'].first}.ca") + .with_content('--- SSL CERTIFICATE CHAIN ---') + expect(chef_run) + .to render_file("/etc/apache2/ssl/#{aws_opsworks_app['domains'].first}.dhparams.pem") + .with_content('--- DH PARAMS ---') + end + + it 'cleans default sites' do + expect(chef_run).to run_execute('find /etc/apache2/sites-enabled -maxdepth 1 -mindepth 1 -exec rm -rf {} \;') + end + + context 'rhel' do + let(:chef_run_rhel) do + ChefSpec::SoloRunner.new(platform: 'amazon', version: '2015.03') do |solo_node| + deploy = node['deploy'] + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + solo_node.set['deploy'] = deploy + end.converge(described_recipe) + end + + it 'renders apache2 configuration files in proper place' do + expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.key") + expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.crt") + expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.ca") + expect(chef_run_rhel).to render_file("/etc/httpd/ssl/#{aws_opsworks_app['domains'].first}.dhparams.pem") + expect(chef_run_rhel).to render_file("/etc/httpd/sites-available/#{aws_opsworks_app['shortname']}.conf") + expect(chef_run_rhel).to create_directory('/etc/httpd/ssl') + expect(chef_run_rhel).to create_link("/etc/httpd/sites-enabled/#{aws_opsworks_app['shortname']}.conf") + end + + it 'cleans default sites' do + expect(chef_run_rhel).to run_execute('find /etc/httpd/sites-enabled -maxdepth 1 -mindepth 1 -exec rm -rf {} \;') + end end end @@ -448,6 +508,9 @@ expect(chef_run) .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/thin.yml") .with_content('servers: 4') + expect(chef_run) + .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/thin.yml") + .with_content("socket: \"/srv/www/#{aws_opsworks_app['shortname']}/shared/sockets/thin.sock\"") expect(chef_run) .to render_file("/srv/www/#{aws_opsworks_app['shortname']}/shared/config/thin.yml") .with_content('environment: "staging"') @@ -492,42 +555,42 @@ it 'creates nginx thin proxy handler config' do expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('upstream thin_dummy-project.example.com {') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('client_max_body_size 125m;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('client_body_timeout 30;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") - .with_content('keepalive_timeout 15;') + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") + .with_content('keepalive_timeout 65;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_certificate_key /etc/nginx/ssl/dummy-project.example.com.key;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_dhparam /etc/nginx/ssl/dummy-project.example.com.dhparams.pem;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_ecdh_curve secp384r1;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_stapling on;') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('ssl_session_tickets off;') expect(chef_run) - .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('extra_config {}') expect(chef_run) - .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}") + .not_to render_file("/etc/nginx/sites-available/#{aws_opsworks_app['shortname']}.conf") .with_content('extra_config_ssl {}') - expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}") + expect(chef_run).to create_link("/etc/nginx/sites-enabled/#{aws_opsworks_app['shortname']}.conf") end end diff --git a/spec/unit/recipes/deploy_spec.rb b/spec/unit/recipes/deploy_spec.rb index b3d81e21..b9ad3fbd 100644 --- a/spec/unit/recipes/deploy_spec.rb +++ b/spec/unit/recipes/deploy_spec.rb @@ -70,19 +70,39 @@ end end - context 'Puma' do + context 'Puma + Apache' do let(:chef_run) do ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node| deploy = node['deploy'] deploy['dummy_project']['appserver']['adapter'] = 'puma' + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + solo_node.set['deploy'] = deploy + end.converge(described_recipe) + end + let(:chef_run_rhel) do + ChefSpec::SoloRunner.new(platform: 'amazon', version: '2016.03') do |solo_node| + deploy = node['deploy'] + deploy['dummy_project']['appserver']['adapter'] = 'puma' + deploy['dummy_project']['webserver']['adapter'] = 'apache2' solo_node.set['deploy'] = deploy end.converge(described_recipe) end - it 'performs a deploy' do + it 'performs a deploy on debian' do + deploy_debian = chef_run.deploy(aws_opsworks_app['shortname']) + + expect(deploy_debian).to notify('service[apache2]').to(:restart).delayed expect(chef_run).to run_execute('stop puma') expect(chef_run).to run_execute('start puma') end + + it 'performs a deploy on rhel' do + deploy_rhel = chef_run_rhel.deploy(aws_opsworks_app['shortname']) + + expect(deploy_rhel).to notify('service[httpd]').to(:restart).delayed + expect(chef_run_rhel).to run_execute('stop puma') + expect(chef_run_rhel).to run_execute('start puma') + end end it 'empty node[\'deploy\']' do @@ -117,8 +137,8 @@ expect(chef_run).to create_template('/srv/www/a1/shared/config/database.yml') expect(chef_run).to create_template('/srv/www/a1/shared/config/unicorn.conf') expect(chef_run).to create_template('/srv/www/a1/shared/scripts/unicorn.service') - expect(chef_run).to create_template('/etc/nginx/sites-available/a1') - expect(chef_run).to create_link('/etc/nginx/sites-enabled/a1') + expect(chef_run).to create_template('/etc/nginx/sites-available/a1.conf') + expect(chef_run).to create_link('/etc/nginx/sites-enabled/a1.conf') expect(service_a1).to do_nothing expect(chef_run).to deploy_deploy('a1') expect(chef_run).not_to deploy_deploy('a2') diff --git a/spec/unit/recipes/setup_spec.rb b/spec/unit/recipes/setup_spec.rb index b33ffe01..ffec4800 100644 --- a/spec/unit/recipes/setup_spec.rb +++ b/spec/unit/recipes/setup_spec.rb @@ -149,17 +149,60 @@ end end - context 'Mysql' do + context 'Mysql + apache2' do before do stub_search(:aws_opsworks_rds_db_instance, '*:*').and_return([aws_opsworks_rds_db_instance(engine: 'mysql')]) end - it 'installs required packages for debian' do - expect(chef_run).to install_package('libmysqlclient-dev') + let(:chef_run) do + ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node| + deploy = node['deploy'] + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + solo_node.set['deploy'] = deploy + end.converge(described_recipe) end - it 'installs required packages for rhel' do - expect(chef_run_rhel).to install_package('mysql-devel') + let(:chef_run_rhel) do + ChefSpec::SoloRunner.new(platform: 'amazon', version: '2015.03') do |solo_node| + deploy = node['deploy'] + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + solo_node.set['deploy'] = deploy + end.converge(described_recipe) + end + + context 'debian' do + it 'installs required packages' do + expect(chef_run).to install_package('libmysqlclient-dev') + expect(chef_run).to install_package('apache2') + end + + it 'defines service which starts apache2' do + expect(chef_run).to start_service('apache2') + end + + it 'enables necessary modules for apache2' do + expect(chef_run) + .to run_execute('a2enmod expires headers lbmethod_byrequests proxy proxy_balancer proxy_http rewrite ssl') + end + end + + context 'rhel' do + it 'installs required packages' do + expect(chef_run_rhel).to install_package('mysql-devel') + expect(chef_run_rhel).to install_package('httpd24') + expect(chef_run_rhel).to install_package('mod24_ssl') + end + + it 'defines service which starts httpd' do + expect(chef_run_rhel).to start_service('httpd') + end + + it 'creates sites-* directories' do + expect(chef_run_rhel).to create_directory('/etc/httpd/sites-available') + expect(chef_run_rhel).to create_directory('/etc/httpd/sites-enabled') + expect(chef_run_rhel) + .to run_execute('echo "IncludeOptional sites-enabled/*.conf" >> /etc/httpd/conf/httpd.conf') + end end end diff --git a/spec/unit/recipes/undeploy_spec.rb b/spec/unit/recipes/undeploy_spec.rb index 2b475e8c..0a874a68 100644 --- a/spec/unit/recipes/undeploy_spec.rb +++ b/spec/unit/recipes/undeploy_spec.rb @@ -40,19 +40,39 @@ end end - context 'Puma' do + context 'Puma + Apache' do let(:chef_run) do ChefSpec::SoloRunner.new(platform: 'ubuntu', version: '14.04') do |solo_node| deploy = node['deploy'] deploy['dummy_project']['appserver']['adapter'] = 'puma' + deploy['dummy_project']['webserver']['adapter'] = 'apache2' + solo_node.set['deploy'] = deploy + end.converge(described_recipe) + end + let(:chef_run_rhel) do + ChefSpec::SoloRunner.new(platform: 'amazon', version: '2016.03') do |solo_node| + deploy = node['deploy'] + deploy['dummy_project']['appserver']['adapter'] = 'puma' + deploy['dummy_project']['webserver']['adapter'] = 'apache2' solo_node.set['deploy'] = deploy end.converge(described_recipe) end - it 'performs a rollback' do + it 'performs a rollback on debian' do + undeploy_debian = chef_run.deploy(aws_opsworks_app['shortname']) + + expect(undeploy_debian).to notify('service[apache2]').to(:restart).delayed expect(chef_run).to run_execute('stop puma') expect(chef_run).to run_execute('start puma') end + + it 'performs a rollback on rhel' do + undeploy_rhel = chef_run_rhel.deploy(aws_opsworks_app['shortname']) + + expect(undeploy_rhel).to notify('service[httpd]').to(:restart).delayed + expect(chef_run_rhel).to run_execute('stop puma') + expect(chef_run_rhel).to run_execute('start puma') + end end it 'empty node[\'deploy\']' do diff --git a/templates/default/appserver.apache2.conf.erb b/templates/default/appserver.apache2.conf.erb new file mode 100644 index 00000000..cafed2cb --- /dev/null +++ b/templates/default/appserver.apache2.conf.erb @@ -0,0 +1,136 @@ +<% upstream = "#{@name}_#{@application[:domains].first}".gsub(/[^a-zA-Z0-9]+/, '_') %> + + + ServerName <%= node['hostname'] %> + ServerAlias <%= @application[:domains].join(" ") %> + + DocumentRoot <%= File.join(@deploy_dir, 'current', 'public') %> + + > + Options FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + + LogLevel <%= @out[:log_level] %> + ErrorLog <%= @out[:log_dir] %>/<%= @application[:domains].first %>.error.log + CustomLog <%= @out[:log_dir] %>/<%= @application[:domains].first %>.access.log combined + + FileETag none + LimitRequestBody <%= @out[:limit_request_body] || '1048576' %> + KeepAliveTimeout <%= @out[:keepalive_timeout] || '15' %> + + + ExpiresActive on + + Header set Cache-Control "public" + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, PUT, POST, DELETE" + Header set Access-Control-Expose-Headers "ETag" + + + RewriteEngine on + + > + BalancerMember http://127.0.0.1:3000 + + + RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f + RewriteRule ^/(.*)$ balancer://<%= upstream %>%{REQUEST_URI} [P,QSA,L] + + ProxyPass / balancer://<%= upstream %>/ + ProxyPassReverse / balancer://<%= upstream %>/ + ProxyPreserveHost on + ProxyAddHeaders On + ProxyTimeout <%= @out[:proxy_timeout] || '60' %> + + + Order deny,allow + Allow from all + + + <%= @out[:extra_config] %> + + + +<% if @application[:enable_ssl] %> + + ServerName <%= node['hostname'] %> + ServerAlias <%= @application[:domains].join(" ") %> + + DocumentRoot <%= File.join(@deploy_dir, 'current', 'public') %> + + > + Options FollowSymLinks + AllowOverride None + Order allow,deny + Allow from all + + + SSLEngine on + SSLProxyEngine on + SSLCertificateFile /etc/apache2/ssl/<%= @application[:domains].first %>.crt + SSLCertificateKeyFile /etc/apache2/ssl/<%= @application[:domains].first %>.key + <% if @application[:ssl_configuration][:chain] -%> + SSLCACertificateFile /etc/apache2/ssl/<%= @application[:domains].first %>.ca + <% end %> + SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 + + <% if @out[:ssl_for_legacy_browsers] -%> + SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH:ECDHE-RSA-AES128-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA128:DHE-RSA-AES128-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES128-GCM-SHA128:ECDHE-RSA-AES128-SHA384:ECDHE-RSA-AES128-SHA128:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA128:DHE-RSA-AES128-SHA:DHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA384:AES128-GCM-SHA128:AES128-SHA128:AES128-SHA128:AES128-SHA:AES128-SHA:DES-CBC3-SHA:HIGH:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!PSK:!RC4 + <% else %> + SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH + <% end %> + + SSLProtocol All -SSLv2 -SSLv3 + SSLHonorCipherOrder On + SSLCompression off + SSLUseStapling on + SSLStaplingCache "shmcb:logs/stapling-cache(150000)" + + <% if @out[:dhparams].present? -%> + SSLOpenSSLConfCmd DHParameters "/etc/apache2/ssl/<%= @application[:domains].first %>.dhparams.pem" + <% end %> + + LogLevel <%= @out[:log_level] %> + ErrorLog <%= @out[:log_dir] %>/<%= @application[:domains].first %>.error.log + CustomLog <%= @out[:log_dir] %>/<%= @application[:domains].first %>.access.log combined + + FileETag none + LimitRequestBody <%= @out[:client_max_body_size] || '1048576' %> + KeepAliveTimeout <%= @out[:keepalive_timeout] || '15' %> + + + ExpiresActive on + + Header set Cache-Control "public" + Header set Access-Control-Allow-Origin "*" + Header set Access-Control-Allow-Methods "GET, PUT, POST, DELETE" + Header set Access-Control-Expose-Headers "ETag" + + + RewriteEngine on + + > + BalancerMember http://127.0.0.1:3000 + + + RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f + RewriteRule ^/(.*)$ balancer://<%= upstream %>%{REQUEST_URI} [P,QSA,L] + + ProxyPass / balancer://<%= upstream %>/ + ProxyPassReverse / balancer://<%= upstream %>/ + ProxyPreserveHost on + ProxyAddHeaders On + ProxyTimeout <%= @out[:proxy_timeout] || '60' %> + + + Order deny,allow + Allow from all + + + <%= @out[:extra_config_ssl] %> + + +<% end %> diff --git a/templates/default/puma.rb.erb b/templates/default/puma.rb.erb index 3c0c92a4..ba9d13f4 100644 --- a/templates/default/puma.rb.erb +++ b/templates/default/puma.rb.erb @@ -54,8 +54,11 @@ threads <%= @out[:thread_min] %>, <%= @out[:thread_max] %> # bind 'unix:///var/run/puma.sock' # bind 'unix:///var/run/puma.sock?umask=0777' # bind 'ssl://127.0.0.1:9292?key=path_to_key&cert=path_to_cert' +<% if @webserver == 'apache2' %> +bind "tcp://127.0.0.1:3000" +<% else %> bind "unix://<%= @deploy_dir %>/shared/sockets/puma.sock" - +<% end %> # === Cluster mode === # How many worker processes to run. # The default is "0". diff --git a/templates/default/thin.yml.erb b/templates/default/thin.yml.erb index 6ffebfed..eca6f537 100644 --- a/templates/default/thin.yml.erb +++ b/templates/default/thin.yml.erb @@ -11,5 +11,10 @@ servers: <%= @out[:worker_processes] %> threaded: true no-epoll: true daemonize: true +<% if @webserver == 'apache2' %> +address: "127.0.0.1" +port: 3000 +<% else %> socket: "<%= @deploy_dir %>/shared/sockets/thin.sock" +<% end %> chdir: "<%= @deploy_dir %>/current" diff --git a/templates/default/unicorn.conf.erb b/templates/default/unicorn.conf.erb index 8f5ec237..62c2fe10 100644 --- a/templates/default/unicorn.conf.erb +++ b/templates/default/unicorn.conf.erb @@ -3,8 +3,11 @@ worker_processes <%= @out[:worker_processes] %> user "<%= node['deployer']['user'] %>" working_directory "<%= @deploy_dir %>/current" - +<% if @webserver == 'apache2' %> +listen "127.0.0.1:3000", +<% else %> listen "<%= @deploy_dir %>/shared/sockets/unicorn.sock", +<% end %> :backlog => <%= @out[:backlog] %>, :tcp_nodelay => <%= @out[:tcp_nodelay] %>, :tcp_nopush => <%= @out[:tcp_nopush] %>,