ConfigLMM 0.3.0 → 0.4.0

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 (99) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +36 -0
  3. data/Plugins/Apps/Authentik/Authentik-ProxyOutpost.container +14 -0
  4. data/Plugins/Apps/Authentik/Authentik-Server.container +1 -0
  5. data/Plugins/Apps/Authentik/Authentik-Worker.container +1 -0
  6. data/Plugins/Apps/Authentik/Authentik.conf.erb +7 -0
  7. data/Plugins/Apps/Authentik/Authentik.lmm.rb +24 -2
  8. data/Plugins/Apps/BookStack/BookStack.conf.erb +41 -0
  9. data/Plugins/Apps/BookStack/BookStack.container +15 -0
  10. data/Plugins/Apps/BookStack/BookStack.lmm.rb +80 -0
  11. data/Plugins/Apps/Discourse/Discourse-Sidekiq.container +17 -0
  12. data/Plugins/Apps/Discourse/Discourse.conf.erb +41 -0
  13. data/Plugins/Apps/Discourse/Discourse.container +17 -0
  14. data/Plugins/Apps/Discourse/Discourse.lmm.rb +95 -0
  15. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +25 -2
  16. data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +19 -0
  17. data/Plugins/Apps/ERPNext/ERPNext-Queue.container +17 -0
  18. data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +17 -0
  19. data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +19 -0
  20. data/Plugins/Apps/ERPNext/ERPNext.container +18 -0
  21. data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +193 -0
  22. data/Plugins/Apps/ERPNext/ERPNext.network +12 -0
  23. data/Plugins/Apps/ERPNext/sites/apps.json +10 -0
  24. data/Plugins/Apps/ERPNext/sites/apps.txt +3 -0
  25. data/Plugins/Apps/ERPNext/sites/common_site_config.json +11 -0
  26. data/Plugins/Apps/GitLab/GitLab.container +3 -2
  27. data/Plugins/Apps/GitLab/GitLab.lmm.rb +37 -12
  28. data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +57 -0
  29. data/Plugins/Apps/LetsEncrypt/hooks/dovecot.sh +2 -0
  30. data/Plugins/Apps/LetsEncrypt/hooks/nginx.sh +2 -0
  31. data/Plugins/Apps/LetsEncrypt/hooks/postfix.sh +2 -0
  32. data/Plugins/Apps/LetsEncrypt/renew-certificates.service +7 -0
  33. data/Plugins/Apps/LetsEncrypt/renew-certificates.timer +12 -0
  34. data/Plugins/Apps/LetsEncrypt/rfc2136.ini +11 -0
  35. data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +115 -0
  36. data/Plugins/Apps/Matrix/Element.container +14 -0
  37. data/Plugins/Apps/Matrix/Matrix.conf.erb +49 -5
  38. data/Plugins/Apps/Matrix/Matrix.lmm.rb +86 -1
  39. data/Plugins/Apps/Matrix/Synapse.container +17 -0
  40. data/Plugins/Apps/Matrix/config.json +50 -0
  41. data/Plugins/Apps/Matrix/homeserver.yaml +70 -0
  42. data/Plugins/Apps/Matrix/log.config +30 -0
  43. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +70 -45
  44. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +9 -0
  45. data/Plugins/Apps/Nginx/config-lmm/errors.conf +10 -4
  46. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +5 -1
  47. data/Plugins/Apps/Nginx/nginx.lmm.rb +15 -11
  48. data/Plugins/Apps/Nginx/proxy.conf.erb +13 -3
  49. data/Plugins/Apps/Odoo/Odoo.container +2 -1
  50. data/Plugins/Apps/Odoo/Odoo.lmm.rb +1 -1
  51. data/Plugins/Apps/OpenVidu/Ingress.container +18 -0
  52. data/Plugins/Apps/OpenVidu/OpenVidu.conf.erb +34 -0
  53. data/Plugins/Apps/OpenVidu/OpenVidu.container +16 -0
  54. data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +90 -0
  55. data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +35 -0
  56. data/Plugins/Apps/OpenVidu/OpenViduCall.container +15 -0
  57. data/Plugins/Apps/OpenVidu/ingress.yaml +10 -0
  58. data/Plugins/Apps/OpenVidu/livekit.yaml +13 -0
  59. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +0 -4
  60. data/Plugins/Apps/Peppermint/Peppermint.container +2 -1
  61. data/Plugins/Apps/Postfix/Postfix.lmm.rb +32 -6
  62. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +80 -11
  63. data/Plugins/Apps/Roundcube/Roundcube.conf.erb +75 -0
  64. data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +145 -0
  65. data/Plugins/Apps/Tunnel/tunnel.lmm.rb +63 -0
  66. data/Plugins/Apps/Tunnel/tunnelTCP.service +9 -0
  67. data/Plugins/Apps/Tunnel/tunnelTCP.socket +9 -0
  68. data/Plugins/Apps/Tunnel/tunnelUDP.service +9 -0
  69. data/Plugins/Apps/Tunnel/tunnelUDP.socket +9 -0
  70. data/Plugins/Apps/Valkey/Valkey.lmm.rb +32 -0
  71. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +4 -0
  72. data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +42 -0
  73. data/Plugins/Apps/Wiki.js/Wiki.js.container +15 -0
  74. data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +61 -0
  75. data/Plugins/Apps/gollum/gollum.conf.erb +39 -1
  76. data/Plugins/Apps/gollum/gollum.container +4 -1
  77. data/Plugins/Apps/gollum/gollum.lmm.rb +11 -3
  78. data/Plugins/OS/Linux/Debian/preseed.cfg.erb +62 -0
  79. data/Plugins/OS/Linux/Distributions.yaml +32 -0
  80. data/Plugins/OS/Linux/Flavours.yaml +11 -0
  81. data/Plugins/OS/Linux/Linux.lmm.rb +255 -67
  82. data/Plugins/OS/Linux/Packages.yaml +47 -2
  83. data/Plugins/OS/Linux/Proxmox/answer.toml.erb +30 -0
  84. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +33 -4
  85. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +1 -1
  86. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +3 -2
  87. data/Plugins/Services/DNS/PowerDNS.lmm.rb +95 -8
  88. data/bootstrap.sh +41 -3
  89. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +146 -64
  90. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +34 -3
  91. data/lib/ConfigLMM/Framework/plugins/plugin.rb +62 -6
  92. data/lib/ConfigLMM/cli.rb +3 -1
  93. data/lib/ConfigLMM/commands/cleanup.rb +1 -0
  94. data/lib/ConfigLMM/commands/configsCommand.rb +3 -1
  95. data/lib/ConfigLMM/io/configList.rb +3 -1
  96. data/lib/ConfigLMM/state.rb +10 -2
  97. data/lib/ConfigLMM/version.rb +1 -1
  98. metadata +54 -3
  99. data/Plugins/Apps/GitLab/GitLab.conf.erb +0 -26
@@ -4,7 +4,7 @@ Description=Odoo container
4
4
  After=local-fs.target
5
5
 
6
6
  [Container]
7
- Image=odoo:latest
7
+ Image=docker.io/odoo:latest
8
8
  EnvironmentFile=/var/lib/odoo/.config/containers/systemd/Odoo.env
9
9
  Network=slirp4netns:allow_host_loopback=true
10
10
  PublishPort=0.0.0.0:8069:8069
@@ -12,6 +12,7 @@ UserNS=keep-id:uid=101,gid=101
12
12
  Volume=/var/lib/odoo/config:/etc/odoo
13
13
  Volume=/var/lib/odoo/data:/var/lib/odoo
14
14
  Volume=/var/lib/odoo/addons:/mnt/extra-addons
15
+ AutoUpdate=registry
15
16
 
16
17
  [Install]
17
18
  WantedBy=multi-user.target default.target
@@ -71,7 +71,7 @@ module ConfigLMM
71
71
  def configurePostgreSQL(settings, ssh)
72
72
  user = USER
73
73
  password = SecureRandom.alphanumeric(20)
74
- PostgreSQL.executeRemotelyOverSSH(settings, ssh) do |ssh|
74
+ PostgreSQL.executeRemotely(settings, ssh) do |ssh|
75
75
  self.class.sshExec!(ssh, "su --login #{PostgreSQL::USER_NAME} --command 'createuser --createdb #{user}'", true)
76
76
  PostgreSQL.executeSQL("ALTER USER #{user} WITH PASSWORD '#{password}'", nil, ssh)
77
77
  end
@@ -0,0 +1,18 @@
1
+
2
+ [Unit]
3
+ Description=LiveKit Ingress container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ Image=docker.io/livekit/ingress:latest
8
+ EnvironmentFile=/var/lib/openvidu/.config/containers/systemd/OpenVidu.env
9
+ Network=slirp4netns:allow_host_loopback=true
10
+ PublishPort=127.0.0.1:1935:1935
11
+ PublishPort=127.0.0.1:8085:8085
12
+ PublishPort=127.0.0.1:7895:7895/udp
13
+ UserNS=keep-id:uid=1000,gid=1000
14
+ Volume=/var/lib/openvidu/ingress.yaml:/etc/ingress.yaml
15
+ AutoUpdate=registry
16
+
17
+ [Install]
18
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,34 @@
1
+
2
+ server {
3
+ <% if config['NginxVersion'] >= 1.25 %>
4
+ listen 443 ssl;
5
+ listen [::]:443 ssl;
6
+ http2 on;
7
+ http3 on;
8
+ quic_retry on;
9
+ add_header Alt-Svc 'h3=":443"; ma=86400';
10
+ <% else %>
11
+ listen 443 ssl http2;
12
+ listen [::]:443 ssl http2;
13
+ <% end %>
14
+
15
+ include config-lmm/ssl.conf;
16
+
17
+ server_name <%= config['Domain'] %>;
18
+
19
+ <% if config['CertName'] %>
20
+ ssl_certificate "/etc/letsencrypt/live/<%= config['CertName'] %>/fullchain.pem";
21
+ ssl_certificate_key "/etc/letsencrypt/live/<%= config['CertName'] %>/privkey.pem";
22
+ ssl_trusted_certificate "/etc/letsencrypt/live/<%= config['CertName'] %>/chain.pem";
23
+ <% end %>
24
+
25
+ access_log /var/log/nginx/openvidu.access.log;
26
+ error_log /var/log/nginx/openvidu.error.log;
27
+
28
+ # Proxy site
29
+ location / {
30
+ proxy_pass http://127.0.0.1:7880;
31
+ include config-lmm/proxy.conf;
32
+ }
33
+
34
+ }
@@ -0,0 +1,16 @@
1
+
2
+ [Unit]
3
+ Description=OpenVidu container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ Image=docker.io/openvidu/openvidu-server:main
8
+ Exec=--config /etc/livekit.yaml --bind=$BindIP
9
+ EnvironmentFile=/var/lib/openvidu/.config/containers/systemd/OpenVidu.env
10
+ Network=host
11
+ UserNS=keep-id:uid=1000,gid=1000
12
+ Volume=/var/lib/openvidu/livekit.yaml:/etc/livekit.yaml
13
+ AutoUpdate=registry
14
+
15
+ [Install]
16
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,90 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class OpenVidu < Framework::NginxApp
5
+
6
+ USER = 'openvidu'
7
+ HOME_DIR = '/var/lib/openvidu'
8
+ HOST_IP = '10.0.2.2'
9
+
10
+ def actionOpenViduDeploy(id, target, activeState, context, options)
11
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
12
+ raise Framework::PluginProcessError.new('CallDomain field must be set!') unless target['CallDomain']
13
+
14
+ if target['Location'] && target['Location'] != '@me'
15
+ uri = Addressable::URI.parse(target['Location'])
16
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
17
+
18
+ self.class.sshStart(uri) do |ssh|
19
+
20
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
21
+ Framework::LinuxApp.configurePodmanServiceOverSSH(USER, HOME_DIR, 'OpenVidu', distroInfo, ssh)
22
+
23
+ secretKey = SecureRandom.alphanumeric(40)
24
+ bindIp = target['BindIP']
25
+ bindIp = '127.0.0.1' unless bindIp
26
+
27
+ path = Framework::LinuxApp::SYSTEMD_CONTAINERS_PATH.gsub('~', HOME_DIR)
28
+ self.class.exec("echo 'INGRESS_CONFIG_FILE=/etc/ingress.yaml' > #{path}/OpenVidu.env", ssh)
29
+ self.class.exec("echo 'LIVEKIT_URL=wss://#{target['Domain']}' >> #{path}/OpenVidu.env", ssh)
30
+ self.class.exec("echo 'LIVEKIT_API_KEY=Main' >> #{path}/OpenVidu.env", ssh)
31
+ self.class.exec("echo 'LIVEKIT_API_SECRET=#{secretKey}' >> #{path}/OpenVidu.env", ssh)
32
+ self.class.exec("echo 'CALL_PRIVATE_ACCESS=true' >> #{path}/OpenVidu.env", ssh)
33
+ self.class.exec("echo 'CALL_USER=guest' >> #{path}/OpenVidu.env", ssh)
34
+ callSecret = SecureRandom.alphanumeric(20)
35
+ prompt.say("OpenVidu Call guest password: #{callSecret}", :color => :magenta)
36
+ self.class.exec("echo 'CALL_SECRET=#{callSecret}' >> #{path}/OpenVidu.env", ssh)
37
+ self.class.exec("echo 'CALL_ADMIN_USER=admin' >> #{path}/OpenVidu.env", ssh)
38
+ callAdminSecret = SecureRandom.alphanumeric(20)
39
+ prompt.say("OpenVidu Call admin password: #{callAdminSecret}", :color => :magenta)
40
+ self.class.exec("echo 'CALL_ADMIN_SECRET=#{callAdminSecret}' >> #{path}/OpenVidu.env", ssh)
41
+
42
+ ssh.scp.upload!(__dir__ + '/livekit.yaml', HOME_DIR)
43
+ ssh.scp.upload!(__dir__ + '/ingress.yaml', HOME_DIR)
44
+
45
+ self.class.exec("sed -i 's|$SECRET|#{secretKey}|' #{HOME_DIR}/livekit.yaml", ssh)
46
+
47
+ if target['Valkey']
48
+ self.class.exec("sed -i 's|10.0.2.2|#{target['Valkey']['Host']}|' #{HOME_DIR}/ingress.yaml", ssh) if target['Valkey']['Host']
49
+ end
50
+ if ENV['VALKEY_PASSWORD']
51
+ self.class.exec("sed -i 's|password:|password: #{ENV['VALKEY_PASSWORD']}|' #{HOME_DIR}/ingress.yaml", ssh)
52
+ end
53
+
54
+ self.class.exec("chown #{USER}:#{USER} #{path}/OpenVidu.env #{HOME_DIR}/livekit.yaml #{HOME_DIR}/ingress.yaml", ssh)
55
+ self.class.exec("chmod 600 #{path}/OpenVidu.env #{HOME_DIR}/livekit.yaml #{HOME_DIR}/ingress.yaml", ssh)
56
+
57
+ ssh.scp.upload!(__dir__ + '/OpenVidu.container', path)
58
+ ssh.scp.upload!(__dir__ + '/OpenViduCall.container', path)
59
+ ssh.scp.upload!(__dir__ + '/Ingress.container', path)
60
+
61
+ self.class.exec("sed -i 's|$BindIP|#{bindIp}|' #{path}/OpenVidu.container", ssh)
62
+
63
+ Framework::LinuxApp.firewallAddPortOverSSH('7881/tcp', ssh)
64
+ Framework::LinuxApp.firewallAddPortOverSSH('7900-7999/udp', ssh)
65
+ Framework::LinuxApp.firewallAddPortOverSSH('45000-55000/udp', ssh)
66
+
67
+ self.class.exec("systemctl --user --machine=#{USER}@ daemon-reload", ssh)
68
+ self.class.exec("systemctl --user --machine=#{USER}@ restart OpenVidu", ssh)
69
+ self.class.exec("systemctl --user --machine=#{USER}@ restart OpenViduCall", ssh)
70
+ self.class.exec("systemctl --user --machine=#{USER}@ restart Ingress", ssh)
71
+
72
+ Framework::LinuxApp.ensurePackages([NGINX_PACKAGE], ssh)
73
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(NGINX_PACKAGE, ssh)
74
+ self.class.prepareNginxConfig(target, ssh)
75
+ target['CallDomain'] = Addressable::IDNA.to_ascii(target['CallDomain'])
76
+ self.writeNginxConfig(__dir__, 'OpenVidu', id, target, state, context, options)
77
+ self.writeNginxConfig(__dir__, 'OpenViduCall', id, target, state, context, options)
78
+ self.deployNginxConfig(id, target, activeState, context, options)
79
+ Framework::LinuxApp.startServiceOverSSH(NGINX_PACKAGE, ssh)
80
+
81
+ end
82
+ else
83
+ # TODO
84
+ end
85
+ end
86
+
87
+ end
88
+ end
89
+ end
90
+
@@ -0,0 +1,35 @@
1
+
2
+ server {
3
+ <% if config['NginxVersion'] >= 1.25 %>
4
+ listen 443 ssl;
5
+ listen [::]:443 ssl;
6
+ http2 on;
7
+ http3 on;
8
+ quic_retry on;
9
+ add_header Alt-Svc 'h3=":443"; ma=86400';
10
+ <% else %>
11
+ listen 443 ssl http2;
12
+ listen [::]:443 ssl http2;
13
+ <% end %>
14
+
15
+ include config-lmm/ssl.conf;
16
+
17
+ server_name <%= config['CallDomain'] %>;
18
+
19
+ <% if config['CallCertName'] %>
20
+ ssl_certificate "/etc/letsencrypt/live/<%= config['CallCertName'] %>/fullchain.pem";
21
+ ssl_certificate_key "/etc/letsencrypt/live/<%= config['CallCertName'] %>/privkey.pem";
22
+ ssl_trusted_certificate "/etc/letsencrypt/live/<%= config['CallCertName'] %>/chain.pem";
23
+ <% end %>
24
+
25
+ access_log /var/log/nginx/openvidu-call.access.log;
26
+ error_log /var/log/nginx/openvidu-call.error.log;
27
+
28
+ # Proxy site
29
+ location / {
30
+ proxy_pass http://127.0.0.1:6080;
31
+ include config-lmm/proxy.conf;
32
+ }
33
+
34
+ }
35
+
@@ -0,0 +1,15 @@
1
+
2
+
3
+ [Unit]
4
+ Description=OpenVidu Call container
5
+ After=local-fs.target
6
+
7
+ [Container]
8
+ Image=docker.io/openvidu/openvidu-call:main
9
+ EnvironmentFile=/var/lib/openvidu/.config/containers/systemd/OpenVidu.env
10
+ PublishPort=127.0.0.1:6080:6080
11
+ UserNS=keep-id:uid=1000,gid=1000
12
+ AutoUpdate=registry
13
+
14
+ [Install]
15
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,10 @@
1
+ redis:
2
+ address: 10.0.2.2:6379
3
+ username: ""
4
+ password:
5
+
6
+ cpu_cost:
7
+ rtmp_cpu_cost: 2
8
+ whip_cpu_cost: 2
9
+ whip_bypass_transcoding_cpu_cost: 0.1
10
+ url_cpu_cost: 2
@@ -0,0 +1,13 @@
1
+ keys:
2
+ Main: $SECRET
3
+
4
+ rtc:
5
+ tcp_port: 7881
6
+ port_range_start: 7900
7
+ port_range_end: 7999
8
+
9
+ turn:
10
+ enabled: true
11
+ udp_port: 3478
12
+ relay_range_start: 45000
13
+ relay_range_end: 55000
@@ -1,9 +1,5 @@
1
1
 
2
2
  server {
3
- listen 80;
4
- listen [::]:80;
5
- server_name peppermint.example.com;
6
- add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
7
3
 
8
4
  <% if !config['TLS'] %>
9
5
  listen <%= config['Port'] %>;
@@ -4,11 +4,12 @@ Description=Peppermint Ticket Management container
4
4
  After=local-fs.target
5
5
 
6
6
  [Container]
7
- Image=pepperlabs/peppermint:latest
7
+ Image=docker.io/pepperlabs/peppermint:latest
8
8
  EnvironmentFile=/var/lib/peppermint/.config/containers/systemd/Peppermint.env
9
9
  Network=slirp4netns:allow_host_loopback=true
10
10
  PublishPort=127.0.0.1:13000:3000
11
11
  PublishPort=127.0.0.1:15003:5003
12
+ AutoUpdate=registry
12
13
 
13
14
  [Install]
14
15
  WantedBy=multi-user.target default.target
@@ -12,9 +12,13 @@ module ConfigLMM
12
12
  plugins[:Linux].ensurePackages([PACKAGE_NAME, 'CyrusSASL'], target['Location'])
13
13
  plugins[:Linux].ensureServiceAutoStart(SERVICE_NAME, target['Location'])
14
14
 
15
+ activeState['Instance'] = target['Instance']
16
+ activeState['AlternativePort'] = target['AlternativePort']
15
17
  deploySettings(target, target['Location'], options)
16
18
 
17
19
  plugins[:Linux].startService(SERVICE_NAME, target['Location'])
20
+
21
+ activeState['Status'] = State::STATUS_DEPLOYED
18
22
  end
19
23
 
20
24
  def deploySettings(target, location, options)
@@ -91,14 +95,11 @@ module ConfigLMM
91
95
 
92
96
 
93
97
  if target['AlternativePort']
94
- self.class.sshExec!(ssh, "firewall-cmd -q --add-port='#{target['AlternativePort']}/tcp'")
95
- self.class.sshExec!(ssh, "firewall-cmd -q --permanent --add-port='#{target['AlternativePort']}/tcp'")
98
+ Framework::LinuxApp.firewallAddPort("#{target['AlternativePort']}/tcp", ssh)
96
99
  else
97
- self.class.sshExec!(ssh, "firewall-cmd -q --add-service='smtp'")
98
- self.class.sshExec!(ssh, "firewall-cmd -q --permanent --add-service='smtp'")
100
+ Framework::LinuxApp.firewallAddService('smtp', ssh)
99
101
  end
100
- self.class.sshExec!(ssh, "firewall-cmd -q --add-service='smtps'")
101
- self.class.sshExec!(ssh, "firewall-cmd -q --permanent --add-service='smtps'")
102
+ Framework::LinuxApp.firewallAddService('smtps', ssh)
102
103
 
103
104
  ssh.scp.upload!(__dir__ + '/smtpd.conf', '/etc/sasl2/smtpd.conf')
104
105
  self.class.sshExec!(ssh, "touch /etc/sasldb2")
@@ -178,6 +179,31 @@ module ConfigLMM
178
179
  end
179
180
  end
180
181
 
182
+ def cleanup(configs, state, context, options)
183
+ cleanupType(:Postfix, configs, state, context, options) do |item, id, state, context, options, ssh|
184
+ instances = self.class.exec('postmulti -l | wc -l', ssh, true).strip.to_i
185
+ if instances <= 1
186
+ Framework::LinuxApp.stopService(SERVICE_NAME, ssh, options[:dry])
187
+ Framework::LinuxApp.firewallRemoveService('smtps', ssh, options[:dry])
188
+ if item['AlternativePort']
189
+ Framework::LinuxApp.firewallRemovePort("#{item['AlternativePort']}/tcp", ssh, options[:dry])
190
+ else
191
+ Framework::LinuxApp.firewallRemoveService('smtp', ssh, options[:dry])
192
+ end
193
+ Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
194
+
195
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
196
+
197
+ if options[:destroy]
198
+ rm('/etc/postfix', options[:dry], ssh)
199
+
200
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
201
+ end
202
+ else
203
+ prompt.say('Postfix multiple instance cleanup not implemented!', :color => :red)
204
+ end
205
+ end
206
+ end
181
207
  end
182
208
 
183
209
  end
@@ -12,26 +12,60 @@ module ConfigLMM
12
12
  CONFIG_FILE = 'data/postgresql.conf'
13
13
 
14
14
  def actionPostgreSQLDeploy(id, target, activeState, context, options)
15
- self.ensurePackage(PACKAGE_NAME, target['Location'])
16
- self.ensureServiceAutoStart(SERVICE_NAME, target['Location'])
17
- self.startService(SERVICE_NAME, target['Location'])
15
+ target['Deploy'] = !!(target['ListenAll'] || target['Listen'] || target['Settings']) unless target.key?('Deploy')
16
+ activeState['Deploy'] = target['Deploy']
17
+ activeState['Users'] = target['Users']
18
+ activeState['Databases'] = target['Databases']
19
+ activeState['Publications'] = target['Publications']
20
+ activeState['Subscriptions'] = target['Subscriptions']
21
+
22
+ if target['Deploy']
23
+ self.ensurePackage(PACKAGE_NAME, target['Location'])
24
+ self.ensureServiceAutoStart(SERVICE_NAME, target['Location'])
25
+ self.startService(SERVICE_NAME, target['Location'])
26
+ end
18
27
 
19
28
  if target['Location'] && target['Location'] != '@me'
20
29
  uri = Addressable::URI.parse(target['Location'])
21
30
  raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
22
31
 
23
32
  self.class.sshStart(uri) do |ssh|
24
- self.updateSettingsOverSSH(target, ssh, options)
25
- self.class.sshExec!(ssh, "su --login #{USER_NAME} --command 'pg_ctl reload'")
33
+ if target['Deploy']
34
+ self.updateSettingsOverSSH(target, ssh, options)
35
+ self.class.sshExec!(ssh, "su --login #{USER_NAME} --command 'pg_ctl reload'")
36
+ end
26
37
  self.class.createUsersOverSSH(target, ssh)
27
38
  self.class.createDatabasesOverSSH(target, ssh)
28
39
  self.class.createPublicationsOverSSH(target, ssh)
29
40
  self.class.createSubscriptionsOverSSH(target, ssh)
30
41
  end
31
42
  else
32
- `pg_ctl reload`
43
+ if target['Deploy']
44
+ `pg_ctl reload`
45
+ end
33
46
  end
34
47
 
48
+ activeState['Status'] = State::STATUS_DEPLOYED
49
+ end
50
+
51
+ def cleanup(configs, state, context, options)
52
+ cleanupType(:PostgreSQL, configs, state, context, options) do |item, id, state, context, options, ssh|
53
+ if item['Deploy']
54
+ Framework::LinuxApp.stopService(SERVICE_NAME, ssh, options[:dry])
55
+ Framework::LinuxApp.disableService(SERVICE_NAME, ssh, options[:dry])
56
+ Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
57
+
58
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
59
+
60
+ if options[:destroy]
61
+ Framework::LinuxApp.deleteUserAndGroup(USER_NAME, ssh, options[:dry])
62
+
63
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
64
+ end
65
+ else
66
+ # TODO
67
+ end
68
+ end
35
69
  end
36
70
 
37
71
  def updateListenLocal(target)
@@ -154,6 +188,26 @@ module ConfigLMM
154
188
  self.sshExec!(ssh, cmd)
155
189
  end
156
190
 
191
+ def self.updateOwner(db, owner, ssh)
192
+ sql = "SELECT tablename FROM pg_tables WHERE NOT schemaname IN ('pg_catalog', 'information_schema')"
193
+ tables = self.executeSQL(sql, db, ssh, false, ['--csv', '--tuples-only']).strip.lines
194
+ tables.each do |table|
195
+ self.executeSQL("ALTER TABLE public.#{table} OWNER TO #{owner};", db, ssh)
196
+ end
197
+
198
+ sql = "SELECT sequence_name FROM information_schema.sequences WHERE NOT sequence_schema IN ('pg_catalog', 'information_schema')"
199
+ sequences = self.executeSQL(sql, db, ssh, false, ['--csv', '--tuples-only']).strip.lines
200
+ sequences.each do |sequence|
201
+ self.executeSQL("ALTER SEQUENCE public.#{sequence} OWNER TO #{owner};", db, ssh)
202
+ end
203
+
204
+ sql = "SELECT table_name FROM information_schema.views WHERE NOT table_schema IN ('pg_catalog', 'information_schema')"
205
+ views = self.executeSQL(sql, db, ssh, false, ['--csv', '--tuples-only']).strip.lines
206
+ views.each do |view|
207
+ self.executeSQL("ALTER VIEW public.#{view} OWNER TO #{owner};", db, ssh)
208
+ end
209
+ end
210
+
157
211
  def updateConfigOverSSH(ssh, cmd)
158
212
  dir = ''
159
213
  distroID = self.class.distroID(ssh)
@@ -163,12 +217,27 @@ module ConfigLMM
163
217
  end
164
218
 
165
219
  def self.createRemoteUserAndDBOverSSH(settings, user, password, ssh)
166
- self.executeRemotelyOverSSH(settings, ssh) do |ssh|
167
- self.createUserAndDBOverSSH(user, password, ssh)
220
+ self.executeRemotely(settings, ssh) do |ssh|
221
+ self.createUserAndDBOverSSH(user, password, ssh)
222
+ end
223
+ end
224
+
225
+ def self.dropUserAndDB(settings, user, ssh, dry)
226
+ self.executeRemotely(settings, ssh) do |ssh|
227
+ self.exec("su --login #{USER_NAME} --command 'dropdb #{user}'", ssh, true, dry)
228
+ self.exec("su --login #{USER_NAME} --command 'dropuser #{user}'", ssh, true, dry)
229
+ end
230
+ end
231
+
232
+ def self.createExtensions(settings, db, extensions, ssh)
233
+ self.executeRemotely(settings, ssh) do |ssh|
234
+ extensions.each do |extension|
235
+ self.executeSQL("CREATE EXTENSION #{extension}", db, ssh, true)
168
236
  end
237
+ end
169
238
  end
170
239
 
171
- def self.executeRemotelyOverSSH(settings, ssh)
240
+ def self.executeRemotely(settings, ssh = nil)
172
241
  settings['HostName'] = 'localhost' unless settings['HostName']
173
242
  if settings['HostName'] == 'localhost'
174
243
  yield(ssh)
@@ -199,10 +268,10 @@ module ConfigLMM
199
268
  end
200
269
  end
201
270
 
202
- def self.executeSQL(sql, db, ssh = nil, allowFailure = false)
271
+ def self.executeSQL(sql, db, ssh = nil, allowFailure = false, options = [])
203
272
  if ssh
204
273
  db = 'postgres' unless db
205
- cmd = " su --login #{USER_NAME} --command ' psql --dbname=#{db} --command=\"#{sql.gsub("'", "\\\\'")};\"'"
274
+ cmd = " su --login #{USER_NAME} --command ' psql #{options.join(' ')} --dbname=#{db} --command=\"#{sql.gsub("'", "'\"'\"'")};\"'"
206
275
  self.sshExec!(ssh, cmd, allowFailure)
207
276
  else
208
277
  # TODO
@@ -0,0 +1,75 @@
1
+
2
+ upstream roundcube
3
+ {
4
+ <% if config['Server'] %>
5
+ server <%= config['Server'] %>;
6
+ <% else %>
7
+ server unix:/run/php-fpm/roundcube.sock;
8
+ <% end %>
9
+ }
10
+
11
+ server
12
+ {
13
+ <% if !config['TLS'] %>
14
+ listen <%= config['Port'] %>;
15
+ listen [::]:<%= config['Port'] %>;
16
+ <% else %>
17
+ <% if config['NginxVersion'] >= 1.25 %>
18
+ listen <%= config['Port'] %> ssl;
19
+ listen [::]:<%= config['Port'] %> ssl;
20
+ http2 on;
21
+ http3 on;
22
+ quic_retry on;
23
+ add_header Alt-Svc 'h3=":<%= config['Port'] %>"; ma=86400';
24
+ <% else %>
25
+ listen <%= config['Port'] %> ssl http2;
26
+ listen [::]:<%= config['Port'] %> ssl http2;
27
+ <% end %>
28
+
29
+ include config-lmm/ssl.conf;
30
+ <% end %>
31
+
32
+ server_name <%= config['Domain'] %>;
33
+
34
+ access_log /var/log/nginx/roundcube.access.log;
35
+ error_log /var/log/nginx/roundcube.error.log;
36
+
37
+ index index.php;
38
+ root /usr/share/webapps/roundcubemail;
39
+
40
+ include config-lmm/private.conf;
41
+ include config-lmm/errors.conf;
42
+
43
+ location / {
44
+ try_files $uri $uri/ $uri/index.php;
45
+ }
46
+
47
+ location ~ \.php$
48
+ {
49
+ fastcgi_pass roundcube;
50
+ include fastcgi.conf;
51
+
52
+ try_files $uri =404;
53
+ fastcgi_index index.php;
54
+ fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
55
+ include fastcgi_params;
56
+
57
+ fastcgi_intercept_errors off;
58
+ }
59
+
60
+ location ~ ^/(README|INSTALL|LICENSE|CHANGELOG|UPGRADING)$
61
+ {
62
+ deny all;
63
+ }
64
+
65
+ location ~ ^/(bin|SQL)/
66
+ {
67
+ deny all;
68
+ }
69
+
70
+ location ~* \.(jpg|jpeg|gif|png|webp|svg|woff|woff2|ttf|css|js|ico|xml)$
71
+ {
72
+ access_log off;
73
+ expires 360d;
74
+ }
75
+ }