From 3855a5a12407284d8628ae8de676b0d2d73e0842 Mon Sep 17 00:00:00 2001 From: Karl Brightman Date: Thu, 18 Oct 2012 22:38:39 +0800 Subject: [PATCH] New rubber config, minimal --- config/deploy.rb | 6 +- config/rubber/common/crontab | 18 + config/rubber/common/database.yml | 12 + config/rubber/common/ntp-sysctl.conf | 7 + config/rubber/common/ntp.conf | 57 ++ config/rubber/common/rsyslog.conf | 71 +++ config/rubber/common/rubber.profile | 13 + config/rubber/deploy-apache.rb | 59 ++ config/rubber/deploy-collectd.rb | 48 ++ config/rubber/deploy-graphite.rb | 255 ++++++++ config/rubber/deploy-monit.rb | 33 + config/rubber/deploy-passenger.rb | 45 ++ config/rubber/deploy-postgresql.rb | 140 +++++ config/rubber/deploy-setup.rb | 107 ++++ config/rubber/deploy-util.rb | 91 +++ config/rubber/role/apache/deflate.conf | 10 + config/rubber/role/apache/expires.conf | 9 + config/rubber/role/apache/headers.conf | 6 + config/rubber/role/apache/monit-apache.conf | 7 + config/rubber/role/apache/ports.conf | 8 + config/rubber/role/apache/setenvif.conf | 52 ++ .../rubber/role/collectd/collectd-ping.conf | 21 + config/rubber/role/collectd/collectd.conf | 69 +++ config/rubber/role/collectd/filters.conf | 35 ++ .../role/collectd/graphite-collectd.conf | 21 + config/rubber/role/collectd/thresholds.conf | 88 +++ config/rubber/role/collectd/types.db | 5 + .../rubber/role/graphite_server/carbon.conf | 232 +++++++ .../graphite_server-upstart.conf | 16 + .../role/graphite_server/storage-schemas.conf | 19 + config/rubber/role/graphite_web/crontab | 8 + .../rubber/role/graphite_web/dashboard.conf | 60 ++ .../rubber/role/graphite_web/dashboard.html | 385 ++++++++++++ .../role/graphite_web/graphite-vhost.conf | 62 ++ config/rubber/role/graphite_web/graphite.wsgi | 10 + .../role/graphite_web/local_settings.py | 98 +++ config/rubber/role/monit/monit-default.conf | 18 + config/rubber/role/monit/monit-postfix.conf | 8 + config/rubber/role/monit/monit.conf | 252 ++++++++ .../role/passenger/collectd-passenger.conf | 7 + .../role/passenger/collectd-passenger.rb.conf | 77 +++ .../passenger/passenger-apache-vhost.conf | 90 +++ .../passenger/passenger-status-sudoers.conf | 8 + config/rubber/role/passenger/passenger.conf | 45 ++ .../role/postgresql/collectd-postgresql.conf | 22 + config/rubber/role/postgresql/crontab | 16 + .../role/postgresql/monit-postgresql.conf | 10 + config/rubber/role/postgresql/pg_hba.conf | 98 +++ .../role/postgresql/postgresql-sysctl.conf | 7 + config/rubber/role/postgresql/postgresql.conf | 574 ++++++++++++++++++ .../collectd-postgresql-threshold.conf | 23 + .../role/postgresql_slave/recovery.conf | 135 ++++ .../role/web_tools/monit-admin-nginx.conf | 11 + .../web_tools/rubber-web-tools-monit.html | 19 + .../role/web_tools/tools-apache-vhost.conf | 122 ++++ .../rubber/role/web_tools/tools-apache.auth | 7 + config/rubber/role/web_tools/tools-index.html | 38 ++ config/rubber/rubber-apache.yml | 6 + config/rubber/rubber-collectd.yml | 11 + config/rubber/rubber-dns.yml | 7 + config/rubber/rubber-graphite.yml | 22 + config/rubber/rubber-monit.yml | 11 + config/rubber/rubber-passenger.yml | 16 + config/rubber/rubber-postgresql.yml | 45 ++ config/rubber/rubber-rvm.yml | 42 ++ config/rubber/rubber.yml | 34 ++ 66 files changed, 3961 insertions(+), 3 deletions(-) create mode 100644 config/rubber/common/crontab create mode 100644 config/rubber/common/database.yml create mode 100644 config/rubber/common/ntp-sysctl.conf create mode 100644 config/rubber/common/ntp.conf create mode 100644 config/rubber/common/rsyslog.conf create mode 100644 config/rubber/common/rubber.profile create mode 100644 config/rubber/deploy-apache.rb create mode 100644 config/rubber/deploy-collectd.rb create mode 100644 config/rubber/deploy-graphite.rb create mode 100644 config/rubber/deploy-monit.rb create mode 100644 config/rubber/deploy-passenger.rb create mode 100644 config/rubber/deploy-postgresql.rb create mode 100644 config/rubber/deploy-setup.rb create mode 100644 config/rubber/deploy-util.rb create mode 100644 config/rubber/role/apache/deflate.conf create mode 100644 config/rubber/role/apache/expires.conf create mode 100644 config/rubber/role/apache/headers.conf create mode 100644 config/rubber/role/apache/monit-apache.conf create mode 100644 config/rubber/role/apache/ports.conf create mode 100644 config/rubber/role/apache/setenvif.conf create mode 100644 config/rubber/role/collectd/collectd-ping.conf create mode 100644 config/rubber/role/collectd/collectd.conf create mode 100644 config/rubber/role/collectd/filters.conf create mode 100644 config/rubber/role/collectd/graphite-collectd.conf create mode 100644 config/rubber/role/collectd/thresholds.conf create mode 100644 config/rubber/role/collectd/types.db create mode 100644 config/rubber/role/graphite_server/carbon.conf create mode 100644 config/rubber/role/graphite_server/graphite_server-upstart.conf create mode 100644 config/rubber/role/graphite_server/storage-schemas.conf create mode 100644 config/rubber/role/graphite_web/crontab create mode 100644 config/rubber/role/graphite_web/dashboard.conf create mode 100644 config/rubber/role/graphite_web/dashboard.html create mode 100644 config/rubber/role/graphite_web/graphite-vhost.conf create mode 100644 config/rubber/role/graphite_web/graphite.wsgi create mode 100644 config/rubber/role/graphite_web/local_settings.py create mode 100644 config/rubber/role/monit/monit-default.conf create mode 100644 config/rubber/role/monit/monit-postfix.conf create mode 100644 config/rubber/role/monit/monit.conf create mode 100644 config/rubber/role/passenger/collectd-passenger.conf create mode 100644 config/rubber/role/passenger/collectd-passenger.rb.conf create mode 100644 config/rubber/role/passenger/passenger-apache-vhost.conf create mode 100644 config/rubber/role/passenger/passenger-status-sudoers.conf create mode 100644 config/rubber/role/passenger/passenger.conf create mode 100644 config/rubber/role/postgresql/collectd-postgresql.conf create mode 100644 config/rubber/role/postgresql/crontab create mode 100644 config/rubber/role/postgresql/monit-postgresql.conf create mode 100644 config/rubber/role/postgresql/pg_hba.conf create mode 100644 config/rubber/role/postgresql/postgresql-sysctl.conf create mode 100644 config/rubber/role/postgresql/postgresql.conf create mode 100644 config/rubber/role/postgresql_slave/collectd-postgresql-threshold.conf create mode 100644 config/rubber/role/postgresql_slave/recovery.conf create mode 100644 config/rubber/role/web_tools/monit-admin-nginx.conf create mode 100644 config/rubber/role/web_tools/rubber-web-tools-monit.html create mode 100644 config/rubber/role/web_tools/tools-apache-vhost.conf create mode 100644 config/rubber/role/web_tools/tools-apache.auth create mode 100644 config/rubber/role/web_tools/tools-index.html create mode 100644 config/rubber/rubber-apache.yml create mode 100644 config/rubber/rubber-collectd.yml create mode 100644 config/rubber/rubber-dns.yml create mode 100644 config/rubber/rubber-graphite.yml create mode 100644 config/rubber/rubber-monit.yml create mode 100644 config/rubber/rubber-passenger.yml create mode 100644 config/rubber/rubber-postgresql.yml create mode 100644 config/rubber/rubber-rvm.yml create mode 100644 config/rubber/rubber.yml diff --git a/config/deploy.rb b/config/deploy.rb index 653ca77..85584b6 100644 --- a/config/deploy.rb +++ b/config/deploy.rb @@ -11,9 +11,9 @@ # Use a simple directory tree copy here to make demo easier. # You probably want to use your own repository for a real app -set :scm, :git -set :repository, "git://github.com/Whatlock/doyle.git" -set :deploy_via, :remote_cache +set :scm, :none +set :repository, "." +set :deploy_via, :copy # Easier to do system level config as root - probably should do it through # sudo in the future. We use ssh keys for access, so no passwd needed diff --git a/config/rubber/common/crontab b/config/rubber/common/crontab new file mode 100644 index 0000000..2a97a1d --- /dev/null +++ b/config/rubber/common/crontab @@ -0,0 +1,18 @@ +<% + @read_cmd = 'crontab -l' + @write_cmd = 'crontab -' + +%> + +# cron clears out environment variables, but Rubber.root/script/rubber uses +# "rvm do default" to run, so no longer any need to setup ruby env vars here, +# all we need is PATH +PATH=<%= ENV['PATH'] %> + +MAILTO=<%= rubber_env.admin_email %> +# don't need to set RUBBER_ENV for each script since we set it for all cron here +RUBBER_ENV=<%= Rubber.env %> +RAILS_ENV=<%= Rubber.env %> + +# Roll all rails logs at midnight +0 0 * * * <%= Rubber.root %>/script/rubber cron --task util:rotate_logs --directory=<%= Rubber.root %>/log diff --git a/config/rubber/common/database.yml b/config/rubber/common/database.yml new file mode 100644 index 0000000..67283df --- /dev/null +++ b/config/rubber/common/database.yml @@ -0,0 +1,12 @@ +<% + @path = "#{Rubber.root}/config/database.yml" +%> + +<%= Rubber.env %>: + adapter: postgresql + encoding: unicode + database: <%= rubber_env.db_name %> + username: <%= rubber_env.db_user %> + password: <%= rubber_env.db_pass %> + host: <%= rubber_instances.for_role('db', 'primary' => true).first.full_name %> + pool: 5 diff --git a/config/rubber/common/ntp-sysctl.conf b/config/rubber/common/ntp-sysctl.conf new file mode 100644 index 0000000..9c0acf4 --- /dev/null +++ b/config/rubber/common/ntp-sysctl.conf @@ -0,0 +1,7 @@ +<% + @path = "/etc/sysctl.d/60-ntp.conf" + @post = "/usr/sbin/service procps start" +%> + +# allows us to set machine clock (xen clocks from ec2 tend to drift a lot) +xen.independent_wallclock=1 diff --git a/config/rubber/common/ntp.conf b/config/rubber/common/ntp.conf new file mode 100644 index 0000000..7608e1c --- /dev/null +++ b/config/rubber/common/ntp.conf @@ -0,0 +1,57 @@ +<% + @path = "/etc/ntp.conf" + @post = "/usr/sbin/service ntp restart" +%> +# /etc/ntp.conf, configuration for ntpd; see ntp.conf(5) for help + +driftfile /var/lib/ntp/ntp.drift + + +# Enable this if you want statistics to be logged. +#statsdir /var/log/ntpstats/ + +statistics loopstats peerstats clockstats +filegen loopstats file loopstats type day enable +filegen peerstats file peerstats type day enable +filegen clockstats file clockstats type day enable + + +# You do need to talk to an NTP server or two (or three). +server 0.us.pool.ntp.org +server 1.us.pool.ntp.org +server 2.us.pool.ntp.org +server 3.us.pool.ntp.org + +<% rubber_instances.each do |ic| %> +peer <%= ic.full_name %> +<% end %> + +# Access control configuration; see /usr/share/doc/ntp-doc/html/accopt.html for +# details. The web page +# might also be helpful. +# +# Note that "restrict" applies to both servers and clients, so a configuration +# that might be intended to block requests from certain clients could also end +# up blocking replies from your own upstream servers. + +# By default, exchange time with everybody, but don't allow configuration. +restrict -4 default kod notrap nomodify nopeer noquery +restrict -6 default kod notrap nomodify nopeer noquery + +# Local users may interrogate the ntp server more closely. +restrict 127.0.0.1 +restrict ::1 + +# Clients from this (example!) subnet have unlimited access, but only if +# cryptographically authenticated. +#restrict 192.168.123.0 mask 255.255.255.0 notrust + + +# If you want to provide time to your local subnet, change the next line. +# (Again, the address is an example only.) +#broadcast 192.168.123.255 + +# If you want to listen to time broadcasts on your local subnet, de-comment the +# next lines. Please do this only if you trust everybody on the network! +#disable auth +#broadcastclient diff --git a/config/rubber/common/rsyslog.conf b/config/rubber/common/rsyslog.conf new file mode 100644 index 0000000..6a1d3f5 --- /dev/null +++ b/config/rubber/common/rsyslog.conf @@ -0,0 +1,71 @@ +<% + log_dir = "/var/log/#{rubber_env.app_name}" + log_spool_dir = "/var/spool/rsyslog" + + @path = "/etc/rsyslog.conf" + @post = <<-ENDSCRIPT + mkdir -p #{log_dir} #{log_spool_dir} + chown syslog:adm #{log_dir} #{log_spool_dir} + /usr/sbin/service rsyslog restart + ENDSCRIPT +%> + +# /etc/rsyslog.conf Configuration file for rsyslog. +# +# For more information see +# /usr/share/doc/rsyslog-doc/html/rsyslog_conf.html +# +# Default logging rules can be found in /etc/rsyslog.d/50-default.conf + + +################# +#### MODULES #### +################# + +$ModLoad imuxsock # provides support for local system logging +$ModLoad imklog # provides kernel logging support (previously done by rklogd) +#$ModLoad immark # provides --MARK-- message capability + +$KLogPath /proc/kmsg + +# provides UDP syslog reception +$ModLoad imudp +$UDPServerRun 514 + +# provides TCP syslog reception +#$ModLoad imtcp +#$InputTCPServerRun 514 + +$WorkDirectory <%= log_spool_dir %> +$template LogCollectorDynFile,"<%= log_dir %>/%$YEAR%/%$MONTH%/%$DAY%/%programname%.log" + +########################### +#### GLOBAL DIRECTIVES #### +########################### + +# +# Use traditional timestamp format. +# To enable high precision timestamps, comment out the following line. +# +$ActionFileDefaultTemplate RSYSLOG_TraditionalFileFormat + +# Don't filter duplicated messages +$RepeatedMsgReduction off + +# +# Set the default permissions for all log files. +# +$FileOwner syslog +$FileGroup adm +$FileCreateMode 0640 +$DirCreateMode 0755 +$Umask 0022 +$PrivDropToUser syslog +$PrivDropToGroup adm +# https://bugs.launchpad.net/ubuntu/+source/rsyslog/+bug/484336 + +# +# Include all config files in /etc/rsyslog.d/ +# +$IncludeConfig /etc/rsyslog.d/*.conf + diff --git a/config/rubber/common/rubber.profile b/config/rubber/common/rubber.profile new file mode 100644 index 0000000..a6560af --- /dev/null +++ b/config/rubber/common/rubber.profile @@ -0,0 +1,13 @@ +<% + @path = "/etc/profile.d/rubber.sh" + current_path = "/mnt/#{rubber_env.app_name}-#{Rubber.env}/current" +%> + +# convenience to simply running rails console, etc with correct env +export RUBBER_ENV=<%= Rubber.env %> +export RAILS_ENV=<%= Rubber.env %> +alias current="cd <%= current_path %>" +alias release="cd <%= Rubber.root %>" + +# Always use rubygems +export RUBYOPT="rubygems" diff --git a/config/rubber/deploy-apache.rb b/config/rubber/deploy-apache.rb new file mode 100644 index 0000000..d6cad39 --- /dev/null +++ b/config/rubber/deploy-apache.rb @@ -0,0 +1,59 @@ + +namespace :rubber do + + namespace :apache do + + rubber.allow_optional_tasks(self) + + after "rubber:install_packages", "rubber:apache:install" + + task :install, :roles => :apache do + rubber.sudo_script 'install_apache', <<-ENDSCRIPT + a2dissite default + + # TODO: remove this once 12.04 is fixed + # https://bugs.launchpad.net/ubuntu/+source/mod-proxy-html/+bug/964397 + if [[ ! -f /usr/lib/libxml2.so.2 ]]; then + ln -sf /usr/lib/x86_64-linux-gnu/libxml2.so.2 /usr/lib/libxml2.so.2 + fi + ENDSCRIPT + end + + # serial_task can only be called after roles defined - not normally a problem, but + # rubber auto-roles don't get defined till after all tasks are defined + on :load do + rubber.serial_task self, :serial_restart, :roles => :apache do + rsudo "service apache2 stop; service apache2 start" + end + rubber.serial_task self, :serial_reload, :roles => :apache do + rsudo "if ! ps ax | grep -v grep | grep -c apache2 &> /dev/null; then service apache2 start; else service apache2 reload; fi" + end + end + + before "deploy:stop", "rubber:apache:stop" + after "deploy:start", "rubber:apache:start" + after "deploy:restart", "rubber:apache:reload" + + desc "Stops the apache web server" + task :stop, :roles => :apache do + rsudo "service apache2 stop || true" + end + + desc "Starts the apache web server" + task :start, :roles => :apache do + rsudo "service apache2 start" + end + + desc "Restarts the apache web server" + task :restart, :roles => :apache do + serial_restart + end + + desc "Reloads the apache web server" + task :reload, :roles => :apache do + serial_reload + end + + end + +end diff --git a/config/rubber/deploy-collectd.rb b/config/rubber/deploy-collectd.rb new file mode 100644 index 0000000..490c462 --- /dev/null +++ b/config/rubber/deploy-collectd.rb @@ -0,0 +1,48 @@ + +namespace :rubber do + + namespace :collectd do + + rubber.allow_optional_tasks(self) + + after "rubber:bootstrap", "rubber:collectd:bootstrap" + after "deploy:restart", "rubber:collectd:restart_rubber_plugin" + + + task :bootstrap, :roles => :collectd do + exists = capture("echo $(grep Rubber /etc/collectd/collectd.conf 2> /dev/null)") + if exists.strip.size == 0 + rubber.update_code_for_bootstrap + + rubber.run_config(:file => "role/collectd", :force => true, :deploy_path => release_path) + + restart + end + end + + desc "Start collectd system monitoring" + task :start, :roles => :collectd do + rsudo "service collectd start" + end + + desc "Stop collectd system monitoring" + task :stop, :roles => :collectd do + rsudo "service collectd stop || true" + end + + desc "Restart collectd system monitoring" + task :restart, :roles => :collectd do + stop + start + end + + desc "Restart collectd rubber plugin" + task :restart_rubber_plugin, :roles => :collectd do + # Need to kill rubber collectd runner script to force collectd to restart + # it after deploy so that the runner script gets the new paths + rsudo "pkill -fn #{rubber_env.rubber_collectd_runner.sub(/./, '[\0]')} ; exit 0" + end + + end + +end diff --git a/config/rubber/deploy-graphite.rb b/config/rubber/deploy-graphite.rb new file mode 100644 index 0000000..5970261 --- /dev/null +++ b/config/rubber/deploy-graphite.rb @@ -0,0 +1,255 @@ + +namespace :rubber do + + namespace :graphite do + + rubber.allow_optional_tasks(self) + + after "rubber:install_packages", "rubber:graphite:install_collectd_graphite_plugin" + + task :install_collectd_graphite_plugin, :roles => :collectd do + rubber.sudo_script 'install_collectd', <<-ENDSCRIPT + if [[ ! -f "/usr/local/share/perl/5.10.1/Collectd/Plugins/Graphite.pm" ]]; then + wget --no-check-certificate -qNO /tmp/joemiller-collectd-graphite.tar.gz https://github.com/joemiller/collectd-graphite/tarball/#{rubber_env.collectd_graphite_plugin_version} + tar -C /tmp -zxf /tmp/joemiller-collectd-graphite.tar.gz + cd /tmp/joemiller-collectd-graphite-* + perl Makefile.PL + make + make test + make install + fi + ENDSCRIPT + end + + # graphite collectd plugin needs newer collectd (>= 4.9) + before "rubber:install_packages", "rubber:graphite:setup_apt_backport_of_collectd" + + task :setup_apt_backport_of_collectd do + sources = <<-EOF + deb http://gb.archive.ubuntu.com/ubuntu/ maverick main universe + deb-src http://gb.archive.ubuntu.com/ubuntu/ maverick main universe + EOF + sources.gsub!(/^[ \t]*/, '') + + prefs = <<-EOF + Package: * + Pin: release a=maverick + Pin-Priority: 400 + + Package: libxml2 + Pin: release a=maverick + Pin-Priority: 900 + + Package: libxml2-dev + Pin: release a=maverick + Pin-Priority: 900 + + Package: collectd-core + Pin: release a=maverick + Pin-Priority: 900 + + Package: collectd-utils + Pin: release a=maverick + Pin-Priority: 900 + + Package: collectd + Pin: release a=maverick + Pin-Priority: 900 + EOF + prefs.gsub!(/^[ \t]*/, '') + + rubber.sudo_script 'setup_apt_backport_of_collectd', <<-ENDSCRIPT + release=`lsb_release -sr` + needs_backport=`echo "$release <= 10.04" | bc` + if [[ $needs_backport == 1 && ! -f /etc/apt/preferences.d/rubber-collectd ]]; then + echo -e #{sources.inspect} > /etc/apt/sources.list.d/rubber-collectd.list + echo -e #{prefs.inspect} > /etc/apt/preferences.d/rubber-collectd + fi + ENDSCRIPT + end + + task :install_graphite_from_repo, :roles => [:graphite_server, :graphite_web] do + rubber.sudo_script 'install_graphite_from_repo', <<-ENDSCRIPT + if [[ ! -d "/opt/graphite" ]]; then + mkdir -p /tmp/graphite_install + cd /tmp/graphite_install + bzr branch lp:graphite -r #{rubber_env.graphite_repo_version} + + pushd graphite/whisper + python setup.py install + popd + + pushd graphite/carbon + python setup.py install + popd + + pushd graphite + python setup.py install + popd + fi + ENDSCRIPT + end + + desc <<-DESC + Cleans out old whisper storage files for non-existant instances so they don't show in webui + DESC + task :clean_storage, :roles => [:graphite_server] do + active_instances = rubber_instances.collect {|ic| ic.name }.sort + stored_instances = capture("ls /opt/graphite/storage/whisper/servers/").split.sort + cleaning_instances = stored_instances - active_instances + + if cleaning_instances.size > 0 + logger.info "Cleaning dead instances from graphite storage: #{cleaning_instances.join(',')}" + + do_clean = true + if (cleaning_instances.size.to_f / stored_instances.size) > 0.01 + value = Capistrano::CLI.ui.ask("Graphite storage files to be cleaned exceeds threshold, proceed? [y/N]?: ") + do_clean = (value =~ /^y/) + end + + if do_clean + rsudo "rm -rf /opt/graphite/storage/whisper/servers/{#{cleaning_instances.join(',')}}" + end + + end + end + + namespace :server do + + rubber.allow_optional_tasks(self) + + if Rubber::Configuration.rubber_env.graphite_repo_version + after "rubber:install_packages", "rubber:graphite:install_graphite_from_repo" + else + after "rubber:install_packages", "rubber:graphite:server:install" + end + + after "rubber:bootstrap", "rubber:graphite:server:bootstrap" + + desc <<-DESC + Installs graphite server components + DESC + task :install, :roles => :graphite_server do + rubber.sudo_script 'install_graphite_server', <<-ENDSCRIPT + if [[ ! -f "/opt/graphite/bin/carbon-cache.py" ]]; then + wget -qNP /tmp #{rubber_env.graphite_whisper_package_url} + tar -C /tmp -zxf /tmp/#{rubber_env.graphite_whisper_package_url.gsub(/.*\//, '')} + cd /tmp/#{rubber_env.graphite_whisper_package_url.gsub(/.*\//, '').gsub('.tar.gz', '')} + python setup.py install + + wget -qNP /tmp #{rubber_env.graphite_carbon_package_url} + tar -C /tmp -zxf /tmp/#{rubber_env.graphite_carbon_package_url.gsub(/.*\//, '')} + cd /tmp/#{rubber_env.graphite_carbon_package_url.gsub(/.*\//, '').gsub('.tar.gz', '')} + python setup.py install + + fi + ENDSCRIPT + end + + task :bootstrap, :roles => :graphite_server do + exists = capture("echo $(ls /opt/graphite/storage/whisper/ 2> /dev/null)") + if exists.strip.size == 0 + rubber.update_code_for_bootstrap + + rubber.run_config(:file => "role/graphite_server", :force => true, :deploy_path => release_path) + + restart + end + end + + desc "Start graphite system monitoring" + task :start, :roles => :graphite_server do + rsudo "service graphite-server start" + end + + desc "Stop graphite system monitoring" + task :stop, :roles => :graphite_server do + rsudo "service graphite-server stop || true" + end + + desc "Restart graphite system monitoring" + task :restart, :roles => :graphite_server do + stop + start + end + end + + namespace :web do + + rubber.allow_optional_tasks(self) + + if Rubber::Configuration.rubber_env.graphite_repo_version + after "rubber:graphite:server:install", "rubber:graphite:install_graphite_from_repo" + else + after "rubber:graphite:server:install", "rubber:graphite:web:install" + end + + after "rubber:graphite:server:bootstrap", "rubber:graphite:web:bootstrap" + + desc <<-DESC + Installs graphite web components + DESC + task :install, :roles => :graphite_web do + rubber.sudo_script 'install_graphite_web', <<-ENDSCRIPT + if [[ ! -d "/opt/graphite/webapp" ]]; then + wget -qNP /tmp #{rubber_env.graphite_web_package_url} + tar -C /tmp -zxf /tmp/#{rubber_env.graphite_web_package_url.gsub(/.*\//, '')} + cd /tmp/#{rubber_env.graphite_web_package_url.gsub(/.*\//, '').gsub('.tar.gz', '')} + # python check-dependencies.py + python setup.py install + fi + ENDSCRIPT + end + + task :bootstrap, :roles => :graphite_web do + exists = capture("echo $(ls /opt/graphite/storage/graphite.db 2> /dev/null)") + if exists.strip.size == 0 + rubber.update_code_for_bootstrap + + rubber.run_config(:file => "role/graphite_web", :force => true, :deploy_path => release_path) + + # django email validation barfs on localhost, but for full_host to work + # in admin_email, we need a env with host defined + web_instance = rubber_instances.for_role("graphite_web").first + env = rubber_cfg.environment.bind("graphite_web", web_instance.name) + email = env.admin_email + + rubber.sudo_script 'bootstrap_graphite_web', <<-ENDSCRIPT + cd /opt/graphite/webapp/graphite + python manage.py syncdb --noinput + python manage.py createsuperuser --username admin --email #{email} --noinput + python manage.py shell < :graphite_web do + rsudo "service apache2 start" + end + + desc "Stop graphite system monitoring" + task :stop, :roles => :graphite_web do + rsudo "service apache2 stop || true" + end + + desc "Restart graphite system monitoring" + task :restart, :roles => :graphite_web do + stop + start + end + + end + + end + +end diff --git a/config/rubber/deploy-monit.rb b/config/rubber/deploy-monit.rb new file mode 100644 index 0000000..8822293 --- /dev/null +++ b/config/rubber/deploy-monit.rb @@ -0,0 +1,33 @@ + +namespace :rubber do + + namespace :monit do + + rubber.allow_optional_tasks(self) + + # monit needs to get stopped first and started last so that it doesn't + # mess with us restarting everything as part of a deploy. + before "rubber:pre_stop", "rubber:monit:stop" + before "rubber:pre_restart", "rubber:monit:stop" + after "rubber:post_start", "rubber:monit:start" + after "rubber:post_restart", "rubber:monit:start" + + desc "Start monit daemon monitoring" + task :start, :roles => :monit do + rsudo "service monit start" + end + + desc "Stop monit daemon monitoring" + task :stop, :roles => :monit do + rsudo "service monit stop || true" + end + + desc "Restart monit daemon monitoring" + task :restart, :roles => :monit do + stop + start + end + + end + +end diff --git a/config/rubber/deploy-passenger.rb b/config/rubber/deploy-passenger.rb new file mode 100644 index 0000000..054880e --- /dev/null +++ b/config/rubber/deploy-passenger.rb @@ -0,0 +1,45 @@ + +namespace :rubber do + + namespace :passenger do + + rubber.allow_optional_tasks(self) + + after "rubber:install_gems", "rubber:passenger:custom_install" + + task :custom_install, :roles => :passenger do + rubber.sudo_script 'install_passenger', <<-ENDSCRIPT + # can't use passenger_lib from rubber here as it only evaluates correctly + # when variable interpolation of rvm_gem_home is run remotely, and since we + # are in cap, we run the interpolation locally + # + passenger_lib=$(find /usr/local/rvm/gems/`rvm current` -path "*/passenger-#{rubber_env.passenger_version}/*/mod_passenger.so" 2> /dev/null) + if [[ -z $passenger_lib ]]; then + echo -en "\n\n\n\n" | passenger-install-apache2-module + rvm #{rubber_env.rvm_ruby} --passenger + fi + ENDSCRIPT + end + + # passenger does things differently for rack apps, so if this is a rails app, remove config.ru + # to stop passenger from treating this like a rack app + after "deploy:update_code", "rubber:passenger:remove_config_ru" if Rubber::Util.is_rails? + + task :remove_config_ru, :roles => :passenger do + rsudo "rm -f #{releases_path}/*/config.ru" + end + + # passenger depends on apache for start/stop/restart, just need these defined + # as apache hooks into standard deploy lifecycle + + deploy.task :restart, :roles => :app do + end + + deploy.task :stop, :roles => :app do + end + + deploy.task :start, :roles => :app do + end + + end +end diff --git a/config/rubber/deploy-postgresql.rb b/config/rubber/deploy-postgresql.rb new file mode 100644 index 0000000..3560956 --- /dev/null +++ b/config/rubber/deploy-postgresql.rb @@ -0,0 +1,140 @@ + +namespace :rubber do + + namespace :postgresql do + + rubber.allow_optional_tasks(self) + + before "rubber:install_packages", "rubber:postgresql:setup_apt_sources" + + task :setup_apt_sources do + rubber.sudo_script 'configure_postgresql_repository', <<-ENDSCRIPT + # PostgreSQL 9.1 is the default starting in Ubuntu 11.10. + release=`lsb_release -sr` + needs_repo=`echo "$release < 11.10" | bc` + if [[ $needs_repo == 1 ]]; then + add-apt-repository ppa:pitti/postgresql + fi + ENDSCRIPT + end + + after "rubber:create", "rubber:postgresql:validate_db_roles" + + task :validate_db_roles do + db_instances = rubber_instances.for_role("postgresql_slave") + db_instances.each do |instance| + if instance.role_names.find {|n| n == 'postgresql_master'} + fatal "Cannot have a postgresql slave and master on the same instance, please remove slave role for #{instance.name}" + end + end + end + + after "rubber:bootstrap", "rubber:postgresql:bootstrap" + + # Bootstrap the production database config. Db bootstrap is special - the + # user could be requiring the rails env inside some of their config + # templates, which creates a catch 22 situation with the db, so we try and + # bootstrap the db separate from the rest of the config + task :bootstrap, :roles => [:postgresql_master, :postgresql_slave] do + + # Conditionally bootstrap for each node/role only if that node has not + # been bootstrapped for that role before + master_instances = rubber_instances.for_role("postgresql_master") & rubber_instances.filtered + master_instances.each do |ic| + task_name = "_bootstrap_postgresql_master_#{ic.full_name}".to_sym() + task task_name, :hosts => ic.full_name do + env = rubber_cfg.environment.bind("postgresql_master", ic.name) + exists = capture("echo $(ls #{env.postgresql_data_dir}/ 2> /dev/null)") + if exists.strip.size == 0 + common_bootstrap + sudo "/usr/lib/postgresql/#{rubber_env.postgresql_ver}/bin/initdb -D #{rubber_env.postgresql_data_dir}", :as => 'postgres' + sudo "#{rubber_env.postgresql_ctl} start" + sleep 5 + + create_user_cmd = "CREATE USER #{env.db_user} WITH NOSUPERUSER CREATEDB NOCREATEROLE" + create_user_cmd << " PASSWORD '#{env.db_pass}'" if env.db_pass + + create_replication_user_cmd = "CREATE USER #{env.db_replication_user} WITH NOSUPERUSER NOCREATEROLE REPLICATION" + create_replication_user_cmd << " PASSWORD '#{env.db_replication_pass}'" if env.db_replication_pass + + rubber.sudo_script "create_master_db", <<-ENDSCRIPT + sudo -u postgres psql -c "#{create_user_cmd}" + sudo -u postgres psql -c "#{create_replication_user_cmd}" + sudo -u postgres psql -c "CREATE DATABASE #{env.db_name} WITH OWNER #{env.db_user}" + ENDSCRIPT + end + end + send task_name + end + + slave_instances = rubber_instances.for_role("postgresql_slave") & rubber_instances.filtered + slave_instances.each do |ic| + task_name = "_bootstrap_postgresql_slave_#{ic.full_name}".to_sym() + task task_name, :hosts => ic.full_name do + env = rubber_cfg.environment.bind("postgresql_slave", ic.name) + exists = capture("echo $(ls #{env.postgresql_data_dir}/ 2> /dev/null)") + if exists.strip.size == 0 + common_bootstrap + master = rubber_instances.for_role("postgresql_master").first + + rsudo "/usr/lib/postgresql/#{env.postgresql_ver}/bin/pg_basebackup -D #{env.postgresql_data_dir} -U #{env.db_replication_user} -h #{master.full_name}", :as => 'postgres' + + # Gen just the slave-specific conf. + rubber.run_config(:file => "role/postgresql_slave/", :force => true, :deploy_path => release_path) + + # Start up the server. + rsudo "#{rubber_env.postgresql_ctl} start" + sleep 5 + end + end + + send task_name + end + end + + # TODO: Make the setup/update happen just once per host + def common_bootstrap + # postgresql package install starts postgresql, so stop it + rsudo "#{rubber_env.postgresql_ctl} stop" rescue nil + + # After everything installed on machines, we need the source tree + # on hosts in order to run rubber:config for bootstrapping the db + rubber.update_code_for_bootstrap + + # Gen just the conf for the given postgresql role + rubber.run_config(:file => "role/(db|postgresql)/", :force => true, :deploy_path => release_path) + + # reconfigure postgresql so that it sets up data dir in /mnt with correct files + dirs = [rubber_env.postgresql_data_dir, rubber_env.postgresql_archive_dir] + sudo_script 'reconfigure-postgresql', <<-ENDSCRIPT + mkdir -p #{dirs.join(' ')} + chown -R postgres:postgres #{dirs.join(' ')} + chmod 700 #{rubber_env.postgresql_data_dir} + ENDSCRIPT + end + + desc <<-DESC + Starts the postgresql daemons + DESC + task :start, :roles => [:postgresql_master, :postgresql_slave] do + rsudo "#{rubber_env.postgresql_ctl} start" + end + + desc <<-DESC + Stops the postgresql daemons + DESC + task :stop, :roles => [:postgresql_master, :postgresql_slave] do + rsudo "#{rubber_env.postgresql_ctl} stop || true" + end + + desc <<-DESC + Restarts the postgresql daemons + DESC + task :restart, :roles => [:postgresql_master, :postgresql_slave] do + stop + start + end + + end + +end \ No newline at end of file diff --git a/config/rubber/deploy-setup.rb b/config/rubber/deploy-setup.rb new file mode 100644 index 0000000..e4ff2c5 --- /dev/null +++ b/config/rubber/deploy-setup.rb @@ -0,0 +1,107 @@ +namespace :rubber do + namespace :base do + + rubber.allow_optional_tasks(self) + + before "rubber:setup_gem_sources", "rubber:base:install_rvm" + task :install_rvm do + rubber.sudo_script "install_rvm", <<-ENDSCRIPT + if [[ ! `rvm --version 2> /dev/null` =~ "#{rubber_env.rvm_version}" ]]; then + cd /tmp + curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer -o rvm-installer + chmod +x rvm-installer + rm -f /etc/rvmrc + rvm_path=#{rubber_env.rvm_prefix} ./rvm-installer --version #{rubber_env.rvm_version} + + # Set up the rubygems version + sed -i 's/rubygems_version=.*/rubygems_version=#{rubber_env.rubygems_version}/' #{rubber_env.rvm_prefix}/config/db + + # Set up the rake version + sed -i 's/rake.*/rake -v#{rubber_env.rake_version}/' #{rubber_env.rvm_prefix}/gemsets/default.gems + sed -i 's/rake.*/rake -v#{rubber_env.rake_version}/' #{rubber_env.rvm_prefix}/gemsets/global.gems + + # Set up the .gemrc file + if [[ ! -f ~/.gemrc ]]; then + echo "--- " >> ~/.gemrc + fi + + if ! grep -q 'gem: ' ~/.gemrc; then + echo "gem: --no-ri --no-rdoc" >> ~/.gemrc + fi + fi + ENDSCRIPT + end + + # ensure that the rvm profile script gets sourced by reconnecting + after "rubber:base:install_rvm" do + teardown_connections_to(sessions.keys) + end + + after "rubber:base:install_rvm", "rubber:base:install_rvm_ruby" + task :install_rvm_ruby do + opts = get_host_options('rvm_ruby') + + # sudo_script only takes a single hash with host -> VAR, so combine our + # two vars so we can extract them out in the bash script + install_opts = get_host_options('rvm_install_options') + install_opts.each do |k, v| + opts[k] = "#{opts[k]} #{v}" + end + + install_rvm_ruby_script = <<-ENDSCRIPT + rvm_ver=$1 + shift + install_opts=$* + + if [[ ! `rvm list default 2> /dev/null` =~ "$rvm_ver" ]]; then + echo "RVM is compiling/installing ruby $rvm_ver, this may take a while" + + nohup rvm install $rvm_ver $install_opts &> /tmp/install_rvm_ruby.log & + sleep 1 + + while true; do + if ! ps ax | grep -q "[r]vm install"; then break; fi + echo -n . + sleep 5 + done + + # need to set default after using once or something in env is broken + rvm use $rvm_ver &> /dev/null + rvm use $rvm_ver --default + + # Something flaky with $PATH having an entry for "bin" which breaks + # munin, the below seems to fix it + rvm use $rvm_ver + rvm repair environments + rvm use $rvm_ver + fi + ENDSCRIPT + opts[:script_args] = '$CAPISTRANO:VAR$' + rubber.sudo_script "install_rvm_ruby", install_rvm_ruby_script, opts + end + + after "rubber:install_packages", "rubber:base:configure_git" if scm == "git" + task :configure_git do + rubber.sudo_script 'configure_git', <<-ENDSCRIPT + if [[ "#{repository}" =~ "@" ]]; then + # Get host key for src machine to prevent ssh from failing + rm -f ~/.ssh/known_hosts + ssh -o 'StrictHostKeyChecking=no' #{repository.gsub(/:.*/, '')} &> /dev/null || true + fi + ENDSCRIPT + end + + # We need a rails user for safer permissions used by deploy.rb + after "rubber:install_packages", "rubber:base:custom_install" + task :custom_install do + rubber.sudo_script 'custom_install', <<-ENDSCRIPT + # add the user for running app server with + if ! id #{rubber_env.app_user} &> /dev/null; then adduser --system --group #{rubber_env.app_user}; fi + + # add ssh keys for root + if [[ ! -f /root/.ssh/id_dsa ]]; then ssh-keygen -q -t dsa -N '' -f /root/.ssh/id_dsa; fi + ENDSCRIPT + end + + end +end diff --git a/config/rubber/deploy-util.rb b/config/rubber/deploy-util.rb new file mode 100644 index 0000000..786d579 --- /dev/null +++ b/config/rubber/deploy-util.rb @@ -0,0 +1,91 @@ +namespace :rubber do + namespace :util do + + rubber.allow_optional_tasks(self) + + desc <<-DESC + Backup database using rubber util:backup_db + DESC + task :backup do + master_instances = rubber_instances.for_role('db', 'primary' => true) + slaves = rubber_instances.for_role('db', {}) + + # Select only one instance for backup. Favor slave database. + selected_db_instance = (slaves+master_instances).first + + task_name = "_backup_db_#{selected_db_instance.full_name}".to_sym() + task task_name, :hosts => selected_db_instance.full_name do + rsudo "cd #{current_path} && RUBBER_ENV=#{Rubber.env} ./script/rubber util:backup_db --directory=/mnt/db_backups --dbuser=#{rubber_env.db_user} --dbpass=#{rubber_env.db_pass} --dbname=#{rubber_env.db_name} --dbhost=#{selected_db_instance.full_name}" + end + send task_name + end + + desc <<-DESC + Restore database from cloud using rubber util:restore_db + DESC + task :restore_cloud do + filename = get_env('FILENAME', "The cloud key to restore", true) + master_instances = rubber_instances.for_role('db', 'primary' => true) + slaves = rubber_instances.for_role('db', {}) + + for instance in master_instances+slaves + task_name = "_restore_db_cloud_#{instance.full_name}".to_sym() + task task_name, :hosts => instance.full_name do + rsudo "cd #{current_path} && RUBBER_ENV=#{Rubber.env} ./script/rubber util:restore_db --filename=#{filename} --dbuser=#{rubber_env.db_user} --dbpass=#{rubber_env.db_pass} --dbname=#{rubber_env.db_name} --dbhost=#{instance.full_name}" + end + send task_name + end + end + + desc <<-DESC + Overwrite production database with export from local production database. + DESC + task :local_to_cloud do + require 'yaml' + master_instances = rubber_instances.for_role('db', 'primary' => true) + slaves = rubber_instances.for_role('db', {}) + + # Select only one instance for backup. Favor slave database. + selected_db_instance = (slaves+master_instances).first + + task_name = "_load_local_to_#{selected_db_instance.full_name}".to_sym() + task task_name, :hosts => selected_db_instance.full_name do + + # Dump Local to tmp folder + filename = "#{application}.local.#{Time.now.to_i}.sql.gz" + backup_file = "/tmp/#{filename}" + on_rollback { delete file } + FileUtils.mkdir_p(File.dirname(backup_file)) + + # Use database.yml to get connection params + db = YAML::load(ERB.new(IO.read(File.join(File.dirname(__FILE__), '..','database.yml'))).result)[Rubber.env] + user = db['username'] + pass = db['password'] + pass = nil if pass and pass.strip.size == 0 + host = db['host'] + name = db['database'] + + raise "No db_backup_cmd defined in rubber.yml, cannot backup!" unless rubber_env.db_backup_cmd + db_backup_cmd = rubber_env.db_backup_cmd.gsub(/%([^%]+)%/, '#{\1}') + db_backup_cmd = eval('%Q{' + db_backup_cmd + '}') + + # dbdump (or backup app) needs to be in your path + puts "Backing up database with command:" + system(db_backup_cmd) + puts "Created backup: #{backup_file}" + + # Upload Local to Cloud + backup_bucket = Rubber.cloud.env.backup_bucket + dest = "db/#{File.basename(backup_file)}" + + puts "Saving db dump to cloud: #{backup_bucket}:#{dest}" + Rubber.cloud.storage(backup_bucket).store(dest, open(backup_file)) + + send :restore_cloud + + end + send task_name + end + + end +end diff --git a/config/rubber/role/apache/deflate.conf b/config/rubber/role/apache/deflate.conf new file mode 100644 index 0000000..db0c840 --- /dev/null +++ b/config/rubber/role/apache/deflate.conf @@ -0,0 +1,10 @@ +<% + @path = "/etc/apache2/mods-available/deflate.conf" + @post = "a2enmod deflate" +%> + + SetOutputFilter DEFLATE + BrowserMatch ^Mozilla/4 gzip-only-text/html + BrowserMatch ^Mozilla/4.0[678] no-gzip + BrowserMatch bMSIE !no-gzip !gzip-only-text/html + diff --git a/config/rubber/role/apache/expires.conf b/config/rubber/role/apache/expires.conf new file mode 100644 index 0000000..802359b --- /dev/null +++ b/config/rubber/role/apache/expires.conf @@ -0,0 +1,9 @@ +<% + @path = "/etc/apache2/mods-available/expires.conf" + @post = "a2enmod expires" +%> +ExpiresActive On + + ExpiresDefault "access plus 1 year" + + diff --git a/config/rubber/role/apache/headers.conf b/config/rubber/role/apache/headers.conf new file mode 100644 index 0000000..e1edab2 --- /dev/null +++ b/config/rubber/role/apache/headers.conf @@ -0,0 +1,6 @@ +<% + @path = "/etc/apache2/mods-available/headers.conf" + @post = "a2enmod headers" +%> +# Make sure proxies don't deliver the wrong content +Header append Vary User-Agent env=!dont-vary diff --git a/config/rubber/role/apache/monit-apache.conf b/config/rubber/role/apache/monit-apache.conf new file mode 100644 index 0000000..a73840d --- /dev/null +++ b/config/rubber/role/apache/monit-apache.conf @@ -0,0 +1,7 @@ +<% + @path = '/etc/monit/monit.d/monit-apache.conf' +%> +check process apache with pidfile /var/run/apache2.pid + group apache-<%= Rubber.env %> + start program = "/usr/bin/env service apache2 start" + stop program = "/usr/bin/env service apache2 stop" diff --git a/config/rubber/role/apache/ports.conf b/config/rubber/role/apache/ports.conf new file mode 100644 index 0000000..d1ce1f8 --- /dev/null +++ b/config/rubber/role/apache/ports.conf @@ -0,0 +1,8 @@ +<% + @path = '/etc/apache2/ports.conf' + # need to stop here so that apache will release port 80 before other + # services start and need to bind to it (e.g. haproxy) + @post = 'service apache2 stop' +%> +# empty ports file since other modules contribute which ports to open (vhosts) + diff --git a/config/rubber/role/apache/setenvif.conf b/config/rubber/role/apache/setenvif.conf new file mode 100644 index 0000000..30dc3d1 --- /dev/null +++ b/config/rubber/role/apache/setenvif.conf @@ -0,0 +1,52 @@ +<% + @path = "/etc/apache2/mods-available/setenvif.conf" + @post = "a2enmod setenvif" +%> + + +# +# The following directives modify normal HTTP response behavior to +# handle known problems with browser implementations. +# +BrowserMatch "Mozilla/2" nokeepalive +BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0 +BrowserMatch "RealPlayer 4\.0" force-response-1.0 +BrowserMatch "Java/1\.0" force-response-1.0 +BrowserMatch "JDK/1\.0" force-response-1.0 + +# +# The following directive disables redirects on non-GET requests for +# a directory that does not include the trailing slash. This fixes a +# problem with Microsoft WebFolders which does not appropriately handle +# redirects for folders with DAV methods. +# Same deal with Apple's DAV filesystem and Gnome VFS support for DAV. +# +BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully +BrowserMatch "MS FrontPage" redirect-carefully +BrowserMatch "^WebDrive" redirect-carefully +BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully +BrowserMatch "^gnome-vfs/1.0" redirect-carefully +BrowserMatch "^XML Spy" redirect-carefully +BrowserMatch "^Dreamweaver-WebDAV-SCM1" redirect-carefully + +SetEnvIf User-Agent "^websitepulse.*" no-log + +# Netscape 4.x has some problems... + BrowserMatch ^Mozilla/4 gzip-only-text/html + + # Netscape 4.06-4.08 have some more problems + BrowserMatch ^Mozilla/4\.0[678] no-gzip + + # MSIE masquerades as Netscape, but it is fine + BrowserMatch \bMSIE !no-gzip !gzip-only-text/html + + # Don't compress images + SetEnvIfNoCase Request_URI \ + \.(?:gif|jpe?g|png)$ no-gzip dont-vary + + # Don't compress downloads from files that are + # downloaded before they have been pushed to S3. + SetEnvIfNoCase Request_URI ^/assets/.* no-gzip dont-vary + + + diff --git a/config/rubber/role/collectd/collectd-ping.conf b/config/rubber/role/collectd/collectd-ping.conf new file mode 100644 index 0000000..b41e9ef --- /dev/null +++ b/config/rubber/role/collectd/collectd-ping.conf @@ -0,0 +1,21 @@ +<% + @path = '/etc/collectd/conf.d/collectd-ping.conf' + + ping_hosts = [] + if rubber_instances[rubber_env.host].role_names.include?('graphite_server') + # monitor all servers from graphite_server + ping_hosts = rubber_instances.collect {|ic| ic.full_name }.select {|h| h != rubber_env.full_host } + elsif rubber_instances[rubber_env.host].role_names.include?('web_tools') + # monitor just graphite_server from tools + ping_hosts = Array((rubber_instances.for_role('graphite_server').first.full_name rescue nil)) + end + + @skip = (ping_hosts.size == 0) +%> + +LoadPlugin ping + + <% ping_hosts.each do |h| %> + Host "<%= h %>" + <% end %> + diff --git a/config/rubber/role/collectd/collectd.conf b/config/rubber/role/collectd/collectd.conf new file mode 100644 index 0000000..0220956 --- /dev/null +++ b/config/rubber/role/collectd/collectd.conf @@ -0,0 +1,69 @@ +<% + rubber_scripts = `#{Rubber.root}/#{rubber_env.rubber_collectd_runner} config`.split("\n") rescue [] + + @path = '/etc/collectd/collectd.conf' + @post = "mkdir -p /etc/collectd/conf.d/ /etc/collectd/thresholds.d/ /etc/collectd/filters.d/ /etc/collectd/plugins/ " +%> +# Config file for collectd(1). Generated by Rubber +# +# Some plugins need additional configuration and are disabled by default. +# Please read collectd.conf(5) for details. +# +# You should also read /usr/share/doc/collectd-core/README.Debian.plugins +# before enabling any more plugins. + +Hostname "<%= rubber_env.host %>" +#BaseDir "/var/lib/collectd" +#PluginDir "/usr/lib/collectd" +TypesDB "/usr/share/collectd/types.db" "/etc/collectd/types.db" +Interval 60 +#Timeout 2 +#ReadThreads 5 + +LoadPlugin syslog + + + LogLevel info + + +LoadPlugin cpu +LoadPlugin df +LoadPlugin disk +LoadPlugin exec +LoadPlugin entropy +LoadPlugin interface +LoadPlugin irq +LoadPlugin load +LoadPlugin memory +LoadPlugin processes +#LoadPlugin python +LoadPlugin rrdtool +<% if `swapon -s | wc -l`.to_i > 1 %> +LoadPlugin swap +<% end %> +#LoadPlugin table +#LoadPlugin tail +#LoadPlugin tcpconns +LoadPlugin users + +LoadPlugin notify_email + + + From "collectd@<%= rubber_env.full_host %>" + Recipient "<%= rubber_env.admin_email %>" + Subject "Collectd notify: %s@%s" + + +<% + if rubber_scripts.size > 0 +%> + + + Exec <%= rubber_env.app_user %> "/bin/bash" "-l" "-c" "cd <%= "/mnt/#{rubber_env.app_name}-#{Rubber.env}/current" %> && bundle exec <%= rubber_env.rubber_collectd_runner %>" + + +<% end %> + +Include "/etc/collectd/conf.d/*.conf" +Include "/etc/collectd/thresholds.d/*.conf" +Include "/etc/collectd/filters.d/*.conf" diff --git a/config/rubber/role/collectd/filters.conf b/config/rubber/role/collectd/filters.conf new file mode 100644 index 0000000..4ca089d --- /dev/null +++ b/config/rubber/role/collectd/filters.conf @@ -0,0 +1,35 @@ +<% + @path = '/etc/collectd/filters.d/filters.conf' +%> +# Filter configuration for collectd(1). +# +# See the section "FILTER CONFIGURATION" in collectd.conf(5) for details. + +#PreCacheChain "PreCache" +#PostCacheChain "PostCache" + +#LoadPlugin match_empty_counter +#LoadPlugin match_hashed +#LoadPlugin match_regex +#LoadPlugin match_timediff +#LoadPlugin match_value + +#LoadPlugin target_notification +#LoadPlugin target_replace +#LoadPlugin target_scale +#LoadPlugin target_set + +# +# +# +# Host "^[^\.]*$" +# Invert false +# +# Target "stop" +# +# + +# +# Target "write" +# + diff --git a/config/rubber/role/collectd/graphite-collectd.conf b/config/rubber/role/collectd/graphite-collectd.conf new file mode 100644 index 0000000..bb71f33 --- /dev/null +++ b/config/rubber/role/collectd/graphite-collectd.conf @@ -0,0 +1,21 @@ +<% + graphite_server = rubber_instances.for_role('graphite_server').first.full_name rescue nil + @path = '/etc/collectd/conf.d/graphite.conf' + @skip = graphite_server.nil? +%> + + + Globals true + + + + BaseName "Collectd::Plugins" + LoadPlugin "Graphite" + + + Buffer "<%= Rubber.env == 'production' ? 1024 : 0 %>" + Prefix "servers" + Host "<%= graphite_server %>" + Port "<%= rubber_env.graphite_server_port %>" + + diff --git a/config/rubber/role/collectd/thresholds.conf b/config/rubber/role/collectd/thresholds.conf new file mode 100644 index 0000000..4e4860a --- /dev/null +++ b/config/rubber/role/collectd/thresholds.conf @@ -0,0 +1,88 @@ +<% + is_worker_instance = rubber_instances[rubber_env.host].role_names.include?('resque_worker') + + @path = '/etc/collectd/thresholds.d/thresholds.conf' +%> +# Threshold configuration for collectd(1). +# +# See the section "THRESHOLD CONFIGURATION" in collectd.conf(5) for details. + + + + + DataSource "used" + WarningMax 80 + FailureMax 95 + Percentage true + + + + DataSource "midterm" + WarningMax <%= is_worker_instance ? 100 : 20 %> + Hysteresis 0.3 + + + + + Datasource "value" + WarningMax 50 + FailureMax 100 + + + Datasource "value" + FailureMax 0.05 + + + + + +# +# +# WarningMin 0.00 +# WarningMax 1000.00 +# FailureMin 0 +# FailureMax 1200.00 +# Invert false +# Persist false +# Instance "some_instance" +# +# +# +# WarningMax 90 +# Percentage true +# +# +# +# DataSource "midterm" +# WarningMax 1 +# Hysteresis 0.3 +# +# +# +# Instance "user" +# WarningMax 85 +# Hits 6 +# +# +# +# Instance "eth0" +# +# DataSource "rx" +# FailureMax 10000000 +# +# +# +# +# +# Instance "idle" +# FailureMin 10 +# +# +# +# +# Instance "cached" +# WarningMin 100000000 +# +# +# +# diff --git a/config/rubber/role/collectd/types.db b/config/rubber/role/collectd/types.db new file mode 100644 index 0000000..ba78206 --- /dev/null +++ b/config/rubber/role/collectd/types.db @@ -0,0 +1,5 @@ +<% + @path = '/etc/collectd/types.db' +%> + +domains_by_segment domain_count:GAUGE:0:U, avg_user_count:GAUGE:0:U, avg_storage:GAUGE:0:U diff --git a/config/rubber/role/graphite_server/carbon.conf b/config/rubber/role/graphite_server/carbon.conf new file mode 100644 index 0000000..d222956 --- /dev/null +++ b/config/rubber/role/graphite_server/carbon.conf @@ -0,0 +1,232 @@ +<% + @path = '/opt/graphite/conf/carbon.conf' +%> +[cache] +# Configure carbon directories. +# +# OS environment variables can be used to tell carbon where graphite is +# installed, where to read configuration from and where to write data. +# +# GRAPHITE_ROOT - Root directory of the graphite installation. +# Defaults to ../ +# GRAPHITE_CONF_DIR - Configuration directory (where this file lives). +# Defaults to $GRAPHITE_ROOT/conf/ +# GRAPHITE_STORAGE_DIR - Storage directory for whipser/rrd/log/pid files. +# Defaults to $GRAPHITE_ROOT/storage/ +# +# To change other directory paths, add settings to this file. The following +# configuration variables are available with these default values: +# +# STORAGE_DIR = $GRAPHITE_STORAGE_DIR +# LOCAL_DATA_DIR = STORAGE_DIR/whisper/ +# WHITELISTS_DIR = STORAGE_DIR/lists/ +# CONF_DIR = STORAGE_DIR/conf/ +# LOG_DIR = STORAGE_DIR/log/ +# PID_DIR = STORAGE_DIR/ +# +# For FHS style directory structures, use: +# +# STORAGE_DIR = /var/lib/carbon/ +# CONF_DIR = /etc/carbon/ +# LOG_DIR = /var/log/carbon/ +# PID_DIR = /var/run/ +# +LOCAL_DATA_DIR = /opt/graphite/storage/whisper/ + +# Specify the user to drop privileges to +# If this is blank carbon runs as the user that invokes it +# This user must have write access to the local data directory +USER = + +# Limit the size of the cache to avoid swapping or becoming CPU bound. +# Sorts and serving cache queries gets more expensive as the cache grows. +# Use the value "inf" (infinity) for an unlimited cache size. +MAX_CACHE_SIZE = inf + +# Limits the number of whisper update_many() calls per second, which effectively +# means the number of write requests sent to the disk. This is intended to +# prevent over-utilizing the disk and thus starving the rest of the system. +# When the rate of required updates exceeds this, then carbon's caching will +# take effect and increase the overall throughput accordingly. +MAX_UPDATES_PER_SECOND = 1000 + +# Softly limits the number of whisper files that get created each minute. +# Setting this value low (like at 50) is a good way to ensure your graphite +# system will not be adversely impacted when a bunch of new metrics are +# sent to it. The trade off is that it will take much longer for those metrics' +# database files to all get created and thus longer until the data becomes usable. +# Setting this value high (like "inf" for infinity) will cause graphite to create +# the files quickly but at the risk of slowing I/O down considerably for a while. +MAX_CREATES_PER_MINUTE = 50 + +LINE_RECEIVER_INTERFACE = 0.0.0.0 +LINE_RECEIVER_PORT = <%= rubber_env.graphite_server_port %> + +# Set this to True to enable the UDP listener. By default this is off +# because it is very common to run multiple carbon daemons and managing +# another (rarely used) port for every carbon instance is not fun. +ENABLE_UDP_LISTENER = False +UDP_RECEIVER_INTERFACE = 0.0.0.0 +UDP_RECEIVER_PORT = 2003 + +PICKLE_RECEIVER_INTERFACE = 0.0.0.0 +PICKLE_RECEIVER_PORT = 2004 + +# Per security concerns outlined in Bug #817247 the pickle receiver +# will use a more secure and slightly less efficient unpickler. +# Set this to True to revert to the old-fashioned insecure unpickler. +USE_INSECURE_UNPICKLER = False + +CACHE_QUERY_INTERFACE = 0.0.0.0 +CACHE_QUERY_PORT = 7002 + +# Set this to False to drop datapoints received after the cache +# reaches MAX_CACHE_SIZE. If this is True (the default) then sockets +# over which metrics are received will temporarily stop accepting +# data until the cache size falls below 95% MAX_CACHE_SIZE. +USE_FLOW_CONTROL = True + +# By default, carbon-cache will log every whisper update. This can be excessive and +# degrade performance if logging on the same volume as the whisper data is stored. +LOG_UPDATES = False + +# On some systems it is desirable for whisper to write synchronously. +# Set this option to True if you'd like to try this. Basically it will +# shift the onus of buffering writes from the kernel into carbon's cache. +WHISPER_AUTOFLUSH = False + +# Enable AMQP if you want to receve metrics using an amqp broker +# ENABLE_AMQP = False + +# Verbose means a line will be logged for every metric received +# useful for testing +# AMQP_VERBOSE = False + +# AMQP_HOST = localhost +# AMQP_PORT = 5672 +# AMQP_VHOST = / +# AMQP_USER = guest +# AMQP_PASSWORD = guest +# AMQP_EXCHANGE = graphite +# AMQP_METRIC_NAME_IN_BODY = False + +# The manhole interface allows you to SSH into the carbon daemon +# and get a python interpreter. BE CAREFUL WITH THIS! If you do +# something like time.sleep() in the interpreter, the whole process +# will sleep! This is *extremely* helpful in debugging, assuming +# you are familiar with the code. If you are not, please don't +# mess with this, you are asking for trouble :) +# +# ENABLE_MANHOLE = False +# MANHOLE_INTERFACE = 127.0.0.1 +# MANHOLE_PORT = 7222 +# MANHOLE_USER = admin +# MANHOLE_PUBLIC_KEY = ssh-rsa AAAAB3NzaC1yc2EAAAABiwAaAIEAoxN0sv/e4eZCPpi3N3KYvyzRaBaMeS2RsOQ/cDuKv11dlNzVeiyc3RFmCv5Rjwn/lQ79y0zyHxw67qLyhQ/kDzINc4cY41ivuQXm2tPmgvexdrBv5nsfEpjs3gLZfJnyvlcVyWK/lId8WUvEWSWHTzsbtmXAF2raJMdgLTbQ8wE= + +# Patterns for all of the metrics this machine will store. Read more at +# http://en.wikipedia.org/wiki/Advanced_Message_Queuing_Protocol#Bindings +# +# Example: store all sales, linux servers, and utilization metrics +# BIND_PATTERNS = sales.#, servers.linux.#, #.utilization +# +# Example: store everything +# BIND_PATTERNS = # + +# To configure special settings for the 'foo' carbon-cache instance, uncomment this: +#[cache:foo] +#LINE_RECEIVER_PORT = 2103 +#PICKLE_RECEIVER_PORT = 2104 +#CACHE_QUERY_PORT = 7102 +# and any other settings you want to customize, defaults are inherited +# from [carbon] section. + + +[relay] +LINE_RECEIVER_INTERFACE = 0.0.0.0 +LINE_RECEIVER_PORT = 2013 +PICKLE_RECEIVER_INTERFACE = 0.0.0.0 +PICKLE_RECEIVER_PORT = 2014 + +# To use consistent hashing instead of the user defined relay-rules.conf, +# change this to: +# RELAY_METHOD = consistent-hashing +RELAY_METHOD = rules + +# If you use consistent-hashing you may want to add redundancy +# of your data by replicating every datapoint to more than +# one machine. +REPLICATION_FACTOR = 1 + +# This is a list of carbon daemons we will send any relayed or +# generated metrics to. The default provided would send to a single +# carbon-cache instance on the default port. However if you +# use multiple carbon-cache instances then it would look like this: +# +# DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b +# +# The general form is IP:PORT:INSTANCE where the :INSTANCE part is +# optional and refers to the "None" instance if omitted. +# +# Note that if the destinations are all carbon-caches then this should +# exactly match the webapp's CARBONLINK_HOSTS setting in terms of +# instances listed (order matters!). +DESTINATIONS = 127.0.0.1:2004 + +# This defines the maximum "message size" between carbon daemons. +# You shouldn't need to tune this unless you really know what you're doing. +MAX_DATAPOINTS_PER_MESSAGE = 500 +MAX_QUEUE_SIZE = 10000 + +# Set this to False to drop datapoints when any send queue (sending datapoints +# to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the +# default) then sockets over which metrics are received will temporarily stop accepting +# data until the send queues fall below 80% MAX_QUEUE_SIZE. +USE_FLOW_CONTROL = True + + +[aggregator] +LINE_RECEIVER_INTERFACE = 0.0.0.0 +LINE_RECEIVER_PORT = 2023 + +PICKLE_RECEIVER_INTERFACE = 0.0.0.0 +PICKLE_RECEIVER_PORT = 2024 + +# This is a list of carbon daemons we will send any relayed or +# generated metrics to. The default provided would send to a single +# carbon-cache instance on the default port. However if you +# use multiple carbon-cache instances then it would look like this: +# +# DESTINATIONS = 127.0.0.1:2004:a, 127.0.0.1:2104:b +# +# The format is comma-delimited IP:PORT:INSTANCE where the :INSTANCE part is +# optional and refers to the "None" instance if omitted. +# +# Note that if the destinations are all carbon-caches then this should +# exactly match the webapp's CARBONLINK_HOSTS setting in terms of +# instances listed (order matters!). +DESTINATIONS = 127.0.0.1:2004 + +# If you want to add redundancy to your data by replicating every +# datapoint to more than one machine, increase this. +REPLICATION_FACTOR = 1 + +# This is the maximum number of datapoints that can be queued up +# for a single destination. Once this limit is hit, we will +# stop accepting new data if USE_FLOW_CONTROL is True, otherwise +# we will drop any subsequently received datapoints. +MAX_QUEUE_SIZE = 10000 + +# Set this to False to drop datapoints when any send queue (sending datapoints +# to a downstream carbon daemon) hits MAX_QUEUE_SIZE. If this is True (the +# default) then sockets over which metrics are received will temporarily stop accepting +# data until the send queues fall below 80% MAX_QUEUE_SIZE. +USE_FLOW_CONTROL = True + +# This defines the maximum "message size" between carbon daemons. +# You shouldn't need to tune this unless you really know what you're doing. +MAX_DATAPOINTS_PER_MESSAGE = 500 + +# This defines how many datapoints the aggregator remembers for +# each metric. Aggregation only happens for datapoints that fall in +# the past MAX_AGGREGATION_INTERVALS * intervalSize seconds. +MAX_AGGREGATION_INTERVALS = 5 diff --git a/config/rubber/role/graphite_server/graphite_server-upstart.conf b/config/rubber/role/graphite_server/graphite_server-upstart.conf new file mode 100644 index 0000000..cab667d --- /dev/null +++ b/config/rubber/role/graphite_server/graphite_server-upstart.conf @@ -0,0 +1,16 @@ +<% + @path = "/etc/init/graphite-server.conf" + @backup = false +%> +description "graphite server" + +start on [2345] +stop on runlevel [016] + +expect daemon + +script + cd <%= rubber_env.graphite_dir %> + rm -f <%= rubber_env.graphite_server_pid_file %> + exec ./bin/carbon-cache.py --pidfile <%= rubber_env.graphite_server_pid_file %> start +end script diff --git a/config/rubber/role/graphite_server/storage-schemas.conf b/config/rubber/role/graphite_server/storage-schemas.conf new file mode 100644 index 0000000..f351b07 --- /dev/null +++ b/config/rubber/role/graphite_server/storage-schemas.conf @@ -0,0 +1,19 @@ +<% + @path = '/opt/graphite/conf/storage-schemas.conf' +%> + +# Schema definitions for whisper files. Entries are scanned in order, +# and first match wins. +# +# [name] +# pattern = regex +# retentions = timePerPoint:timeToStore, timePerPoint:timeToStore, ... +# +# [default_1min_for_1day] +# pattern = .* +# retentions = 60s:1d + +[everything_1min_13months] +priority = 100 +pattern = .* +retentions = 60:565920 diff --git a/config/rubber/role/graphite_web/crontab b/config/rubber/role/graphite_web/crontab new file mode 100644 index 0000000..5757c89 --- /dev/null +++ b/config/rubber/role/graphite_web/crontab @@ -0,0 +1,8 @@ +<% + @read_cmd = 'crontab -l' + @write_cmd = 'crontab -' + @additive = ['# start-graphite_web-crontab', '# end-graphite_web-crontab'] +%> + +# Backup graphite web UI db every day +0 1 * * * <%= Rubber.root %>/script/rubber cron --task util:backup --directory /mnt/graphite_backups --name graphite --command "nice zip \%dir\%/\%name\%_<%= rubber_env.host %>_\%time_stamp\%.zip /opt/graphite/storage/*.db" diff --git a/config/rubber/role/graphite_web/dashboard.conf b/config/rubber/role/graphite_web/dashboard.conf new file mode 100644 index 0000000..88b879f --- /dev/null +++ b/config/rubber/role/graphite_web/dashboard.conf @@ -0,0 +1,60 @@ +<% + @path = '/opt/graphite/conf/dashboard.conf' +%> +# This configuration file controls the behavior of the Dashboard UI, available +# at http://my-graphite-server/dashboard/. +# +# This file must contain a [ui] section that defines values for all of the +# following settings. +[ui] +default_graph_width = 400 +default_graph_height = 250 +automatic_variants = true +refresh_interval = 60 +autocomplete_delay = 375 +merge_hover_delay = 750 + +# You can set this 'default', 'white', or a custom theme name. +# To create a custom theme, copy the dashboard-default.css file +# to dashboard-myThemeName.css in the content/css directory and +# modify it to your liking. +theme = default + +[keyboard-shortcuts] +toggle_toolbar = ctrl-z +toggle_metrics_panel = ctrl-space +erase_all_graphs = alt-x +save_dashboard = alt-s +completer_add_metrics = alt-enter +completer_del_metrics = alt-backspace +give_completer_focus = shift-space + +# These settings apply to the UI as a whole, all other sections in this file +# pertain only to specific metric types. +# +# The dashboard presents only metrics that fall into specified naming schemes +# defined in this file. This creates a simpler, more targetted view of the +# data. The general form for defining a naming scheme is as follows: +# +#[Metric Type] +#scheme = basis.path... +#field1.label = Foo +#field2.label = Bar +# +# +# Where each will be displayed as a dropdown box +# in the UI and the remaining portion of the namespace +# shown in the Metric Selector panel. The .label options set the labels +# displayed for each dropdown. +# +# For example: +# +#[Sales] +#scheme = sales... +#channel.label = Channel +#type.label = Product Type +#brand.label = Brand +# +# This defines a 'Sales' metric type that uses 3 dropdowns in the Context Selector +# (the upper-left panel) while any deeper metrics (per-product counts or revenue, etc) +# will be available in the Metric Selector (upper-right panel). diff --git a/config/rubber/role/graphite_web/dashboard.html b/config/rubber/role/graphite_web/dashboard.html new file mode 100644 index 0000000..4c0c776 --- /dev/null +++ b/config/rubber/role/graphite_web/dashboard.html @@ -0,0 +1,385 @@ + + + + + Graphite TV Dashboards + + + + + + + + +
+
Paused
+
+ + diff --git a/config/rubber/role/graphite_web/graphite-vhost.conf b/config/rubber/role/graphite_web/graphite-vhost.conf new file mode 100644 index 0000000..15428e7 --- /dev/null +++ b/config/rubber/role/graphite_web/graphite-vhost.conf @@ -0,0 +1,62 @@ +<% + @path = '/etc/apache2/sites-available/graphite' + @post = <<-SCRIPT + a2ensite graphite + SCRIPT +%> + +# This needs to be in your server's config somewhere, probably +# the main httpd.conf +# NameVirtualHost *:80 + +# This line also needs to be in your server's config. +# LoadModule wsgi_module modules/mod_wsgi.so + +# You may need to manually edit this file to fit your needs. +# This configuration assumes the default installation prefix +# of /opt/graphite/, if you installed graphite somewhere else +# you will need to change all the occurances of /opt/graphite/ +# in this file to your chosen install location. + +Listen <%= rubber_env.graphite_web_port %> +> + ServerName <%= rubber_env.full_host %> + DocumentRoot "/opt/graphite/webapp" + ErrorLog /opt/graphite/storage/log/webapp/error.log + CustomLog /opt/graphite/storage/log/webapp/access.log common + + # I've found that an equal number of processes & threads tends + # to show the best performance for Graphite (ymmv). + WSGIDaemonProcess graphite processes=5 threads=5 display-name='%{GROUP}' inactivity-timeout=120 + WSGIProcessGroup graphite + + # XXX You need to set this up! + # Read http://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGISocketPrefix + # WSGISocketPrefix /var/run/apache2/ + + # XXX You will need to create this file! There is a graphite.wsgi.example + # file in this directory that you can safely use, just copy it to graphite.wgsi + WSGIScriptAlias / /opt/graphite/conf/graphite.wsgi + + Alias /content/ /opt/graphite/webapp/content/ + + SetHandler None + + + # XXX In order for the django admin site media to work you + # must change @DJANGO_ROOT@ to be the path to your django + # installation, which is probably something like: + # /usr/lib/python2.6/site-packages/django + Alias /media/ "/usr/lib/pymodules/python2.6/django/contrib/admin/media/" + + SetHandler None + + + # The graphite.wsgi file has to be accessible by apache. It won't + # be visible to clients because of the DocumentRoot though. + + Order deny,allow + Allow from all + + + diff --git a/config/rubber/role/graphite_web/graphite.wsgi b/config/rubber/role/graphite_web/graphite.wsgi new file mode 100644 index 0000000..9d0cb7b --- /dev/null +++ b/config/rubber/role/graphite_web/graphite.wsgi @@ -0,0 +1,10 @@ +<% + @path = '/opt/graphite/conf/graphite.wsgi' +%> +import os, sys +sys.path.append('/opt/graphite/webapp') +os.environ['DJANGO_SETTINGS_MODULE'] = 'graphite.settings' + +import django.core.handlers.wsgi + +application = django.core.handlers.wsgi.WSGIHandler() diff --git a/config/rubber/role/graphite_web/local_settings.py b/config/rubber/role/graphite_web/local_settings.py new file mode 100644 index 0000000..39f00a0 --- /dev/null +++ b/config/rubber/role/graphite_web/local_settings.py @@ -0,0 +1,98 @@ +<% + @path = '/opt/graphite/webapp/graphite/local_settings.py' +%> +# Edit this file to override the default graphite settings, do not edit settings.py!!! + +# Turn on debugging and restart apache if you ever see an "Internal Server Error" page +#DEBUG = True + +# Set your local timezone (django will *try* to figure this out automatically) +# If your graphs appear to be offset by a couple hours then this probably +# needs to be explicitly set to your local timezone. +TIME_ZONE = 'America/New_York' + +# Uncomment these to enable more performance-related logging +#LOG_RENDERING_PERFORMANCE = True +#LOG_CACHE_PERFORMANCE = True + +# Override this if you need to provide documentation specific to your graphite deployment +#DOCUMENTATION_URL = "http://wiki.mycompany.com/graphite" + +# Enable email-related features +#SMTP_SERVER = "mail.mycompany.com" + + +##################################### +# LDAP Authentication Configuration # +##################################### +# LDAP / ActiveDirectory authentication setup +#USE_LDAP_AUTH = True +#LDAP_SERVER = "ldap.mycompany.com" +#LDAP_PORT = 389 +# OR +#LDAP_URI = "ldaps://ldap.mycompany.com:636" +#LDAP_SEARCH_BASE = "OU=users,DC=mycompany,DC=com" +#LDAP_BASE_USER = "CN=some_readonly_account,DC=mycompany,DC=com" +#LDAP_BASE_PASS = "readonly_account_password" +#LDAP_USER_QUERY = "(username=%s)" #For Active Directory use "(sAMAccountName=%s)" +# +# If you want to further customize the ldap connection options you should +# directly use ldap.set_option to set the ldap module's global options. +# For example: +# +#import ldap +#ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_ALLOW) +#ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, "/etc/ssl/ca") +#ldap.set_option(ldap.OPT_X_TLS_CERTFILE, "/etc/ssl/mycert.pem") +#ldap.set_option(ldap.OPT_X_TLS_KEYFILE, "/etc/ssl/mykey.pem") +# See http://www.python-ldap.org/ for further details on these options. + + +########################## +# Database Configuration # +########################## +# By default sqlite is used. If you cluster multiple webapps you will need +# to setup an external database (like mysql) and configure all the webapps +# to use the same database. Note that this database is only used to store +# django models like saved graphs, dashboards, user preferences, etc. Metric +# data is not stored here. +# +# DON'T FORGET TO RUN 'manage.py syncdb' AFTER SETTING UP A NEW DB! +# +#DATABASE_ENGINE = 'mysql' # or 'postgres' +#DATABASE_NAME = 'graphite' +#DATABASE_USER = 'graphite' +#DATABASE_PASSWORD = 'graphite-is-awesome' +#DATABASE_HOST = 'mysql.mycompany.com' +#DATABASE_PORT = '3306' + + +######################### +# Cluster Configuration # +######################### +# (To avoid excessive DNS lookups you want to stick to using IP addresses only in this entire section) +# +# This should list the IP address (and optionally port) of each webapp in your cluster. +# Strings are of the form "ip[:port]" +# Usually this will be the same as MEMCACHE_HOSTS except for the port numbers. +# +#CLUSTER_SERVERS = [] + +# This lists all the memcached servers that will be used by this webapp. +# If you have a cluster of webapps you want to make sure all of them +# have the *exact* same value for this setting. That will maximize cache +# efficiency. Setting MEMCACHE_HOSTS to be empty will turn off use of +# memcached entirely. +# +# You should not use the loopback address 127.0.0.1 here because every webapp in +# the cluster should use the exact same value and should list every member in the +# cluster. +#MEMCACHE_HOSTS = ['10.10.10.10:11211', '10.10.10.11:11211', '10.10.10.12:11211'] + +# If you are running multiple carbon-caches on this machine (typically behind a relay using +# consistent hashing), you'll need to list the ip address, cache query port, and instance name of each carbon-cache +# instance on the local machine (NOT every carbon-cache in the entire cluster). The default cache query port is 7002 +# and a common scheme is to use 7102 for instance b, 7202 for instance c, etc. +# +# You *should* use 127.0.0.1 here. +#CARBONLINK_HOSTS = ["127.0.0.1:7002:a", "127.0.0.1:7102:b", "127.0.0.1:7202:c"] diff --git a/config/rubber/role/monit/monit-default.conf b/config/rubber/role/monit/monit-default.conf new file mode 100644 index 0000000..9c3f4b4 --- /dev/null +++ b/config/rubber/role/monit/monit-default.conf @@ -0,0 +1,18 @@ +<% + @path = '/etc/default/monit' +%> + +# Defaults for monit initscript +# sourced by /etc/init.d/monit +# installed at /etc/default/monit by maintainer scripts +# Fredrik Steen + +# You must set this variable for monit to start (Ubuntu < 11.10) +startup=1 + +# You must set this variable for monit to start (Ubuntu >= 11.10) +START=yes + +# To change the intervals which monit should run uncomment +# and change this variable. +# CHECK_INTERVALS=180 diff --git a/config/rubber/role/monit/monit-postfix.conf b/config/rubber/role/monit/monit-postfix.conf new file mode 100644 index 0000000..519cedf --- /dev/null +++ b/config/rubber/role/monit/monit-postfix.conf @@ -0,0 +1,8 @@ +<% + @path = '/etc/monit/monit.d/monit-postfix.conf' +%> + +check process postfix with pidfile /var/spool/postfix/pid/master.pid + start program "/usr/bin/env service postfix start" + stop program "/usr/bin/env service postfix stop" + if 5 restarts within 5 cycles then timeout diff --git a/config/rubber/role/monit/monit.conf b/config/rubber/role/monit/monit.conf new file mode 100644 index 0000000..17b746a --- /dev/null +++ b/config/rubber/role/monit/monit.conf @@ -0,0 +1,252 @@ +<% + @path = '/etc/monit/monitrc' +%> + +############################################################################### +## Monit control file +############################################################################### +## +## Comments begin with a '#' and extend through the end of the line. Keywords +## are case insensitive. All path's MUST BE FULLY QUALIFIED, starting with '/'. +## +## Bellow is the example of some frequently used statements. For information +## about the control file, a complete list of statements and options please +## have a look in the monit manual. +## +## +############################################################################### +## Global section +############################################################################### +## +## Start monit in background (run as daemon) and check the services at 2-minute +## intervals. +# +# set daemon 120 +set daemon 60 + +# +# +## Set syslog logging with the 'daemon' facility. If the FACILITY option is +## omited, monit will use 'user' facility by default. You can specify the +## path to the file for monit native logging. +# +# set logfile syslog facility log_daemon +set logfile /var/log/monit.log +# +# +## Set list of mailservers for alert delivery. Multiple servers may be +## specified using comma separator. By default monit uses port 25 - it is +## possible to override it with the PORT option. +# +# set mailserver mail.bar.baz, # primary mailserver +# backup.bar.baz port 10025, # backup mailserver on port 10025 +# localhost # fallback relay +# +set mailserver localhost + +# +## By default monit will drop the event alert, in the case that there is no +## mailserver available. In the case that you want to keep the events for +## later delivery retry, you can use the EVENTQUEUE statement. The base +## directory where undelivered events will be stored is specified by the +## BASEDIR option. You can limit the maximal queue size using the SLOTS +## option (if omited then the queue is limited just by the backend filesystem). +# +# set eventqueue +# basedir /var/monit # set the base directory where events will be stored +# slots 100 # optionaly limit the queue size +# +# +## Monit by default uses the following alert mail format: +## +## --8<-- +## From: monit@$HOST # sender +## Subject: monit alert -- $EVENT $SERVICE # subject +## +## $EVENT Service $SERVICE # +## # +## Date: $DATE # +## Action: $ACTION # +## Host: $HOST # body +## Description: $DESCRIPTION # +## # +## Your faithful employee, # +## monit # +## --8<-- +## +## You can override the alert message format or its parts such as subject +## or sender using the MAIL-FORMAT statement. Macros such as $DATE, etc. +## are expanded on runtime. For example to override the sender: +# +# set mail-format { from: monit@foo.bar } +# +# +## You can set the alert recipients here, which will receive the alert for +## each service. The event alerts may be restricted using the list. +# +# set alert sysadm@foo.bar # receive all alerts +# set alert manager@foo.bar only on { timeout } # receive just service- +# # timeout alert + +# excluding instance, changed +set alert <%= rubber_env.admin_email %> only on { + connection + checksum + data + exec + gid + icmp + invalid + nonexist + permission + resource + size + timeout + timestamp + uid +} + +# +# +## Monit has an embedded webserver, which can be used to view the +## configuration, actual services parameters or manage the services using the +## web interface. +# +# set httpd port 2812 and +# use address localhost # only accept connection from localhost +# allow localhost # allow localhost to connect to the server and +# allow admin:monit # require user 'admin' with password 'monit' +# + +<% + tools_server = rubber_instances.for_role('web_tools').first.internal_ip rescue "127.0.0.1" +%> +set httpd port <%= rubber_env.monit_admin_port %> + allow <%= tools_server %> + +# +############################################################################### +## Services +############################################################################### +## +## Check the general system resources such as load average, cpu and memory +## usage. Each rule specifies the tested resource, the limit and the action +## which will be performed in the case that the test failed. +# +# check system myhost.mydomain.tld +# if loadavg (1min) > 4 then alert +# if loadavg (5min) > 2 then alert +# if memory usage > 75% then alert +# if cpu usage (user) > 70% then alert +# if cpu usage (system) > 30% then alert +# if cpu usage (wait) > 20% then alert +# +# +## Check a file for existence, checksum, permissions, uid and gid. In addition +## to the recipients in the global section, customized alert will be send to +## the additional recipient. The service may be grouped using the GROUP option. +# +# check file apache_bin with path /usr/local/apache/bin/httpd +# if failed checksum and +# expect the sum 8f7f419955cefa0b33a2ba316cba3659 then unmonitor +# if failed permission 755 then unmonitor +# if failed uid root then unmonitor +# if failed gid root then unmonitor +# alert security@foo.bar on { +# checksum, permission, uid, gid, unmonitor +# } with the mail-format { subject: Alarm! } +# group server +# +# +## Check that a process is running, responding on the HTTP and HTTPS request, +## check its resource usage such as cpu and memory, number of childrens. +## In the case that the process is not running, monit will restart it by +## default. In the case that the service was restarted very often and the +## problem remains, it is possible to disable the monitoring using the +## TIMEOUT statement. The service depends on another service (apache_bin) which +## is defined in the monit control file as well. +# +# check process apache with pidfile /usr/local/apache/logs/httpd.pid +# start program = "/etc/init.d/httpd start" +# stop program = "/etc/init.d/httpd stop" +# if cpu > 60% for 2 cycles then alert +# if cpu > 80% for 5 cycles then restart +# if totalmem > 200.0 MB for 5 cycles then restart +# if children > 250 then restart +# if loadavg(5min) greater than 10 for 8 cycles then stop +# if failed host www.tildeslash.com port 80 protocol http +# and request "/monit/doc/next.php" +# then restart +# if failed port 443 type tcpssl protocol http +# with timeout 15 seconds +# then restart +# if 3 restarts within 5 cycles then timeout +# depends on apache_bin +# group server +# +# +## Check the device permissions, uid, gid, space and inode usage. Other +## services such as databases may depend on this resource and automatical +## graceful stop may be cascaded to them before the filesystem will become +## full and the data will be lost. +# +# check device datafs with path /dev/sdb1 +# start program = "/bin/mount /data" +# stop program = "/bin/umount /data" +# if failed permission 660 then unmonitor +# if failed uid root then unmonitor +# if failed gid disk then unmonitor +# if space usage > 80% for 5 times within 15 cycles then alert +# if space usage > 99% then stop +# if inode usage > 30000 then alert +# if inode usage > 99% then stop +# group server +# +# +## Check a file's timestamp: when it becomes older then 15 minutes, the +## file is not updated and something is wrong. In the case that the size +## of the file exceeded given limit, perform the script. +# +# check file database with path /data/mydatabase.db +# if failed permission 700 then alert +# if failed uid data then alert +# if failed gid data then alert +# if timestamp > 15 minutes then alert +# if size > 100 MB then exec "/my/cleanup/script" +# +# +## Check the directory permission, uid and gid. An event is triggered +## if the directory does not belong to the user with the uid 0 and +## the gid 0. In the addition the permissions have to match the octal +## description of 755 (see chmod(1)). +# +# check directory bin with path /bin +# if failed permission 755 then unmonitor +# if failed uid 0 then unmonitor +# if failed gid 0 then unmonitor +# +# +## Check the remote host network services availability and the response +## content. One of three pings, a successfull connection to a port and +## application level network check is performed. +# +# check host myserver with address 192.168.1.1 +# if failed icmp type echo count 3 with timeout 3 seconds then alert +# if failed port 3306 protocol mysql with timeout 15 seconds then alert +# if failed url +# http://user:password@www.foo.bar:8080/?querystring +# and content == 'action="j_security_check"' +# then alert +# +# +############################################################################### +## Includes +############################################################################### +## +## It is possible to include the configuration or its parts from other files or +## directories. +# +include /etc/monit/monit.d/*.conf +# +# + diff --git a/config/rubber/role/passenger/collectd-passenger.conf b/config/rubber/role/passenger/collectd-passenger.conf new file mode 100644 index 0000000..867d410 --- /dev/null +++ b/config/rubber/role/passenger/collectd-passenger.conf @@ -0,0 +1,7 @@ +<% + @path = "/etc/collectd/conf.d/passenger_info.conf" +%> + + + Exec nobody "/bin/bash" "-l" "-c" "/etc/collectd/plugins/passenger_info.rb" + diff --git a/config/rubber/role/passenger/collectd-passenger.rb.conf b/config/rubber/role/passenger/collectd-passenger.rb.conf new file mode 100644 index 0000000..f567d62 --- /dev/null +++ b/config/rubber/role/passenger/collectd-passenger.rb.conf @@ -0,0 +1,77 @@ +<% + @path = "/etc/collectd/plugins/passenger_info.rb" + @perms = 0755 +-%> +#!/usr/bin/env ruby + + +# Direct api access tricky to get working right with sudo, etc, so commenting out +# and shelling out to passenger provided scripts for now +# +# require 'phusion_passenger' +# require 'phusion_passenger/platform_info' +# require 'phusion_passenger/admin_tools/memory_stats' +# require 'phusion_passenger/admin_tools/server_instance' +# +# procs = PhusionPassenger::AdminTools::MemoryStats.new.passenger_processes +# total_rss = procs.inject(0) {|sum, val| sum + val.rss } +# puts "PUTVAL #{HOSTNAME}/passenger/gauge-total_rss interval=#{INTERVAL} N:#{total_rss}" +# +# server_instance = PhusionPassenger::AdminTools::ServerInstance.list.first +# server_instance.connect(:passenger_status) do +# stats = server_instance.stats +# puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_max interval=#{INTERVAL} N:#{stats.max}" +# puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_count interval=#{INTERVAL} N:#{stats.count}" +# puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_active interval=#{INTERVAL} N:#{stats.active}" +# +# sessions = server_instance.groups.collect {|group| group.processes.collect {|process| process.sessions } }.flatten +# total_sessions = sessions.inject(0) {|sum, val| sum + val } +# puts "PUTVAL #{HOSTNAME}/passenger/gauge-total_sessions interval=#{INTERVAL} N:#{total_sessions}" +# end + +STDOUT.sync = STDERR.sync = true +HOSTNAME = ENV["COLLECTD_HOSTNAME"] || `hostname -f`.chomp +INTERVAL = (ENV["COLLECTD_INTERVAL"] || 60).to_i + +loop do + start_time = Time.now.to_i + + status = `sudo <%= rubber_env.rvm_gem_home %>/bin/passenger-status` + unless $?.success? + $stderr.puts "failed executing passenger-status" + exit 1 + end + + if status =~ /max\s+=\s+(\d+)/ + puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_max interval=#{INTERVAL} N:#{$1}" + end + + if status =~ /count\s+=\s+(\d+)/ + puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_count interval=#{INTERVAL} N:#{$1}" + end + + if status =~ /active\s+=\s+(\d+)/ + puts "PUTVAL #{HOSTNAME}/passenger/gauge-instances_active interval=#{INTERVAL} N:#{$1}" + end + + total_sessions = 0 + status.scan(/Sessions: (\d+)/).flatten.each { |count| total_sessions += count.to_i } + puts "PUTVAL #{HOSTNAME}/passenger/gauge-total_sessions interval=#{INTERVAL} N:#{total_sessions}" + + + status = `sudo <%= rubber_env.rvm_gem_home %>/bin/passenger-memory-stats | tail -1` + unless $?.success? + $stderr.puts "failed executing passenger-memory-stats" + exit 1 + end + + if status =~ /(\d+\.\d+)/ + puts "PUTVAL #{HOSTNAME}/passenger/gauge-total_rss interval=#{INTERVAL} N:#{$1}" + end + + run_time = Time.now.to_i - start_time + sleep_time = INTERVAL - run_time + sleep_time = INTERVAL if sleep_time < 0 + + sleep sleep_time +end diff --git a/config/rubber/role/passenger/passenger-apache-vhost.conf b/config/rubber/role/passenger/passenger-apache-vhost.conf new file mode 100644 index 0000000..0d72a80 --- /dev/null +++ b/config/rubber/role/passenger/passenger-apache-vhost.conf @@ -0,0 +1,90 @@ +<% + @path = "/etc/apache2/sites-available/#{rubber_env.app_name}-passenger" + @post = "a2enmod rewrite && a2enmod ssl && a2enmod expires && a2enmod xsendfile && a2ensite #{rubber_env.app_name}-passenger" +%> + +<% [rubber_env.passenger_listen_port, rubber_env.passenger_listen_ssl_port].each do |port| %> + +Listen <%= port %> +> + ServerName <%= rubber_env.domain %> +<%- if rubber_env.web_aliases -%> + ServerAlias <%= rubber_env.web_aliases.join(" ") %> +<%- end -%> + DocumentRoot <%= Rubber.root + "/public" %> + + ErrorDocument 404 /404.html + ErrorDocument 500 /500.html + + SetEnvIf User-Agent "^(.*MSIE.*)|(.*AppleWebKit.*)$" nokeepalive + + # Don't show haproxy checks in access log (see also apache2.conf) + SetEnvIf Request_URI "^/httpchk.txt$" dontlog + + RailsEnv <%= Rubber.env %> + + XSendFile on + + RewriteEngine On + RewriteCond %{HTTP_HOST} ^<%= rubber_env.domain %>$ + RewriteRule ^(.*)$ http://www.<%= rubber_env.domain %>$1 [R,L] + + # Include <%= Rubber.root %>/config/apache/rewrites.conf + + RewriteCond %{DOCUMENT_ROOT}/system/maintenance.html -f + RewriteCond %{SCRIPT_FILENAME} !maintenance.html + RewriteRule ^.*$ /system/maintenance.html [L] + + <% if Rubber::Util.has_asset_pipeline? %> + + Header unset ETag + FileETag None + + # RFC says only cache for 1 year. + ExpiresActive On + ExpiresDefault "access plus 1 year" + + # Cache the resource even if SSL is in use. + Header merge Cache-Control public + + SetEnv no-gzip + + + # Serve the gzip'd assets directly from disk if they were generated by Sprockets. + # This avoids gzipping the asset on the fly by Apache and Sprockets will usually use a higher level + # of compression than mod_deflate will, yielding savings all around. + + RewriteCond %{HTTP:Accept-Encoding} \b(x-)?gzip\b + RewriteCond <%= Rubber.root + "/public" %>%{REQUEST_FILENAME}.gz -s + RewriteRule ^(.+) $1.gz [L] + + + ForceType text/css + Header set Content-Encoding gzip + + + + ForceType text/javascript + Header set Content-Encoding gzip + + <% end %> + + <% if port == rubber_env.passenger_listen_ssl_port %> + SSLEngine on + SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + # SSLCertificateFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.crt + # SSLCertificateKeyFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.key + # SSLCertificateChainFile /etc/ssl/certs/gd_intermediate_bundle.crt + + SSLHonorCipherOrder On + SSLCipherSuite ECDHE-RSA-AES256-SHA384:AES256-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH:!AESGCM + <% end %> + + + +<% end %> + +# The host here needs to match ServerName. +PassengerPreStart http://<%= rubber_env.domain %>:<%= rubber_env.passenger_listen_port %>/ diff --git a/config/rubber/role/passenger/passenger-status-sudoers.conf b/config/rubber/role/passenger/passenger-status-sudoers.conf new file mode 100644 index 0000000..b2b1477 --- /dev/null +++ b/config/rubber/role/passenger/passenger-status-sudoers.conf @@ -0,0 +1,8 @@ +<% + @path = '/etc/sudoers' + @additive = ["# passenger-status start", "# passenger-status end"] +%> +Defaults env_keep = GEM_PATH + +nobody ALL=(ALL) NOPASSWD: <%= rubber_env.rvm_gem_home %>/bin/passenger-status +nobody ALL=(ALL) NOPASSWD: <%= rubber_env.rvm_gem_home %>/bin/passenger-memory-stats diff --git a/config/rubber/role/passenger/passenger.conf b/config/rubber/role/passenger/passenger.conf new file mode 100644 index 0000000..ae68990 --- /dev/null +++ b/config/rubber/role/passenger/passenger.conf @@ -0,0 +1,45 @@ +<% + @path = '/etc/apache2/mods-available/passenger.conf' + @post = 'cd /etc/apache2/mods-enabled && ln -fs ../mods-available/passenger.conf' +%> +LoadModule passenger_module <%= rubber_env.passenger_lib %> +PassengerRoot <%= rubber_env.passenger_root %> +PassengerRuby <%= rubber_env.passenger_ruby %> +PassengerUseGlobalQueue on + +PassengerUserSwitching on +PassengerUser <%= rubber_env.app_user %> +PassengerGroup <%= rubber_env.app_user %> + +# max number of rails instances per appserver +PassengerMaxPoolSize <%= rubber_env.max_app_connections %> + +# min number of rails instances per appserver (by setting this as the max, we make sure we only wait for workers to spawn on the first request) +PassengerMinInstances <%= rubber_env.max_app_connections %> + +# Use PassengerMaxPoolSize for limit as we only have 1 app +PassengerMaxInstancesPerApp 0 + +# For performances sake, never shutdown rails instances when idle +PassengerPoolIdleTime 0 + +# For performances sake, never shutdown a rails instance after N requests +PassengerMaxRequests 0 + +# Passenger checks stuff like restart.txt on every request when this is 0 +PassengerStatThrottleRate <%= Rubber.env == 'production' ? '60' : '0' %> + +# Turning this on breaks mod_rewrite +PassengerHighPerformance off + +# Cache framework code per application +RailsSpawnMethod smart-lv2 + +# For performances sake, don't ever unload framework spawner +RailsFrameworkSpawnerIdleTime 0 + +# For performances sake, don't ever unload app spawner +RailsAppSpawnerIdleTime 0 + +# Don't show the friendly error pages in production because it could leak information the public shouldn't see. +PassengerFriendlyErrorPages <%= Rubber.env == 'production' ? 'off' : 'on' %> diff --git a/config/rubber/role/postgresql/collectd-postgresql.conf b/config/rubber/role/postgresql/collectd-postgresql.conf new file mode 100644 index 0000000..0e15ff8 --- /dev/null +++ b/config/rubber/role/postgresql/collectd-postgresql.conf @@ -0,0 +1,22 @@ +<% + @path = "/etc/collectd/conf.d/postgresql.conf" +%> + +LoadPlugin postgresql + + + + > + User "<%= rubber_env.db_user %>" + + # Predefined, see /usr/share/collectd/postgresql_default.conf + Query backends + Query transactions + Query queries + Query query_plans + Query table_states + Query disk_io + Query disk_usage + + + diff --git a/config/rubber/role/postgresql/crontab b/config/rubber/role/postgresql/crontab new file mode 100644 index 0000000..2d8e3fa --- /dev/null +++ b/config/rubber/role/postgresql/crontab @@ -0,0 +1,16 @@ +<% + @read_cmd = 'crontab -l' + @write_cmd = 'crontab -' + @additive = ["# rubber-postgresql-start", "# rubber-postgresql-end"] +%> + +<% + # Backup db every 3 hours to secondary db if available, else primary db + backup_db_host = rubber_instances.for_role('postgresql_slave').first rescue nil + backup_db_host ||= rubber_instances.for_role('postgresql_master').first + if backup_db_host.name == rubber_env.host +%> + +0 */3 * * * <%= Rubber.root %>/script/rubber cron --task util:backup_db --directory=/mnt/db_backups --dbuser=<%= rubber_env.db_user %> --dbpass=<%= rubber_env.db_pass %> --dbname=<%= rubber_env.db_name %> --dbhost=<%= backup_db_host.full_name %> + +<% end %> diff --git a/config/rubber/role/postgresql/monit-postgresql.conf b/config/rubber/role/postgresql/monit-postgresql.conf new file mode 100644 index 0000000..de09781 --- /dev/null +++ b/config/rubber/role/postgresql/monit-postgresql.conf @@ -0,0 +1,10 @@ +<% + @path = '/etc/monit/monit.d/monit-postgresql.conf' +%> + +check process postgresql with pidfile <%= rubber_env.postgresql_pid_file %> + group postgresql-<%= Rubber.env %> + start program = "<%= rubber_env.postgresql_ctl %> restart" + stop program = "<%= rubber_env.postgresql_ctl %> stop" + if failed host 127.0.0.1 port 5432 protocol pgsql then alert + if 5 restarts within 5 cycles then timeout diff --git a/config/rubber/role/postgresql/pg_hba.conf b/config/rubber/role/postgresql/pg_hba.conf new file mode 100644 index 0000000..462c75a --- /dev/null +++ b/config/rubber/role/postgresql/pg_hba.conf @@ -0,0 +1,98 @@ +<% + @path = "#{rubber_env.postgresql_conf_dir}/pg_hba.conf" +%> +# PostgreSQL Client Authentication Configuration File +# =================================================== +# +# Refer to the "Client Authentication" section in the PostgreSQL +# documentation for a complete description of this file. A short +# synopsis follows. +# +# This file controls: which hosts are allowed to connect, how clients +# are authenticated, which PostgreSQL user names they can use, which +# databases they can access. Records take one of these forms: +# +# local DATABASE USER METHOD [OPTIONS] +# host DATABASE USER ADDRESS METHOD [OPTIONS] +# hostssl DATABASE USER ADDRESS METHOD [OPTIONS] +# hostnossl DATABASE USER ADDRESS METHOD [OPTIONS] +# +# (The uppercase items must be replaced by actual values.) +# +# The first field is the connection type: "local" is a Unix-domain +# socket, "host" is either a plain or SSL-encrypted TCP/IP socket, +# "hostssl" is an SSL-encrypted TCP/IP socket, and "hostnossl" is a +# plain TCP/IP socket. +# +# DATABASE can be "all", "sameuser", "samerole", "replication", a +# database name, or a comma-separated list thereof. The "all" +# keyword does not match "replication". Access to replication +# must be enabled in a separate record (see example below). +# +# USER can be "all", a user name, a group name prefixed with "+", or a +# comma-separated list thereof. In both the DATABASE and USER fields +# you can also write a file name prefixed with "@" to include names +# from a separate file. +# +# ADDRESS specifies the set of hosts the record matches. It can be a +# host name, or it is made up of an IP address and a CIDR mask that is +# an integer (between 0 and 32 (IPv4) or 128 (IPv6) inclusive) that +# specifies the number of significant bits in the mask. A host name +# that starts with a dot (.) matches a suffix of the actual host name. +# Alternatively, you can write an IP address and netmask in separate +# columns to specify the set of hosts. Instead of a CIDR-address, you +# can write "samehost" to match any of the server's own IP addresses, +# or "samenet" to match any address in any subnet that the server is +# directly connected to. +# +# METHOD can be "trust", "reject", "md5", "password", "gss", "sspi", +# "krb5", "ident", "peer", "pam", "ldap", "radius" or "cert". Note that +# "password" sends passwords in clear text; "md5" is preferred since +# it sends encrypted passwords. +# +# OPTIONS are a set of options for the authentication in the format +# NAME=VALUE. The available options depend on the different +# authentication methods -- refer to the "Client Authentication" +# section in the documentation for a list of which options are +# available for which authentication methods. +# +# Database and user names containing spaces, commas, quotes and other +# special characters must be quoted. Quoting one of the keywords +# "all", "sameuser", "samerole" or "replication" makes the name lose +# its special character, and just match a database or username with +# that name. +# +# This file is read on server startup and when the postmaster receives +# a SIGHUP signal. If you edit the file on a running system, you have +# to SIGHUP the postmaster for the changes to take effect. You can +# use "pg_ctl reload" to do that. + +# Put your actual configuration here +# ---------------------------------- +# +# If you want to allow non-local connections, you need to add more +# "host" records. In that case you will also need to make PostgreSQL +# listen on a non-local interface via the listen_addresses +# configuration parameter, or via the -i or -h command line switches. + + + + +# DO NOT DISABLE! +# If you change this first entry you will need to make sure that the +# database superuser can access the database using some other method. +# Noninteractive access to all databases is required during automatic +# maintenance (custom daily cronjobs, replication, and similar tasks). +# +# Database administrative login by Unix domain socket +local all postgres ident + +# TYPE DATABASE USER CIDR-ADDRESS METHOD +<% + scheme = rubber_env.db_pass ? 'md5' : 'trust' +%> +local all <%= rubber_env.db_user %> <%= scheme %> +host all all 127.0.0.1/32 <%= scheme %> +host all all ::1/128 <%= scheme %> +host replication <%= rubber_env.db_replication_user %> 10.0.0.1/8 <%= scheme %> +host all <%= rubber_env.db_user %> 10.0.0.1/8 <%= scheme %> \ No newline at end of file diff --git a/config/rubber/role/postgresql/postgresql-sysctl.conf b/config/rubber/role/postgresql/postgresql-sysctl.conf new file mode 100644 index 0000000..a01d60d --- /dev/null +++ b/config/rubber/role/postgresql/postgresql-sysctl.conf @@ -0,0 +1,7 @@ +<% + @path = "/etc/sysctl.d/30-postgresql.conf" + @post = "service procps start" +%> +kernel.shmmax=1610612736 +kernel.shmall=393216 +kernel.sem=2500 320000 320 1280 diff --git a/config/rubber/role/postgresql/postgresql.conf b/config/rubber/role/postgresql/postgresql.conf new file mode 100644 index 0000000..b4fc4ac --- /dev/null +++ b/config/rubber/role/postgresql/postgresql.conf @@ -0,0 +1,574 @@ +<% + @path = "#{rubber_env.postgresql_conf_dir}/postgresql.conf" +%> +# ----------------------------- +# PostgreSQL configuration file +# ----------------------------- +# +# This file consists of lines of the form: +# +# name = value +# +# (The "=" is optional.) Whitespace may be used. Comments are introduced with +# "#" anywhere on a line. The complete list of parameter names and allowed +# values can be found in the PostgreSQL documentation. +# +# The commented-out settings shown in this file represent the default values. +# Re-commenting a setting is NOT sufficient to revert it to the default value; +# you need to reload the server. +# +# This file is read on server startup and when the server receives a SIGHUP +# signal. If you edit the file on a running system, you have to SIGHUP the +# server for the changes to take effect, or use "pg_ctl reload". Some +# parameters, which are marked below, require a server shutdown and restart to +# take effect. +# +# Any parameter can also be given as a command-line option to the server, e.g., +# "postgres -c log_connections=on". Some parameters can be changed at run time +# with the "SET" SQL command. +# +# Memory units: kB = kilobytes Time units: ms = milliseconds +# MB = megabytes s = seconds +# GB = gigabytes min = minutes +# h = hours +# d = days + + +#------------------------------------------------------------------------------ +# FILE LOCATIONS +#------------------------------------------------------------------------------ + +# The default values of these variables are driven from the -D command-line +# option or PGDATA environment variable, represented here as ConfigDir. + +data_directory = '<%= rubber_env.postgresql_data_dir %>' # use data in another directory + # (change requires restart) +hba_file = '<%= rubber_env.postgresql_conf_dir %>/pg_hba.conf' # host-based authentication file + # (change requires restart) +ident_file = '<%= rubber_env.postgresql_conf_dir %>/pg_ident.conf' # ident configuration file + # (change requires restart) + +# If external_pid_file is not explicitly set, no extra PID file is written. +external_pid_file = '<%= rubber_env.postgresql_pid_file %>' # write an extra PID file + # (change requires restart) + + +#------------------------------------------------------------------------------ +# CONNECTIONS AND AUTHENTICATION +#------------------------------------------------------------------------------ + +# - Connection Settings - + +listen_addresses = '*' # what IP address(es) to listen on; + # comma-separated list of addresses; + # defaults to 'localhost', '*' = all + # (change requires restart) +port = 5432 # (change requires restart) +max_connections = 100 # (change requires restart) +# Note: Increasing max_connections costs ~400 bytes of shared memory per +# connection slot, plus lock space (see max_locks_per_transaction). +#superuser_reserved_connections = 3 # (change requires restart) +unix_socket_directory = '/var/run/postgresql' # (change requires restart) +#unix_socket_group = '' # (change requires restart) +#unix_socket_permissions = 0777 # begin with 0 to use octal notation + # (change requires restart) +#bonjour = off # advertise server via Bonjour + # (change requires restart) +#bonjour_name = '' # defaults to the computer name + # (change requires restart) + +# - Security and Authentication - + +#authentication_timeout = 1min # 1s-600s +#ssl = off # (change requires restart) +#ssl_ciphers = 'ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH' # allowed SSL ciphers + # (change requires restart) +#ssl_renegotiation_limit = 512MB # amount of data between renegotiations +#password_encryption = on +#db_user_namespace = off + +# Kerberos and GSSAPI +#krb_server_keyfile = '' +#krb_srvname = 'postgres' # (Kerberos only) +#krb_caseins_users = off + +# - TCP Keepalives - +# see "man 7 tcp" for details + +#tcp_keepalives_idle = 0 # TCP_KEEPIDLE, in seconds; + # 0 selects the system default +#tcp_keepalives_interval = 0 # TCP_KEEPINTVL, in seconds; + # 0 selects the system default +#tcp_keepalives_count = 0 # TCP_KEEPCNT; + # 0 selects the system default + + +#------------------------------------------------------------------------------ +# RESOURCE USAGE (except WAL) +#------------------------------------------------------------------------------ + +# - Memory - + +shared_buffers = 384MB # min 128kB + # (change requires restart) +#temp_buffers = 8MB # min 800kB +#max_prepared_transactions = 0 # zero disables the feature + # (change requires restart) +# Note: Increasing max_prepared_transactions costs ~600 bytes of shared memory +# per transaction slot, plus lock space (see max_locks_per_transaction). +# It is not advisable to set max_prepared_transactions nonzero unless you +# actively intend to use prepared transactions. +#work_mem = 1MB # min 64kB +#maintenance_work_mem = 16MB # min 1MB +#max_stack_depth = 2MB # min 100kB + +# - Kernel Resource Usage - + +#max_files_per_process = 1000 # min 25 + # (change requires restart) +#shared_preload_libraries = '' # (change requires restart) + +# - Cost-Based Vacuum Delay - + +#vacuum_cost_delay = 0ms # 0-100 milliseconds +#vacuum_cost_page_hit = 1 # 0-10000 credits +#vacuum_cost_page_miss = 10 # 0-10000 credits +#vacuum_cost_page_dirty = 20 # 0-10000 credits +#vacuum_cost_limit = 200 # 1-10000 credits + +# - Background Writer - + +#bgwriter_delay = 200ms # 10-10000ms between rounds +#bgwriter_lru_maxpages = 100 # 0-1000 max buffers written/round +#bgwriter_lru_multiplier = 2.0 # 0-10.0 multipler on buffers scanned/round + +# - Asynchronous Behavior - + +#effective_io_concurrency = 1 # 1-1000. 0 disables prefetching + + +#------------------------------------------------------------------------------ +# WRITE AHEAD LOG +#------------------------------------------------------------------------------ + +# - Settings - + +wal_level = hot_standby # minimal, archive, or hot_standby + # (change requires restart) +#fsync = on # turns forced synchronization on or off +#synchronous_commit = on # synchronization level; on, off, or local +#wal_sync_method = fsync # the default is the first option + # supported by the operating system: + # open_datasync + # fdatasync (default on Linux) + # fsync + # fsync_writethrough + # open_sync +#full_page_writes = on # recover from partial page writes +#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers + # (change requires restart) +#wal_writer_delay = 200ms # 1-10000 milliseconds + +#commit_delay = 0 # range 0-100000, in microseconds +#commit_siblings = 5 # range 1-1000 + +# - Checkpoints - + +#checkpoint_segments = 3 # in logfile segments, min 1, 16MB each +#checkpoint_timeout = 5min # range 30s-1h +#checkpoint_completion_target = 0.5 # checkpoint target duration, 0.0 - 1.0 +#checkpoint_warning = 30s # 0 disables + +# - Archiving - + +#archive_mode = off # allows archiving to be done + # (change requires restart) +#archive_command = '' # command to use to archive a logfile segment +#archive_timeout = 0 # force a logfile segment switch after this + # number of seconds; 0 disables + +<%- if rubber_instances[rubber_env.host].role_names.include?('postgresql_master') %> +# - Streaming Replication - + +#------------------------------------------------------------------------------ +# REPLICATION +#------------------------------------------------------------------------------ + +# - Master Server - + +# These settings are ignored on a standby server + +max_wal_senders = 5 # max number of walsender processes + # (change requires restart) +#wal_sender_delay = 1s # walsender cycle time, 1-10000 milliseconds + +# To prevent the primary server from removing the WAL segments required for +# the standby server before shipping them, set the minimum number of segments +# retained in the pg_xlog directory. At least wal_keep_segments should be +# larger than the number of segments generated between the beginning of +# online-backup and the startup of streaming replication. If you enable WAL +# archiving to an archive directory accessible from the standby, this may +# not be necessary. +wal_keep_segments = 128 # in logfile segments, 16MB each; 0 disables +#vacuum_defer_cleanup_age = 0 # number of xacts by which cleanup is delayed +#replication_timeout = 60s # in milliseconds; 0 disables +#synchronous_standby_names = '' # standby servers that provide sync rep + # comma-separated list of application_name + # from standby(s); '*' = all + +<%- if rubber_env.postgresql_synchronous_replication %> +synchronous_standby_names = '<%= rubber_env.app_name %>' +<%- end %> + +<%- else %> +# - Standby Servers - + +# These settings are ignored on a master server + +hot_standby = on # "on" allows queries during recovery + # (change requires restart) +#max_standby_archive_delay = 30s # max delay before canceling queries + # when reading WAL from archive; + # -1 allows indefinite delay +max_standby_streaming_delay = 10min # max delay before canceling queries + # when reading streaming WAL; + # -1 allows indefinite delay +#wal_receiver_status_interval = 10s # send replies at least this often + # 0 disables +hot_standby_feedback = on # send info from standby to prevent + # query conflicts +<%- end %> + +#------------------------------------------------------------------------------ +# QUERY TUNING +#------------------------------------------------------------------------------ + +# - Planner Method Configuration - + +#enable_bitmapscan = on +#enable_hashagg = on +#enable_hashjoin = on +#enable_indexscan = on +#enable_material = on +#enable_mergejoin = on +#enable_nestloop = on +#enable_seqscan = on +#enable_sort = on +#enable_tidscan = on + +# - Planner Cost Constants - + +#seq_page_cost = 1.0 # measured on an arbitrary scale +#random_page_cost = 4.0 # same scale as above +#cpu_tuple_cost = 0.01 # same scale as above +#cpu_index_tuple_cost = 0.005 # same scale as above +#cpu_operator_cost = 0.0025 # same scale as above +#effective_cache_size = 128MB + +# - Genetic Query Optimizer - + +#geqo = on +#geqo_threshold = 12 +#geqo_effort = 5 # range 1-10 +#geqo_pool_size = 0 # selects default based on effort +#geqo_generations = 0 # selects default based on effort +#geqo_selection_bias = 2.0 # range 1.5-2.0 +#geqo_seed = 0.0 # range 0.0-1.0 + +# - Other Planner Options - + +#default_statistics_target = 100 # range 1-10000 +#constraint_exclusion = partition # on, off, or partition +#cursor_tuple_fraction = 0.1 # range 0.0-1.0 +#from_collapse_limit = 8 +#join_collapse_limit = 8 # 1 disables collapsing of explicit + # JOIN clauses + + +#------------------------------------------------------------------------------ +# ERROR REPORTING AND LOGGING +#------------------------------------------------------------------------------ + +# - Where to Log - + +#log_destination = 'stderr' # Valid values are combinations of + # stderr, csvlog, syslog, and eventlog, + # depending on platform. csvlog + # requires logging_collector to be on. + +# This is used when logging to stderr: +#logging_collector = off # Enable capturing of stderr and csvlog + # into log files. Required to be on for + # csvlogs. + # (change requires restart) + +# These are only used if logging_collector is on: +#log_directory = 'pg_log' # directory where log files are written, + # can be absolute or relative to PGDATA +#log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log' # log file name pattern, + # can include strftime() escapes +#log_file_mode = 0600 # creation mode for log files, + # begin with 0 to use octal notation +#log_truncate_on_rotation = off # If on, an existing log file with the + # same name as the new log file will be + # truncated rather than appended to. + # But such truncation only occurs on + # time-driven rotation, not on restarts + # or size-driven rotation. Default is + # off, meaning append to existing files + # in all cases. +#log_rotation_age = 1d # Automatic rotation of logfiles will + # happen after that time. 0 disables. +#log_rotation_size = 10MB # Automatic rotation of logfiles will + # happen after that much log output. + # 0 disables. + +# These are relevant when logging to syslog: +#syslog_facility = 'LOCAL0' +#syslog_ident = 'postgres' + +#silent_mode = off # Run server silently. + # DO NOT USE without syslog or + # logging_collector + # (change requires restart) + + +# - When to Log - + +#client_min_messages = notice # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # log + # notice + # warning + # error + +#log_min_messages = warning # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic + +#log_min_error_statement = error # values in order of decreasing detail: + # debug5 + # debug4 + # debug3 + # debug2 + # debug1 + # info + # notice + # warning + # error + # log + # fatal + # panic (effectively off) + +log_min_duration_statement = 200 # -1 is disabled, 0 logs all statements + # and their durations, > 0 logs only + # statements running at least this number + # of milliseconds + + +# - What to Log - + +#debug_print_parse = off +#debug_print_rewritten = off +#debug_print_plan = off +#debug_pretty_print = on +#log_checkpoints = off +#log_connections = off +#log_disconnections = off +#log_duration = off +#log_error_verbosity = default # terse, default, or verbose messages +#log_hostname = off +log_line_prefix = '%t ' # special values: + # %a = application name + # %u = user name + # %d = database name + # %r = remote host and port + # %h = remote host + # %p = process ID + # %t = timestamp without milliseconds + # %m = timestamp with milliseconds + # %i = command tag + # %e = SQL state + # %c = session ID + # %l = session line number + # %s = session start timestamp + # %v = virtual transaction ID + # %x = transaction ID (0 if none) + # %q = stop here in non-session + # processes + # %% = '%' + # e.g. '<%u%%%d> ' +#log_lock_waits = off # log lock waits >= deadlock_timeout +#log_statement = 'none' # none, ddl, mod, all +log_temp_files = 0 # log temporary files equal or larger + # than the specified size in kilobytes; + # -1 disables, 0 logs all temp files +#log_timezone = '(defaults to server environment setting)' + + +#------------------------------------------------------------------------------ +# RUNTIME STATISTICS +#------------------------------------------------------------------------------ + +# - Query/Index Statistics Collector - + +#track_activities = on +track_counts = on +#track_functions = none # none, pl, all +#track_activity_query_size = 1024 # (change requires restart) +#update_process_title = on +#stats_temp_directory = 'pg_stat_tmp' + + +# - Statistics Monitoring - + +#log_parser_stats = off +#log_planner_stats = off +#log_executor_stats = off +#log_statement_stats = off + + +#------------------------------------------------------------------------------ +# AUTOVACUUM PARAMETERS +#------------------------------------------------------------------------------ + +autovacuum = on # Enable autovacuum subprocess? 'on' + # requires track_counts to also be on. +#log_autovacuum_min_duration = -1 # -1 disables, 0 logs all actions and + # their durations, > 0 logs only + # actions running at least this number + # of milliseconds. +#autovacuum_max_workers = 3 # max number of autovacuum subprocesses + # (change requires restart) +#autovacuum_naptime = 1min # time between autovacuum runs +#autovacuum_vacuum_threshold = 50 # min number of row updates before + # vacuum +#autovacuum_analyze_threshold = 50 # min number of row updates before + # analyze +#autovacuum_vacuum_scale_factor = 0.2 # fraction of table size before vacuum +#autovacuum_analyze_scale_factor = 0.1 # fraction of table size before analyze +#autovacuum_freeze_max_age = 200000000 # maximum XID age before forced vacuum + # (change requires restart) +#autovacuum_vacuum_cost_delay = 20ms # default vacuum cost delay for + # autovacuum, in milliseconds; + # -1 means use vacuum_cost_delay +#autovacuum_vacuum_cost_limit = -1 # default vacuum cost limit for + # autovacuum, -1 means use + # vacuum_cost_limit + + +#------------------------------------------------------------------------------ +# CLIENT CONNECTION DEFAULTS +#------------------------------------------------------------------------------ + +# - Statement Behavior - + +#search_path = '"$user",public' # schema names +#default_tablespace = '' # a tablespace name, '' uses the default +#temp_tablespaces = '' # a list of tablespace names, '' uses + # only default tablespace +#check_function_bodies = on +#default_transaction_isolation = 'read committed' +#default_transaction_read_only = off +#default_transaction_deferrable = off +#session_replication_role = 'origin' +#statement_timeout = 0 # in milliseconds, 0 is disabled +#vacuum_freeze_min_age = 50000000 +#vacuum_freeze_table_age = 150000000 +#bytea_output = 'hex' # hex, escape +#xmlbinary = 'base64' +#xmloption = 'content' + +# - Locale and Formatting - + +datestyle = 'iso, mdy' +#intervalstyle = 'postgres' +#timezone = '(defaults to server environment setting)' +#timezone_abbreviations = 'Default' # Select the set of available time zone + # abbreviations. Currently, there are + # Default + # Australia + # India + # You can create your own file in + # share/timezonesets/. +#extra_float_digits = 0 # min -15, max 3 +#client_encoding = sql_ascii # actually, defaults to database + # encoding + +# These settings are initialized by initdb, but they can be changed. +lc_messages = 'en_US.UTF-8' # locale for system error message + # strings +lc_monetary = 'en_US.UTF-8' # locale for monetary formatting +lc_numeric = 'en_US.UTF-8' # locale for number formatting +lc_time = 'en_US.UTF-8' # locale for time formatting + +# default configuration for text search +default_text_search_config = 'pg_catalog.english' + +# - Other Defaults - + +#dynamic_library_path = '$libdir' +#local_preload_libraries = '' + + +#------------------------------------------------------------------------------ +# LOCK MANAGEMENT +#------------------------------------------------------------------------------ + +#deadlock_timeout = 1s +#max_locks_per_transaction = 64 # min 10 + # (change requires restart) +# Note: Each lock table slot uses ~270 bytes of shared memory, and there are +# max_locks_per_transaction * (max_connections + max_prepared_transactions) +# lock table slots. +#max_pred_locks_per_transaction = 64 # min 10 + # (change requires restart) + +#------------------------------------------------------------------------------ +# VERSION/PLATFORM COMPATIBILITY +#------------------------------------------------------------------------------ + +# - Previous PostgreSQL Versions - + +#array_nulls = on +#backslash_quote = safe_encoding # on, off, or safe_encoding +#default_with_oids = off +#escape_string_warning = on +#lo_compat_privileges = off +#quote_all_identifiers = off +#sql_inheritance = on +standard_conforming_strings = off +#synchronize_seqscans = on + +# - Other Platforms and Clients - + +#transform_null_equals = off + + +#------------------------------------------------------------------------------ +# ERROR HANDLING +#------------------------------------------------------------------------------ + +#exit_on_error = off # terminate session on any error? +#restart_after_crash = on # reinitialize after backend crash? + + +#------------------------------------------------------------------------------ +# CUSTOMIZED OPTIONS +#------------------------------------------------------------------------------ + +#custom_variable_classes = '' # list of custom variable class names \ No newline at end of file diff --git a/config/rubber/role/postgresql_slave/collectd-postgresql-threshold.conf b/config/rubber/role/postgresql_slave/collectd-postgresql-threshold.conf new file mode 100644 index 0000000..bc95250 --- /dev/null +++ b/config/rubber/role/postgresql_slave/collectd-postgresql-threshold.conf @@ -0,0 +1,23 @@ +<% + @path = '/etc/collectd/thresholds.d/postgresql_slave_thresholds.conf' +%> + + + + + + Instance "replication_receive_delay" + DataSource "value" + WarningMax 500000 + FailureMax 1000000 + + + + Instance "replication_replay_delay" + DataSource "value" + WarningMax 20000000 + FailureMax 30000000 + + + + diff --git a/config/rubber/role/postgresql_slave/recovery.conf b/config/rubber/role/postgresql_slave/recovery.conf new file mode 100644 index 0000000..a07fa31 --- /dev/null +++ b/config/rubber/role/postgresql_slave/recovery.conf @@ -0,0 +1,135 @@ +<%- + @path = "#{rubber_env.postgresql_data_dir}/recovery.conf" +%> +# ------------------------------- +# PostgreSQL recovery config file +# ------------------------------- +# +# Edit this file to provide the parameters that PostgreSQL needs to +# perform an archive recovery of a database, or to act as a replication +# standby. +# +# If "recovery.conf" is present in the PostgreSQL data directory, it is +# read on postmaster startup. After successful recovery, it is renamed +# to "recovery.done" to ensure that we do not accidentally re-enter +# archive recovery or standby mode. +# +# This file consists of lines of the form: +# +# name = value +# +# Comments are introduced with '#'. +# +# The complete list of option names and allowed values can be found +# in the PostgreSQL documentation. +# +#--------------------------------------------------------------------------- +# ARCHIVE RECOVERY PARAMETERS +#--------------------------------------------------------------------------- +# +# restore_command +# +# specifies the shell command that is executed to copy log files +# back from archival storage. The command string may contain %f, +# which is replaced by the name of the desired log file, and %p, +# which is replaced by the absolute path to copy the log file to. +# +# This parameter is *required* for an archive recovery, but optional +# for streaming replication. +# +# It is important that the command return nonzero exit status on failure. +# The command *will* be asked for log files that are not present in the +# archive; it must return nonzero when so asked. +# +# NOTE that the basename of %p will be different from %f; do not +# expect them to be interchangeable. +# +#restore_command = '' # e.g. 'cp /mnt/server/archivedir/%f %p' +# +# +# archive_cleanup_command +# +# specifies an optional shell command to execute at every restartpoint. +# This can be useful for cleaning up the archive of a standby server. +# +#archive_cleanup_command = '' +# +# recovery_end_command +# +# specifies an optional shell command to execute at completion of recovery. +# This can be useful for cleaning up after the restore_command. +# +#recovery_end_command = '' +# +#--------------------------------------------------------------------------- +# RECOVERY TARGET PARAMETERS +#--------------------------------------------------------------------------- +# +# By default, recovery will rollforward to the end of the WAL log. +# If you want to stop rollforward at a specific point, you +# must set a recovery target. +# +# You may set a recovery target either by transactionId, by name, +# or by timestamp. Recovery may either include or exclude the +# transaction(s) with the recovery target value (ie, stop either +# just after or just before the given target, respectively). +# +# +#recovery_target_name = '' # e.g. 'daily backup 2011-01-26' +# +#recovery_target_time = '' # e.g. '2004-07-14 22:39:00 EST' +# +#recovery_target_xid = '' +# +#recovery_target_inclusive = true +# +# +# If you want to recover into a timeline other than the "main line" shown in +# pg_control, specify the timeline number here, or write 'latest' to get +# the latest branch for which there's a history file. +# +#recovery_target_timeline = 'latest' +# +# +# If pause_at_recovery_target is enabled, recovery will pause when +# the recovery target is reached. The pause state will continue until +# pg_xlog_replay_resume() is called. This setting has no effect if +# hot standby is not enabled, or if no recovery target is set. +# +#pause_at_recovery_target = true +# +#--------------------------------------------------------------------------- +# STANDBY SERVER PARAMETERS +#--------------------------------------------------------------------------- +# +# standby_mode +# +# When standby_mode is enabled, the PostgreSQL server will work as a +# standby. It will continuously wait for the additional XLOG records, using +# restore_command and/or primary_conninfo. +# +standby_mode = on +# +# primary_conninfo +# +# If set, the PostgreSQL server will try to connect to the primary using this +# connection string and receive XLOG records continuously. +# +primary_conninfo = 'host=<%= rubber_instances.for_role('postgresql_master').first.name %> port=5432 user=<%= rubber_env.db_replication_user %> <%= rubber_env.db_replication_pass ? "password=#{rubber_env.db_replication_pass}" : "" %> application_name=<%= rubber_env.app_name %>' # e.g. 'host=localhost port=5432' +# +# +# By default, a standby server keeps restoring XLOG records from the +# primary indefinitely. If you want to stop the standby mode, finish recovery +# and open the system in read/write mode, specify path to a trigger file. +# The server will poll the trigger file path periodically and start as a +# primary server when it's found. +# +trigger_file = '<%= rubber_env.postgresql_data_dir %>/trigger_file' +# +#--------------------------------------------------------------------------- +# HOT STANDBY PARAMETERS +#--------------------------------------------------------------------------- +# +# Hot Standby related parameters are listed in postgresql.conf +# +#--------------------------------------------------------------------------- \ No newline at end of file diff --git a/config/rubber/role/web_tools/monit-admin-nginx.conf b/config/rubber/role/web_tools/monit-admin-nginx.conf new file mode 100644 index 0000000..92e188b --- /dev/null +++ b/config/rubber/role/web_tools/monit-admin-nginx.conf @@ -0,0 +1,11 @@ +<% + @path = "/etc/nginx/rubber/tools/monit.conf" +%> + +<% rubber_instances.each do |ic| %> + location /monit_<%= ic.name %> + { + rewrite ^/monit_<%= ic.name %>/(.*) /$1 break; + proxy_pass http://<%= ic.full_name %>:<%= rubber_env.monit_admin_port %>; + } +<% end %> diff --git a/config/rubber/role/web_tools/rubber-web-tools-monit.html b/config/rubber/role/web_tools/rubber-web-tools-monit.html new file mode 100644 index 0000000..e1cf959 --- /dev/null +++ b/config/rubber/role/web_tools/rubber-web-tools-monit.html @@ -0,0 +1,19 @@ +<% + @path = "/var/www/rubber-web-tools-monit.html" +%> + + + + + Rubber Monit Admin + + +

Rubber Monit Admin

+ + <% rubber_instances.sort {|a,b| a.name <=> b.name }.each do |ic| %> +
  • Monit <%= ic.name %>
  • + <% end %> + + + + diff --git a/config/rubber/role/web_tools/tools-apache-vhost.conf b/config/rubber/role/web_tools/tools-apache-vhost.conf new file mode 100644 index 0000000..f3a6c43 --- /dev/null +++ b/config/rubber/role/web_tools/tools-apache-vhost.conf @@ -0,0 +1,122 @@ +<% + @path = "/etc/apache2/sites-available/#{rubber_env.app_name}-tools" + @post = <<-EOS + a2enmod rewrite + a2enmod ssl + a2enmod proxy_http + a2enmod proxy_html + a2enmod ext_filter + a2ensite #{rubber_env.app_name}-tools + EOS +%> + +Listen <%= rubber_env.web_tools_port %> +> + ServerName <%= rubber_env.full_host %> + + RewriteEngine on + RewriteCond %{HTTPS} !=on + RewriteRule ^/(.*)$ https://%{SERVER_NAME}:<%= rubber_env.web_tools_ssl_port %>/$1 [L,R] + RewriteLog "/var/log/apache2/rewrite.log" + + +Listen <%= rubber_env.web_tools_ssl_port %> +NameVirtualHost *:<%= rubber_env.web_tools_ssl_port %> + +> + ServerName <%= rubber_env.full_host %> + DocumentRoot /var/www + + SSLEngine on + SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + # SSLCertificateFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.crt + # SSLCertificateKeyFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.key + # SSLCertificateChainFile /etc/ssl/certs/gd_intermediate_bundle.crt + + RequestHeader set X_FORWARDED_PROTO "https" + + + AuthType Basic + AuthName "Rubber Admin Tools" + AuthUserFile <%= Rubber.root %>/config/<%= rubber_env.app_name %>.auth + Require valid-user + + Allow from all + + + SetOutputFilter proxy-html + + <% rubber_instances.for_role('haproxy').each do |ic| %> + ProxyPass /haproxy_<%= ic.name %>/ http://<%= ic.full_name %>:<%= rubber_env.haproxy_admin_port %>/haproxy/ + /> + ProxyPassReverse / + ProxyHTMLURLMap http://<%= ic.full_name %>:<%= rubber_env.haproxy_admin_port %>/ /haproxy_<%= ic.name %>/ + ProxyHTMLURLMap /haproxy/ /haproxy_<%= ic.name %>/ + ProxyHTMLURLMap /haproxy /haproxy_<%= ic.name %>/ + + <% end %> + + <% rubber_instances.each do |ic| %> + ProxyPass /monit_<%= ic.name %>/ http://<%= ic.full_name %>:<%= rubber_env.monit_admin_port %>/ + /> + ProxyPassReverse / + ProxyHTMLURLMap http://<%= ic.full_name %>:<%= rubber_env.monit_admin_port %>/ /monit_<%= ic.name %>/ + ProxyHTMLURLMap / /monit_<%= ic.name %>/ + + <% end %> + + + +<% + Array(rubber_env.web_tools_proxies).each do |name, settings| + proxy_host = rubber_instances.for_role(settings.role).first.full_name rescue nil + next unless proxy_host + + host = "#{name}.#{rubber_env.full_host}" + host_and_port = "#{host}:#{rubber_env.web_tools_ssl_port}" + + # don't use settings.path here - mapping the host/port is sufficient, + # and path can be done in tools-index.html. This allows admin sites + # that hit other paths on same host/port to still function, e.g. elasticsearch + proxy_url = "http://#{proxy_host}:#{settings.port}/" +%> + > + ServerName <%= host %> + DocumentRoot /var/www + + SSLEngine on + SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + + SSLEngine on + SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire + SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem + SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key + # SSLCertificateFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.crt + # SSLCertificateKeyFile <%= Rubber.root %>/config/<%= rubber_env.domain %>.key + # SSLCertificateChainFile /etc/ssl/certs/gd_intermediate_bundle.crt + + RequestHeader set X_FORWARDED_PROTO "https" + + + AuthType Basic + AuthName "Rubber Admin Tools" + AuthUserFile <%= Rubber.root %>/config/<%= rubber_env.app_name %>.auth + Require valid-user + + Allow from all + + + ProxyRequests Off + ProxyPreserveHost On + + ProxyPass / <%= proxy_url %> + + ProxyPassReverse / + + + # Fix any redirects occurring on the backend server, since we're communicating with it via HTTP. + Header edit Location ^http://<%= host_and_port %>/ https://<%= host_and_port %>/ + +<% end %> diff --git a/config/rubber/role/web_tools/tools-apache.auth b/config/rubber/role/web_tools/tools-apache.auth new file mode 100644 index 0000000..febb295 --- /dev/null +++ b/config/rubber/role/web_tools/tools-apache.auth @@ -0,0 +1,7 @@ +<% + @path = "#{Rubber.root}/config/#{rubber_env.app_name}.auth" + user = rubber_env.web_tools_user || 'admin' + pass = rubber_env.web_tools_password || rand(1000000000).to_s +%> + +<%= `htpasswd -nb #{user} #{pass}` %> diff --git a/config/rubber/role/web_tools/tools-index.html b/config/rubber/role/web_tools/tools-index.html new file mode 100644 index 0000000..1883555 --- /dev/null +++ b/config/rubber/role/web_tools/tools-index.html @@ -0,0 +1,38 @@ +<% + @path = "/var/www/index.html" + tools_host = rubber_instances.for_role('web_tools').first +%> + + + + + Rubber Admin Tools + + +

    Rubber Admin Tools

    +
      + + <% + tools_html_path = "/var/www" + tools_html_prefix = "#{tools_html_path}/rubber-web-tools-" + Dir["#{tools_html_prefix}*.html"].each do |tools_file| + tool_path = tools_file.gsub(tools_html_path, '') + tool_name = tools_file.gsub(tools_html_prefix, '').split('.').first + tool_name = tool_name.capitalize + %> +
    • <%= tool_name %>
    • + <% end %> + + <% + # add the ip aliases for web tools hosts so we can map internal tools + # to their own vhost to make proxying easier (rewriting url paths for + # proxy is a real pain, e.g. '/graphite/' externally to '/' on the + # graphite web app) + Array(rubber_env.web_tools_proxies).each do |name, settings| + %> +
    • <%= name.capitalize %>
    • + <% end %> + +
    + + diff --git a/config/rubber/rubber-apache.yml b/config/rubber/rubber-apache.yml new file mode 100644 index 0000000..066e838 --- /dev/null +++ b/config/rubber/rubber-apache.yml @@ -0,0 +1,6 @@ + +roles: + apache: + packages: [apache2] + web_tools: + packages: [libapache2-mod-proxy-html] diff --git a/config/rubber/rubber-collectd.yml b/config/rubber/rubber-collectd.yml new file mode 100644 index 0000000..b80e50d --- /dev/null +++ b/config/rubber/rubber-collectd.yml @@ -0,0 +1,11 @@ + +rubber_collectd_runner: "script/collectd/collectd-runner.rb" +collectd_graphite_plugin_version: 6107730c56b4ede27631 +collectd_syslog: daemon + +roles: + collectd: + packages: [collectd] + +role_dependencies: + common: [collectd] diff --git a/config/rubber/rubber-dns.yml b/config/rubber/rubber-dns.yml new file mode 100644 index 0000000..a52edc0 --- /dev/null +++ b/config/rubber/rubber-dns.yml @@ -0,0 +1,7 @@ +dns_provider: zerigo +dns_records: + - host: doyle + domain: iswhatcddown.com + data: + hosted_zone_id: Z3DZXE0Q79N41H + dns_name: DoyleLoadBalancer-1643562339.us-east-1.elb.amazonaws.com diff --git a/config/rubber/rubber-graphite.yml b/config/rubber/rubber-graphite.yml new file mode 100644 index 0000000..bdc0dc7 --- /dev/null +++ b/config/rubber/rubber-graphite.yml @@ -0,0 +1,22 @@ +graphite_dir: "/opt/graphite" +graphite_server_pid_file: /var/run/graphite-server.pid +graphite_server_port: 2003 +graphite_web_port: 2080 + +# uncomment out the repo version to install from given repo version +# graphite_repo_version: 426 +graphite_whisper_package_url: http://launchpad.net/graphite/0.9/0.9.9/+download/whisper-0.9.9.tar.gz +graphite_carbon_package_url: http://launchpad.net/graphite/0.9/0.9.9/+download/carbon-0.9.9.tar.gz +graphite_web_package_url: http://launchpad.net/graphite/0.9/0.9.9/+download/graphite-web-0.9.9.tar.gz + +web_tools_proxies: + graphite: + role: graphite_web + port: "#{graphite_web_port}" + path: / + +roles: + graphite_web: + packages: [python-django, python-django-tagging, apache2, libapache2-mod-wsgi, python-cairo, python-memcache, memcached, sqlite3, bzr, zip] + collectd: + packages: [libperl-dev] diff --git a/config/rubber/rubber-monit.yml b/config/rubber/rubber-monit.yml new file mode 100644 index 0000000..7e0c404 --- /dev/null +++ b/config/rubber/rubber-monit.yml @@ -0,0 +1,11 @@ +# Uses admin_email from base + +monit_admin_port: 2812 + +role_dependencies: + common: [monit] + +roles: + monit: + packages: [monit] + diff --git a/config/rubber/rubber-passenger.yml b/config/rubber/rubber-passenger.yml new file mode 100644 index 0000000..a24ce1b --- /dev/null +++ b/config/rubber/rubber-passenger.yml @@ -0,0 +1,16 @@ +passenger_version: 3.0.12 +passenger_root: "#{rvm_gem_home}/gems/passenger-#{passenger_version}" +passenger_ruby: "#{rvm_prefix}/wrappers/#{`bash -l -c 'rvm strings #{rvm_ruby}'`.strip}/ruby" +passenger_lib: "#{passenger_root}/ext/apache2/mod_passenger.so" +passenger_listen_port: 7000 +passenger_listen_ssl_port: 7001 +max_app_connections: 20 + +role_dependencies: + passenger: [apache] + +roles: + passenger: + packages: [apache2-mpm-prefork, apache2-prefork-dev, libcurl4-openssl-dev, libapache2-mod-xsendfile] + gems: [fastthread, rack, [passenger, "#{passenger_version}"]] + diff --git a/config/rubber/rubber-postgresql.yml b/config/rubber/rubber-postgresql.yml new file mode 100644 index 0000000..a0a724f --- /dev/null +++ b/config/rubber/rubber-postgresql.yml @@ -0,0 +1,45 @@ +# REQUIRED: The credentials for creating/accessing your app's database +# +db_user: "#{app_name[0,16]}" +db_pass: +db_name: "#{app_name}_#{Rubber.env}" + +db_replication_user: replication +db_replication_pass: +postgresql_synchronous_replication: false + +# REQUIRED: The command to use to do a full backup of your database using +# "rubber util:backup_db" +db_backup_cmd: "set -e -o pipefail; nice sudo -u postgres pg_dumpall -U postgres | gzip -c > %backup_file%" + +# REQUIRED: The command to use to restore the database using +# "rake util:restore_db" +# This command will receive the data generated by db_backup_cmd via +# its standard input +db_restore_cmd: "zcat - | psql -U %user% -h %host% %name%" + +postgresql_ver: 9.1 +postgresql_conf_dir: "/etc/postgresql/#{postgresql_ver}/main" +postgresql_data_dir: "/mnt/postgresql/#{postgresql_ver}/data" +postgresql_archive_dir: "/mnt/postgresql/#{postgresql_ver}/archive" +postgresql_pid_file: "/var/run/postgresql/#{postgresql_ver}-main.pid" +postgresql_ctl: "/usr/bin/env service postgresql" + +# Capistrano needs db:primary role for migrate to work, +# so we might as well just make consistent across the board +role_dependencies: + postgresql_master: [postgresql, "db:primary=true"] + postgresql_slave: [postgresql, db] + "db:primary=true": [postgresql, postgresql_master] + db: [postgresql, postgresql_slave] + +packages: [postgresql-client, libpq-dev] +gems: [pg] + +roles: + postgresql_master: + db_server_id: 1 + postgresql_slave: + db_server_id: 2 + db: + packages: ["postgresql-#{postgresql_ver}"] diff --git a/config/rubber/rubber-rvm.yml b/config/rubber/rubber-rvm.yml new file mode 100644 index 0000000..10aa82f --- /dev/null +++ b/config/rubber/rubber-rvm.yml @@ -0,0 +1,42 @@ +# rvm needs some extra packages to compile/install ruby runtimes +# curl is required. +# patch is required (for ree, some ruby head's). +# For JRuby (if you wish to use it) you will need: +# aptitude install curl sun-java6-bin sun-java6-jre sun-java6-jdk +# For MRI & ree (if you wish to use it) you will need: +# aptitude install curl bison build-essential zlib1g-dev libssl-dev libreadline5-dev libxml2-dev git-core +# For IronRuby (if you wish to use it) you will need: +# aptitude install curl mono-2.0-devel + +packages: [build-essential, git-core, subversion, curl, autoconf, bison, ruby, zlib1g-dev, libssl-dev, libreadline6-dev, libxml2-dev, libyaml-dev] + +# REQUIRED: the version of rvm itself +rvm_version: 1.13.0 + +# REQUIRED: Set to the rvm version string for the ruby version you wish to use +# Run "rvm list known" to see the list of possible options +rvm_ruby: 1.9.3-p194 + +# OPTIONAL: Extra args to pass to rvm when installing ruby +# rvm_install_options: "--patch falcon,debug --force-autoconf -j 3" + +# REQUIRED: Set to version of RubyGems you want RVM to install. Note that older RVMs do not +# know about newer RubyGems. So you may need to bump your rvm_version to get the latest RubyGems release. +rubygems_version: 1.8.23 + +# REQUIRED: Set to version of rake you want RVM to install. +rake_version: 0.9.2.2 + +# When rvm is installed as root, and you set the default, it symlinks ruby executables +# into /usr/local/rvm +ruby_prefix: /usr/local/rvm + +rvm_prefix: /usr/local/rvm + +# lets us setup global environment to use rvm (also needed when running sudo) +rvm_prepare: "source #{rvm_prefix}/scripts/rvm" + +# dirty hack to get the rvm gem home rather than bundler gem home +# When we run rubber:config it loads rails/bundler, which forces the bundler gem home, yet deployment only gems +# like passenger need to be installed in rvm gem home rather than bundler +rvm_gem_home: "#{$rubber_rvm_gem_home ||= `unset GEM_HOME; bash -l -c 'rvm gemdir'`.strip}" diff --git a/config/rubber/rubber.yml b/config/rubber/rubber.yml new file mode 100644 index 0000000..c39570f --- /dev/null +++ b/config/rubber/rubber.yml @@ -0,0 +1,34 @@ +app_name: doyle +app_user: app +admin_email: "karl@karlbright.org" +web_tools_user: admin +web_tools_password: captainDoyl3 +timezone: Australia/Perth +domain: iswhatcddown.com +rubber_secret: "#{File.expand_path('~') + '/.ec2' + (Rubber.env == 'production' ? '' : '_dev') + '/rubber-secret.yml' rescue ''}" + +cloud_providers: + aws: + region: us-east-1 + image_type: t1.micro + image_id: i-56eff72b +cloud_provider: aws + +security_groups: + default: + description: The default security group + rules: + - source_group_name: default + source_group_account: "#{cloud_providers.aws.account}" + - protocol: tcp + from_port: 22 + to_port: 22 + source_ips: [0.0.0.0/0] +assigned_security_groups: [default] +auto_security_groups: true +isolate_security_groups: false +prompt_for_security_group_sync: true + +packages: [postfix, build-essential, git-core, ec2-ami-tools, libxslt-dev, ntp] +gems: [open4, aws-s3, bundler, [rubber, "#{Rubber.version}"]] +stop_on_error_cmd: "function error_exit { exit 99; }; trap error_exit ERR"