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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a8ee6e7ca0b1e3cf4dd9e1007aa696d763ab522c2c1cfc4a401e55ccdeefc4e3
4
- data.tar.gz: 71c10651774b7c6ce347cf3fe9bc2df08ca388244ad8cf0cdbaa77c1f8beb1a7
3
+ metadata.gz: '0078988f4f9bf52b61e5de21839b6ab1da6c56e24e4999987b9818cab6b5c7ca'
4
+ data.tar.gz: 429aed3d4f1a83271175022c479408db601b85c0f991163d0f87527a6fe55135
5
5
  SHA512:
6
- metadata.gz: 17cc1304b94186312fd2c25779234ba4c0354c8dfcc971eeff5d000ebdb1d29138f7decfa5f175f154cbc1174d6e3b5ef3f7077caa8013d53a493c8c2a7ccf7d
7
- data.tar.gz: 50b169c6147cbd7b02da3e0fc3b264b09271bb83813330196a546da4d976c5071b2d53e534e47512fca85927ea5201e1f085b10601febcfaacf0d41ffec7c362
6
+ metadata.gz: afc93dc18858dd5102963d65c27adf37891a69e3cd80a768d2fc8c08c64ccb8cc50478a594a18c3769de7efc6c921d75fc92357fa948ace10091b010a932e6f6
7
+ data.tar.gz: 615fdfbd8cb389fefa0aacd51e6b2cf3739e7e7305d0ed389dec481d79a12cb1289e12a4b3224faf092c8c858cfd357c95e803d584024feb0225409b0d8cca69
data/CHANGELOG.md CHANGED
@@ -1,4 +1,35 @@
1
1
 
2
+ ## [0.3.0] - 2024-08-13
3
+
4
+ Implement:
5
+ - systemd UserCgroups
6
+ - Authentik - https://goauthentik.io/
7
+ - WireGuard - https://www.wireguard.com/
8
+ - Dovecot - https://www.dovecot.org/
9
+ - Nextcloud - https://nextcloud.com/
10
+ - Vaultwarden - https://github.com/dani-garcia/vaultwarden
11
+ - Linux: fstab tmpfs
12
+ - Linux: Network config
13
+ - Linux: deployLocal() and Execute commands
14
+ - SSH settings
15
+ - Odoo - https://www.odoo.com/
16
+ - GitLab - https://about.gitlab.com/
17
+ - Partial UVdesk - https://www.uvdesk.com/en/ticket-management-system/
18
+ - Peppermint - https://peppermint.sh/
19
+ - Cassandra - https://cassandra.apache.org/_/index.html
20
+
21
+ Other improvements:
22
+ - Add bootstrap.sh script
23
+ - PowerDNS
24
+ - GoDaddy
25
+ - Nginx
26
+ - PostgreSQL: Support Logical Replication
27
+ - Postfix
28
+ - gollum
29
+ - Linux: Users SSHKey
30
+ - PostgreSQL
31
+ - Valkey
32
+
2
33
  ## [0.2.0] - 2024-07-19
3
34
 
4
35
  - openSUSE - https://www.opensuse.org/
@@ -49,6 +49,7 @@ Linux:
49
49
  CPU: 2
50
50
  RAM: 4 GiB
51
51
  Storage: 30 GiB
52
+ Tmpfs: 1G
52
53
  Domain: example.org
53
54
  Hosts:
54
55
  127.0.0.1:
@@ -60,6 +61,7 @@ Linux:
60
61
  Users:
61
62
  root:
62
63
  Shell: fish
64
+ SSHKey: yes
63
65
  AuthorizedKeys:
64
66
  - ~/.ssh/id_ed25519.pub
65
67
  SSH:
@@ -68,7 +70,26 @@ Linux:
68
70
  User: root
69
71
  HostName: example.org
70
72
  Sysctl:
71
- vm.overcommit_memory: 1
73
+ vm.overcommit_memory: 1 # Need for ValKey
74
+ net.ipv4.ip_forward: 1 # Need for Wanguard
75
+ Network:
76
+ IP: 192.168.1.2/24
77
+ Gateway: 192.168.1.1
78
+ DNS: 192.168.1.1
79
+ Execute:
80
+ sh: echo Hello World from ConfigLMM > /tmp/hello
81
+
82
+ SSH:
83
+ Type: SSH
84
+ Location: ssh://example.org/
85
+ Port: 1234
86
+ Settings:
87
+ PasswordAuthentication: no
88
+
89
+ Systemd:
90
+ Type: systemd
91
+ Location: ssh://example.org/
92
+ UserCgroups: yes # Need for Podman
72
93
 
73
94
  # https://www.arubanetworks.com/
74
95
  ArubaInstant:
@@ -81,15 +102,39 @@ ArchiSteamFarm:
81
102
  Type: ArchiSteamFarm
82
103
  Domain: ASF.example.org
83
104
 
105
+ # https://goauthentik.io/
106
+ Authentik:
107
+ Type: Authentik
108
+ Location: ssh://example.org/
109
+ Domain: auth.example.org
110
+
84
111
  # https://bitmagnet.io/
85
112
  Bitmagnet:
86
113
  Type: Bitmagnet
87
114
  Domain: bitmagnet.example.org
88
115
 
116
+ # https://cassandra.apache.org/_/index.html
117
+ Cassandra:
118
+ Type: Cassandra
119
+ Location: ssh://example.org/
120
+ ClusterName: Cluster
121
+
122
+ # https://www.dovecot.org/
89
123
  Dovecot:
90
124
  Type: Dovecot
91
125
  Location: ssh://example.org/
92
126
 
127
+ # https://about.gitlab.com/
128
+ GitLab:
129
+ Type: GitLab
130
+ Location: ssh://example.org/
131
+ Domain: git.example.org
132
+ SMTP:
133
+ HostName: email.example.org
134
+ Port: 465
135
+ User: git@example.org
136
+ TLS: yes
137
+
93
138
  # https://github.com/gollum/gollum
94
139
  Gollum:
95
140
  Type: Gollum
@@ -141,18 +186,31 @@ Netdata:
141
186
  Nextcloud:
142
187
  Type: Nextcloud
143
188
  Domain: nextcloud.example.org
189
+ Database:
190
+ Type: pgsql
191
+ HostName: localhost
144
192
 
145
193
  # https://www.odoo.com/
146
194
  Odoo:
147
195
  Type: Odoo
148
196
  Domain: odoo.example.org
197
+ Database:
198
+ HostName: db.example.org
199
+
200
+ # https://peppermint.sh/
201
+ Peppermint:
202
+ Type: Peppermint
203
+ Location: ssh://example.org/
204
+ Domain: Peppermint.example.org
149
205
 
150
206
  # https://www.postfix.org/
151
207
  Postfix:
152
208
  Type: Postfix
153
209
  Location: ssh://example.org/
154
210
  AlternativePort: 2525
211
+ SMTP: unix
155
212
  ForwardAll: example.com
213
+ ForwardDovecot: yes
156
214
  Settings:
157
215
  inet_interfaces: $myhostname, localhost
158
216
 
@@ -160,6 +218,13 @@ PostgreSQL:
160
218
  Type: PostgreSQL
161
219
  Location: ssh://example.org/
162
220
  ListenAll: yes
221
+ Users:
222
+ replication:
223
+ Replication: yes
224
+ Password: ${ENV:POSTGRES_REPLICATION_PASSWORD}
225
+ Subscriptions:
226
+ db:
227
+ Connection: user=replication dbname=db password=${ENV:POSTGRES_REPLICATION_PASSWORD}
163
228
 
164
229
  # https://pterodactyl.io/
165
230
  Pterodactyl:
@@ -199,3 +264,12 @@ Valkey:
199
264
  Vaultwarden:
200
265
  Type: Vaultwarden
201
266
  Domain: vaultwarden.example.org
267
+
268
+ # https://www.wireguard.com/
269
+ WireGuard:
270
+ Type: WireGuard
271
+ Location: ssh://example.org/
272
+ Address: 172.20.0.1/20
273
+ Peers:
274
+ example:
275
+ Endpoint: example.example.org
@@ -0,0 +1,18 @@
1
+
2
+ [Unit]
3
+ Description=Authentik Server container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ Image=ghcr.io/goauthentik/server:latest
8
+ Exec=server
9
+ EnvironmentFile=/var/lib/authentik/.config/containers/systemd/Authentik.env
10
+ Network=slirp4netns:allow_host_loopback=true
11
+ PublishPort=127.0.0.1:19000:9000
12
+ PublishPort=127.0.0.1:19300:9300
13
+ UserNS=keep-id:uid=1000,gid=1000
14
+ Volume=/var/lib/authentik/media:/media
15
+ Volume=/var/lib/authentik/templates:/templates
16
+
17
+ [Install]
18
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,17 @@
1
+
2
+ [Unit]
3
+ Description=Authentik Worker container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ Image=ghcr.io/goauthentik/server:latest
8
+ Exec=worker
9
+ EnvironmentFile=/var/lib/authentik/.config/containers/systemd/Authentik.env
10
+ Network=slirp4netns:allow_host_loopback=true
11
+ UserNS=keep-id:uid=1000,gid=1000
12
+ Volume=/var/lib/authentik/media:/media
13
+ Volume=/var/lib/authentik/templates:/templates
14
+ Volume=/var/lib/authentik/certs:/certs
15
+
16
+ [Install]
17
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,35 @@
1
+
2
+ # Upstream where your authentik server is hosted.
3
+ upstream authentik {
4
+ server localhost:19000;
5
+
6
+ # Improve performance by keeping some connections alive.
7
+ keepalive 10;
8
+ }
9
+
10
+ server {
11
+ <% if config['NginxVersion'] >= 1.25 %>
12
+ listen 443 ssl;
13
+ listen [::]:443 ssl;
14
+ http2 on;
15
+ http3 on;
16
+ quic_retry on;
17
+ add_header Alt-Svc 'h3=":443"; ma=86400';
18
+ <% else %>
19
+ listen 443 ssl http2;
20
+ listen [::]:443 ssl http2;
21
+ <% end %>
22
+
23
+ include config-lmm/ssl.conf;
24
+
25
+ server_name <%= config['Domain'] %>;
26
+
27
+ access_log /var/log/nginx/authentik.access.log;
28
+ error_log /var/log/nginx/authentik.error.log;
29
+
30
+ # Proxy site
31
+ location / {
32
+ proxy_pass http://authentik;
33
+ include config-lmm/proxy.conf;
34
+ }
35
+ }
@@ -0,0 +1,73 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Authentik < Framework::NginxApp
5
+
6
+ USER = 'authentik'
7
+ HOME_DIR = '/var/lib/authentik'
8
+ HOST_IP = '10.0.2.2'
9
+
10
+ def actionAuthentikBuild(id, target, state, context, options)
11
+ self.writeNginxConfig(__dir__, 'Authentik', id, target, state, context, options)
12
+ end
13
+
14
+ def actionAuthentikDeploy(id, target, activeState, context, options)
15
+ if target['Location'] && target['Location'] != '@me'
16
+ uri = Addressable::URI.parse(target['Location'])
17
+ case uri.scheme
18
+ when 'ssh'
19
+ self.class.sshStart(uri) do |ssh|
20
+ self.prepareConfig(target, ssh)
21
+
22
+ dbPassword = self.configurePostgreSQL(target['Database'], ssh)
23
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
24
+ Framework::LinuxApp.configurePodmanServiceOverSSH(USER, HOME_DIR, 'Authentik IdP and SSO', distroInfo, ssh)
25
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mkdir -p ~/media'")
26
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mkdir -p ~/templates'")
27
+ self.class.sshExec!(ssh, "su --login #{USER} --shell /bin/sh --command 'mkdir -p ~/certs'")
28
+
29
+ path = Framework::LinuxApp::SYSTEMD_CONTAINERS_PATH.gsub('~', HOME_DIR)
30
+ self.class.sshExec!(ssh, " echo 'AUTHENTIK_SECRET_KEY=#{SecureRandom.urlsafe_base64(60)}' > #{path}/Authentik.env")
31
+ self.class.sshExec!(ssh, " echo 'AUTHENTIK_REDIS__HOST=#{HOST_IP}' >> #{path}/Authentik.env")
32
+ self.class.sshExec!(ssh, " echo 'AUTHENTIK_POSTGRESQL__HOST=#{HOST_IP}' >> #{path}/Authentik.env")
33
+ self.class.sshExec!(ssh, " echo 'AUTHENTIK_POSTGRESQL__PASSWORD=#{dbPassword}' >> #{path}/Authentik.env")
34
+ self.class.sshExec!(ssh, "chown #{USER}:#{USER} #{path}/Authentik.env")
35
+ self.class.sshExec!(ssh, "chmod 600 #{path}/Authentik.env")
36
+
37
+ ssh.scp.upload!(__dir__ + '/Authentik-Server.container', path)
38
+ ssh.scp.upload!(__dir__ + '/Authentik-Worker.container', path)
39
+ self.class.sshExec!(ssh, "systemctl --user --machine=#{USER}@ daemon-reload")
40
+ self.class.sshExec!(ssh, "systemctl --user --machine=#{USER}@ start Authentik-Server")
41
+ self.class.sshExec!(ssh, "systemctl --user --machine=#{USER}@ start Authentik-Worker")
42
+
43
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(NGINX_PACKAGE, ssh)
44
+ self.writeNginxConfig(__dir__, 'Authentik', id, target, state, context, options)
45
+ self.deployNginxConfig(id, target, activeState, context, options)
46
+ Framework::LinuxApp.startServiceOverSSH(NGINX_PACKAGE, ssh)
47
+ end
48
+ else
49
+ raise Framework::PluginProcessError.new("#{id}: Unknown protocol: #{uri.scheme}!")
50
+ end
51
+ else
52
+ # TODO
53
+ end
54
+ end
55
+
56
+ def prepareConfig(target, ssh)
57
+ target['Database'] ||= {}
58
+
59
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
60
+
61
+ Framework::LinuxApp.ensurePackages([NGINX_PACKAGE], ssh)
62
+ self.class.prepareNginxConfig(target, ssh)
63
+ end
64
+
65
+ def configurePostgreSQL(settings, ssh)
66
+ password = SecureRandom.alphanumeric(20)
67
+ PostgreSQL.createRemoteUserAndDBOverSSH(settings, USER, password, ssh)
68
+ password
69
+ end
70
+
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,41 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Cassandra < Framework::Plugin
5
+ PACKAGE_NAME = 'Cassandra'
6
+ SERVICE_NAME = 'cassandra'
7
+
8
+ def actionCassandraDeploy(id, target, activeState, context, options)
9
+ plugins[:Linux].ensurePackage(PACKAGE_NAME, target['Location'])
10
+ plugins[:Linux].ensureServiceAutoStart(SERVICE_NAME, target['Location'])
11
+
12
+ if target['Location'] && target['Location'] != '@me'
13
+ uri = Addressable::URI.parse(target['Location'])
14
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
15
+
16
+ self.class.sshStart(uri) do |ssh|
17
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
18
+ configFile = '/etc/cassandra/cassandra.yaml'
19
+ if distroInfo['Name'] == 'openSUSE Leap'
20
+ configFile = '/etc/cassandra/conf/cassandra.yaml'
21
+ end
22
+
23
+ cmd = "sed -i 's|^uuid_sstable_identifiers_enabled:.*|uuid_sstable_identifiers_enabled: true|' #{configFile}"
24
+ self.class.sshExec!(ssh, cmd)
25
+ if target['ClusterName']
26
+ cmd = "sed -i 's|^cluster_name:.*|cluster_name: #{target['ClusterName']}|' #{configFile}"
27
+ self.class.sshExec!(ssh, cmd)
28
+ end
29
+ end
30
+ else
31
+ # TODO
32
+ end
33
+
34
+ plugins[:Linux].startService(SERVICE_NAME, target['Location'])
35
+ end
36
+
37
+ end
38
+
39
+ end
40
+ end
41
+
@@ -4,13 +4,161 @@ module ConfigLMM
4
4
  class Dovecot < Framework::Plugin
5
5
  PACKAGE_NAME = 'Dovecot'
6
6
  SERVICE_NAME = 'dovecot'
7
+ DOVECOT_DIR = '/etc/dovecot/'
8
+ EMAIL_HOME = '/var/lib/email'
9
+ EMAIL_USER = 'email'
7
10
 
8
11
  def actionDovecotDeploy(id, target, activeState, context, options)
9
12
  plugins[:Linux].ensurePackage(PACKAGE_NAME, target['Location'])
10
13
  plugins[:Linux].ensureServiceAutoStart(SERVICE_NAME, target['Location'])
14
+
15
+ if target['Location'] && target['Location'] != '@me'
16
+ uri = Addressable::URI.parse(target['Location'])
17
+ raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
18
+
19
+ self.class.sshStart(uri) do |ssh|
20
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
21
+ addUserCmd = "#{distroInfo['CreateServiceUser']} --home-dir '#{EMAIL_HOME}' --create-home --comment 'Dovecot EMail' #{EMAIL_USER}"
22
+ self.class.sshExec!(ssh, addUserCmd, true)
23
+ uid = self.class.sshExec!(ssh, "id -u #{EMAIL_USER}").strip
24
+
25
+ cmd = "sed -i 's|^#mail_uid =.*|mail_uid = #{uid}|' #{DOVECOT_DIR}conf.d/10-mail.conf"
26
+ self.class.sshExec!(ssh, cmd)
27
+ cmd = "sed -i 's|^#mail_gid =.*|mail_gid = #{uid}|' #{DOVECOT_DIR}conf.d/10-mail.conf"
28
+ self.class.sshExec!(ssh, cmd)
29
+ cmd = "sed -i 's|^#mail_location =.*|mail_location = maildir:~/Mail|' #{DOVECOT_DIR}conf.d/10-mail.conf"
30
+ self.class.sshExec!(ssh, cmd)
31
+
32
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/10-mail.conf', options) do |configLines|
33
+ configLines << "mail_home = #{EMAIL_HOME}/emails/%u\n"
34
+ configLines << "first_valid_uid = #{uid}\n"
35
+ configLines << "last_valid_uid = #{uid}\n"
36
+ end
37
+
38
+ self.class.cutConfigSection(DOVECOT_DIR + 'conf.d/10-master.conf', 'service lmtp', options, ssh)
39
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/10-master.conf', options) do |configLines|
40
+ configLines << "service lmtp {\n"
41
+ configLines << " unix_listener lmtp {\n"
42
+ configLines << " user = postfix\n"
43
+ configLines << " group = postfix\n"
44
+ configLines << " mode = 0600\n"
45
+ configLines << " }\n"
46
+ configLines << "}\n"
47
+ end
48
+
49
+ self.class.cutConfigSection(DOVECOT_DIR + 'conf.d/15-mailboxes.conf', 'namespace inbox', options, ssh)
50
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/15-mailboxes.conf', options) do |configLines|
51
+ configLines << "namespace inbox {\n"
52
+ configLines << " mailbox Drafts {\n"
53
+ configLines << " special_use = \\Drafts\n"
54
+ configLines << " auto = subscribe\n"
55
+ configLines << " }\n"
56
+ #configLines << " mailbox Junk {\n"
57
+ #configLines << " special_use = \\Junk\n"
58
+ #configLines << " auto = subscribe\n"
59
+ #configLines << " }\n"
60
+ configLines << " mailbox Trash {\n"
61
+ configLines << " special_use = \\Trash\n"
62
+ configLines << " auto = subscribe\n"
63
+ configLines << " }\n"
64
+ configLines << " mailbox Sent {\n"
65
+ configLines << " special_use = \\Sent\n"
66
+ configLines << " auto = subscribe\n"
67
+ configLines << " }\n"
68
+ configLines << "}\n"
69
+ end
70
+
71
+ self.class.sshExec!(ssh, "firewall-cmd -q --add-service='imaps'")
72
+ self.class.sshExec!(ssh, "firewall-cmd -q --permanent --add-service='imaps'")
73
+
74
+ cmd = "sed -i 's|^!include auth-system.conf.ext|#!include auth-system.conf.ext|' #{DOVECOT_DIR}conf.d/10-auth.conf"
75
+ self.class.sshExec!(ssh, cmd)
76
+
77
+ if target['OAuth2']
78
+ cmd = "sed -i 's|auth_mechanisms =.*|auth_mechanisms = xoauth2 oauthbearer|' #{DOVECOT_DIR}conf.d/10-auth.conf"
79
+ self.class.sshExec!(ssh, cmd)
80
+
81
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/10-auth.conf', options) do |configLines|
82
+ configLines << "userdb {\n"
83
+ configLines << " driver = static\n"
84
+ configLines << " args = allow_all_users=yes\n"
85
+ configLines << "}\n"
86
+ configLines << "passdb {\n"
87
+ configLines << " driver = oauth2\n"
88
+ configLines << " mechanisms = xoauth2 oauthbearer\n"
89
+ configLines << " args = #{DOVECOT_DIR}dovecot-oauth2.conf.ext\n"
90
+ configLines << "}\n"
91
+ end
92
+
93
+ updateRemoteFile(ssh, DOVECOT_DIR + 'dovecot-oauth2.conf.ext', options) do |configLines|
94
+ # Need v2.3.16+
95
+ #configLines << "openid_configuration_url = #{target['OAuth2']['OIDC']}\n"
96
+ if target['OAuth2']['TokenInfo']
97
+ configLines << "tokeninfo_url = #{target['OAuth2']['TokenInfo']}\n"
98
+ end
99
+ if target['OAuth2']['Introspection']
100
+ configLines << "introspection_url = #{target['OAuth2']['Introspection']}\n"
101
+ end
102
+ if target['OAuth2']['ClientID']
103
+ configLines << "client_id = #{target['OAuth2']['ClientID']}\n"
104
+ end
105
+ if ENV['DOVECOT_OAUTH2_SECRET']
106
+ configLines << "client_secret = #{ENV['DOVECOT_OAUTH2_SECRET']}\n"
107
+ end
108
+ end
109
+ else
110
+ cmd = "sed -i 's|auth_mechanisms =.*|auth_mechanisms = plain|' #{DOVECOT_DIR}conf.d/10-auth.conf"
111
+ self.class.sshExec!(ssh, cmd)
112
+
113
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/10-auth.conf', options) do |configLines|
114
+ configLines << "auth_username_format = %u\n"
115
+ configLines << "userdb {\n"
116
+ configLines << " driver = static\n"
117
+ configLines << " args = allow_all_users=yes\n"
118
+ configLines << "}\n"
119
+ configLines << "passdb {\n"
120
+ configLines << " driver = passwd-file\n"
121
+ configLines << " args = #{DOVECOT_DIR}passwords\n"
122
+ configLines << "}\n"
123
+ end
124
+ self.class.sshExec!(ssh, "touch #{DOVECOT_DIR}passwords")
125
+ self.class.sshExec!(ssh, "chown dovecot:dovecot #{DOVECOT_DIR}passwords")
126
+ self.class.sshExec!(ssh, "chmod 600 #{DOVECOT_DIR}passwords")
127
+ end
128
+
129
+ certDir = Framework::LinuxApp.createCertificateOverSSH(ssh)
130
+ updateRemoteFile(ssh, DOVECOT_DIR + 'conf.d/10-ssl.conf', options) do |configLines|
131
+ configLines << "ssl_cert = <#{certDir}fullchain.pem\n"
132
+ configLines << "ssl_key = <#{certDir}privkey.pem\n"
133
+ end
134
+ end
135
+ else
136
+ # TODO
137
+ end
138
+
11
139
  plugins[:Linux].startService(SERVICE_NAME, target['Location'])
12
140
  end
13
141
 
142
+ def self.cutConfigSection(file, sectionStart, options, ssh)
143
+ localFile = options['output'] + '/' + SecureRandom.alphanumeric(10)
144
+ File.write(localFile, '')
145
+ self.sshExec!(ssh, "touch #{file}")
146
+ ssh.scp.download!(file, localFile)
147
+ fileData = File.read(localFile)
148
+ position = fileData.index(sectionStart)
149
+ if position
150
+ # Find the index of the closing brace of the section
151
+ # We use a regular expression to find the next non-nested closing brace
152
+ match = fileData[position..-1].match(/(?<=\{)(.*?)(^\})/m)
153
+ if match
154
+ fileData = fileData[0...position] + fileData[(position + match.end(0))..-1]
155
+ else
156
+ fileData = fileData[0...position]
157
+ end
158
+ File.write(localFile, fileData)
159
+ ssh.scp.upload!(localFile, file)
160
+ end
161
+ end
14
162
  end
15
163
 
16
164
  end
@@ -0,0 +1,26 @@
1
+
2
+ server {
3
+ <% if config['NginxVersion'] >= 1.25 %>
4
+ listen 443 ssl;
5
+ listen [::]:443 ssl;
6
+ http2 on;
7
+ http3 on;
8
+ quic_retry on;
9
+ add_header Alt-Svc 'h3=":443"; ma=86400';
10
+ <% else %>
11
+ listen 443 ssl http2;
12
+ listen [::]:443 ssl http2;
13
+ <% end %>
14
+
15
+ include config-lmm/ssl.conf;
16
+
17
+ server_name <%= config['Domain'] %>;
18
+
19
+ access_log /var/log/nginx/gitlab.access.log;
20
+ error_log /var/log/nginx/gitlab.error.log;
21
+
22
+ location / {
23
+ proxy_pass http://127.0.0.1:18100;
24
+ include config-lmm/proxy.conf;
25
+ }
26
+ }
@@ -0,0 +1,17 @@
1
+
2
+ [Unit]
3
+ Description=GitLab container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ Image=gitlab/gitlab-ce:nightly
8
+ PublishPort=127.0.0.1:18100:80
9
+ PublishPort=0.0.0.0:22:22
10
+ Volume=/var/lib/gitlab/config:/etc/gitlab
11
+ Volume=/var/lib/gitlab/logs:/var/log/gitlab
12
+ Volume=/var/lib/gitlab/data:/var/opt/gitlab
13
+ Volume=/var/lib/gitlab/backups:/var/opt/gitlab/backups
14
+ ShmSize=256M
15
+
16
+ [Install]
17
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,75 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class GitLab < Framework::NginxApp
5
+
6
+ HOME_DIR = '/var/lib/gitlab'
7
+
8
+ def actionGitLabDeploy(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
+ self.prepareConfig(target, ssh)
16
+
17
+ distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
18
+ self.class.sshExec!(ssh, "mkdir -p #{HOME_DIR}/config")
19
+ self.class.sshExec!(ssh, "mkdir -p #{HOME_DIR}/logs")
20
+ self.class.sshExec!(ssh, "mkdir -p #{HOME_DIR}/data")
21
+ self.class.sshExec!(ssh, "mkdir -p #{HOME_DIR}/backups")
22
+
23
+ path = '/etc/containers/systemd'
24
+ ssh.scp.upload!(__dir__ + '/GitLab.container', path)
25
+ self.class.sshExec!(ssh, "systemctl daemon-reload")
26
+ self.class.sshExec!(ssh, "systemctl start GitLab")
27
+
28
+ Framework::LinuxApp.ensureServiceAutoStartOverSSH(NGINX_PACKAGE, ssh)
29
+ self.writeNginxConfig(__dir__, 'GitLab', id, target, state, context, options)
30
+ self.deployNginxConfig(id, target, activeState, context, options)
31
+ Framework::LinuxApp.startServiceOverSSH(NGINX_PACKAGE, ssh)
32
+
33
+ configFile = '/var/lib/gitlab/config/gitlab.rb'
34
+ while !self.class.remoteFilePresent?(configFile, ssh)
35
+ sleep(2)
36
+ end
37
+ updateRemoteFile(ssh, configFile, options, true) do |fileLines|
38
+ fileLines << "external_url 'https://#{target['Domain']}'\n"
39
+ fileLines << "letsencrypt['enable'] = false\n"
40
+ fileLines << "nginx['listen_port'] = 80\n"
41
+ fileLines << "nginx['listen_https'] = false\n"
42
+ fileLines << "registry_nginx['listen_port'] = 80\n"
43
+ fileLines << "registry_nginx['listen_https'] = false\n"
44
+ fileLines << "mattermost_nginx['listen_port'] = 80\n"
45
+ fileLines << "mattermost_nginx['listen_https'] = false\n"
46
+ if target['SMTP']
47
+ fileLines << "gitlab_rails['smtp_address'] = '#{target['SMTP']['HostName']}'\n"
48
+ fileLines << "gitlab_rails['smtp_port'] = '#{target['SMTP']['Port']}'\n"
49
+ fileLines << "gitlab_rails['smtp_user_name'] = '#{target['SMTP']['User']}'\n"
50
+ if target['SMTP']['TLS']
51
+ fileLines << "gitlab_rails['smtp_tls'] = true\n"
52
+ fileLines << "gitlab_rails['smtp_openssl_verify_mode'] = 'peer'\n"
53
+ end
54
+ end
55
+ end
56
+
57
+ self.class.sshExec!(ssh, "systemctl restart GitLab")
58
+ end
59
+ else
60
+ # TODO
61
+ end
62
+ end
63
+
64
+ def prepareConfig(target, ssh)
65
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
66
+
67
+ Framework::LinuxApp.ensurePackages([NGINX_PACKAGE], ssh)
68
+ self.class.prepareNginxConfig(target, ssh)
69
+ end
70
+
71
+ end
72
+
73
+ end
74
+ end
75
+