darkofabijan-astrails-safe 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. data/LICENSE +20 -0
  2. data/README.markdown +237 -0
  3. data/Rakefile +61 -0
  4. data/bin/astrails-safe +53 -0
  5. data/examples/example_helper.rb +19 -0
  6. data/lib/astrails/safe.rb +61 -0
  7. data/lib/astrails/safe/archive.rb +24 -0
  8. data/lib/astrails/safe/backup.rb +20 -0
  9. data/lib/astrails/safe/cloudfiles.rb +70 -0
  10. data/lib/astrails/safe/config/builder.rb +60 -0
  11. data/lib/astrails/safe/config/node.rb +76 -0
  12. data/lib/astrails/safe/gpg.rb +46 -0
  13. data/lib/astrails/safe/gzip.rb +25 -0
  14. data/lib/astrails/safe/local.rb +70 -0
  15. data/lib/astrails/safe/mysqldump.rb +32 -0
  16. data/lib/astrails/safe/pgdump.rb +36 -0
  17. data/lib/astrails/safe/pipe.rb +17 -0
  18. data/lib/astrails/safe/s3.rb +86 -0
  19. data/lib/astrails/safe/sftp.rb +88 -0
  20. data/lib/astrails/safe/sink.rb +35 -0
  21. data/lib/astrails/safe/source.rb +47 -0
  22. data/lib/astrails/safe/stream.rb +20 -0
  23. data/lib/astrails/safe/svndump.rb +13 -0
  24. data/lib/astrails/safe/tmp_file.rb +48 -0
  25. data/lib/extensions/mktmpdir.rb +45 -0
  26. data/spec/integration/archive_integration_spec.rb +88 -0
  27. data/spec/integration/cleanup_spec.rb +61 -0
  28. data/spec/spec.opts +5 -0
  29. data/spec/spec_helper.rb +16 -0
  30. data/spec/unit/archive_spec.rb +67 -0
  31. data/spec/unit/cloudfiles_spec.rb +170 -0
  32. data/spec/unit/config_spec.rb +213 -0
  33. data/spec/unit/gpg_spec.rb +148 -0
  34. data/spec/unit/gzip_spec.rb +64 -0
  35. data/spec/unit/local_spec.rb +110 -0
  36. data/spec/unit/mysqldump_spec.rb +83 -0
  37. data/spec/unit/pgdump_spec.rb +45 -0
  38. data/spec/unit/s3_spec.rb +160 -0
  39. data/spec/unit/svndump_spec.rb +39 -0
  40. data/templates/script.rb +165 -0
  41. metadata +179 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 Astrails Ltd.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,237 @@
1
+ astrails-safe
2
+ =============
3
+
4
+ Simple database and filesystem backups with S3 and Rackspace Cloud Files support (with optional encryption)
5
+
6
+ * Home: [http://astrails.com/opensource/astrails-safe](http://astrails.com/opensource/astrails-safe)
7
+ * Code: [http://github.com/astrails/safe](http://github.com/astrails/safe)
8
+ * Blog: [http://blog.astrails.com/astrails-safe](http://blog.astrails.com/astrails-safe)
9
+
10
+
11
+ Motivation
12
+ ----------
13
+
14
+ We needed a backup solution that will satisfy the following requirements:
15
+
16
+ * opensource
17
+ * simple to install and configure
18
+ * support for simple ‘tar’ backups of directories (with includes/excludes)
19
+ * support for simple mysqldump of mysql databases
20
+ * support for symmetric or public key encryption
21
+ * support for local filesystem, Amazon S3, and Rackspace Cloud Files for storage
22
+ * support for backup rotation. we don’t want backups filling all the diskspace or cost a fortune on S3 or Cloud Files
23
+
24
+ And since we didn't find any, we wrote our own :)
25
+
26
+ Contributions
27
+ -------------
28
+
29
+ The following functionality was contributed by astrails-safe users:
30
+
31
+ * PostgreSQL dump using `pg_dump` (by Mark Mansour <mark@stateofflux.com>)
32
+ * Subversion dump using svndump (by Richard Luther <richard.luther@gmail.com>)
33
+ * SFTP remote storage (by Adam <adam@mediadrive.ca>)
34
+ * benchmarking output (By Neer)
35
+ * README fixes (by Bobby Wilson)
36
+ * improved config file parsing (by Fedor Kocherga <fkocherga@gmail.com>)
37
+ * mysql password file quoting (by Jonathan Sutherland <jonathan.sutherland@gmail.com>)
38
+ * Rackspace Cloud Files support (by H. Wade Minter <minter@lunenburg.org>)
39
+
40
+ Thanks to all :)
41
+
42
+ Installation
43
+ ------------
44
+
45
+ sudo gem install astrails-safe --source http://gemcutter.org
46
+
47
+ Reporting problems
48
+ ------------------
49
+
50
+ Please report problems at the [Issues tracker](http://github.com/astrails/safe/issues)
51
+
52
+ Usage
53
+ -----
54
+
55
+ Usage:
56
+ astrails-safe [OPTIONS] CONFIG_FILE
57
+ Options:
58
+ -h, --help This help screen
59
+ -v, --verbose be verbose, duh!
60
+ -n, --dry-run just pretend, don't do anything.
61
+ -L, --local skip remote storage, only do local backups
62
+
63
+ Note: CONFIG\_FILE will be created from template if missing
64
+
65
+ Encryption
66
+ ----------
67
+
68
+ If you want to encrypt your backups you have 2 options:
69
+ * use simple password encryption
70
+ * use GPG public key encryption
71
+
72
+ > IMPORTANT: some gpg installations automatically set 'use-agent' option in the default
73
+ > configuration file that is created when you run gpg for the first time. This will cause
74
+ > gpg to fail on the 2nd run if you don't have the agent running. The result is that
75
+ > 'astrails-safe' will work ONCE when you manually test it and then fail on any subsequent run.
76
+ > The solution is to remove the 'use-agent' from the config file (usually /root/.gnupg/gpg.conf)
77
+ > To mitigate this problem for the gpg 1.x series '--no-use-agent' option is added by defaults
78
+ > to the autogenerated config file, but for gpg2 is doesn't work. as the manpage says it:
79
+ > "This is dummy option. gpg2 always requires the agent." :(
80
+
81
+ For simple password, just add password entry in gpg section.
82
+ For public key encryption you will need to create a public/secret keypair.
83
+
84
+ We recommend to create your GPG keys only on your local machine and then
85
+ transfer your public key to the server that will do the backups.
86
+
87
+ This way the server will only know how to encrypt the backups but only you
88
+ will be able to decrypt them using the secret key you have locally. Of course
89
+ you MUST backup your backup encryption key :)
90
+ We recommend also pringing the hard paper copy of your GPG key 'just in case'.
91
+
92
+ The procedure to create and transfer the key is as follows:
93
+
94
+ 1. run 'gpg --gen-key' on your local machine and follow onscreen instructions to create the key
95
+ (you can accept all the defaults).
96
+
97
+ 2. extract your public key into a file (assuming you used test@example.com as your key email):
98
+ `gpg -a --export test@example.com > test@example.com.pub`
99
+
100
+ 3. transfer public key to the server
101
+ `scp test@example.com.pub root@example.com:`
102
+
103
+ 4. import public key on the remote system:
104
+
105
+ $ gpg --import test@example.com.pub
106
+ gpg: key 45CA9403: public key "Test Backup <test@example.com>" imported
107
+ gpg: Total number processed: 1
108
+ gpg: imported: 1
109
+
110
+ 5. since we don't keep the secret part of the key on the remote server, gpg has
111
+ no way to know its yours and can be trusted.
112
+ To fix that we can sign it with other trusted key, or just directly modify its
113
+ trust level in gpg (use level 5):
114
+
115
+ $ gpg --edit-key test@example.com
116
+ ...
117
+ Command> trust
118
+ ...
119
+ 1 = I don't know or won't say
120
+ 2 = I do NOT trust
121
+ 3 = I trust marginally
122
+ 4 = I trust fully
123
+ 5 = I trust ultimately
124
+ m = back to the main menu
125
+
126
+ Your decision? 5
127
+ ...
128
+ Command> quit
129
+
130
+ 6. export your secret key for backup
131
+ (we recommend to print it on paper and burn to a CD/DVD and store in a safe place):
132
+
133
+ $ gpg -a --export-secret-key test@example.com > test@example.com.key
134
+
135
+
136
+
137
+ Example configuration
138
+ ---------------------
139
+
140
+ safe do
141
+ local :path => "/backup/:kind/:id"
142
+
143
+ s3 do
144
+ key "...................."
145
+ secret "........................................"
146
+ bucket "backup.astrails.com"
147
+ path "servers/alpha/:kind/:id"
148
+ end
149
+
150
+ cloudfiles do
151
+ user "..........."
152
+ api_key "................................."
153
+ container "safe_backup"
154
+ path ":kind/" # this is default
155
+ service_net false
156
+ end
157
+
158
+ sftp do
159
+ host "sftp.astrails.com"
160
+ user "astrails"
161
+ # port 8023
162
+ password "ssh password for sftp"
163
+ end
164
+
165
+ gpg do
166
+ command "/usr/local/bin/gpg"
167
+ options "--no-use-agent"
168
+ # symmetric encryption key
169
+ # password "qwe"
170
+
171
+ # public GPG key (must be known to GPG, i.e. be on the keyring)
172
+ key "backup@astrails.com"
173
+ end
174
+
175
+ keep do
176
+ local 20
177
+ s3 100
178
+ cloudfiles 100
179
+ sftp 100
180
+ end
181
+
182
+ mysqldump do
183
+ options "-ceKq --single-transaction --create-options"
184
+
185
+ user "root"
186
+ password "............"
187
+ socket "/var/run/mysqld/mysqld.sock"
188
+
189
+ database :blog
190
+ database :servershape
191
+ database :astrails_com
192
+ database :secret_project_com do
193
+ skip_tables "foo"
194
+ skip_tables ["bar", "baz"]
195
+ end
196
+
197
+ end
198
+
199
+ svndump do
200
+ repo :my_repo do
201
+ repo_path "/home/svn/my_repo"
202
+ end
203
+ end
204
+
205
+ pgdump do
206
+ options "-i -x -O" # -i => ignore version, -x => do not dump privileges (grant/revoke), -O => skip restoration of object ownership in plain text format
207
+
208
+ user "username"
209
+ password "............" # shouldn't be used, instead setup ident. Current functionality exports a password env to the shell which pg_dump uses - untested!
210
+
211
+ database :blog
212
+ database :stateofflux_com
213
+ end
214
+
215
+ tar do
216
+ options "-h" # dereference symlinks
217
+ archive "git-repositories", :files => "/home/git/repositories"
218
+ archive "dot-configs", :files => "/home/*/.[^.]*"
219
+ archive "etc", :files => "/etc", :exclude => "/etc/puppet/other"
220
+
221
+ archive "blog-astrails-com" do
222
+ files "/var/www/blog.astrails.com/"
223
+ exclude "/var/www/blog.astrails.com/log"
224
+ exclude "/var/www/blog.astrails.com/tmp"
225
+ end
226
+
227
+ archive "astrails-com" do
228
+ files "/var/www/astrails.com/"
229
+ exclude ["/var/www/astrails.com/log", "/var/www/astrails.com/tmp"]
230
+ end
231
+ end
232
+ end
233
+
234
+ Copyright
235
+ ---------
236
+
237
+ Copyright (c) 2010 Astrails Ltd. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "astrails-safe"
8
+ gem.summary = %Q{Backup filesystem and databases (MySQL and PostgreSQL) locally or to a remote server/service (with encryption)}
9
+ gem.description = <<-DESC
10
+ Astrails-Safe is a simple tool to backup databases (MySQL and PostgreSQL), Subversion repositories (with svndump) and just files.
11
+ Backups can be stored locally or remotely and can be enctypted.
12
+ Remote storage is supported on Amazon S3, Rackspace Cloud Files, or just plain SFTP.
13
+ DESC
14
+ gem.email = "we@astrails.com"
15
+ gem.homepage = "http://blog.astrails.com/astrails-safe"
16
+ gem.authors = ["Astrails Ltd."]
17
+ gem.files = FileList["[A-Z]*.*", "{bin,examples,generators,lib,rails,spec,test,templates}/**/*", 'Rakefile', 'LICENSE*']
18
+
19
+ gem.add_dependency("aws-s3")
20
+ gem.add_dependency("cloudfiles")
21
+ gem.add_dependency("net-sftp")
22
+
23
+ gem.add_development_dependency "rspec"
24
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
25
+ end
26
+ rescue LoadError
27
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
28
+ end
29
+
30
+
31
+ require 'spec/rake/spectask'
32
+ Spec::Rake::SpecTask.new(:spec) do |spec|
33
+ spec.libs << 'lib' << 'spec'
34
+ spec.spec_opts = ['--options', "\"spec/spec.opts\""]
35
+ spec.spec_files = FileList['spec/**/*_spec.rb']
36
+ end
37
+
38
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
39
+ spec.libs << 'lib' << 'spec'
40
+ spec.pattern = 'spec/**/*_spec.rb'
41
+ spec.rcov = true
42
+ end
43
+
44
+ task :spec => :check_dependencies
45
+
46
+ task :default => :spec
47
+
48
+ require 'rake/rdoctask'
49
+ Rake::RDocTask.new do |rdoc|
50
+ if File.exist?('VERSION')
51
+ version = File.read('VERSION')
52
+ else
53
+ version = ""
54
+ end
55
+
56
+ rdoc.rdoc_dir = 'rdoc'
57
+ rdoc.title = "safe #{version}"
58
+ rdoc.rdoc_files.include('README*')
59
+ rdoc.rdoc_files.include('lib/**/*.rb')
60
+ end
61
+
data/bin/astrails-safe ADDED
@@ -0,0 +1,53 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rubygems'
4
+
5
+ require 'ruby-debug'
6
+ $:.unshift File.expand_path("../../lib", __FILE__)
7
+
8
+ require 'astrails/safe'
9
+ include Astrails::Safe
10
+
11
+ def die(msg)
12
+ puts "ERROR: #{msg}"
13
+ exit 1
14
+ end
15
+
16
+ def usage
17
+ puts <<-END
18
+ Usage: astrails-safe [OPTIONS] CONFIG_FILE
19
+ Options:
20
+ -h, --help This help screen
21
+ -v, --verbose be verbose, duh!
22
+ -n, --dry-run just pretend, don't do anything.
23
+ -L, --local skip S3 and Cloud Files
24
+
25
+ Note: config file will be created from template if missing
26
+ END
27
+ exit 1
28
+ end
29
+
30
+ def process_options
31
+ usage if ARGV.delete("-h") || ARGV.delete("--help")
32
+ $_VERBOSE = ARGV.delete("-v") || ARGV.delete("--verbose")
33
+ $DRY_RUN = ARGV.delete("-n") || ARGV.delete("--dry-run")
34
+ $LOCAL = ARGV.delete("-L") || ARGV.delete("--local")
35
+ usage unless ARGV.first
36
+ $CONFIG_FILE_NAME = File.expand_path(ARGV.first)
37
+ end
38
+
39
+ def main
40
+ process_options
41
+
42
+ unless File.exists?($CONFIG_FILE_NAME)
43
+ die "Missing configuration file. NOT CREATED! Rerun w/o the -n argument to create a template configuration file." if $DRY_RUN
44
+
45
+ FileUtils.cp File.join(Astrails::Safe::ROOT, "templates", "script.rb"), $CONFIG_FILE_NAME
46
+
47
+ die "Created default #{$CONFIG_FILE_NAME}. Please edit and run again."
48
+ end
49
+
50
+ load($CONFIG_FILE_NAME)
51
+ end
52
+
53
+ main
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'micronaut'
3
+ require 'ruby-debug'
4
+
5
+ SAFE_ROOT = File.dirname(File.dirname(__FILE__))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ $LOAD_PATH.unshift(File.join(SAFE_ROOT, 'lib'))
8
+
9
+ require 'astrails/safe'
10
+
11
+ def not_in_editor?
12
+ !(ENV.has_key?('TM_MODE') || ENV.has_key?('EMACS') || ENV.has_key?('VIM'))
13
+ end
14
+
15
+ Micronaut.configure do |c|
16
+ c.color_enabled = not_in_editor?
17
+ c.filter_run :focused => true
18
+ c.mock_with :rr
19
+ end
@@ -0,0 +1,61 @@
1
+ require "aws/s3"
2
+ require "cloudfiles"
3
+ require 'net/sftp'
4
+ require 'fileutils'
5
+ require 'benchmark'
6
+
7
+ require 'tempfile'
8
+ require 'extensions/mktmpdir'
9
+
10
+ require 'astrails/safe/tmp_file'
11
+
12
+ require 'astrails/safe/config/node'
13
+ require 'astrails/safe/config/builder'
14
+
15
+ require 'astrails/safe/stream'
16
+
17
+ require 'astrails/safe/backup'
18
+
19
+ require 'astrails/safe/source'
20
+ require 'astrails/safe/mysqldump'
21
+ require 'astrails/safe/pgdump'
22
+ require 'astrails/safe/archive'
23
+ require 'astrails/safe/svndump'
24
+
25
+ require 'astrails/safe/pipe'
26
+ require 'astrails/safe/gpg'
27
+ require 'astrails/safe/gzip'
28
+ require 'astrails/safe/page'
29
+
30
+ require 'astrails/safe/sink'
31
+ require 'astrails/safe/local'
32
+ require 'astrails/safe/s3'
33
+ require 'astrails/safe/cloudfiles'
34
+ require 'astrails/safe/sftp'
35
+
36
+ module Astrails
37
+ module Safe
38
+ ROOT = File.join(File.dirname(__FILE__), "..", "..")
39
+
40
+ def safe(&block)
41
+ config = Config::Node.new(&block)
42
+ #config.dump
43
+
44
+
45
+ [[Mysqldump, [:mysqldump, :databases]],
46
+ [Pgdump, [:pgdump, :databases]],
47
+ [Archive, [:tar, :archives]],
48
+ [Svndump, [:svndump, :repos]]
49
+ ].each do |klass, path|
50
+ if collection = config[*path]
51
+ collection.each do |name, config|
52
+ klass.new(name, config).backup.run(config, :gpg, :page, :gzip, :local, :s3, :cloudfiles, :sftp)
53
+ end
54
+ end
55
+ end
56
+
57
+ Astrails::Safe::TmpFile.cleanup
58
+ end
59
+ module_function :safe
60
+ end
61
+ end