ConfigLMM 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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