pureftpdinator 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ require 'capistrano/setup'
2
+
3
+ load 'pureftpdinator/pureftpd.rb'
4
+ load 'pureftpdinator/config.rb'
5
+ load 'pureftpdinator/built-in.rb'
@@ -0,0 +1,89 @@
1
+ require 'resolv'
2
+ set :pureftpd_config_dir, -> { shared_path.join('pureftpd') }
3
+ set :pureftpd_pid_file, -> { "#{fetch(:pureftpd_config_dir)}/pure-ftpd.pid" }
4
+ set :pureauthd_pid_file, -> { "#{fetch(:pureftpd_config_dir)}/pure-authd.pid" }
5
+ set :pureftpd_socket_dir, "/tmp/pureftpd"
6
+ set :pureauthd_socket_file, -> { "#{fetch(:pureftpd_socket_dir)}/pure-authd.sock" }
7
+ set :pureftpd_entrypoint, "/usr/sbin/pure-ftpd"
8
+ set :pureauthd_entrypoint, "/usr/sbin/pure-authd"
9
+ set :pureauthd_program, -> { shared_path.join('bundle', 'bin', 'ftp_auth') }
10
+ set :pureftpd_templates_path, "templates/pureftpd"
11
+ set :pureftpd_umask, "117:007"
12
+ set :pureftpd_internal_cert_file, "/etc/ssl/private/pure-ftpd.pem"
13
+ set :pureftpd_external_cert_file, -> { "#{fetch(:pureftpd_config_dir)}/ssl.pem" }
14
+ set :pureftpd_custom_vol_mounts, -> {} # Set custom vol mounts w/o overridding methods below
15
+ set :pureftpd_custom_env_vars, -> {} # Set custom env vars w/o overridding methods below
16
+ set :pureftpd_ports_options, -> {
17
+ fetch(:pureftpd_connection_ports).collect do |port|
18
+ ["--publish", "0.0.0.0:#{port}:#{port}"]
19
+ end.flatten
20
+ }
21
+ set :pureftpd_port_range_options, -> {
22
+ ports = fetch(:pureftpd_passive_port_range).split(":")
23
+ ["--publish", "0.0.0.0:#{ports[0]}-#{ports[1]}:#{ports[0]}-#{ports[1]}"]
24
+ }
25
+ set :pureftpd_tls_volume_options, -> {
26
+ if ["1", "2", "3"].include? fetch(:pureftpd_tls_mode)
27
+ ["--volume", "#{fetch(:pureftpd_external_cert_file)}:#{fetch(:pureftpd_internal_cert_file)}:ro"]
28
+ end
29
+ }
30
+
31
+ def pureftpd_run(host)
32
+ warn "Starting a new container named #{fetch(:pureftpd_container_name)} on #{host}"
33
+ execute(
34
+ "docker", "run", "--tty", "--detach",
35
+ "--name", fetch(:pureftpd_container_name),
36
+ "--restart", "always",
37
+ "--memory", "#{fetch(:pureftpd_container_max_mem_mb)}m",
38
+ "--memory-swap='-1'",
39
+ "-e", "RAILS_ROOT=#{current_path}",
40
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
41
+ "--volume", "/home/#{fetch(:pureftpd_username)}:/home/#{fetch(:pureftpd_username)}:rw",
42
+ "--volume", "#{fetch(:pureftpd_socket_dir)}:#{fetch(:pureftpd_socket_dir)}:rw",
43
+ fetch(:pureftpd_tls_volume_options),
44
+ fetch(:pureftpd_custom_vol_mounts),
45
+ fetch(:pureftpd_custom_env_vars),
46
+ fetch(:pureftpd_ports_options),
47
+ fetch(:pureftpd_port_range_options),
48
+ "--entrypoint", fetch(:pureftpd_entrypoint),
49
+ fetch(:pureftpd_image_name),
50
+ "-0", "-4", "-A", "-E",
51
+ "-g", fetch(:pureftpd_pid_file),
52
+ "-G", "-k", "90",
53
+ "-O", "clf:#{shared_path.join('log', 'pure-ftpd.log')}",
54
+ "-l", "extauth:#{fetch(:pureauthd_socket_file)}",
55
+ "-p", fetch(:pureftpd_passive_port_range),
56
+ "-R", "-S", "0.0.0.0,",
57
+ "-P", Resolv::DNS.new(:nameserver => ['8.8.8.8', '8.8.4.4']).getaddress(fetch(:domain)).to_s,
58
+ "-u", "999", "-U", fetch(:pureftpd_umask),
59
+ "-Y", fetch(:pureftpd_tls_mode)
60
+ )
61
+ end
62
+
63
+ def pureauthd_run(host)
64
+ warn "Starting a new container named #{fetch(:pureauthd_container_name)} on #{host}"
65
+ execute(
66
+ "docker", "run", "--tty", "--detach",
67
+ "--name", fetch(:pureauthd_container_name),
68
+ "--restart", "always",
69
+ "--memory", "#{fetch(:pureauthd_container_max_mem_mb)}m",
70
+ "--memory-swap='-1'",
71
+ "-e", "RAILS_ROOT=#{current_path}",
72
+ "--workdir", current_path,
73
+ "--volume", "#{fetch(:deploy_to)}:#{fetch(:deploy_to)}:rw",
74
+ "--volume", "/home/#{fetch(:pureftpd_username)}:/home/#{fetch(:pureftpd_username)}:rw",
75
+ "--volume", "#{fetch(:pureftpd_socket_dir)}:#{fetch(:pureftpd_socket_dir)}:rw",
76
+ "--volume", "/etc/passwd:/etc/passwd:ro",
77
+ "--volume", "/etc/group:/etc/group:ro",
78
+ fetch(:pureftpd_custom_vol_mounts),
79
+ fetch(:pureftpd_custom_env_vars),
80
+ "--entrypoint", fetch(:pureauthd_entrypoint),
81
+ fetch(:pureftpd_image_name),
82
+ "--socket", fetch(:pureauthd_socket_file),
83
+ "--pidfile", fetch(:pureauthd_pid_file),
84
+ "--run", fetch(:pureauthd_program)
85
+ # "--uid", unix_user_get_uid(fetch(:pureftpd_username)), # won't communicate over socket unless run as root for some reason
86
+ # "--gid", unix_user_get_gid(fetch(:pureftpd_username))
87
+ )
88
+ end
89
+
@@ -0,0 +1,96 @@
1
+ module Capistrano
2
+ module TaskEnhancements
3
+ alias_method :pureftpd_original_default_tasks, :default_tasks
4
+ def default_tasks
5
+ pureftpd_original_default_tasks + [
6
+ "pureftpdinator:write_built_in",
7
+ "pureftpdinator:write_example_configs",
8
+ "pureftpdinator:write_example_configs:in_place"
9
+ ]
10
+ end
11
+ end
12
+ end
13
+
14
+ namespace :pureftpdinator do
15
+
16
+ set :example, "_example"
17
+
18
+ desc 'Write example config files'
19
+ task :write_example_configs => 'deployinator:load_settings' do
20
+ run_locally do
21
+ path = fetch(:pureftpd_templates_path)
22
+ execute "mkdir", "-p", "config/deploy", path
23
+ {
24
+ "examples/Capfile" => "Capfile#{fetch(:example)}",
25
+ "examples/config/deploy.rb" => "config/deploy#{fetch(:example)}.rb",
26
+ "examples/config/deploy/staging.rb" => "config/deploy/staging#{fetch(:example)}.rb",
27
+ "examples/Dockerfile" => "#{path}/Dockerfile#{fetch(:example)}",
28
+ "examples/ssl.crt.erb" => "#{path}/ssl.crt#{fetch(:example)}.erb",
29
+ "examples/ssl.key.erb" => "#{path}/ssl.key#{fetch(:example)}.erb"
30
+ }.each do |source, destination|
31
+ config = File.read(File.dirname(__FILE__) + "/#{source}")
32
+ File.open("./#{destination}", 'w') { |f| f.write(config) }
33
+ info "Wrote '#{destination}'"
34
+ end
35
+ unless fetch(:example).empty?
36
+ info(
37
+ "Now remove the '#{fetch(:example)}' portion of their names " +
38
+ "or diff with existing files and add the needed lines."
39
+ )
40
+ end
41
+ end
42
+ end
43
+
44
+ desc 'Write example config files (will overwrite any existing config files).'
45
+ namespace :write_example_configs do
46
+ task :in_place => 'deployinator:load_settings' do
47
+ set :example, ""
48
+ Rake::Task['pureftpdinator:write_example_configs'].invoke
49
+ end
50
+ end
51
+
52
+ desc 'Write a file showing the built-in overridable settings.'
53
+ task :write_built_in => 'deployinator:load_settings' do
54
+ run_locally do
55
+ {
56
+ 'built-in.rb' => 'built-in.rb',
57
+ }.each do |source, destination|
58
+ config = File.read(File.dirname(__FILE__) + "/#{source}")
59
+ File.open("./#{destination}", 'w') { |f| f.write(config) }
60
+ info "Wrote '#{destination}'"
61
+ end
62
+ info "Now examine the file and copy-paste into your deploy.rb or <stage>.rb and customize."
63
+ end
64
+ end
65
+
66
+ # These are the only two tasks using :preexisting_ssh_user
67
+ namespace :deployment_user do
68
+ #desc "Setup or re-setup the deployment user, idempotently"
69
+ task :setup => 'deployinator:load_settings' do
70
+ on roles(:all) do |h|
71
+ on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
72
+ as :root do
73
+ path = fetch(:deploy_templates_path, nil)
74
+ path = fetch(:pureftpd_templates_path) if path.nil?
75
+ deployment_user_setup(path)
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ task :deployment_user => 'deployinator:load_settings' do
83
+ on roles(:all) do |h|
84
+ on "#{fetch(:preexisting_ssh_user)}@#{h}" do |host|
85
+ as :root do
86
+ if unix_user_exists?(fetch(:deployment_username))
87
+ info "User #{fetch(:deployment_username)} already exists. You can safely re-setup the user with 'deployinator:deployment_user:setup'."
88
+ else
89
+ Rake::Task['deployinator:deployment_user:setup'].invoke
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
95
+
96
+ end
@@ -0,0 +1,28 @@
1
+ # Load DSL and Setup Up Stages
2
+ require 'capistrano/setup'
3
+
4
+ # Includes default deployment tasks
5
+ require 'capistrano/deploy'
6
+
7
+ # Includes tasks from other gems included in your Gemfile
8
+ #
9
+ # For documentation on these, see for example:
10
+ #
11
+ # https://github.com/capistrano/rvm
12
+ # https://github.com/capistrano/rbenv
13
+ # https://github.com/capistrano/chruby
14
+ # https://github.com/capistrano/bundler
15
+ # https://github.com/capistrano/rails
16
+ #
17
+ # require 'capistrano/rvm'
18
+ # require 'capistrano/rbenv'
19
+ # require 'capistrano/chruby'
20
+ require 'capistrano/bundler'
21
+ require 'capistrano/rails/assets'
22
+ require 'capistrano/rails/migrations'
23
+
24
+ require 'deployinator'
25
+ require 'deployinator/jobs'
26
+
27
+ # Loads custom tasks from `lib/capistrano/tasks' if you have any defined.
28
+ Dir.glob('lib/capistrano/tasks/*.rake').each { |r| import r }
@@ -0,0 +1,20 @@
1
+ FROM snarlysodboxer/ruby-ree-1.8.7-2012.02:latest
2
+ MAINTAINER david amick <docker@davidamick.com>
3
+
4
+ ENV DEBIAN_FRONTEND noninteractive
5
+
6
+ RUN /bin/bash -c "apt-get update -qq && apt-get -y build-dep pure-ftpd && apt-get install -y openbsd-inetd && apt-get -y autoclean && apt-get -y autoremove"
7
+ RUN /bin/bash -c "mkdir /tmp/pure-ftpd/ && \
8
+ cd /tmp/pure-ftpd/ && \
9
+ wget --no-check-certificate https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.42.tar.gz && \
10
+ tar zxvf pure-ftpd-1.0.42.tar.gz && \
11
+ cd pure-ftpd-1.0.42 && \
12
+ ./configure --prefix /usr --exec-prefix /usr/sbin --sysconfdir=/etc/pure-ftpd \
13
+ CFLAGS=-DMAX_USER_LENGTH=128U \
14
+ --with-everything --with-privsep --with-tls --with-rfc2640 --without-capabilities && \
15
+ make && make install && \
16
+ mv src/pure-ftpd /usr/sbin/ && mv src/pure-authd /usr/sbin/ && \
17
+ rm /tmp/pure-ftpd -rf"
18
+
19
+ ENTRYPOINT ["/bin/bash"]
20
+ CMD ["-l"]
@@ -0,0 +1,15 @@
1
+ # config valid only for Capistrano 3.2.1
2
+ lock '3.2.1'
3
+
4
+ ##### pureftpdinator
5
+ ### ------------------------------------------------------------------
6
+ set :application, 'my_app_name'
7
+ set :preexisting_ssh_user, ENV['USER']
8
+ set :deployment_username, "deployer" # user with SSH access and passwordless sudo rights
9
+ set :ignore_permissions_dirs, [fetch(:pureftpd_config_dir)]
10
+ set :pureftpd_username, "ftpuser"
11
+ # TODO confirm 990 is the right port for TLS
12
+ set :pureftpd_connection_ports, ["21", "990"] # ports 21, 990, etc
13
+ set :pureftpd_passive_port_range, "6500:6700"
14
+ set :pureftpd_tls_mode, "3"
15
+ ### ------------------------------------------------------------------
@@ -0,0 +1,12 @@
1
+ ##### pureftpdinator
2
+ ### ------------------------------------------------------------------
3
+ set :domain, "my-app-staging.example.com"
4
+ server fetch(:domain),
5
+ :user => fetch(:deployment_username),
6
+ :roles => [:app, :web, :db]
7
+ set :pureftpd_image_name, "snarlysodboxer/ruby-ree-1.8.7-2012.02_pure-ftpd-1.0.36:0.0.0"
8
+ set :pureftpd_container_name, "#{fetch(:domain)}-pure-ftpd"
9
+ set :pureftpd_container_max_mem_mb, "512"
10
+ set :pureauthd_container_name, "#{fetch(:domain)}-pure-authd"
11
+ set :pureauthd_container_max_mem_mb, "512"
12
+ ### ------------------------------------------------------------------
@@ -0,0 +1 @@
1
+ # Remove this line and add your cert here
@@ -0,0 +1 @@
1
+ # Remove this line and add your key here
@@ -0,0 +1,164 @@
1
+ # config valid only for Capistrano 3.2.1
2
+ lock '3.2.1'
3
+
4
+ namespace :pureftpd do
5
+
6
+ set :pureftpd_config_file_changed, false
7
+ desc "Setup Pure-FTPd on the host"
8
+ task :setup => ['deployinator:load_settings', 'pureftpdinator:deployment_user', :open_firewall, :ensure_ftp_user, :ensure_ssl_cert] do
9
+ on roles(:app) do |host|
10
+ as :root do
11
+ execute "mkdir", "-p", fetch(:pureftpd_socket_dir)
12
+ execute "chown", "#{fetch(:pureftpd_username)}:#{fetch(:pureftpd_username)}", fetch(:pureftpd_socket_dir)
13
+ execute "chmod", "770", fetch(:pureftpd_socket_dir)
14
+ name = fetch(:pureauthd_container_name)
15
+ unless container_exists?(name)
16
+ pureauthd_run(host)
17
+ check_stayed_running(name)
18
+ else
19
+ unless container_is_running?(name)
20
+ start_container(name)
21
+ else
22
+ info "#{name} is already running; we're setup!"
23
+ end
24
+ end
25
+ name = fetch(:pureftpd_container_name)
26
+ unless container_exists?(name)
27
+ pureftpd_run(host)
28
+ check_stayed_running(name)
29
+ else
30
+ unless container_is_running?(name)
31
+ start_container(name)
32
+ else
33
+ if fetch(:pureftpd_config_file_changed)
34
+ restart_container(name)
35
+ else
36
+ info "No config file changes for #{name} and it is already running; we're setup!"
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ desc 'Restart the PureFTPd and PureAuthd Docker containers'
45
+ task :restart => 'deployinator:load_settings' do
46
+ on roles(:app) do |host|
47
+ name = fetch(:pureauthd_container_name)
48
+ if container_exists?(name)
49
+ if container_is_restarting?(name) or container_is_running?(name)
50
+ execute("docker", "stop", name)
51
+ else
52
+ execute("docker", "start", name)
53
+ end
54
+ else
55
+ pureauthd_run(host)
56
+ check_stayed_running(name)
57
+ end
58
+ name = fetch(:pureftpd_container_name)
59
+ if container_exists?(name)
60
+ if container_is_restarting?(name) or container_is_running?(name)
61
+ execute("docker", "stop", name)
62
+ else
63
+ execute("docker", "start", name)
64
+ end
65
+ else
66
+ pureftpd_run(host)
67
+ check_stayed_running(name)
68
+ end
69
+ end
70
+ end
71
+
72
+ namespace :restart do
73
+ desc 'Restart PureFTPd and PureAuthd by recreating the Docker containers'
74
+ task :force => 'deployinator:load_settings' do
75
+ on roles(:app) do |host|
76
+ [fetch(:pureauthd_container_name), fetch(:pureftpd_container_name)].each do |name|
77
+ if container_exists?(name)
78
+ if container_is_running?(name)
79
+ execute("docker", "stop", name)
80
+ end
81
+ begin
82
+ execute("docker", "rm", name)
83
+ rescue
84
+ sleep 5
85
+ begin
86
+ execute("docker", "rm", name)
87
+ rescue
88
+ fatal "We were not able to remove the container #{name} for some reason. Try running 'cap <stage> deploy:restart:force' again."
89
+ exit
90
+ end
91
+ end
92
+ end
93
+ end
94
+ Rake::Task['pureftpd:restart'].invoke
95
+ end
96
+ end
97
+ end
98
+
99
+ task :ensure_ssl_cert => 'deployinator:load_settings' do
100
+ require 'erb'
101
+ on roles(:app) do
102
+ as :root do
103
+ cert_file = fetch(:pureftpd_external_cert_file)
104
+ if ["1", "2", "3"].include? fetch(:pureftpd_tls_mode)
105
+ execute "mkdir", "-p", fetch(:pureftpd_config_dir)
106
+ execute "chown", "#{fetch(:pureftpd_username)}:#{fetch(:pureftpd_username)}", fetch(:pureftpd_config_dir)
107
+ generated_config_file = ""
108
+ ["ssl.key", "ssl.crt"].each do |file|
109
+ template_path = File.expand_path("#{fetch(:pureftpd_templates_path)}/#{file}.erb")
110
+ generated_config_file += ERB.new(File.new(template_path).read).result(binding)
111
+ end
112
+ temp_file = "/tmp/temp.file"
113
+ upload! StringIO.new(generated_config_file), temp_file
114
+ unless test "diff", "-q", temp_file, cert_file
115
+ warn "Config file #{cert_file} on #{fetch(:domain)} is being updated."
116
+ execute "mv", temp_file, cert_file
117
+ set :pureftpd_config_file_changed, true
118
+ else
119
+ execute "rm", temp_file
120
+ end
121
+ execute "chown", "root:root", cert_file
122
+ execute "chmod", "600", cert_file
123
+ end
124
+ end
125
+ end
126
+ end
127
+
128
+ task :ensure_ftp_user => 'deployinator:load_settings' do
129
+ on roles(:app) do
130
+ as :root do
131
+ name = fetch(:pureftpd_username)
132
+ unless unix_user_exists?(name)
133
+ execute "adduser", "--disabled-password", "--gecos", "\"\"", "--shell", "/bin/false", name
134
+ end
135
+ unless fetch(:webserver_username).nil?
136
+ if unix_user_exists?(fetch(:webserver_username))
137
+ execute "usermod", "-a", "-G", fetch(:pureftpd_username), fetch(:webserver_username)
138
+ end
139
+ end
140
+ execute "mkdir", "-p", "/home/#{name}"
141
+ execute "chown", "#{name}:#{name}", "/home/#{name}"
142
+ execute "chmod", "755", "/home/#{name}"
143
+ end
144
+ end
145
+ end
146
+
147
+ task :open_firewall => 'deployinator:load_settings' do
148
+ on roles(:app) do
149
+ as :root do
150
+ if test "bash", "-c", "\"ufw", "status", "&>" "/dev/null\""
151
+ unless test("ufw", "allow", "#{fetch(:pureftpd_passive_port_range)}/tcp")
152
+ raise "Error opening UFW firewall range #{fetch(:pureftpd_passive_port_range)}"
153
+ end
154
+ fetch(:pureftpd_connection_ports).each do |port|
155
+ raise "Error opening UFW firewall port #{port}" unless test("ufw", "allow", "#{port}/tcp")
156
+ end
157
+ else
158
+ warn "UFW appears not to be installed, not opening the firewall"
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ end
metadata ADDED
@@ -0,0 +1,121 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: pureftpdinator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - david amick
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-02-23 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: capistrano
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: 3.2.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: 3.2.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: deployinator
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.6
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.6
46
+ - !ruby/object:Gem::Dependency
47
+ name: rake
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 10.3.2
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 10.3.2
62
+ - !ruby/object:Gem::Dependency
63
+ name: sshkit
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.5.1
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.5.1
78
+ description: Deploy Ruby on Rails using Capistrano and Docker
79
+ email: davidamick@ctisolutionsinc.com
80
+ executables: []
81
+ extensions: []
82
+ extra_rdoc_files: []
83
+ files:
84
+ - lib/pureftpdinator.rb
85
+ - lib/pureftpdinator/pureftpd.rb
86
+ - lib/pureftpdinator/config.rb
87
+ - lib/pureftpdinator/built-in.rb
88
+ - lib/pureftpdinator/examples/Capfile
89
+ - lib/pureftpdinator/examples/config/deploy.rb
90
+ - lib/pureftpdinator/examples/config/deploy/staging.rb
91
+ - lib/pureftpdinator/examples/Dockerfile
92
+ - lib/pureftpdinator/examples/ssl.crt.erb
93
+ - lib/pureftpdinator/examples/ssl.key.erb
94
+ homepage: https://github.com/snarlysodboxer/pureftpdinator
95
+ licenses:
96
+ - GNU
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: 1.9.3
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements:
114
+ - Docker ~> 1.9.1
115
+ rubyforge_project:
116
+ rubygems_version: 1.8.23.2
117
+ signing_key:
118
+ specification_version: 3
119
+ summary: Deploy Applications
120
+ test_files: []
121
+ has_rdoc: