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
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
+