diff --git a/data_bags/credentials/backup.json b/data_bags/credentials/backup.json new file mode 100644 index 0000000..1116f45 --- /dev/null +++ b/data_bags/credentials/backup.json @@ -0,0 +1,27 @@ +{ + "id": "backup", + "s3_access_key_id": { + "encrypted_data": "eql5TnKGVP2E8RrR0gbihdqGhY6RXC9C0S0Pxq5xi9ALE0qmngGLQVzCML7X\nEyrp\n", + "iv": "qm11KwrZq2+9ghDHv/yTlg==\n", + "version": 1, + "cipher": "aes-256-cbc" + }, + "s3_secret_access_key": { + "encrypted_data": "5Hz7lnRBayVHzNayKyBhgDbBaaR06+gyk+vZYE8bQ4HaP03DEMBaIxkP+OwF\nIDK4Gx9hum/451d7jNN67WmwVg==\n", + "iv": "nP7kmCUvEzETXGHVaks6lQ==\n", + "version": 1, + "cipher": "aes-256-cbc" + }, + "s3_region": { + "encrypted_data": "9APqZm2siyMYshNSYHeOVz2c1ytuuvRw2NjChi7fF0o=\n", + "iv": "XtF6SACoxNv6hgMlwutXPA==\n", + "version": 1, + "cipher": "aes-256-cbc" + }, + "encryption_password": { + "encrypted_data": "0pMCTMXwVeFssELjbrdUeiEfcffJlWR2yIHVq7QRJFtd6EC7imOUupZxKqfr\n3o95nkSo/PWuDpET93LMCXhYCw==\n", + "iv": "/PLTGJDt73Pjt0/2oHyjOw==\n", + "version": 1, + "cipher": "aes-256-cbc" + } +} \ No newline at end of file diff --git a/site-cookbooks/backup/README.rdoc b/site-cookbooks/backup/README.rdoc new file mode 100644 index 0000000..3de2ec7 --- /dev/null +++ b/site-cookbooks/backup/README.rdoc @@ -0,0 +1,8 @@ += DESCRIPTION: + += REQUIREMENTS: + += ATTRIBUTES: + += USAGE: + diff --git a/site-cookbooks/backup/attributes/default.rb b/site-cookbooks/backup/attributes/default.rb new file mode 100644 index 0000000..81b334d --- /dev/null +++ b/site-cookbooks/backup/attributes/default.rb @@ -0,0 +1,40 @@ +# Directory where backup config and models are stored +set_unless["backup"]["dir"] = "/usr/local/lib/backup" + +# Use default backup model? +set_unless["backup"]["default_model"] = true + +# Compression default settings +set_unless["backup"]["compression"]["best"] = true +set_unless["backup"]["compression"]["fast"] = false + +default['backup']['user'] = 'backup' + +# Archive default settings +set_unless["backup"]["archives"] = {} + +# MongoDB default settings +if node["mongodb"] + set_unless["backup"]["mongodb"]["databases"] = [] + set_unless["backup"]["mongodb"]["host"] = "localhost" + set_unless["backup"]["mongodb"]["ipv6"] = false + set_unless["backup"]["mongodb"]["lock"] = false +end + +# MySQL default settings +set_unless["backup"]["mysql"]["databases"] = [] +set_unless["backup"]["mysql"]["username"] = "root" +set_unless["backup"]["mysql"]["host"] = "localhost" + +# Redis default settings +set_unless["backup"]["redis"]["databases"] = [] +set_unless["backup"]["redis"]["host"] = "localhost" +set_unless["backup"]["redis"]["invoke_save"] = false +set_unless["backup"]["redis"]["dump_dir"] = "/var/lib/redis" + +default['backup']['orbit']['keep'] = 10 +default['backup']['cron']['hour'] = "05" +default['backup']['cron']['minute'] = "7" + +default['backup']['s3']['keep'] = 15 +default['backup']['s3']['bucket'] = "kosmos-dev-backups" diff --git a/site-cookbooks/backup/files/default/duplicity-exclude.conf b/site-cookbooks/backup/files/default/duplicity-exclude.conf new file mode 100644 index 0000000..e131ebc --- /dev/null +++ b/site-cookbooks/backup/files/default/duplicity-exclude.conf @@ -0,0 +1,14 @@ +- /dev +- /etc +- /home/backup +- /opt +- /proc +- /root +- /srv +- /sys +- /tmp +- /usr +- /var/cache +- /var/log +- /var/opt +- /var/www diff --git a/site-cookbooks/backup/metadata.rb b/site-cookbooks/backup/metadata.rb new file mode 100644 index 0000000..957763d --- /dev/null +++ b/site-cookbooks/backup/metadata.rb @@ -0,0 +1,9 @@ +maintainer 'Kosmos' +maintainer_email 'mail@kosmos.org' +license 'All rights reserved' +description "Installs/configures backup via the Backup gem" +long_description IO.read(File.join(File.dirname(__FILE__), 'README.rdoc')) +version "0.5.0" +name "backup" + +depends 'logrotate' diff --git a/site-cookbooks/backup/recipes/default.rb b/site-cookbooks/backup/recipes/default.rb new file mode 100644 index 0000000..482753f --- /dev/null +++ b/site-cookbooks/backup/recipes/default.rb @@ -0,0 +1,68 @@ +# +# Cookbook Name:: backup +# Recipe:: default +# +# Copyright 2012, Appcache Ltd / 5apps.com +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +gem_package 'backup' do + version '4.2.3' +end + +backup_data = Chef::EncryptedDataBagItem.load('credentials', 'backup') + +directory node["backup"]["dir"] +directory "#{node["backup"]["dir"]}/models" +directory "#{node["backup"]["dir"]}/log" + +template "#{node["backup"]["dir"]}/config.rb" do + source "config.rb.erb" + mode 0640 + sensitive true + variables s3_access_key_id: backup_data["s3_access_key_id"], + s3_secret_access_key: backup_data["s3_secret_access_key"], + s3_region: backup_data["s3_region"], + encryption_password: backup_data["encryption_password"], + mail_to: "ops@5apps.com", + mail_from: "backups@kosmos.org" +end + +if node["backup"]["default_model"] + template "#{node["backup"]["dir"]}/models/default.rb" do + source "backup.rb.erb" + mode 0640 + end + + cron "default backup model" do + hour node['backup']['cron']['hour'] + minute node['backup']['cron']['minute'] + command "/usr/bin/env HOME=/home/user PATH=/usr/local/bin:/usr/local/ruby/bin:/usr/bin:/bin:$PATH /bin/sh -l -c 'backup perform -t default --root-path #{node["backup"]["dir"]} >> /var/log/backup.log 2>&1'" + end + + include_recipe 'logrotate' + + logrotate_app 'backup' do + path '/var/log/backup.log' + frequency 'daily' + rotate 10 + create '640 root root' + end +end diff --git a/site-cookbooks/backup/templates/default/backup.rb.erb b/site-cookbooks/backup/templates/default/backup.rb.erb new file mode 100644 index 0000000..23ec04f --- /dev/null +++ b/site-cookbooks/backup/templates/default/backup.rb.erb @@ -0,0 +1,59 @@ +# encoding: utf-8 + +# +# Default +# +# $ backup perform -t default -c <%= node["backup"]["dir"] %> +# + +KosmosBackup.new(:default, 'default backup') do + +<%- if node["backup"]["mysql"] -%> +<%- node["backup"]["mysql"]["databases"].each do |db_name| -%> + database MySQL, :"<%= db_name.to_sym %>" do |db| + db.name = "<%= db_name %>" + end +<%- end -%> +<%- end -%> + +<%- if node["mongodb"] -%> +<%- node["backup"]["mongodb"]["databases"].each do |db_name| -%> + database MongoDB, :"<%= db_name.to_sym %>" do |db| + db.name = "<%= db_name %>" + end +<%- end -%> +<%- end -%> + +<%- node["backup"]["redis"]["databases"].each do |db_name| -%> + database Redis, :"<%= db_name.to_sym %>" do |db| + db.rdb_path = "/var/lib/redis/<%= db_name %>.rdb" + end +<%- end -%> + +<% if node["backup"]["archives"].length > 0 %> +<% node["backup"]["archives"].each do |key, items| %> + archive :<%= key %> do |archive| + <% items.each do |item| %> + Dir['<%= item %>'].each do |dir| + archive.add(dir) + end + <% end %> + archive.tar_options '-h --ignore-failed-read' + end +<% end %> +<% end %> + +store_with S3 do |s3| + s3.path = "/<%= node["hostname"] %>" + s3.keep = <%= node['backup']['s3']['keep'] %> +end + +compress_with Bzip2 + +encrypt_with OpenSSL + +notify_by Mail do |mail| + mail.on_success = false +end + +end diff --git a/site-cookbooks/backup/templates/default/config.rb.erb b/site-cookbooks/backup/templates/default/config.rb.erb new file mode 100644 index 0000000..6887e11 --- /dev/null +++ b/site-cookbooks/backup/templates/default/config.rb.erb @@ -0,0 +1,66 @@ +# encoding: utf-8 + +## +# Backup v4.x Configuration +# +# Documentation: http://backup.github.io/backup +# Issue Tracker: https://github.com/backup/backup/issues + +Storage::S3.defaults do |s3| + s3.access_key_id = "<%= @s3_access_key_id %>" + s3.secret_access_key = "<%= @s3_secret_access_key %>" + s3.region = "<%= @s3_region %>" + s3.bucket = "<%= node['backup']['s3']['bucket'] %>" +end + +Encryptor::OpenSSL.defaults do |encryption| + encryption.password = "<%= @encryption_password %>" + encryption.base64 = true + encryption.salt = true +end + +Notifier::Mail.defaults do |mail| + mail.from = "<%= node.name %> <<%= @mail_from %>>" + mail.to = "<%= @mail_to %>" + mail.delivery_method = :sendmail +end + +<%- if node["backup"]["mongodb"] -%> +Database::MongoDB.defaults do |db| + db.host = "<%= node["backup"]["mongodb"]["host"] %>" + db.ipv6 = <%= node["backup"]["mongodb"]["ipv6"] %> + db.lock = <%= node["backup"]["mongodb"]["lock"] %> + <% if node["mongodb"]["port"] -%> + db.port = <%= node["mongodb"]["port"] %> + <% end -%> +end +<%- end -%> + +<%- if node["backup"]["mysql"] -%> +Database::MySQL.defaults do |db| + db.host = "<%= node["backup"]["mysql"]["host"] %>" + db.username = "<%= node["backup"]["mysql"]["username"] %>" + db.password = "<%= node["backup"]["mysql"]["password"] %>" + db.additional_options = ['--quick', '--single-transaction'] +end +<%- end -%> + +Database::Redis.defaults do |db| + db.host = "<%= node["backup"]["redis"]["host"] %>" + db.port = 6379 + db.invoke_save = <%= node["backup"]["redis"]["invoke_save"] %> + <%# db.password = "my_password"%> + <%# db.socket = "/tmp/redis.sock"%> +end + +preconfigure 'KosmosBackup' do + split_into_chunks_of 250 # megabytes + store_with S3 + compress_with Bzip2 + encrypt_with OpenSSL + notify_by Mail do |mail| + mail.on_success = false + mail.on_warning = false + mail.on_failure = true + end +end diff --git a/site-cookbooks/kosmos-mediawiki/metadata.rb b/site-cookbooks/kosmos-mediawiki/metadata.rb index d2ec2b3..c25037b 100644 --- a/site-cookbooks/kosmos-mediawiki/metadata.rb +++ b/site-cookbooks/kosmos-mediawiki/metadata.rb @@ -9,3 +9,4 @@ version '0.1.0' depends "mediawiki" depends "firewall" depends "ark" +depends "backup" diff --git a/site-cookbooks/kosmos-mediawiki/recipes/default.rb b/site-cookbooks/kosmos-mediawiki/recipes/default.rb index 45982af..897eaab 100644 --- a/site-cookbooks/kosmos-mediawiki/recipes/default.rb +++ b/site-cookbooks/kosmos-mediawiki/recipes/default.rb @@ -152,3 +152,13 @@ $wgArticlePath = "/$1"; file.write_file end end + +node.override["backup"]["mysql"]["host"] = "localhost" +node.override["backup"]["mysql"]["username"] = "root" +node.override["backup"]["mysql"]["password"] = node["mediawiki"]["db"]["root_password"] +unless node["backup"]["mysql"]["databases"].include? 'mediawikidb' + node.override["backup"]["mysql"]["databases"] = + node["backup"]["mysql"]["databases"].to_a << "mediawikidb" +end + +include_recipe "backup" diff --git a/site-cookbooks/kosmos-wordpress/recipes/default.rb b/site-cookbooks/kosmos-wordpress/recipes/default.rb index 262df54..c03b946 100644 --- a/site-cookbooks/kosmos-wordpress/recipes/default.rb +++ b/site-cookbooks/kosmos-wordpress/recipes/default.rb @@ -26,3 +26,12 @@ node.set['wordpress']['salt']['logged_in'] = credentials["salt_logged_in" node.set['wordpress']['salt']['nonce'] = credentials["salt_nonce"] include_recipe 'kosmos-wordpress::nginx' + +node.override["backup"]["mysql"]["host"] = "localhost" +node.override["backup"]["mysql"]["username"] = "root" +node.override["backup"]["mysql"]["password"] = node["mediawiki"]["db"]["root_password"] +unless node["backup"]["mysql"]["databases"].include? "wordpressdb" + node.override["backup"]["mysql"]["databases"] = + node["backup"]["mysql"]["databases"].to_a << "wordpressdb" +end +include_recipe "backup"