smartmachine 1.2.2 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +4 -4
  2. data/lib/smart_machine/buildpackers/buildpacker.rb +0 -42
  3. data/lib/smart_machine/buildpackers/rails.rb +60 -0
  4. data/lib/smart_machine/commands/grid.rb +8 -0
  5. data/lib/smart_machine/commands/grid_commands/emailer.rb +107 -0
  6. data/lib/smart_machine/commands/grid_commands/roundcube.rb +65 -0
  7. data/lib/smart_machine/configuration.rb +35 -2
  8. data/lib/smart_machine/credentials.rb +10 -0
  9. data/lib/smart_machine/engine.rb +6 -0
  10. data/lib/smart_machine/grids/adminer.rb +1 -0
  11. data/lib/smart_machine/grids/certbot.rb +1 -0
  12. data/lib/smart_machine/grids/emailer/.keep +0 -0
  13. data/lib/smart_machine/grids/emailer.rb +188 -0
  14. data/lib/smart_machine/grids/haproxy.rb +1 -0
  15. data/lib/smart_machine/grids/mariadb.rb +1 -0
  16. data/lib/smart_machine/grids/postgresql.rb +1 -0
  17. data/lib/smart_machine/grids/roundcube.rb +114 -0
  18. data/lib/smart_machine/machine.rb +49 -0
  19. data/lib/smart_machine/syncer.rb +10 -0
  20. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/docker/command.rb +50 -0
  21. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/docker/entrypoint.rb +196 -0
  22. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/docker/logtailer.rb +75 -0
  23. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/10-auth.conf +132 -0
  24. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/10-mail.conf +427 -0
  25. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/10-master.conf +153 -0
  26. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/10-ssl.conf +87 -0
  27. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/15-mailboxes.conf +94 -0
  28. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/20-imap.conf +102 -0
  29. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/20-lmtp.conf +43 -0
  30. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/90-quota.conf +114 -0
  31. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/conf.d/90-sieve.conf +229 -0
  32. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/dovecot-sql.conf.ext +163 -0
  33. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/sieve/learn-ham.sh +2 -0
  34. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/sieve/learn-ham.sieve +5 -0
  35. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/sieve/learn-spam.sh +2 -0
  36. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/sieve/learn-spam.sieve +2 -0
  37. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/dovecot/sieve-after/spam-to-folder.sieve +6 -0
  38. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/haproxy/haproxy.cfg +58 -0
  39. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/monit/conf.d/services.cfg +70 -0
  40. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/monit/monitrc +344 -0
  41. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/opendkim.conf +71 -0
  42. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/main.cf +123 -0
  43. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/master.cf +149 -0
  44. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-sender-login-maps.cf +7 -0
  45. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-alias-domains.cf +7 -0
  46. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-domains.cf +7 -0
  47. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-masters.cf +7 -0
  48. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-users.cf +7 -0
  49. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-userstothemselves.cf +7 -0
  50. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-mailbox-domains.cf +7 -0
  51. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix/mysql-virtual-mailbox-maps.cf +7 -0
  52. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/postfix-policyd-spf-python/policyd-spf.conf +12 -0
  53. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/etc/spamassassin/local.cf +124 -0
  54. data/lib/smart_machine/templates/dotsmartmachine/config/emailer/usr/local/bin/quota-warning.sh +22 -0
  55. data/lib/smart_machine/templates/dotsmartmachine/config/emailer.yml +37 -0
  56. data/lib/smart_machine/templates/dotsmartmachine/config/engine.yml +2 -0
  57. data/lib/smart_machine/templates/dotsmartmachine/config/roundcube/etc/apache2/sites-available/000-default.conf +35 -0
  58. data/lib/smart_machine/templates/dotsmartmachine/config/roundcube/usr/local/etc/php/conf.d/zzz_roundcube-custom.ini +4 -0
  59. data/lib/smart_machine/templates/dotsmartmachine/config/roundcube/var/roundcube/config/config.custom.inc.php +25 -0
  60. data/lib/smart_machine/templates/dotsmartmachine/config/roundcube.yml +41 -0
  61. data/lib/smart_machine/templates/dotsmartmachine/config/users.yml +1 -1
  62. data/lib/smart_machine/version.rb +2 -2
  63. data/lib/smart_machine.rb +2 -0
  64. metadata +55 -4
@@ -0,0 +1,114 @@
1
+ module SmartMachine
2
+ class Grids
3
+ class Roundcube < SmartMachine::Base
4
+ def initialize(name:)
5
+ config = SmartMachine.config.grids.roundcube.dig(name.to_sym)
6
+ raise "roundcube config for #{name} not found." unless config
7
+
8
+ @fqdn = config.dig(:fqdn)
9
+ @image = config.dig(:image)
10
+ @sysadmin_email = config.dig(:sysadmin_email)
11
+ @networks = config.dig(:networks)
12
+ @database_type = config.dig(:database_type)
13
+ @database_host = config.dig(:database_host)
14
+ @database_port = config.dig(:database_port)
15
+ @database_user = config.dig(:database_user)
16
+ @database_pass = config.dig(:database_pass)
17
+ @database_name = config.dig(:database_name)
18
+ @mail_host = config.dig(:mail_host)
19
+ @mail_port = config.dig(:mail_port)
20
+ @smtp_host = config.dig(:smtp_host)
21
+ @smtp_port = config.dig(:smtp_port)
22
+ @request_path = config.dig(:request_path)
23
+ @plugins = config.dig(:plugins)
24
+ @skin = config.dig(:skin)
25
+ @upload_max_filesize = config.dig(:upload_max_filesize)
26
+ @aspell_dictionaries = config.dig(:aspell_dictionaries)
27
+
28
+ @name = name.to_s
29
+ @home_dir = File.expand_path('~')
30
+ end
31
+
32
+ def uper
33
+ FileUtils.mkdir_p("#{@home_dir}/machine/grids/roundcube/#{@name}/backups")
34
+ FileUtils.mkdir_p("#{@home_dir}/machine/grids/roundcube/#{@name}/data/html")
35
+ FileUtils.mkdir_p("#{@home_dir}/machine/grids/roundcube/#{@name}/data/roundcube-temp")
36
+
37
+ # Creating & Starting containers
38
+ print "-----> Creating container #{@name} ... "
39
+
40
+ command = [
41
+ "docker create",
42
+ "--name='#{@name}'",
43
+ "--env VIRTUAL_HOST=#{@fqdn}",
44
+ "--env VIRTUAL_PATH='#{@request_path}'",
45
+ "--env LETSENCRYPT_HOST=#{@fqdn}",
46
+ "--env LETSENCRYPT_EMAIL=#{@sysadmin_email}",
47
+ "--env LETSENCRYPT_TEST=false",
48
+ "--env CONTAINER_NAME='#{@name}'",
49
+ "--env FQDN='#{@fqdn}'",
50
+ "--env ROUNDCUBEMAIL_DEFAULT_HOST='#{@mail_host}'",
51
+ "--env ROUNDCUBEMAIL_DEFAULT_PORT='#{@mail_port}'",
52
+ "--env ROUNDCUBEMAIL_SMTP_SERVER='#{@smtp_host}'",
53
+ "--env ROUNDCUBEMAIL_SMTP_PORT='#{@smtp_port}'",
54
+ "--env ROUNDCUBEMAIL_USERNAME_DOMAIN=''",
55
+ "--env ROUNDCUBEMAIL_REQUEST_PATH='#{@request_path}'",
56
+ "--env ROUNDCUBEMAIL_PLUGINS='#{@plugins.join(',')}'",
57
+ "--env ROUNDCUBEMAIL_INSTALL_PLUGINS='1'",
58
+ "--env ROUNDCUBEMAIL_SKIN='#{@skin}'",
59
+ "--env ROUNDCUBEMAIL_UPLOAD_MAX_FILESIZE='#{@upload_max_filesize}'",
60
+ "--env ROUNDCUBEMAIL_SPELLCHECK_URI=''",
61
+ "--env ROUNDCUBEMAIL_ASPELL_DICTS='#{@aspell_dictionaries.join(',')}'",
62
+ "--env ROUNDCUBEMAIL_DB_TYPE='#{@database_type}'",
63
+ "--env ROUNDCUBEMAIL_DB_HOST='#{@database_host}'",
64
+ "--env ROUNDCUBEMAIL_DB_PORT='#{@database_port}'",
65
+ "--env ROUNDCUBEMAIL_DB_USER='#{@database_user}'",
66
+ "--env ROUNDCUBEMAIL_DB_PASSWORD='#{@database_pass}'",
67
+ "--env ROUNDCUBEMAIL_DB_NAME='#{@database_name}'",
68
+ "--volume='#{@home_dir}/smartmachine/config/roundcube/etc/apache2/sites-available/000-default.conf:/etc/apache2/sites-available/000-default.conf:ro'",
69
+ "--volume='#{@home_dir}/smartmachine/config/roundcube/usr/local/etc/php/conf.d/zzz_roundcube-custom.ini:/usr/local/etc/php/conf.d/zzz_roundcube-custom.ini:ro'",
70
+ "--volume='#{@home_dir}/smartmachine/config/roundcube/var/roundcube/config:/var/roundcube/config:ro'",
71
+ "--volume='#{@home_dir}/smartmachine/grids/roundcube/#{@name}/data/html:/var/www/html'",
72
+ "--volume='#{@home_dir}/smartmachine/grids/roundcube/#{@name}/data/roundcube-temp:/tmp/roundcube-temp'",
73
+ "--tmpfs /run/tmpfs",
74
+ "--init",
75
+ "--restart='always'",
76
+ "--network='nginx-network'",
77
+ "#{@image}"
78
+ ]
79
+ if system(command.compact.join(" "), out: File::NULL)
80
+ @networks.each do |network|
81
+ system("docker network connect #{network} #{@name}")
82
+ end
83
+
84
+ puts "done"
85
+ puts "-----> Starting container #{@name} ... "
86
+ if system("docker start #{@name}", out: File::NULL)
87
+ puts "done"
88
+ else
89
+ raise "Error: Could not start container: #{@name}"
90
+ end
91
+ else
92
+ raise "Error: Could not create container: #{@name}"
93
+ end
94
+ end
95
+
96
+ def downer
97
+ # Disconnecting networks
98
+ @networks.reverse.each do |network|
99
+ system("docker network disconnect #{network} #{@name}")
100
+ end
101
+
102
+ # Stopping & Removing containers - in reverse order
103
+ print "-----> Stopping container #{@name} ... "
104
+ if system("docker stop '#{@name}'", out: File::NULL)
105
+ puts "done"
106
+ print "-----> Removing container #{@name} ... "
107
+ if system("docker rm '#{@name}'", out: File::NULL)
108
+ puts "done"
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -77,6 +77,13 @@ module SmartMachine
77
77
  # puts 'You may be prompted to make a menu selection when the Grub package is updated on Ubuntu. If prompted, select keep the local version currently installed.'
78
78
 
79
79
  # dpkg-reconfigure tzdata
80
+ # debconf-set-selections <<EOF
81
+ # tzdata tzdata/Areas select Asia
82
+ # tzdata tzdata/Areas seen true
83
+ # tzdata tzdata/Zones/Asia select Kolkata
84
+ # tzdata tzdata/Zones/Asia seen true
85
+ # EOF
86
+ # dpkg-reconfigure -fnoninteractive tzdata
80
87
  # date
81
88
 
82
89
  # hostnamectl set-hostname SmartMachine.credentials.machine[:name]
@@ -161,5 +168,47 @@ module SmartMachine
161
168
  ]
162
169
  run_on_machine(commands: commands)
163
170
  end
171
+
172
+ # These swapfile methods can be used (after required modification), when you need to make swapfile for more memory.
173
+ # def self.create_swapfile
174
+ # # Creating swapfile for bundler to work properly
175
+ # unless system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
176
+ # print "-----> Creating swap swapfile ... "
177
+ # system("sudo install -o root -g root -m 0600 /dev/null /swapfile", out: File::NULL)
178
+ # system("sudo dd if=/dev/zero of=/swapfile bs=1k count=2048k", [:out, :err] => File::NULL)
179
+ # system("sudo mkswap /swapfile", out: File::NULL)
180
+ # system("sudo sh -c 'echo \"/swapfile none swap sw 0 0\" >> /etc/fstab'", out: File::NULL)
181
+ # system("echo 10 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
182
+ # system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
183
+ # system("echo vm.swappiness = 10 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
184
+ # system("echo 50 | sudo tee /proc/sys/vm/vfs_cache_pressure", out: File::NULL)
185
+ # system("sudo sed -i '/^vm.vfs_cache_pressure = /d' /etc/sysctl.conf", out: File::NULL)
186
+ # system("echo vm.vfs_cache_pressure = 50 | sudo tee -a /etc/sysctl.conf", out: File::NULL)
187
+ # puts "done"
188
+ #
189
+ # print "-----> Starting swap swapfile ... "
190
+ # if system("sudo swapon /swapfile", out: File::NULL)
191
+ # puts "done"
192
+ # end
193
+ # end
194
+ # end
195
+ #
196
+ # def self.destroy_swapfile
197
+ # if system("sudo swapon -s | grep -ci '/swapfile'", out: File::NULL)
198
+ # print "-----> Stopping swap swapfile ... "
199
+ # if system("sudo swapoff /swapfile", out: File::NULL)
200
+ # system("sudo sed -i '/^vm.swappiness = /d' /etc/sysctl.conf", out: File::NULL)
201
+ # system("echo 100 | sudo tee /proc/sys/vm/vfs_cache_pressure", out: File::NULL)
202
+ # system("echo 60 | sudo tee /proc/sys/vm/swappiness", out: File::NULL)
203
+ # puts "done"
204
+ #
205
+ # print "-----> Removing swap swapfile ... "
206
+ # system("sudo sed -i '/^\\/swapfile/d' /etc/fstab", out: File::NULL)
207
+ # if system("sudo rm /swapfile", out: File::NULL)
208
+ # puts "done"
209
+ # end
210
+ # end
211
+ # end
212
+ # end
164
213
  end
165
214
  end
@@ -64,6 +64,9 @@ module SmartMachine
64
64
  'grids/elasticsearch',
65
65
  'grids/elasticsearch/***',
66
66
 
67
+ 'grids/emailer',
68
+ 'grids/emailer/***',
69
+
67
70
  'grids/minio',
68
71
  'grids/minio/***',
69
72
 
@@ -103,11 +106,17 @@ module SmartMachine
103
106
  'bin/smartmachine',
104
107
 
105
108
  'config',
109
+ 'config/emailer',
110
+ 'config/emailer/***',
106
111
  'config/mysql',
107
112
  'config/mysql/schedule.rb',
108
113
  'config/phpmyadmin',
109
114
  'config/phpmyadmin/***',
115
+ 'config/roundcube',
116
+ 'config/roundcube/***',
110
117
  'config/credentials.yml.enc',
118
+ 'config/emailer.yml',
119
+ 'config/engine.yml',
111
120
  'config/environment.rb',
112
121
  'config/elasticsearch.yml',
113
122
  'config/minio.yml',
@@ -117,6 +126,7 @@ module SmartMachine
117
126
  'config/phpmyadmin.yml',
118
127
  'config/prereceiver.yml',
119
128
  'config/redis.yml',
129
+ 'config/roundcube.yml',
120
130
  'config/terminal.yml',
121
131
 
122
132
  'grids',
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ STDOUT.sync = true
5
+
6
+ class Services
7
+ def initialize
8
+ @services = %w(rsyslog haproxy spamassassin spamassassin.update opendkim postfix dovecot)
9
+ end
10
+
11
+ def start
12
+ puts "Starting Services..."
13
+ @services.each { |service| system("monit start #{service}") }
14
+ system("monit")
15
+
16
+ puts "Starting Logtailer..."
17
+ system("/usr/bin/logtailer.rb start")
18
+ end
19
+
20
+ def stop(signo)
21
+ puts "Stopping Logtailer..."
22
+ system("/usr/bin/logtailer.rb stop")
23
+
24
+ puts "Stopping Services... SIGNAL: SIG#{Signal.signame(signo)}."
25
+ system("monit quit")
26
+ sleep(3)
27
+ @services.reverse.each { |service| system("monit stop #{service}") }
28
+
29
+ puts "Flushing Logtailer..."
30
+ system("/usr/bin/logtailer.rb flush")
31
+
32
+ exit
33
+ end
34
+ end
35
+
36
+ trap('SIGINT') do |signo|
37
+ Services.new.stop(signo)
38
+ end
39
+
40
+ trap('SIGTERM') do |signo|
41
+ Services.new.stop(signo)
42
+ end
43
+
44
+ at_exit do
45
+ # Clean up.
46
+ end
47
+
48
+ Services.new.start
49
+
50
+ sleep
@@ -0,0 +1,196 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require 'fileutils'
5
+ require 'logger'
6
+
7
+ logger = Logger.new(STDOUT)
8
+ STDOUT.sync = true
9
+
10
+ def update_envkeys_in(filepaths, envkeys)
11
+ filepaths.each do |filepath|
12
+ str = File.read(filepath)
13
+ str = str.gsub(/%(?!<)/, '%%')
14
+ str = format(str, envkeys)
15
+ File.open(filepath, "w") { |file| file << str }
16
+ end
17
+ end
18
+
19
+ # initial setup
20
+ unless File.exist?('/run/initial_container_start')
21
+ FileUtils.touch('/run/initial_container_start')
22
+
23
+ # EnvKeys
24
+ envkeys = {
25
+ container_name: ENV.delete('CONTAINER_NAME'),
26
+ fqdn: ENV.delete('FQDN'),
27
+ mailname: ENV.delete('MAILNAME'),
28
+ sysadmin_email: ENV.delete('SYSADMIN_EMAIL'),
29
+ mysql_host: ENV.delete('MYSQL_HOST'),
30
+ mysql_port: ENV.delete('MYSQL_PORT'),
31
+ mysql_user: ENV.delete('MYSQL_USER'),
32
+ mysql_password: ENV.delete('MYSQL_PASSWORD'),
33
+ mysql_database_name: ENV.delete('MYSQL_DATABASE_NAME'),
34
+ monit_smtp_email_name: ENV.delete('MONIT_SMTP_EMAIL_NAME'),
35
+ monit_smtp_email_address: ENV.delete('MONIT_SMTP_EMAIL_ADDRESS'),
36
+ monit_smtp_host: ENV.delete('MONIT_SMTP_HOST'),
37
+ monit_smtp_port: ENV.delete('MONIT_SMTP_PORT'),
38
+ monit_smtp_username: ENV.delete('MONIT_SMTP_USERNAME'),
39
+ monit_smtp_password: ENV.delete('MONIT_SMTP_PASSWORD'),
40
+ oracle_ips_allowed: ENV.delete('ORACLE_IPS_ALLOWED'),
41
+ oracle_deflect_url: ENV.delete('ORACLE_DEFLECT_URL'),
42
+ timezone: `cat /etc/timezone`.chomp
43
+ }
44
+
45
+ # rsyslog
46
+ # imklog module is commented in rsyslog.conf because rsyslog does not
47
+ # have privileges to run it and hence throws error on startup.
48
+ system("sed -i '/imklog/s/^/#/' /etc/rsyslog.conf")
49
+
50
+ # Postfix
51
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/main.cf', '/etc/postfix/main.cf'
52
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/master.cf', '/etc/postfix/master.cf'
53
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-sender-login-maps.cf', '/etc/postfix/mysql-sender-login-maps.cf'
54
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-alias-domains.cf', '/etc/postfix/mysql-virtual-alias-domains.cf'
55
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-domains.cf', '/etc/postfix/mysql-virtual-alias-maps-domains.cf'
56
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-masters.cf', '/etc/postfix/mysql-virtual-alias-maps-masters.cf'
57
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-users.cf', '/etc/postfix/mysql-virtual-alias-maps-users.cf'
58
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-alias-maps-userstothemselves.cf', '/etc/postfix/mysql-virtual-alias-maps-userstothemselves.cf'
59
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-mailbox-domains.cf', '/etc/postfix/mysql-virtual-mailbox-domains.cf'
60
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix/mysql-virtual-mailbox-maps.cf', '/etc/postfix/mysql-virtual-mailbox-maps.cf'
61
+ FileUtils.cp '/smartmachine/config/emailer/etc/postfix-policyd-spf-python/policyd-spf.conf', '/etc/postfix-policyd-spf-python/policyd-spf.conf'
62
+ filepaths = [
63
+ '/etc/postfix/main.cf',
64
+ '/etc/postfix/mysql-sender-login-maps.cf',
65
+ '/etc/postfix/mysql-virtual-alias-domains.cf',
66
+ '/etc/postfix/mysql-virtual-alias-maps-domains.cf',
67
+ '/etc/postfix/mysql-virtual-alias-maps-masters.cf',
68
+ '/etc/postfix/mysql-virtual-alias-maps-users.cf',
69
+ '/etc/postfix/mysql-virtual-alias-maps-userstothemselves.cf',
70
+ '/etc/postfix/mysql-virtual-mailbox-domains.cf',
71
+ '/etc/postfix/mysql-virtual-mailbox-maps.cf'
72
+ ]
73
+ update_envkeys_in(filepaths, envkeys)
74
+ system("chgrp postfix /etc/postfix/mysql-*.cf")
75
+ system("chmod -R o-rwx /etc/postfix/mysql-*.cf")
76
+
77
+ # Dovecot
78
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/10-auth.conf', '/etc/dovecot/conf.d/10-auth.conf'
79
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/10-mail.conf', '/etc/dovecot/conf.d/10-mail.conf'
80
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/10-master.conf', '/etc/dovecot/conf.d/10-master.conf'
81
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/10-ssl.conf', '/etc/dovecot/conf.d/10-ssl.conf'
82
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/15-mailboxes.conf', '/etc/dovecot/conf.d/15-mailboxes.conf'
83
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/20-imap.conf', '/etc/dovecot/conf.d/20-imap.conf'
84
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/20-lmtp.conf', '/etc/dovecot/conf.d/20-lmtp.conf'
85
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/90-quota.conf', '/etc/dovecot/conf.d/90-quota.conf'
86
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/conf.d/90-sieve.conf', '/etc/dovecot/conf.d/90-sieve.conf'
87
+
88
+ FileUtils.mkdir '/etc/dovecot/sieve'
89
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/sieve/learn-ham.sh', '/etc/dovecot/sieve/learn-ham.sh'
90
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/sieve/learn-spam.sh', '/etc/dovecot/sieve/learn-spam.sh'
91
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/sieve/learn-ham.sieve', '/etc/dovecot/sieve/learn-ham.sieve'
92
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/sieve/learn-spam.sieve', '/etc/dovecot/sieve/learn-spam.sieve'
93
+
94
+ FileUtils.mkdir '/etc/dovecot/sieve-after'
95
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/sieve-after/spam-to-folder.sieve', '/etc/dovecot/sieve-after/spam-to-folder.sieve'
96
+
97
+ FileUtils.cp '/smartmachine/config/emailer/etc/dovecot/dovecot-sql.conf.ext', '/etc/dovecot/dovecot-sql.conf.ext'
98
+
99
+ FileUtils.cp '/smartmachine/config/emailer/usr/local/bin/quota-warning.sh', '/usr/local/bin/quota-warning.sh'
100
+
101
+ filepaths = [
102
+ '/etc/dovecot/conf.d/10-ssl.conf',
103
+ '/etc/dovecot/dovecot-sql.conf.ext',
104
+ '/usr/local/bin/quota-warning.sh'
105
+ ]
106
+ update_envkeys_in(filepaths, envkeys)
107
+
108
+ system("groupadd -g 5000 vmail")
109
+ system("useradd -g vmail -u 5000 vmail -d /var/vmail")
110
+ system("chown -R vmail:vmail /var/vmail")
111
+
112
+ system("sievec /etc/dovecot/sieve/learn-ham.sieve")
113
+ system("sievec /etc/dovecot/sieve/learn-spam.sieve")
114
+ system("chmod u=rwx,go= /etc/dovecot/sieve/learn-*.sh")
115
+ system("chown vmail:vmail /etc/dovecot/sieve/learn-*.sh")
116
+ system("chmod u=rw,go= /etc/dovecot/sieve/learn-*.sieve")
117
+ system("chown vmail:vmail /etc/dovecot/sieve/learn-*.sieve")
118
+ system("chmod u=rw,go= /etc/dovecot/sieve/learn-*.svbin")
119
+ system("chown vmail:vmail /etc/dovecot/sieve/learn-*.svbin")
120
+
121
+ system("sievec /etc/dovecot/sieve-after/spam-to-folder.sieve")
122
+ system("chmod u=rw,go= /etc/dovecot/sieve-after/spam-to-folder.sieve")
123
+ system("chown vmail:vmail /etc/dovecot/sieve-after/spam-to-folder.sieve")
124
+ system("chmod u=rw,go= /etc/dovecot/sieve-after/spam-to-folder.svbin")
125
+ system("chown vmail:vmail /etc/dovecot/sieve-after/spam-to-folder.svbin")
126
+
127
+ system("chown root:root /etc/dovecot/dovecot-sql.conf.ext")
128
+ system("chmod go= /etc/dovecot/dovecot-sql.conf.ext")
129
+
130
+ system("chmod +x /usr/local/bin/quota-warning.sh")
131
+
132
+ # Spamassassin
133
+ FileUtils.cp '/smartmachine/config/emailer/etc/spamassassin/local.cf', '/etc/spamassassin/local.cf'
134
+ system("adduser --gecos '' --disabled-login spamd", out: File::NULL)
135
+
136
+ # OpenDKIM
137
+ FileUtils.cp '/smartmachine/config/emailer/etc/opendkim.conf', '/etc/opendkim.conf'
138
+ system("adduser postfix opendkim", out: File::NULL)
139
+ system("chmod u=rw,go=r /etc/opendkim.conf")
140
+ unless File.exists? '/etc/opendkim/key.table'
141
+ FileUtils.mkdir_p '/etc/opendkim/keys'
142
+ FileUtils.touch '/etc/opendkim/key.table'
143
+ FileUtils.touch '/etc/opendkim/signing.table'
144
+ FileUtils.touch '/etc/opendkim/trusted.hosts'
145
+ key_shortname = envkeys[:mailname].gsub(/[^[:alnum:]]/, "")
146
+ raise "Could not create key_shortname from mailname to use in opendkim." if key_shortname.match(/\A[a-zA-Z0-9]*\z/).nil?
147
+ key_selector = Time.now.getlocal('+05:30').strftime("%Y%m")
148
+ raise "Could not create key_selector from Local Time to use in opendkim." if key_selector.match(/\A[0-9]*\z/).nil?
149
+ key_filename = "#{key_shortname}_#{key_selector}"
150
+ IO.write("/etc/opendkim/key.table",
151
+ "#{key_shortname} #{envkeys[:mailname]}:#{key_selector}:/etc/opendkim/keys/#{key_filename}.private\n")
152
+ IO.write("/etc/opendkim/signing.table",
153
+ "*@#{envkeys[:mailname]} #{key_shortname}\n")
154
+ IO.write("/etc/opendkim/trusted.hosts",
155
+ "127.0.0.1\n::1\nlocalhost\n#{envkeys[:fqdn]}\n#{envkeys[:mailname]}\n")
156
+ Dir.chdir("/etc/opendkim/keys") do
157
+ raise "Could not create DKIM keys." unless system("opendkim-genkey -b 2048 -h rsa-sha256 -r -s #{key_selector} -d #{envkeys[:mailname]} -v")
158
+ FileUtils.mv("#{key_selector}.private", "#{key_filename}.private")
159
+ FileUtils.mv("#{key_selector}.txt", "#{key_filename}.txt")
160
+ end
161
+ end
162
+ system("chown -R opendkim:opendkim /etc/opendkim")
163
+ system("chmod -R go-rw /etc/opendkim/keys")
164
+ system("mkdir /var/spool/postfix/opendkim")
165
+ system("chown opendkim:postfix /var/spool/postfix/opendkim")
166
+
167
+ # Haproxy
168
+ FileUtils.mkdir_p '/var/lib/haproxy/dev'
169
+ FileUtils.mkdir_p '/run/haproxy'
170
+ FileUtils.cp '/smartmachine/config/emailer/etc/haproxy/haproxy.cfg', '/etc/haproxy/haproxy.cfg'
171
+ filepaths = [
172
+ '/etc/haproxy/haproxy.cfg'
173
+ ]
174
+ update_envkeys_in(filepaths, envkeys)
175
+
176
+ # Monit
177
+ FileUtils.cp '/smartmachine/config/emailer/etc/monit/monitrc', '/etc/monit/monitrc'
178
+ FileUtils.cp_r '/smartmachine/config/emailer/etc/monit/conf.d/.', '/etc/monit/conf.d'
179
+ filepaths = [
180
+ '/etc/monit/conf.d/services.cfg',
181
+ '/etc/monit/monitrc'
182
+ ]
183
+ update_envkeys_in(filepaths, envkeys)
184
+
185
+ # Logtailer
186
+ FileUtils.cp '/smartmachine/config/emailer/docker/logtailer.rb', '/usr/bin/logtailer.rb'
187
+ system("chmod +x /usr/bin/logtailer.rb")
188
+
189
+ # Command
190
+ FileUtils.cp '/smartmachine/config/emailer/docker/command.rb', '/usr/bin/command.rb'
191
+ system("chmod +x /usr/bin/command.rb")
192
+
193
+ logger.info "Initial setup completed for #{envkeys[:container_name]}."
194
+ end
195
+
196
+ ARGV.empty? ? exec("/usr/bin/command.rb") : exec(*ARGV)
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ STDOUT.sync = true
5
+
6
+ require 'fileutils'
7
+
8
+ class Logtailer
9
+ def initialize
10
+ @tailers = {
11
+ "/var/log/monit.log" => 1,
12
+ "/var/log/haproxy.log" => 1,
13
+ "/var/log/mail.log" => 1,
14
+ "/home/spamd/spamd.log" => 1
15
+ }
16
+ end
17
+
18
+ def start
19
+ set_start_from_line
20
+
21
+ pids = []
22
+ @tailers.each do |path, start_from_line|
23
+ pid = Process.spawn("tail", "--lines=+#{start_from_line}", "-q", "-F", "#{path}", [:out, :err] => "/proc/1/fd/1")
24
+ Process.detach(pid)
25
+ pids.push(pid)
26
+ end
27
+ IO.write("/run/tmpfs/logtailer.pid", "#{pids.join(' ')}\n")
28
+
29
+ puts "Started Logtailer with PIDs " + `cat /run/tmpfs/logtailer.pid`.chomp + "."
30
+ end
31
+
32
+ def stop
33
+ pids = `cat /run/tmpfs/logtailer.pid`.chomp.split(" ")
34
+ pids.each do |pid|
35
+ system("/bin/kill --signal SIGTERM #{pid}")
36
+ end
37
+ save_start_from_line
38
+
39
+ puts "Stopped Logtailer with PIDs " + `cat /run/tmpfs/logtailer.pid`.chomp + "."
40
+ FileUtils.rm("/run/tmpfs/logtailer.pid")
41
+ end
42
+
43
+ def flush
44
+ set_start_from_line
45
+ @tailers.each do |path, start_from_line|
46
+ system("tail --lines=+#{start_from_line} -q #{path} >> /proc/1/fd/1")
47
+ end
48
+ save_start_from_line
49
+ end
50
+
51
+ private
52
+
53
+ def set_start_from_line
54
+ if File.exist?('/run/logtailer.lines')
55
+ lines = IO.read('/run/logtailer.lines').split("\n")
56
+ lines.each do |line|
57
+ previous_line_no, path = line.split(" ")
58
+ @tailers[path] = previous_line_no.to_i + 1
59
+ end
60
+ end
61
+ end
62
+
63
+ def save_start_from_line
64
+ str = `wc -l #{@tailers.keys.join(' ')} | head --lines=-1`
65
+ IO.write("/run/logtailer.lines", "#{str}")
66
+ end
67
+ end
68
+
69
+ if ARGV[0] == "start"
70
+ Logtailer.new.start
71
+ elsif ARGV[0] == "stop"
72
+ Logtailer.new.stop
73
+ elsif ARGV[0] == "flush"
74
+ Logtailer.new.flush
75
+ end
@@ -0,0 +1,132 @@
1
+ ##
2
+ ## Authentication processes
3
+ ##
4
+
5
+ # Disable LOGIN command and all other plaintext authentications unless
6
+ # SSL/TLS is used (LOGINDISABLED capability). Note that if the remote IP
7
+ # matches the local IP (ie. you're connecting from the same computer), the
8
+ # connection is considered secure and plaintext authentication is allowed.
9
+ # See also ssl=required setting.
10
+ #disable_plaintext_auth = yes
11
+
12
+ # Authentication cache size (e.g. 10M). 0 means it's disabled. Note that
13
+ # bsdauth and PAM require cache_key to be set for caching to be used.
14
+ #auth_cache_size = 0
15
+ # Time to live for cached data. After TTL expires the cached record is no
16
+ # longer used, *except* if the main database lookup returns internal failure.
17
+ # We also try to handle password changes automatically: If user's previous
18
+ # authentication was successful, but this one wasn't, the cache isn't used.
19
+ # For now this works only with plaintext authentication.
20
+ #auth_cache_ttl = 1 hour
21
+ # TTL for negative hits (user not found, password mismatch).
22
+ # 0 disables caching them completely.
23
+ #auth_cache_negative_ttl = 1 hour
24
+
25
+ # Space separated list of realms for SASL authentication mechanisms that need
26
+ # them. You can leave it empty if you don't want to support multiple realms.
27
+ # Many clients simply use the first one listed here, so keep the default realm
28
+ # first.
29
+ #auth_realms =
30
+
31
+ # Default realm/domain to use if none was specified. This is used for both
32
+ # SASL realms and appending @domain to username in plaintext logins.
33
+ #auth_default_realm =
34
+
35
+ # List of allowed characters in username. If the user-given username contains
36
+ # a character not listed in here, the login automatically fails. This is just
37
+ # an extra check to make sure user can't exploit any potential quote escaping
38
+ # vulnerabilities with SQL/LDAP databases. If you want to allow all characters,
39
+ # set this value to empty.
40
+ #auth_username_chars = abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890.-_@
41
+
42
+ # Username character translations before it's looked up from databases. The
43
+ # value contains series of from -> to characters. For example "#@/@" means
44
+ # that '#' and '/' characters are translated to '@'.
45
+ #auth_username_translation =
46
+
47
+ # Username formatting before it's looked up from databases. You can use
48
+ # the standard variables here, eg. %Lu would lowercase the username, %n would
49
+ # drop away the domain if it was given, or "%n-AT-%d" would change the '@' into
50
+ # "-AT-". This translation is done after auth_username_translation changes.
51
+ #auth_username_format = %Lu
52
+
53
+ # If you want to allow master users to log in by specifying the master
54
+ # username within the normal username string (ie. not using SASL mechanism's
55
+ # support for it), you can specify the separator character here. The format
56
+ # is then <username><separator><master username>. UW-IMAP uses "*" as the
57
+ # separator, so that could be a good choice.
58
+ #auth_master_user_separator =
59
+
60
+ # Username to use for users logging in with ANONYMOUS SASL mechanism
61
+ #auth_anonymous_username = anonymous
62
+
63
+ # Maximum number of dovecot-auth worker processes. They're used to execute
64
+ # blocking passdb and userdb queries (eg. MySQL and PAM). They're
65
+ # automatically created and destroyed as needed.
66
+ #auth_worker_max_count = 30
67
+
68
+ # Host name to use in GSSAPI principal names. The default is to use the
69
+ # name returned by gethostname(). Use "$ALL" (with quotes) to allow all keytab
70
+ # entries.
71
+ #auth_gssapi_hostname =
72
+
73
+ # Kerberos keytab to use for the GSSAPI mechanism. Will use the system
74
+ # default (usually /etc/krb5.keytab) if not specified. You may need to change
75
+ # the auth service to run as root to be able to read this file.
76
+ #auth_krb5_keytab =
77
+
78
+ # Do NTLM and GSS-SPNEGO authentication using Samba's winbind daemon and
79
+ # ntlm_auth helper. <doc/wiki/Authentication/Mechanisms/Winbind.txt>
80
+ #auth_use_winbind = no
81
+
82
+ # Path for Samba's ntlm_auth helper binary.
83
+ #auth_winbind_helper_path = /usr/bin/ntlm_auth
84
+
85
+ # Time to delay before replying to failed authentications.
86
+ #auth_failure_delay = 2 secs
87
+
88
+ # Require a valid SSL client certificate or the authentication fails.
89
+ #auth_ssl_require_client_cert = no
90
+
91
+ # Take the username from client's SSL certificate, using
92
+ # X509_NAME_get_text_by_NID() which returns the subject's DN's
93
+ # CommonName.
94
+ #auth_ssl_username_from_cert = no
95
+
96
+ # Space separated list of wanted authentication mechanisms:
97
+ # plain login digest-md5 cram-md5 ntlm rpa apop anonymous gssapi otp
98
+ # gss-spnego
99
+ # NOTE: See also disable_plaintext_auth setting.
100
+ ##### SmartMachine Begin.
101
+ #auth_mechanisms = plain
102
+ auth_mechanisms = plain login
103
+ ##### SmartMachine Close.
104
+
105
+ ##
106
+ ## Password and user databases
107
+ ##
108
+
109
+ #
110
+ # Password database is used to verify user's password (and nothing more).
111
+ # You can have multiple passdbs and userdbs. This is useful if you want to
112
+ # allow both system users (/etc/passwd) and virtual users to login without
113
+ # duplicating the system users into virtual database.
114
+ #
115
+ # <doc/wiki/PasswordDatabase.txt>
116
+ #
117
+ # User database specifies where mails are located and what user/group IDs
118
+ # own them. For single-UID configuration use "static" userdb.
119
+ #
120
+ # <doc/wiki/UserDatabase.txt>
121
+
122
+ #!include auth-deny.conf.ext
123
+ #!include auth-master.conf.ext
124
+
125
+ ##### SmartMachine Begin.
126
+ #!include auth-system.conf.ext
127
+ !include auth-sql.conf.ext
128
+ ##### SmartMachine Close.
129
+ #!include auth-ldap.conf.ext
130
+ #!include auth-passwdfile.conf.ext
131
+ #!include auth-checkpassword.conf.ext
132
+ #!include auth-static.conf.ext