ConfigLMM 0.2.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 (121) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +67 -0
  3. data/Examples/Implemented.mm.yaml +75 -1
  4. data/Plugins/Apps/Authentik/Authentik-ProxyOutpost.container +14 -0
  5. data/Plugins/Apps/Authentik/Authentik-Server.container +19 -0
  6. data/Plugins/Apps/Authentik/Authentik-Worker.container +18 -0
  7. data/Plugins/Apps/Authentik/Authentik.conf.erb +42 -0
  8. data/Plugins/Apps/Authentik/Authentik.lmm.rb +95 -0
  9. data/Plugins/Apps/BookStack/BookStack.conf.erb +41 -0
  10. data/Plugins/Apps/BookStack/BookStack.container +15 -0
  11. data/Plugins/Apps/BookStack/BookStack.lmm.rb +80 -0
  12. data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +41 -0
  13. data/Plugins/Apps/Discourse/Discourse-Sidekiq.container +17 -0
  14. data/Plugins/Apps/Discourse/Discourse.conf.erb +41 -0
  15. data/Plugins/Apps/Discourse/Discourse.container +17 -0
  16. data/Plugins/Apps/Discourse/Discourse.lmm.rb +95 -0
  17. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +171 -0
  18. data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +19 -0
  19. data/Plugins/Apps/ERPNext/ERPNext-Queue.container +17 -0
  20. data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +17 -0
  21. data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +19 -0
  22. data/Plugins/Apps/ERPNext/ERPNext.container +18 -0
  23. data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +193 -0
  24. data/Plugins/Apps/ERPNext/ERPNext.network +12 -0
  25. data/Plugins/Apps/ERPNext/sites/apps.json +10 -0
  26. data/Plugins/Apps/ERPNext/sites/apps.txt +3 -0
  27. data/Plugins/Apps/ERPNext/sites/common_site_config.json +11 -0
  28. data/Plugins/Apps/GitLab/GitLab.container +18 -0
  29. data/Plugins/Apps/GitLab/GitLab.lmm.rb +100 -0
  30. data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +57 -0
  31. data/Plugins/Apps/LetsEncrypt/hooks/dovecot.sh +2 -0
  32. data/Plugins/Apps/LetsEncrypt/hooks/nginx.sh +2 -0
  33. data/Plugins/Apps/LetsEncrypt/hooks/postfix.sh +2 -0
  34. data/Plugins/Apps/LetsEncrypt/renew-certificates.service +7 -0
  35. data/Plugins/Apps/LetsEncrypt/renew-certificates.timer +12 -0
  36. data/Plugins/Apps/LetsEncrypt/rfc2136.ini +11 -0
  37. data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +115 -0
  38. data/Plugins/Apps/Matrix/Element.container +14 -0
  39. data/Plugins/Apps/Matrix/Matrix.conf.erb +49 -5
  40. data/Plugins/Apps/Matrix/Matrix.lmm.rb +86 -1
  41. data/Plugins/Apps/Matrix/Synapse.container +17 -0
  42. data/Plugins/Apps/Matrix/config.json +50 -0
  43. data/Plugins/Apps/Matrix/homeserver.yaml +70 -0
  44. data/Plugins/Apps/Matrix/log.config +30 -0
  45. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +48 -10
  46. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +83 -1
  47. data/Plugins/Apps/Nextcloud/config.php +18 -0
  48. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +71 -0
  49. data/Plugins/Apps/Nginx/config-lmm/errors.conf +11 -5
  50. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +5 -1
  51. data/Plugins/Apps/Nginx/main.conf.erb +31 -0
  52. data/Plugins/Apps/Nginx/nginx.conf +3 -68
  53. data/Plugins/Apps/Nginx/nginx.lmm.rb +83 -22
  54. data/Plugins/Apps/Nginx/proxy.conf.erb +13 -3
  55. data/Plugins/Apps/Odoo/Odoo.conf.erb +30 -13
  56. data/Plugins/Apps/Odoo/Odoo.container +18 -0
  57. data/Plugins/Apps/Odoo/Odoo.lmm.rb +62 -2
  58. data/Plugins/Apps/Odoo/odoo.conf +37 -0
  59. data/Plugins/Apps/OpenVidu/Ingress.container +18 -0
  60. data/Plugins/Apps/OpenVidu/OpenVidu.conf.erb +34 -0
  61. data/Plugins/Apps/OpenVidu/OpenVidu.container +16 -0
  62. data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +90 -0
  63. data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +35 -0
  64. data/Plugins/Apps/OpenVidu/OpenViduCall.container +15 -0
  65. data/Plugins/Apps/OpenVidu/ingress.yaml +10 -0
  66. data/Plugins/Apps/OpenVidu/livekit.yaml +13 -0
  67. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +95 -0
  68. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +60 -0
  69. data/Plugins/Apps/Peppermint/Peppermint.container +15 -0
  70. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +58 -0
  71. data/Plugins/Apps/Postfix/Postfix.lmm.rb +165 -31
  72. data/Plugins/Apps/Postfix/smtpd.conf +3 -0
  73. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +242 -24
  74. data/Plugins/Apps/Roundcube/Roundcube.conf.erb +75 -0
  75. data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +145 -0
  76. data/Plugins/Apps/SSH/SSH.lmm.rb +51 -0
  77. data/Plugins/Apps/Tunnel/tunnel.lmm.rb +63 -0
  78. data/Plugins/Apps/Tunnel/tunnelTCP.service +9 -0
  79. data/Plugins/Apps/Tunnel/tunnelTCP.socket +9 -0
  80. data/Plugins/Apps/Tunnel/tunnelUDP.service +9 -0
  81. data/Plugins/Apps/Tunnel/tunnelUDP.socket +9 -0
  82. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +52 -0
  83. data/Plugins/Apps/UVdesk/UVdesk.lmm.rb +85 -0
  84. data/Plugins/Apps/Valkey/Valkey.lmm.rb +34 -1
  85. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +35 -18
  86. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +16 -0
  87. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +46 -3
  88. data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +42 -0
  89. data/Plugins/Apps/Wiki.js/Wiki.js.container +15 -0
  90. data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +61 -0
  91. data/Plugins/Apps/gollum/gollum.conf.erb +84 -19
  92. data/Plugins/Apps/gollum/gollum.container +15 -0
  93. data/Plugins/Apps/gollum/gollum.lmm.rb +48 -11
  94. data/Plugins/OS/Linux/Debian/preseed.cfg.erb +62 -0
  95. data/Plugins/OS/Linux/Distributions.yaml +42 -0
  96. data/Plugins/OS/Linux/Flavours.yaml +11 -0
  97. data/Plugins/OS/Linux/Linux.lmm.rb +362 -41
  98. data/Plugins/OS/Linux/Packages.yaml +88 -5
  99. data/Plugins/OS/Linux/Proxmox/answer.toml.erb +30 -0
  100. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +137 -0
  101. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +15 -0
  102. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +28 -0
  103. data/Plugins/OS/Linux/systemd/user-0.slice +9 -0
  104. data/Plugins/OS/Linux/systemd/user@.service.d/delegate.conf +3 -0
  105. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +7 -3
  106. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +3 -2
  107. data/Plugins/Services/DNS/PowerDNS.lmm.rb +158 -8
  108. data/README.md +6 -0
  109. data/bootstrap.sh +92 -0
  110. data/lib/ConfigLMM/Framework/plugins/dns.rb +1 -2
  111. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +249 -45
  112. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +56 -7
  113. data/lib/ConfigLMM/Framework/plugins/plugin.rb +112 -16
  114. data/lib/ConfigLMM/cli.rb +3 -1
  115. data/lib/ConfigLMM/commands/cleanup.rb +1 -0
  116. data/lib/ConfigLMM/commands/configsCommand.rb +3 -1
  117. data/lib/ConfigLMM/io/configList.rb +3 -1
  118. data/lib/ConfigLMM/state.rb +10 -2
  119. data/lib/ConfigLMM/version.rb +1 -1
  120. metadata +82 -3
  121. data/Plugins/Apps/Nginx/main.conf +0 -30
@@ -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
+ }
@@ -0,0 +1,145 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Roundcube < Framework::NginxApp
5
+
6
+ USER = 'roundcube'
7
+ HOME_DIR = '/var/lib/roundcube'
8
+ PACKAGE_NAME = 'Roundcube'
9
+
10
+ def actionRoundcubeDeploy(id, target, activeState, context, options)
11
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
12
+
13
+ target['Database'] ||= {}
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
+ Framework::LinuxApp.ensurePackages([PHP_FPM::PHPFPM_PACKAGE], ssh)
21
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
22
+ distroInfo = Framework::LinuxApp.ensurePackages([PACKAGE_NAME], ssh)
23
+ addUserCmd = "#{distroInfo['CreateServiceUser']} --home-dir '#{HOME_DIR}' --create-home --comment 'Roundcube' #{USER}"
24
+ self.class.exec(addUserCmd, ssh, true)
25
+ self.class.exec("chmod o-rwx #{HOME_DIR}", ssh)
26
+
27
+ self.class.exec("touch /var/log/php/roundcube.errors.log", ssh)
28
+ self.class.exec("touch /var/log/php/roundcube.mail.log", ssh)
29
+ self.class.exec("chown #{USER}:#{USER} /var/log/php/roundcube.errors.log", ssh)
30
+ self.class.exec("chown #{USER}:#{USER} /var/log/php/roundcube.mail.log", ssh)
31
+ self.class.exec("chown -R #{USER}:#{USER} /var/log/roundcubemail /var/lib/roundcubemail", ssh)
32
+ PHP_FPM::fixConfigFileOverSSH(distroInfo, ssh)
33
+
34
+ roundcubeBaseDir = '/usr/share/webapps/roundcubemail'
35
+ if distroInfo['Name'] == 'openSUSE Leap'
36
+ roundcubeBaseDir = '/srv/www/roundcubemail'
37
+ end
38
+
39
+ self.class.exec("sed -i 's|$config\\[\\'des_key\\'\\].*|$config\\[\\'des_key\\'\\] = \\'#{SecureRandom.alphanumeric(24)}\\';|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
40
+ self.class.exec("sed -i 's|$config\\[\\'product_name\\'\\].*|$config\\[\\'product_name\\'\\] = \\'Webmail\\';|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
41
+
42
+ if target['IMAP']['Host']
43
+ protocol = ''
44
+ if target['IMAP']['Port'] == 993
45
+ protocol = 'ssl://'
46
+ end
47
+ self.class.exec("sed -i 's|$config\\[\\'imap_host\\'\\].*|$config\\[\\'imap_host\\'\\] = \\'#{protocol}#{target['IMAP']['Host']}:#{target['IMAP']['Port']}\\';|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
48
+ end
49
+
50
+ if target['SMTP']['Host']
51
+ protocol = ''
52
+ if target['SMTP']['Port'] == 465
53
+ protocol = 'ssl://'
54
+ end
55
+ self.class.exec("sed -i 's|$config\\[\\'smtp_host\\'\\].*|$config\\[\\'smtp_host\\'\\] = \\'#{protocol}#{target['SMTP']['Host']}:#{target['SMTP']['Port']}\\';|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
56
+ end
57
+
58
+ target['Database'] ||= {}
59
+ activeState['Database'] = target['Database']
60
+ if !target['Database']['Type'] || target['Database']['Type'] == 'pgsql'
61
+ password = SecureRandom.alphanumeric(20)
62
+ PostgreSQL.createRemoteUserAndDBOverSSH(target['Database'], USER, password, ssh)
63
+ self.class.exec("sed -i 's|$config\\[\\'db_dsnw\\'\\].*|$config\\[\\'db_dsnw\\'\\] = \\'pgsql://#{USER}:#{password}@#{target['Database']['HostName']}/#{USER}\\';|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
64
+ end
65
+
66
+ self.updateRemoteFile(ssh, roundcubeBaseDir + '/config/config.inc.php', options, false, '//') do |configLines|
67
+ if target['Settings']
68
+ target['Settings'].each do |name, value|
69
+ configLines << "$config['#{name}'] = '#{value}';\n"
70
+ end
71
+ end
72
+ configLines << "$config['login_lc'] = 0;\n"
73
+ configLines << "$config['enable_installer'] = true;\n"
74
+ end
75
+
76
+ target['User'] = USER unless target['User']
77
+ name = 'roundcube'
78
+ target['PHP-FPM'] ||= {}
79
+ if distroInfo['Name'] == 'openSUSE Leap'
80
+ target['PHP-FPM']['chdir'] = roundcubeBaseDir
81
+ end
82
+ self.updateRemoteFile(ssh, PHP_FPM.configDir(distroInfo) + name + '.conf', options, false, ';') do |configLines|
83
+ PHP_FPM.writeConfig(name, target, distroInfo, configLines)
84
+ end
85
+
86
+ Framework::LinuxApp.startServiceOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
87
+
88
+ if !target.key?('Proxy') || target['Proxy']
89
+ self.class.ensurePackage(ssh)
90
+ self.class.prepareNginxConfig(target, ssh)
91
+ self.writeNginxConfig(__dir__, 'Roundcube', id, target, state, context, options)
92
+ if distroInfo['Name'] == 'openSUSE Leap'
93
+ nginxFile = options['output'] + '/nginx/servers-lmm/Roundcube.conf'
94
+ `sed -i 's|root .*|root #{roundcubeBaseDir}/public_html;|' #{nginxFile}`
95
+ end
96
+ self.deployNginxConfig(id, target, activeState, context, options)
97
+ Framework::LinuxApp.startServiceOverSSH(NGINX_PACKAGE, ssh)
98
+ self.class.reload(ssh)
99
+ end
100
+
101
+ self.class.exec("curl 'https://#{target['Domain']}/installer/index.php?_step=3' -X POST --data-raw 'initdb=Initialize+database'", ssh)
102
+ self.class.exec("rm -f #{roundcubeBaseDir}/public_html/installer", ssh)
103
+ self.class.exec("sed -i 's|$config\\[\\'enable_installer\\'\\].*|$config\\[\\'enable_installer\\'\\] = false;|' #{roundcubeBaseDir}/config/config.inc.php", ssh)
104
+ end
105
+ else
106
+ # TODO
107
+ end
108
+ activeState['Status'] = State::STATUS_DEPLOYED
109
+ end
110
+
111
+ def cleanup(configs, state, context, options)
112
+ cleanupType(:Roundcube, configs, state, context, options) do |item, id, state, context, options, ssh|
113
+ cleanupConfig(item, id, state, context, options, ssh)
114
+ end
115
+ end
116
+
117
+ def cleanupConfig(item, id, state, context, options, ssh = nil)
118
+ if item['Proxy'].nil? || item['Proxy']
119
+ self.cleanupNginxConfig('Roundcube', id, state, context, options, ssh)
120
+ self.class.reload(ssh, options[:dry])
121
+ end
122
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
123
+ rm(PHP_FPM.configDir(distroInfo) + 'roundcube.conf', options[:dry], ssh)
124
+ Framework::LinuxApp.reloadService(PHP_FPM::PHPFPM_SERVICE, ssh, options[:dry])
125
+ Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
126
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
127
+ if options[:destroy]
128
+ item['Database'] ||= {}
129
+ if !item['Database']['Type'] || item['Database']['Type'] == 'pgsql'
130
+ PostgreSQL.dropUserAndDB(item['Database'], USER, ssh, options[:dry])
131
+ end
132
+ Framework::LinuxApp.deleteUserAndGroup(USER, ssh, options[:dry])
133
+ rm('/var/log/roundcubemail', options[:dry], ssh)
134
+ rm('/var/log/php/roundcube.access.log', options[:dry], ssh)
135
+ rm('/var/log/php/roundcube.errors.log', options[:dry], ssh)
136
+ rm('/var/log/php/roundcube.mail.log', options[:dry], ssh)
137
+ rm('/var/log/nginx/roundcube.access.log', options[:dry], ssh)
138
+ rm('/var/log/nginx/roundcube.error.log', options[:dry], ssh)
139
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
140
+ end
141
+ end
142
+
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,51 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class SSH < Framework::LinuxApp
5
+
6
+ CONFIG_FILE = '/etc/ssh/sshd_config'
7
+
8
+ def actionSSHDeploy(id, target, activeState, context, options)
9
+
10
+ if target['Location'] && target['Location'] != '@me'
11
+ uri = Addressable::URI.parse(target['Location'])
12
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
13
+
14
+ self.class.sshStart(uri) do |ssh|
15
+ if target['Port']
16
+ self.class.sshExec!(ssh, "sed -i 's|^Port |#Port |' #{CONFIG_FILE}")
17
+ end
18
+ if target['ListenAddress']
19
+ self.class.sshExec!(ssh, "sed -i 's|^ListenAddress |#ListenAddress |' #{CONFIG_FILE}")
20
+ end
21
+ target['Settings'].to_h.each do |name, value|
22
+ self.class.sshExec!(ssh, "sed -i 's|^#{name} |##{name} |' #{CONFIG_FILE}")
23
+ end
24
+ updateRemoteFile(ssh, CONFIG_FILE, options) do |configLines|
25
+ if target['Port']
26
+ configLines << "Port #{target['Port']}\n"
27
+ end
28
+ if target['ListenAddress']
29
+ configLines << "ListenAddress #{target['ListenAddress']}\n"
30
+ end
31
+ target['Settings'].to_h.each do |name, value|
32
+ value = 'yes' if value.is_a?(TrueClass)
33
+ value = 'no' if value.is_a?(FalseClass)
34
+ configLines << "#{name} #{value}\n"
35
+ end
36
+ configLines
37
+ end
38
+ if target['Port']
39
+ Framework::LinuxApp.firewallAddPortOverSSH(target['Port'].to_s + '/tcp', uri)
40
+ end
41
+ end
42
+ else
43
+ # TODO
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,63 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Tunnel < Framework::NginxApp
5
+
6
+ def actionTunnelDeploy(id, target, activeState, context, options)
7
+
8
+ if target['Location'] && target['Location'] != '@me'
9
+ uri = Addressable::URI.parse(target['Location'])
10
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
11
+
12
+ self.class.sshStart(uri) do |ssh|
13
+
14
+ Framework::LinuxApp.ensurePackage('socat', ssh)
15
+
16
+ port = target['Port']
17
+ activeState['Port'] = port
18
+ activeState['UDP'] = target['UDP']
19
+ if target['UDP']
20
+ name = "tunnelUDP-#{port}"
21
+ ssh.scp.upload!(__dir__ + '/tunnelUDP.service', "/etc/systemd/system/#{name}.service")
22
+ ssh.scp.upload!(__dir__ + '/tunnelUDP.socket', "/etc/systemd/system/#{name}.socket")
23
+ self.class.exec("sed -i 's|$PORT|#{port}|' /etc/systemd/system/#{name}.service", ssh)
24
+ self.class.exec("sed -i 's|$PORT|#{port}|' /etc/systemd/system/#{name}.socket", ssh)
25
+ self.class.exec("sed -i 's|$REMOTE|#{target['Remote']}|' /etc/systemd/system/#{name}.service", ssh)
26
+ else
27
+ name = "tunnelTCP-#{port}"
28
+ ssh.scp.upload!(__dir__ + '/tunnelTCP.service', "/etc/systemd/system/#{name}.service")
29
+ ssh.scp.upload!(__dir__ + '/tunnelTCP.socket', "/etc/systemd/system/#{name}.socket")
30
+ self.class.exec("sed -i 's|$PORT|#{port}|' /etc/systemd/system/#{name}.service", ssh)
31
+ self.class.exec("sed -i 's|$PORT|#{port}|' /etc/systemd/system/#{name}.socket", ssh)
32
+ self.class.exec("sed -i 's|$REMOTE|#{target['Remote']}|' /etc/systemd/system/#{name}.service", ssh)
33
+ end
34
+
35
+ Framework::LinuxApp.reloadServiceManager(ssh)
36
+ Framework::LinuxApp.ensureServiceAutoStart(name + '.socket', ssh)
37
+ Framework::LinuxApp.stopService(name + '.service', ssh)
38
+ Framework::LinuxApp.startService(name + '.socket', ssh)
39
+ end
40
+ else
41
+ # TODO
42
+ end
43
+ activeState['Status'] = State::STATUS_DEPLOYED
44
+ end
45
+
46
+ def cleanup(configs, state, context, options)
47
+ cleanupType(:Tunnel, configs, state, context, options) do |item, id, state, context, options, ssh|
48
+ if item['UDP']
49
+ name = "tunnelUDP-#{item['Port']}"
50
+ else
51
+ name = "tunnelTCP-#{item['Port']}"
52
+ end
53
+ Framework::LinuxApp.stopService(name + '.socket', ssh)
54
+ Framework::LinuxApp.disableService(name + '.socket', ssh)
55
+ rm("/etc/systemd/system/#{name}.service", options[:dry], ssh)
56
+ rm("/etc/systemd/system/#{name}.socket", options[:dry], ssh)
57
+ state.item(id)['Status'] = State::STATUS_DESTROYED
58
+ end
59
+ end
60
+
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,9 @@
1
+
2
+ [Unit]
3
+ Description=Forward TCP $PORT to remote
4
+
5
+ [Service]
6
+ ExecStart=/usr/lib/systemd/systemd-socket-proxyd $REMOTE
7
+
8
+ [Install]
9
+ WantedBy=multi-user.target
@@ -0,0 +1,9 @@
1
+
2
+ [Unit]
3
+ Description=TCP tunnel listening on local port $PORT
4
+
5
+ [Socket]
6
+ ListenStream=$PORT
7
+
8
+ [Install]
9
+ WantedBy=sockets.target
@@ -0,0 +1,9 @@
1
+
2
+ [Unit]
3
+ Description=Forward UDP $PORT to remote
4
+
5
+ [Service]
6
+ ExecStart=/usr/bin/socat UDP-RECVFROM:$PORT,reuseaddr,fork UDP-SENDTO:$REMOTE
7
+
8
+ [Install]
9
+ WantedBy=multi-user.target
@@ -0,0 +1,9 @@
1
+
2
+ [Unit]
3
+ Description=UDP tunnel listening on local port $PORT
4
+
5
+ [Socket]
6
+ ListenDatagram=$PORT
7
+
8
+ [Install]
9
+ WantedBy=sockets.target
@@ -0,0 +1,52 @@
1
+
2
+ upstream uvdesk
3
+ {
4
+ <% if config['Server'] %>
5
+ server <%= config['Server'] %>;
6
+ <% else %>
7
+ server unix:/run/php-fpm/uvdesk.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/uvdesk.access.log;
35
+ error_log /var/log/nginx/uvdesk.error.log;
36
+
37
+ root /srv/uvdesk/public;
38
+ index index.php;
39
+
40
+ include config-lmm/errors.conf;
41
+
42
+ location ~ \.php(?:$|/)
43
+ {
44
+ fastcgi_pass uvdesk;
45
+ include fastcgi.conf;
46
+ }
47
+
48
+ location / {
49
+ try_files $uri $uri/ /index.php$request_uri;
50
+ }
51
+
52
+ }
@@ -0,0 +1,85 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class UVdesk < Framework::NginxApp
5
+
6
+ USER = 'uvdesk'
7
+ HOME_DIR = '/srv/uvdesk'
8
+ DOWNLOAD_URL = 'https://cdn.uvdesk.com/uvdesk/downloads/opensource/uvdesk-community-current-stable.zip'
9
+
10
+ def actionUVdeskDeploy(id, target, activeState, context, options)
11
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
12
+
13
+ target['Database'] ||= {}
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
+ dbPassword = self.configureMariaDB(target['Database'], ssh)
20
+
21
+ Framework::LinuxApp.ensurePackages([PHP_FPM::PHPFPM_PACKAGE, 'php-pecl', 'make'], ssh)
22
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
23
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
24
+ addUserCmd = "#{distroInfo['CreateServiceUser']} --home-dir '#{HOME_DIR}' --create-home --comment 'UVdesk' #{USER}"
25
+ self.class.sshExec!(ssh, addUserCmd, true)
26
+ if !self.class.remoteFilePresent?(HOME_DIR + '/public/index.php', ssh)
27
+ self.class.sshExec!(ssh, "curl #{DOWNLOAD_URL} > /tmp/uvdesk.zip")
28
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'cd ~ && unzip /tmp/uvdesk.zip'")
29
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mv ~/uvdesk-*/* ~/'")
30
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mv ~/uvdesk-*/.[!.]* ~/'")
31
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'rm -r ~/uvdesk-*'")
32
+ self.class.sshExec!(ssh, 'rm -f /tmp/uvdesk.zip')
33
+ end
34
+
35
+ self.class.sshExec!(ssh, "mkdir -p /var/log/php/")
36
+ self.class.sshExec!(ssh, "touch /var/log/php/uvdesk.errors.log")
37
+ self.class.sshExec!(ssh, "touch /var/log/php/uvdesk.mail.log")
38
+ self.class.sshExec!(ssh, "chown #{USER}:#{USER} /var/log/php/uvdesk.errors.log")
39
+ self.class.sshExec!(ssh, "chown #{USER}:#{USER} /var/log/php/uvdesk.mail.log")
40
+ PHP_FPM::fixConfigFileOverSSH(distroInfo, ssh)
41
+
42
+ target['User'] = USER unless target['User']
43
+ target['PHP-FPM'] ||= {}
44
+ target['PHP-FPM']['chdir'] = HOME_DIR unless target['PHP-FPM']['chdir']
45
+ name = 'uvdesk'
46
+ self.updateRemoteFile(ssh, PHP_FPM.configDir(distroInfo) + name + '.conf', options, false, ';') do |configLines|
47
+ PHP_FPM.writeConfig(name, target, distroInfo, configLines)
48
+ end
49
+
50
+
51
+ PHP_FPM.enableExtensionOverSSH('mysqli', distroInfo, ssh)
52
+ PHP_FPM.enableExtensionOverSSH('mbstring', distroInfo, ssh) # Needed by mailparse
53
+
54
+ imapPackage = 'imap'
55
+ imapPackage = 'imap-1.0.0' if distroInfo['Name'] == 'openSUSE Leap'
56
+ PHP_FPM.peclInstallOverSSH(imapPackage, ssh)
57
+ PHP_FPM.enableExtensionOverSSH('imap', distroInfo, ssh)
58
+
59
+ PHP_FPM.peclInstallOverSSH('mailparse', ssh)
60
+ PHP_FPM.enableExtensionOverSSH('mailparse', distroInfo, ssh)
61
+
62
+ Framework::LinuxApp.startServiceOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
63
+
64
+ Framework::LinuxApp.ensurePackages([NGINX_PACKAGE], ssh)
65
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(NGINX_PACKAGE, ssh)
66
+ self.class.prepareNginxConfig(target, ssh)
67
+ self.writeNginxConfig(__dir__, 'UVdesk', id, target, state, context, options)
68
+ self.deployNginxConfig(id, target, activeState, context, options)
69
+ Framework::LinuxApp.startServiceOverSSH(NGINX_PACKAGE, ssh)
70
+ end
71
+ else
72
+ # TODO
73
+ end
74
+ end
75
+
76
+ def configureMariaDB(settings, ssh)
77
+ password = SecureRandom.alphanumeric(20)
78
+ # TODO
79
+ password
80
+ end
81
+
82
+ end
83
+ end
84
+ end
85
+
@@ -13,7 +13,7 @@ module ConfigLMM
13
13
 
14
14
  if target['Location'] && target['Location'] != '@me'
15
15
  self.class.sshStart(target['Location']) do |ssh|
16
- distroId = self.class.distroIDfromSSH(ssh)
16
+ distroId = self.class.distroID(ssh)
17
17
  if distroId == SUSE_ID
18
18
  serviceName = 'redis@redis'
19
19
  self.class.sshExec!(ssh, "touch #{CONFIG_FILE}")
@@ -24,7 +24,14 @@ module ConfigLMM
24
24
  target['Settings']['dir'] = '/var/lib/redis/default/'
25
25
  end
26
26
 
27
+ if ENV[id + '-VALKEY_PASSWORD']
28
+ target['Settings']['requirepass'] = ENV[id + '-VALKEY_PASSWORD']
29
+ elsif ENV['VALKEY_PASSWORD']
30
+ target['Settings']['requirepass'] = ENV['VALKEY_PASSWORD']
31
+ end
32
+
27
33
  if target['Settings']
34
+ target['Settings']['bind'] = '127.0.0.1' unless target['Settings']['bind']
28
35
  updateRemoteFile(ssh, CONFIG_FILE, options, false) do |configLines|
29
36
  target['Settings'].each do |name, value|
30
37
  configLines << "#{name} #{value}\n"
@@ -32,6 +39,9 @@ module ConfigLMM
32
39
  configLines
33
40
  end
34
41
  end
42
+
43
+ self.class.exec("chgrp redis #{CONFIG_FILE}", ssh)
44
+ self.class.exec("chmod 640 #{CONFIG_FILE}", ssh)
35
45
  end
36
46
  else
37
47
  if target['Settings']
@@ -43,10 +53,33 @@ module ConfigLMM
43
53
  configLines
44
54
  end
45
55
  end
56
+ self.class.exec("chgrp redis #{CONFIG_FILE}", ssh)
57
+ self.class.exec("chmod 640 #{CONFIG_FILE}", nil)
46
58
  end
47
59
 
48
60
  self.ensureServiceAutoStart(serviceName, target['Location'])
49
61
  self.startService(serviceName, target['Location'])
62
+
63
+ activeState['Status'] = State::STATUS_DEPLOYED
64
+ end
65
+
66
+ def cleanup(configs, state, context, options)
67
+ cleanupType(:Valkey, configs, state, context, options) do |item, id, state, context, options, ssh|
68
+ serviceName = 'redis'
69
+ distroId = self.class.distroID(ssh)
70
+ serviceName = 'redis@redis' if distroId == SUSE_ID
71
+
72
+ Framework::LinuxApp.stopService(serviceName, ssh, options[:dry])
73
+ Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
74
+
75
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
76
+
77
+ if options[:destroy]
78
+ rm('/etc/redis', options[:dry], ssh)
79
+
80
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
81
+ end
82
+ end
50
83
  end
51
84
 
52
85
  end
@@ -1,22 +1,39 @@
1
1
 
2
2
  upstream vaultwarden {
3
- server 127.0.0.1:8000;
4
- }
5
-
6
- upstream vaultwarden-websocket {
7
- server 127.0.0.1:3012;
3
+ <% if config['Server'] %>
4
+ server <%= config['Server'] %>;
5
+ <% else %>
6
+ server 127.0.0.1:18000;
7
+ <% end %>
8
+ keepalive 2;
8
9
  }
9
10
 
10
11
  server {
11
12
 
12
- <% if !config['TLS'] %>
13
- listen <%= config['Port'] %>;
14
- listen [::]:<%= config['Port'] %>;
15
- <% else %>
16
- listen <%= config['Port'] %> ssl;
17
- listen [::]:<%= config['Port'] %> ssl;
13
+ <% if config['NginxVersion'] >= 1.25 %>
14
+ <% if !config['TLS'] %>
15
+ listen <%= config['Port'] %>;
16
+ listen [::]:<%= config['Port'] %>;
17
+ <% else %>
18
+ listen <%= config['Port'] %> ssl;
19
+ listen [::]:<%= config['Port'] %> ssl;
20
+
21
+ include config-lmm/ssl.conf;
22
+ <% end %>
18
23
  http2 on;
19
- include config-lmm/ssl.conf;
24
+ http3 on;
25
+ quic_retry on;
26
+ add_header Alt-Svc 'h3=":443"; ma=86400';
27
+ <% else %>
28
+ <% if !config['TLS'] %>
29
+ listen <%= config['Port'] %>;
30
+ listen [::]:<%= config['Port'] %>;
31
+ <% else %>
32
+ listen <%= config['Port'] %> ssl http2;
33
+ listen [::]:<%= config['Port'] %> ssl http2;
34
+
35
+ include config-lmm/ssl.conf;
36
+ <% end %>
20
37
  <% end %>
21
38
 
22
39
  server_name <%= config['Domain'] %>;
@@ -37,12 +54,12 @@ server {
37
54
  include config-lmm/proxy.conf;
38
55
  }
39
56
 
40
- location /notifications/ {
41
- proxy_pass http://vaultwarden-websocket/;
57
+ #location /notifications/ {
58
+ # proxy_pass http://127.0.0.1:3012/;
42
59
 
43
- proxy_set_header Upgrade $http_upgrade;
44
- proxy_set_header Connection "upgrade";
45
- include config-lmm/proxy.conf;
46
- }
60
+ # proxy_set_header Upgrade $http_upgrade;
61
+ # proxy_set_header Connection "upgrade";
62
+ # include config-lmm/proxy.conf;
63
+ #}
47
64
 
48
65
  }