ConfigLMM 0.1.0 → 0.3.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 (70) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +63 -1
  3. data/Examples/Implemented.mm.yaml +120 -0
  4. data/Examples/Keys.ini +2 -0
  5. data/Examples/Linux.mm.yaml +14 -3
  6. data/Images/configINconfig.png +0 -0
  7. data/Images/singleConfig.png +0 -0
  8. data/Plugins/Apps/Authentik/Authentik-Server.container +18 -0
  9. data/Plugins/Apps/Authentik/Authentik-Worker.container +17 -0
  10. data/Plugins/Apps/Authentik/Authentik.conf.erb +35 -0
  11. data/Plugins/Apps/Authentik/Authentik.lmm.rb +73 -0
  12. data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +41 -0
  13. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +165 -0
  14. data/Plugins/Apps/GitLab/GitLab.conf.erb +26 -0
  15. data/Plugins/Apps/GitLab/GitLab.container +17 -0
  16. data/Plugins/Apps/GitLab/GitLab.lmm.rb +75 -0
  17. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +48 -10
  18. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +59 -2
  19. data/Plugins/Apps/Nextcloud/config.php +18 -0
  20. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +62 -0
  21. data/Plugins/Apps/Nginx/config-lmm/errors.conf +2 -2
  22. data/Plugins/Apps/Nginx/config-lmm/security.conf +4 -0
  23. data/Plugins/Apps/Nginx/main.conf.erb +31 -0
  24. data/Plugins/Apps/Nginx/nginx.conf +3 -68
  25. data/Plugins/Apps/Nginx/nginx.lmm.rb +71 -14
  26. data/Plugins/Apps/Odoo/Odoo.conf.erb +30 -13
  27. data/Plugins/Apps/Odoo/Odoo.container +17 -0
  28. data/Plugins/Apps/Odoo/Odoo.lmm.rb +62 -2
  29. data/Plugins/Apps/Odoo/odoo.conf +37 -0
  30. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +95 -0
  31. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +64 -0
  32. data/Plugins/Apps/Peppermint/Peppermint.container +14 -0
  33. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +58 -0
  34. data/Plugins/Apps/Postfix/Postfix.lmm.rb +184 -0
  35. data/Plugins/Apps/Postfix/smtpd.conf +3 -0
  36. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +225 -0
  37. data/Plugins/Apps/SSH/SSH.lmm.rb +51 -0
  38. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +52 -0
  39. data/Plugins/Apps/UVdesk/UVdesk.lmm.rb +85 -0
  40. data/Plugins/Apps/Valkey/Valkey.lmm.rb +56 -0
  41. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +35 -18
  42. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +16 -0
  43. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +42 -3
  44. data/Plugins/Apps/gollum/gollum.conf.erb +45 -18
  45. data/Plugins/Apps/gollum/gollum.container +12 -0
  46. data/Plugins/Apps/gollum/gollum.lmm.rb +39 -10
  47. data/Plugins/OS/Linux/Distributions.yaml +16 -0
  48. data/Plugins/OS/Linux/Linux.lmm.rb +389 -0
  49. data/Plugins/OS/Linux/Packages.yaml +51 -0
  50. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +108 -0
  51. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +15 -0
  52. data/Plugins/OS/Linux/openSUSE/autoinst.xml.erb +87 -0
  53. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +28 -0
  54. data/Plugins/OS/Linux/systemd/user-0.slice +9 -0
  55. data/Plugins/OS/Linux/systemd/user@.service.d/delegate.conf +3 -0
  56. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +6 -1
  57. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +103 -0
  58. data/Plugins/Services/DNS/PowerDNS.lmm.rb +69 -6
  59. data/README.md +10 -0
  60. data/bootstrap.sh +54 -0
  61. data/lib/ConfigLMM/Framework/plugins/dns.rb +1 -2
  62. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +237 -0
  63. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +24 -6
  64. data/lib/ConfigLMM/Framework/plugins/plugin.rb +150 -0
  65. data/lib/ConfigLMM/Framework/plugins.rb +1 -0
  66. data/lib/ConfigLMM/commands/configsCommand.rb +3 -0
  67. data/lib/ConfigLMM/version.rb +1 -1
  68. metadata +87 -5
  69. data/Plugins/Apps/Nginx/main.conf +0 -30
  70. data/Plugins/OS/Linux.lmm.rb +0 -64
@@ -0,0 +1,225 @@
1
+
2
+ require_relative '../../OS/Linux/Linux.lmm.rb'
3
+
4
+ module ConfigLMM
5
+ module LMM
6
+ class PostgreSQL < Framework::LinuxApp
7
+ PACKAGE_NAME = 'PostgreSQL'
8
+ SERVICE_NAME = 'postgresql'
9
+ USER_NAME = 'postgres'
10
+
11
+ HBA_FILE = 'data/pg_hba.conf'
12
+ CONFIG_FILE = 'data/postgresql.conf'
13
+
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'])
18
+
19
+ if target['Location'] && target['Location'] != '@me'
20
+ uri = Addressable::URI.parse(target['Location'])
21
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
22
+
23
+ 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'")
26
+ self.class.createUsersOverSSH(target, ssh)
27
+ self.class.createDatabasesOverSSH(target, ssh)
28
+ self.class.createPublicationsOverSSH(target, ssh)
29
+ self.class.createSubscriptionsOverSSH(target, ssh)
30
+ end
31
+ else
32
+ `pg_ctl reload`
33
+ end
34
+
35
+ end
36
+
37
+ def updateListenLocal(target)
38
+ dir = pgsqlDir(self.class.distroID)
39
+ if target['ListenAll']
40
+ `sed -i 's|^host all all 127.0.0.1/32 ident|host all all 0.0.0.0/0 scram-sha-256|' #{dir + HBA_FILE}`
41
+ updateLocalFile(dir + CONFIG_FILE, options) do |configLines|
42
+ configLines << "listen_addresses = '*'\n"
43
+ end
44
+ else
45
+ `sed -i 's|^host all all 127.0.0.1/32 ident|host all all 127.0.0.1/32 scram-sha-256|' #{dir + HBA_FILE}`
46
+ end
47
+ end
48
+
49
+ def updateSettingsOverSSH(target, ssh, options)
50
+ dir = nil
51
+ settingLines = []
52
+ hbaLines = []
53
+ if target['ListenAll']
54
+ cmd = "sed -i 's|^host all all 127.0.0.1/32 ident|host all all 0.0.0.0/0 scram-sha-256|'"
55
+ dir = updateConfigOverSSH(ssh, cmd)
56
+ settingLines << "listen_addresses = '*'\n"
57
+ Framework::LinuxApp.firewallAddPortOverSSH('5432/tcp', ssh)
58
+ elsif target['Listen'] && !target['Listen'].empty?
59
+ cmd = "sed -i 's|^host all all 127.0.0.1/32 ident|host all all 127.0.0.1/32 scram-sha-256|'"
60
+ dir = updateConfigOverSSH(ssh, cmd)
61
+
62
+ ips = target['Listen'].map { |addr| addr.split('/').first }.join(',')
63
+ settingLines << "listen_addresses = '#{ips}'\n"
64
+
65
+ target['Listen'].each do |addr|
66
+ if addr != 'localhost' && !addr.start_with?('127.0.0.1') && !addr.start_with?('::1')
67
+ hbaLines << "host all all #{addr} scram-sha-256\n"
68
+ end
69
+ end
70
+ else
71
+ cmd = "sed -i 's|^host all all 127.0.0.1/32 ident|host all all 127.0.0.1/32 scram-sha-256|'"
72
+ dir = updateConfigOverSSH(ssh, cmd)
73
+ end
74
+ #if !target['Publications'].to_h.empty?
75
+ # target['Settings'] ||= {}
76
+ # target['Settings']['wal_level'] = 'logical'
77
+ #end
78
+ target['Settings'].to_h.each do |name, value|
79
+ settingLines << "#{name} = #{value}\n"
80
+ end
81
+ if !hbaLines.empty?
82
+ updateRemoteFile(ssh, dir + HBA_FILE, options, false) do |configLines|
83
+ configLines += hbaLines
84
+ end
85
+ end
86
+ if !settingLines.empty?
87
+ updateRemoteFile(ssh, dir + CONFIG_FILE, options, false) do |configLines|
88
+ configLines += settingLines
89
+ end
90
+ end
91
+ end
92
+
93
+ def self.createUsersOverSSH(target, ssh)
94
+ target['Users'].to_a.each do |user, info|
95
+ self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createuser #{user}'", true)
96
+ if !info['Password'].to_s.empty?
97
+ password = self.loadVariable(info['Password'], target).to_s
98
+ if !password.empty?
99
+ sql = "ALTER USER #{user} WITH PASSWORD '#{password}'"
100
+ self.executeSQL(sql, nil, ssh)
101
+ end
102
+ end
103
+ if info['Replication'] && info['Replication'] != 'no'
104
+ self.executeSQL("ALTER USER #{user} REPLICATION", nil, ssh)
105
+ self.executeSQL("GRANT pg_read_all_data TO #{user}", nil, ssh)
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.createDatabasesOverSSH(target, ssh)
111
+ target['Databases'].to_a.each do |db, info|
112
+ self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createdb #{db}'", true)
113
+ end
114
+ end
115
+
116
+ def self.createPublicationsOverSSH(target, ssh)
117
+ return if target['Publications'].to_h.empty?
118
+
119
+ target['Publications'].each do |name, data|
120
+ data['Database'] = name unless data['Database']
121
+ if data['Tables'].is_a?(Array)
122
+ # TODO
123
+ elsif data['Tables'] == 'All'
124
+ sql = "CREATE PUBLICATION #{name} FOR ALL TABLES"
125
+ self.executeSQL(sql, data['Database'], ssh, true)
126
+ else
127
+ raise "Invalid Tables field: #{data['Tables']}"
128
+ end
129
+ end
130
+ end
131
+
132
+ def self.createSubscriptionsOverSSH(target, ssh)
133
+ return if target['Subscriptions'].to_h.empty?
134
+
135
+ target['Subscriptions'].each do |name, data|
136
+ data['Database'] = name unless data['Database']
137
+ data['Publication'] = name unless data['Publication']
138
+ connection = self.loadVariable(data['Connection'], target).to_s
139
+
140
+ authParams = '--host=' + connection.match('host=([^ ]+)')[1]
141
+ authParams += ' --username=' + connection.match('user=([^ ]+)')[1]
142
+ password = connection.match('password=([^ ]+)')[1]
143
+
144
+ self.importRemoteSchemaOverSSH(name, data['Database'], password, authParams, ssh)
145
+
146
+ sql = "CREATE SUBSCRIPTION #{name} CONNECTION '#{connection}' PUBLICATION #{data['Publication']}"
147
+ self.executeSQL(sql, data['Database'], ssh, true)
148
+ end
149
+ end
150
+
151
+ def self.importRemoteSchemaOverSSH(sourceDB, targetDB, password, authParams, ssh)
152
+ self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createdb #{targetDB}'", true)
153
+ cmd = " su --login #{USER_NAME} --command 'PGPASSWORD=#{password} pg_dump --schema-only --no-owner --dbname=#{sourceDB} #{authParams} | psql --dbname=#{targetDB}'"
154
+ self.sshExec!(ssh, cmd)
155
+ end
156
+
157
+ def updateConfigOverSSH(ssh, cmd)
158
+ dir = ''
159
+ distroID = self.class.distroID(ssh)
160
+ dir = pgsqlDir(distroID)
161
+ self.class.sshExec!(ssh, cmd + ' ' + dir + HBA_FILE)
162
+ dir
163
+ end
164
+
165
+ def self.createRemoteUserAndDBOverSSH(settings, user, password, ssh)
166
+ self.executeRemotelyOverSSH(settings, ssh) do |ssh|
167
+ self.createUserAndDBOverSSH(user, password, ssh)
168
+ end
169
+ end
170
+
171
+ def self.executeRemotelyOverSSH(settings, ssh)
172
+ settings['HostName'] = 'localhost' unless settings['HostName']
173
+ if settings['HostName'] == 'localhost'
174
+ yield(ssh)
175
+ else
176
+ self.sshStart("ssh://#{settings['HostName']}/") do |ssh|
177
+ yield(ssh)
178
+ end
179
+ end
180
+ end
181
+
182
+ def self.createUserAndDBOverSSH(user, password, ssh)
183
+ self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createuser #{user}'", true)
184
+ self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createdb --owner=#{user} #{user}'", true)
185
+ if password
186
+ sql = "ALTER USER #{user} WITH PASSWORD '#{password}'"
187
+ self.executeSQL(sql, nil, ssh)
188
+ end
189
+ end
190
+
191
+ def self.importSQL(owner, db, sqlFile, ssh = nil)
192
+ if ssh
193
+ self.sshExec!(ssh, "echo \"SET ROLE '#{owner}';\" > /tmp/postgres_import.sql")
194
+ self.sshExec!(ssh, "cat #{sqlFile} >> /tmp/postgres_import.sql")
195
+ cmd = "su --login #{USER_NAME} --command 'psql #{db} < /tmp/postgres_import.sql'"
196
+ self.sshExec!(ssh, cmd)
197
+ else
198
+ # TODO
199
+ end
200
+ end
201
+
202
+ def self.executeSQL(sql, db, ssh = nil, allowFailure = false)
203
+ if ssh
204
+ db = 'postgres' unless db
205
+ cmd = " su --login #{USER_NAME} --command ' psql --dbname=#{db} --command=\"#{sql.gsub("'", "\\\\'")};\"'"
206
+ self.sshExec!(ssh, cmd, allowFailure)
207
+ else
208
+ # TODO
209
+ end
210
+ end
211
+
212
+ def pgsqlDir(distroID)
213
+ if distroID == 'opensuse-leap'
214
+ '/var/lib/pgsql/'
215
+ elsif distroID == 'arch'
216
+ '/var/lib/postgres/'
217
+ else
218
+ raise Framework::PluginProcessError.new("Unknown Linux Distro: #{distroID}!")
219
+ end
220
+ end
221
+
222
+ end
223
+
224
+ end
225
+ 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,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
+
@@ -0,0 +1,56 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Valkey < Framework::LinuxApp
5
+ PACKAGE_NAME = 'Valkey'
6
+ CONFIG_FILE = '/etc/redis/redis.conf'
7
+ PID_FILE = '/run/redis/redis.pid'
8
+
9
+ def actionValkeyDeploy(id, target, activeState, context, options)
10
+ self.ensurePackage(PACKAGE_NAME, target['Location'])
11
+
12
+ serviceName = 'redis'
13
+
14
+ if target['Location'] && target['Location'] != '@me'
15
+ self.class.sshStart(target['Location']) do |ssh|
16
+ distroId = self.class.distroID(ssh)
17
+ if distroId == SUSE_ID
18
+ serviceName = 'redis@redis'
19
+ self.class.sshExec!(ssh, "touch #{CONFIG_FILE}")
20
+
21
+ target['Settings'] ||= {}
22
+ target['Settings']['pidfile'] = PID_FILE
23
+ target['Settings']['supervised'] = 'systemd'
24
+ target['Settings']['dir'] = '/var/lib/redis/default/'
25
+ end
26
+
27
+ if target['Settings']
28
+ target['Settings']['bind'] = '127.0.0.1' unless target['Settings']['bind']
29
+ updateRemoteFile(ssh, CONFIG_FILE, options, false) do |configLines|
30
+ target['Settings'].each do |name, value|
31
+ configLines << "#{name} #{value}\n"
32
+ end
33
+ configLines
34
+ end
35
+ end
36
+ end
37
+ else
38
+ if target['Settings']
39
+ `touch #{CONFIG_FILE}`
40
+ updateLocalFile(CONFIG_FILE, options) do |configLines|
41
+ target['Settings'].each do |name, value|
42
+ configLines << "#{name} #{value}\n"
43
+ end
44
+ configLines
45
+ end
46
+ end
47
+ end
48
+
49
+ self.ensureServiceAutoStart(serviceName, target['Location'])
50
+ self.startService(serviceName, target['Location'])
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ 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
  }
@@ -0,0 +1,16 @@
1
+ [Unit]
2
+ Description=vaultwarden container
3
+ After=local-fs.target
4
+
5
+ [Container]
6
+ AutoUpdate=registry
7
+ Image=ghcr.io/dani-garcia/vaultwarden:latest
8
+ Exec=/start.sh
9
+ EnvironmentFile=/var/lib/vaultwarden/.config/containers/systemd/Vaultwarden.env
10
+ Network=slirp4netns:allow_host_loopback=true
11
+ PublishPort=0.0.0.0:18000:8000
12
+ UserNS=keep-id:uid=1000,gid=1000
13
+ Volume=/var/lib/vaultwarden/data/:/data/
14
+
15
+ [Install]
16
+ WantedBy=multi-user.target default.target
@@ -5,8 +5,12 @@ module ConfigLMM
5
5
  module LMM
6
6
  class Vaultwarden < Framework::NginxApp
7
7
 
8
+ NAME = 'Vaultwarden'
9
+ USER = 'vaultwarden'
10
+ HOME_DIR = '/var/lib/vaultwarden'
11
+
8
12
  def actionVaultwardenBuild(id, target, state, context, options)
9
- writeNginxConfig(__dir__, 'Vaultwarden', id, target, state, context, options)
13
+ writeNginxConfig(__dir__, NAME, id, target, state, context, options)
10
14
  end
11
15
 
12
16
  def actionVaultwardenDiff(id, target, activeState, context, options)
@@ -14,8 +18,43 @@ module ConfigLMM
14
18
  end
15
19
 
16
20
  def actionVaultwardenDeploy(id, target, activeState, context, options)
17
- if !target['Location'] || target['Location'] == '@me'
18
- deployNginxConfig(id, target, activeState, context, options)
21
+ if target['Location'] && target['Location'] != '@me'
22
+ uri = Addressable::URI.parse(target['Location'])
23
+ self.class.sshStart(uri) do |ssh|
24
+ if !target.key?('Proxy') || target['Proxy'] != 'only'
25
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
26
+ Framework::LinuxApp.configurePodmanServiceOverSSH(USER, HOME_DIR, 'Vaultwarden', distroInfo, ssh)
27
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mkdir -p ~/data'")
28
+ path = Framework::LinuxApp::SYSTEMD_CONTAINERS_PATH.gsub('~', HOME_DIR)
29
+ self.class.sshExec!(ssh, "echo 'ROCKET_PORT=8000' > #{path}/Vaultwarden.env")
30
+ if target['Domain']
31
+ self.class.sshExec!(ssh, "echo 'DOMAIN=https://#{target['Domain']}' >> #{path}/Vaultwarden.env")
32
+ end
33
+ target['Signups'] = false unless target['Signups']
34
+ self.class.sshExec!(ssh, "echo 'SIGNUPS_ALLOWED=#{target['Signups'].to_s}' >> #{path}/Vaultwarden.env")
35
+ if target.key?('Invitations')
36
+ self.class.sshExec!(ssh, "echo 'INVITATIONS_ALLOWED=#{target['Invitations'].to_s}' >> #{path}/Vaultwarden.env")
37
+ end
38
+ if ENV.key?('VAULTWARDEN_ADMIN_TOKEN')
39
+ token = ENV['VAULTWARDEN_ADMIN_TOKEN']
40
+ token = SecureRandom.alphanumeric(40) if token.empty?
41
+ self.class.sshExec!(ssh, "echo 'ADMIN_TOKEN=#{token}' >> #{path}/Vaultwarden.env")
42
+ end
43
+ self.class.sshExec!(ssh, "chown #{USER}:#{USER} #{path}/Vaultwarden.env")
44
+ self.class.sshExec!(ssh, "chmod 600 #{path}/Vaultwarden.env")
45
+
46
+ ssh.scp.upload!(__dir__ + '/Vaultwarden.container', path)
47
+ self.class.sshExec!(ssh, "systemctl --user --machine=#{USER}@ daemon-reload")
48
+ self.class.sshExec!(ssh, "systemctl --user --machine=#{USER}@ start Vaultwarden")
49
+ end
50
+ if !target.key?('Proxy') || !!target['Proxy']
51
+ self.class.prepareNginxConfig(target, ssh)
52
+ writeNginxConfig(__dir__, NAME, id, target, state, context, options)
53
+ deployNginxConfig(id, target, activeState, context, options)
54
+ end
55
+ end
56
+ else
57
+ # TODO
19
58
  activeState['Location'] = '@me'
20
59
  end
21
60
  end