ConfigLMM 0.2.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +31 -0
  3. data/Examples/Implemented.mm.yaml +75 -1
  4. data/Plugins/Apps/Authentik/Authentik-Server.container +18 -0
  5. data/Plugins/Apps/Authentik/Authentik-Worker.container +17 -0
  6. data/Plugins/Apps/Authentik/Authentik.conf.erb +35 -0
  7. data/Plugins/Apps/Authentik/Authentik.lmm.rb +73 -0
  8. data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +41 -0
  9. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +148 -0
  10. data/Plugins/Apps/GitLab/GitLab.conf.erb +26 -0
  11. data/Plugins/Apps/GitLab/GitLab.container +17 -0
  12. data/Plugins/Apps/GitLab/GitLab.lmm.rb +75 -0
  13. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +48 -10
  14. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +59 -2
  15. data/Plugins/Apps/Nextcloud/config.php +18 -0
  16. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +62 -0
  17. data/Plugins/Apps/Nginx/config-lmm/errors.conf +1 -1
  18. data/Plugins/Apps/Nginx/main.conf.erb +31 -0
  19. data/Plugins/Apps/Nginx/nginx.conf +3 -68
  20. data/Plugins/Apps/Nginx/nginx.lmm.rb +71 -14
  21. data/Plugins/Apps/Odoo/Odoo.conf.erb +30 -13
  22. data/Plugins/Apps/Odoo/Odoo.container +17 -0
  23. data/Plugins/Apps/Odoo/Odoo.lmm.rb +62 -2
  24. data/Plugins/Apps/Odoo/odoo.conf +37 -0
  25. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +95 -0
  26. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +64 -0
  27. data/Plugins/Apps/Peppermint/Peppermint.container +14 -0
  28. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +58 -0
  29. data/Plugins/Apps/Postfix/Postfix.lmm.rb +139 -31
  30. data/Plugins/Apps/Postfix/smtpd.conf +3 -0
  31. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +172 -23
  32. data/Plugins/Apps/SSH/SSH.lmm.rb +51 -0
  33. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +52 -0
  34. data/Plugins/Apps/UVdesk/UVdesk.lmm.rb +85 -0
  35. data/Plugins/Apps/Valkey/Valkey.lmm.rb +2 -1
  36. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +35 -18
  37. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +16 -0
  38. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +42 -3
  39. data/Plugins/Apps/gollum/gollum.conf.erb +45 -18
  40. data/Plugins/Apps/gollum/gollum.container +12 -0
  41. data/Plugins/Apps/gollum/gollum.lmm.rb +39 -10
  42. data/Plugins/OS/Linux/Distributions.yaml +10 -0
  43. data/Plugins/OS/Linux/Linux.lmm.rb +145 -12
  44. data/Plugins/OS/Linux/Packages.yaml +42 -4
  45. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +108 -0
  46. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +15 -0
  47. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +28 -0
  48. data/Plugins/OS/Linux/systemd/user-0.slice +9 -0
  49. data/Plugins/OS/Linux/systemd/user@.service.d/delegate.conf +3 -0
  50. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +6 -2
  51. data/Plugins/Services/DNS/PowerDNS.lmm.rb +69 -6
  52. data/README.md +6 -0
  53. data/bootstrap.sh +54 -0
  54. data/lib/ConfigLMM/Framework/plugins/dns.rb +1 -2
  55. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +157 -35
  56. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +24 -6
  57. data/lib/ConfigLMM/Framework/plugins/plugin.rb +52 -12
  58. data/lib/ConfigLMM/version.rb +1 -1
  59. metadata +31 -3
  60. data/Plugins/Apps/Nginx/main.conf +0 -30
@@ -14,50 +14,199 @@ module ConfigLMM
14
14
  def actionPostgreSQLDeploy(id, target, activeState, context, options)
15
15
  self.ensurePackage(PACKAGE_NAME, target['Location'])
16
16
  self.ensureServiceAutoStart(SERVICE_NAME, target['Location'])
17
+ self.startService(SERVICE_NAME, target['Location'])
17
18
 
18
19
  if target['Location'] && target['Location'] != '@me'
19
20
  uri = Addressable::URI.parse(target['Location'])
20
21
  raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
21
- if target['ListenAll']
22
- cmd = "sed -i 's|^host all all 127.0.0.1/32 ident|host all all 0.0.0.0/0 scram-sha-256|'"
23
- dir = updateConfigOverSSH(uri, cmd)
24
- updateRemoteFile(uri, dir + CONFIG_FILE, options, false) do |configLines|
25
- configLines << "listen_addresses = '*'\n"
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"
26
68
  end
27
- else
28
- cmd = "sed -i 's|^host all all 127.0.0.1/32 ident|host all all 127.0.0.1/32 scram-sha-256|'"
29
- updateConfigOverSSH(uri, cmd)
30
69
  end
31
70
  else
32
- dir = pgsqlDir(self.class.distroID)
33
- if target['ListenAll']
34
- `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}`
35
- updateLocalFile(dir + CONFIG_FILE, options) do |configLines|
36
- configLines << "listen_addresses = '*'"
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)
37
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)
38
126
  else
39
- `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}`
127
+ raise "Invalid Tables field: #{data['Tables']}"
40
128
  end
41
129
  end
130
+ end
42
131
 
43
- self.startService(SERVICE_NAME, target['Location'])
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)
44
155
  end
45
156
 
46
- def updateConfigOverSSH(uri, cmd)
157
+ def updateConfigOverSSH(ssh, cmd)
47
158
  dir = ''
48
- self.class.sshStart(uri) do |ssh|
49
- distroID = self.class.distroIDfromSSH(ssh)
50
- dir = pgsqlDir(distroID)
51
- self.class.sshExec!(ssh, cmd + ' ' + dir + HBA_FILE)
52
- end
159
+ distroID = self.class.distroID(ssh)
160
+ dir = pgsqlDir(distroID)
161
+ self.class.sshExec!(ssh, cmd + ' ' + dir + HBA_FILE)
53
162
  dir
54
163
  end
55
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
+
56
182
  def self.createUserAndDBOverSSH(user, password, ssh)
57
183
  self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createuser #{user}'", true)
58
184
  self.sshExec!(ssh, "su --login #{USER_NAME} --command 'createdb --owner=#{user} #{user}'", true)
59
- cmd = " su --login #{USER_NAME} --command ' psql -c \"ALTER USER #{user} WITH PASSWORD \\'#{password}\\';\"'"
60
- self.sshExec!(ssh, cmd)
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
61
210
  end
62
211
 
63
212
  def pgsqlDir(distroID)
@@ -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
+
@@ -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}")
@@ -25,6 +25,7 @@ module ConfigLMM
25
25
  end
26
26
 
27
27
  if target['Settings']
28
+ target['Settings']['bind'] = '127.0.0.1' unless target['Settings']['bind']
28
29
  updateRemoteFile(ssh, CONFIG_FILE, options, false) do |configLines|
29
30
  target['Settings'].each do |name, value|
30
31
  configLines << "#{name} #{value}\n"
@@ -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