ConfigLMM 0.4.0 → 0.5.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 (227) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +34 -0
  3. data/CNAME +1 -0
  4. data/Examples/.lmm.state.yaml +159 -0
  5. data/Examples/ConfigLMM.mm.yaml +32 -0
  6. data/Examples/Implemented.mm.yaml +252 -4
  7. data/Examples/SmallBusiness.mm.yaml +492 -0
  8. data/Plugins/Apps/Answer/answer.lmm.rb +165 -0
  9. data/Plugins/Apps/Answer/answer@.service +40 -0
  10. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.conf.erb +0 -3
  11. data/Plugins/Apps/ArchiSteamFarm/ArchiSteamFarm.lmm.rb +0 -1
  12. data/Plugins/Apps/Authentik/Authentik-ProxyOutpost.container +7 -1
  13. data/Plugins/Apps/Authentik/Authentik-Server.container +6 -1
  14. data/Plugins/Apps/Authentik/Authentik-Worker.container +6 -1
  15. data/Plugins/Apps/Authentik/Authentik.conf.erb +12 -7
  16. data/Plugins/Apps/Authentik/Authentik.lmm.rb +226 -61
  17. data/Plugins/Apps/BookStack/BookStack.conf.erb +0 -3
  18. data/Plugins/Apps/BookStack/BookStack.container +5 -0
  19. data/Plugins/Apps/BookStack/BookStack.lmm.rb +14 -3
  20. data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +9 -19
  21. data/Plugins/Apps/ClickHouse/ClickHouse.container +28 -0
  22. data/Plugins/Apps/ClickHouse/ClickHouse.lmm.rb +113 -0
  23. data/Plugins/Apps/ClickHouse/Config/listen.yaml +2 -0
  24. data/Plugins/Apps/ClickHouse/Config/logger.yaml +8 -0
  25. data/Plugins/Apps/ClickHouse/Config/zookeepers.yaml +5 -0
  26. data/Plugins/Apps/ClickHouse/Connection.rb +96 -0
  27. data/Plugins/Apps/Discourse/Discourse-Sidekiq.container +5 -0
  28. data/Plugins/Apps/Discourse/Discourse.conf.erb +1 -4
  29. data/Plugins/Apps/Discourse/Discourse.container +4 -0
  30. data/Plugins/Apps/Discourse/Discourse.lmm.rb +116 -55
  31. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +74 -62
  32. data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +6 -1
  33. data/Plugins/Apps/ERPNext/ERPNext-Queue.container +5 -0
  34. data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +5 -0
  35. data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +6 -1
  36. data/Plugins/Apps/ERPNext/ERPNext.container +6 -1
  37. data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +138 -127
  38. data/Plugins/Apps/GitLab/GitLab.container +6 -0
  39. data/Plugins/Apps/GitLab/GitLab.lmm.rb +43 -49
  40. data/Plugins/Apps/Homepage/Homepage.conf.erb +86 -0
  41. data/Plugins/Apps/Homepage/Homepage.container +19 -0
  42. data/Plugins/Apps/Homepage/Homepage.lmm.rb +54 -0
  43. data/Plugins/Apps/IPFS/IPFS.conf.erb +0 -3
  44. data/Plugins/Apps/IPFS/IPFS.lmm.rb +0 -1
  45. data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +0 -3
  46. data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +0 -1
  47. data/Plugins/Apps/Jackett/Jackett.conf.erb +0 -3
  48. data/Plugins/Apps/Jackett/Jackett.lmm.rb +0 -1
  49. data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +0 -3
  50. data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +0 -1
  51. data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +49 -28
  52. data/Plugins/Apps/LibreTranslate/LibreTranslate.container +21 -0
  53. data/Plugins/Apps/LibreTranslate/LibreTranslate.lmm.rb +34 -0
  54. data/Plugins/Apps/Lobsters/Containerfile +81 -0
  55. data/Plugins/Apps/Lobsters/Lobsters-Tasks.container +26 -0
  56. data/Plugins/Apps/Lobsters/Lobsters.conf.erb +99 -0
  57. data/Plugins/Apps/Lobsters/Lobsters.container +27 -0
  58. data/Plugins/Apps/Lobsters/Lobsters.lmm.rb +196 -0
  59. data/Plugins/Apps/Lobsters/crontab +3 -0
  60. data/Plugins/Apps/Lobsters/database.yml +26 -0
  61. data/Plugins/Apps/Lobsters/entrypoint.sh +30 -0
  62. data/Plugins/Apps/Lobsters/generateCredentials.rb +19 -0
  63. data/Plugins/Apps/Lobsters/lobsters-cron.sh +25 -0
  64. data/Plugins/Apps/Lobsters/lobsters-daily.sh +23 -0
  65. data/Plugins/Apps/Lobsters/puma.rb +49 -0
  66. data/Plugins/Apps/MariaDB/Connection.rb +55 -0
  67. data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +60 -53
  68. data/Plugins/Apps/Mastodon/Mastodon-Sidekiq.container +22 -0
  69. data/Plugins/Apps/Mastodon/Mastodon-Streaming.container +20 -0
  70. data/Plugins/Apps/Mastodon/Mastodon.conf.erb +34 -45
  71. data/Plugins/Apps/Mastodon/Mastodon.container +28 -0
  72. data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +240 -5
  73. data/Plugins/Apps/Mastodon/configlmm.rake +30 -0
  74. data/Plugins/Apps/Mastodon/entrypoint.sh +16 -0
  75. data/Plugins/Apps/Matrix/Element.container +5 -0
  76. data/Plugins/Apps/Matrix/Matrix.conf.erb +2 -8
  77. data/Plugins/Apps/Matrix/Matrix.lmm.rb +100 -71
  78. data/Plugins/Apps/Matrix/Synapse.container +5 -0
  79. data/Plugins/Apps/Netdata/Netdata.conf.erb +0 -3
  80. data/Plugins/Apps/Netdata/Netdata.lmm.rb +0 -1
  81. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +3 -4
  82. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +150 -68
  83. data/Plugins/Apps/Nextcloud/autoconfig.php +13 -0
  84. data/Plugins/Apps/Nextcloud/config.php +10 -1
  85. data/Plugins/Apps/Nextcloud/nextcloudcron.service +8 -0
  86. data/Plugins/Apps/Nextcloud/nextcloudcron.timer +10 -0
  87. data/Plugins/Apps/Nginx/Connection.rb +93 -0
  88. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +50 -9
  89. data/Plugins/Apps/Nginx/conf.d/languages.conf +21 -0
  90. data/Plugins/Apps/Nginx/config-lmm/errors.conf +25 -20
  91. data/Plugins/Apps/Nginx/config-lmm/gateway-errors.conf +20 -0
  92. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +1 -1
  93. data/Plugins/Apps/Nginx/main.conf.erb +7 -3
  94. data/Plugins/Apps/Nginx/nginx.conf +2 -2
  95. data/Plugins/Apps/Nginx/nginx.lmm.rb +99 -81
  96. data/Plugins/Apps/Nginx/proxy.conf.erb +11 -3
  97. data/Plugins/Apps/Odoo/Odoo.conf.erb +0 -3
  98. data/Plugins/Apps/Odoo/Odoo.container +5 -0
  99. data/Plugins/Apps/Odoo/Odoo.lmm.rb +4 -5
  100. data/Plugins/Apps/Ollama/Ollama.container +26 -0
  101. data/Plugins/Apps/Ollama/Ollama.lmm.rb +73 -0
  102. data/Plugins/Apps/OpenTelemetry/Config/config.yaml +704 -0
  103. data/Plugins/Apps/OpenTelemetry/OpenTelemetry.lmm.rb +154 -0
  104. data/Plugins/Apps/OpenVidu/Ingress.container +5 -0
  105. data/Plugins/Apps/OpenVidu/OpenVidu.conf.erb +0 -3
  106. data/Plugins/Apps/OpenVidu/OpenVidu.container +5 -0
  107. data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +7 -3
  108. data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +0 -3
  109. data/Plugins/Apps/OpenVidu/OpenViduCall.container +5 -0
  110. data/Plugins/Apps/PHP-FPM/Connection.rb +91 -0
  111. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +31 -4
  112. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +2 -5
  113. data/Plugins/Apps/Peppermint/Peppermint.container +5 -0
  114. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +29 -33
  115. data/Plugins/Apps/Perplexica/Perplexica.container +25 -0
  116. data/Plugins/Apps/Perplexica/Perplexica.lmm.rb +92 -0
  117. data/Plugins/Apps/Perplexica/config.toml +26 -0
  118. data/Plugins/Apps/Podman/Connection.rb +24 -0
  119. data/Plugins/Apps/Podman/Podman.lmm.rb +80 -0
  120. data/Plugins/Apps/Podman/storage.conf +6 -0
  121. data/Plugins/Apps/Postfix/Postfix.lmm.rb +242 -164
  122. data/Plugins/Apps/PostgreSQL/Connection.rb +97 -0
  123. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +184 -148
  124. data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +0 -3
  125. data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +0 -2
  126. data/Plugins/Apps/Pterodactyl/Wings.conf.erb +0 -3
  127. data/Plugins/Apps/RVM/RVM.lmm.rb +57 -0
  128. data/Plugins/Apps/Roundcube/Roundcube.conf.erb +0 -3
  129. data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +15 -19
  130. data/Plugins/Apps/SSH/SSH.lmm.rb +9 -15
  131. data/Plugins/Apps/SearXNG/SearXNG.container +22 -0
  132. data/Plugins/Apps/SearXNG/SearXNG.lmm.rb +79 -0
  133. data/Plugins/Apps/SearXNG/limiter.toml +40 -0
  134. data/Plugins/Apps/SearXNG/settings.yml +2 -0
  135. data/Plugins/Apps/SigNoz/Config/alerts.yml +11 -0
  136. data/Plugins/Apps/SigNoz/Config/otel-collector-config.yaml +110 -0
  137. data/Plugins/Apps/SigNoz/Config/otel-collector-opamp-config.yaml +1 -0
  138. data/Plugins/Apps/SigNoz/Config/prometheus.yml +18 -0
  139. data/Plugins/Apps/SigNoz/SigNoz-Collector.container +23 -0
  140. data/Plugins/Apps/SigNoz/SigNoz-Migrator.container +17 -0
  141. data/Plugins/Apps/SigNoz/SigNoz.conf.erb +61 -0
  142. data/Plugins/Apps/SigNoz/SigNoz.container +26 -0
  143. data/Plugins/Apps/SigNoz/SigNoz.lmm.rb +319 -0
  144. data/Plugins/Apps/Solr/log4j2.xml +89 -0
  145. data/Plugins/Apps/Solr/solr.lmm.rb +82 -0
  146. data/Plugins/Apps/Sunshine/Sunshine.conf.erb +0 -3
  147. data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +0 -1
  148. data/Plugins/Apps/Tunnel/tunnel.lmm.rb +33 -37
  149. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +0 -3
  150. data/Plugins/Apps/Umami/Umami.container +19 -0
  151. data/Plugins/Apps/Umami/Umami.lmm.rb +108 -0
  152. data/Plugins/Apps/Valkey/Valkey.lmm.rb +54 -42
  153. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +9 -6
  154. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +7 -1
  155. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +64 -29
  156. data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +1 -4
  157. data/Plugins/Apps/Wiki.js/Wiki.js.container +5 -0
  158. data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +31 -37
  159. data/Plugins/Apps/YaCy/YaCy.conf.erb +93 -0
  160. data/Plugins/Apps/YaCy/YaCy.container +21 -0
  161. data/Plugins/Apps/YaCy/YaCy.lmm.rb +160 -0
  162. data/Plugins/Apps/ZooKeeper/ZooKeeper.container +24 -0
  163. data/Plugins/Apps/ZooKeeper/ZooKeeper.lmm.rb +68 -0
  164. data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +0 -3
  165. data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +0 -1
  166. data/Plugins/Apps/gollum/gollum.conf.erb +2 -4
  167. data/Plugins/Apps/gollum/gollum.container +6 -0
  168. data/Plugins/Apps/gollum/gollum.lmm.rb +51 -50
  169. data/Plugins/Apps/llama.cpp/llama.cpp.container +28 -0
  170. data/Plugins/Apps/llama.cpp/llama.cpp.lmm.rb +90 -0
  171. data/Plugins/Apps/vLLM/vLLM.container +32 -0
  172. data/Plugins/Apps/vLLM/vLLM.lmm.rb +89 -0
  173. data/Plugins/OS/General/Utils.lmm.rb +26 -0
  174. data/Plugins/OS/Linux/Connection.rb +472 -0
  175. data/Plugins/OS/Linux/Debian/preseed.cfg.erb +25 -6
  176. data/Plugins/OS/Linux/Flavours.yaml +13 -0
  177. data/Plugins/OS/Linux/Grub/grub.cfg +10 -0
  178. data/Plugins/OS/Linux/HTTP.rb +32 -0
  179. data/Plugins/OS/Linux/Linux.lmm.rb +533 -187
  180. data/Plugins/OS/Linux/Packages.yaml +20 -1
  181. data/Plugins/OS/Linux/Services.yaml +8 -0
  182. data/Plugins/OS/Linux/Shell.rb +70 -0
  183. data/Plugins/OS/Linux/Syslinux/default +8 -0
  184. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +83 -59
  185. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +3 -0
  186. data/Plugins/OS/Linux/openSUSE/autoinst.xml.erb +29 -3
  187. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +13 -11
  188. data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +6 -5
  189. data/Plugins/Platforms/GitHub.lmm.rb +73 -28
  190. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +9 -6
  191. data/Plugins/Platforms/Proxmox/Proxmox.lmm.rb +402 -0
  192. data/Plugins/Platforms/Proxmox/XTerm.rb +321 -0
  193. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +38 -13
  194. data/Plugins/Platforms/porkbun.lmm.rb +12 -2
  195. data/Plugins/Platforms/porkbun_spec.rb +2 -2
  196. data/Plugins/Services/DNS/AmberBit.lmm.rb +1 -1
  197. data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +1 -1
  198. data/Plugins/Services/DNS/NICLV.lmm.rb +1 -1
  199. data/Plugins/Services/DNS/PowerDNS.lmm.rb +70 -68
  200. data/Plugins/Services/DNS/tonic.lmm.rb +22 -12
  201. data/lib/ConfigLMM/Framework/plugins/dns.rb +4 -3
  202. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +145 -184
  203. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +34 -17
  204. data/lib/ConfigLMM/Framework/plugins/plugin.rb +53 -181
  205. data/lib/ConfigLMM/Framework/plugins/store.rb +4 -4
  206. data/lib/ConfigLMM/Framework/variables.rb +75 -0
  207. data/lib/ConfigLMM/Framework.rb +1 -0
  208. data/lib/ConfigLMM/cli.rb +12 -6
  209. data/lib/ConfigLMM/commands/configsCommand.rb +37 -6
  210. data/lib/ConfigLMM/commands/diff.rb +33 -9
  211. data/lib/ConfigLMM/context.rb +22 -3
  212. data/lib/ConfigLMM/io/configList.rb +82 -6
  213. data/lib/ConfigLMM/io/connection.rb +143 -0
  214. data/lib/ConfigLMM/io/dhcp.rb +330 -0
  215. data/lib/ConfigLMM/io/http.rb +78 -0
  216. data/lib/ConfigLMM/io/local.rb +207 -0
  217. data/lib/ConfigLMM/io/pxe.rb +92 -0
  218. data/lib/ConfigLMM/io/ssh.rb +156 -0
  219. data/lib/ConfigLMM/io/tftp.rb +105 -0
  220. data/lib/ConfigLMM/io.rb +2 -0
  221. data/lib/ConfigLMM/secrets/envStore.rb +39 -0
  222. data/lib/ConfigLMM/secrets/fileStore.rb +43 -0
  223. data/lib/ConfigLMM/state.rb +2 -1
  224. data/lib/ConfigLMM/version.rb +2 -1
  225. data/lib/ConfigLMM.rb +1 -0
  226. data/{Examples → scripts}/configlmmAuth.sh +7 -5
  227. metadata +205 -8
@@ -0,0 +1,54 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class Homepage < Framework::Plugin
5
+
6
+ NAME = 'Homepage'
7
+ USER = 'homepage'
8
+ HOME_DIR = '/var/lib/homepage'
9
+
10
+ def actionHomepageBuild(id, target, activeState, context, options)
11
+ Nginx.withConnection(local) do |nginxConnection|
12
+ nginxConnection.writeConfig(__dir__, NAME, target, state, context, options)
13
+ end
14
+ end
15
+
16
+ def actionHomepageDeploy(id, target, activeState, context, options)
17
+ self.withConnection(target['Location'], target) do |connection|
18
+ Linux.withConnection(connection) do |linuxConnection|
19
+ if !target.key?('Proxy') || target['Proxy'] != 'only'
20
+ Podman.ensurePresent(linuxConnection, options)
21
+ Podman.createUser(USER, HOME_DIR, 'Homepage', linuxConnection, options)
22
+ linuxConnection.withUserShell(USER) do |shell|
23
+ shell.createDirs(options, '~/config')
24
+ end
25
+
26
+ configPath = './Homepage'
27
+ configPath = target['ConfigPath'] if target['ConfigPath']
28
+ Dir[configPath + '/*'].each do |file|
29
+ linuxConnection.upload(file, HOME_DIR + '/config/', options)
30
+ end
31
+
32
+ path = Podman.containersPath(HOME_DIR)
33
+ linuxConnection.upload(__dir__ + '/Homepage.container', path, options)
34
+ if target.key?('Proxy') && target['Proxy'] == false
35
+ linuxConnection.exec("sed -i 's|PublishPort=127.0.0.1:13400:|PublishPort=0.0.0.0:13400:|' #{path}/Homepage.container", false, options)
36
+ linuxConnection.firewallAddPort('13400/tcp', options)
37
+ end
38
+
39
+ linuxConnection.reloadUserServices(USER, options)
40
+ linuxConnection.restartUserService(USER, 'Homepage', options)
41
+ end
42
+ if !target.key?('Proxy') || !!target['Proxy']
43
+ Nginx.withConnection(linuxConnection) do |nginxConnection|
44
+ target['ConfigName'] = target['Name']
45
+ nginxConnection.provision(__dir__, NAME, target, activeState, context, options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+
52
+ end
53
+ end
54
+ end
@@ -20,9 +20,6 @@ server {
20
20
 
21
21
  server_name <%= config['Domain'] %>;
22
22
 
23
- access_log /var/log/nginx/ipfs.access.log;
24
- error_log /var/log/nginx/ipfs.error.log;
25
-
26
23
  include config-lmm/private.conf;
27
24
  include config-lmm/errors.conf;
28
25
 
@@ -14,7 +14,6 @@ module ConfigLMM
14
14
  def actionIPFSDeploy(id, target, activeState, context, options)
15
15
  if !target['Location'] || target['Location'] == '@me'
16
16
  deployNginxConfig(id, target, activeState, context, options)
17
- activeState['Location'] = '@me'
18
17
  end
19
18
  end
20
19
 
@@ -16,9 +16,6 @@ server {
16
16
 
17
17
  server_name <%= config['Domain'] %>;
18
18
 
19
- access_log /var/log/nginx/influxdb.access.log;
20
- error_log /var/log/nginx/influxdb.error.log;
21
-
22
19
  include config-lmm/private.conf;
23
20
  include config-lmm/errors.conf;
24
21
 
@@ -10,7 +10,6 @@ module ConfigLMM
10
10
  def actionInfluxDBDeploy(id, target, activeState, context, options)
11
11
  if !target['Location'] || target['Location'] == '@me'
12
12
  deployNginxConfig(id, target, activeState, context, options)
13
- activeState['Location'] = '@me'
14
13
  end
15
14
  end
16
15
 
@@ -16,9 +16,6 @@ server {
16
16
 
17
17
  server_name <%= config['Domain'] %>;
18
18
 
19
- access_log /var/log/nginx/jackett.access.log;
20
- error_log /var/log/nginx/jackett.error.log;
21
-
22
19
  include config-lmm/private.conf;
23
20
  include config-lmm/errors.conf;
24
21
 
@@ -10,7 +10,6 @@ module ConfigLMM
10
10
  def actionJackettDeploy(id, target, activeState, context, options)
11
11
  if !target['Location'] || target['Location'] == '@me'
12
12
  deployNginxConfig(id, target, activeState, context, options)
13
- activeState['Location'] = '@me'
14
13
  end
15
14
  end
16
15
 
@@ -17,9 +17,6 @@ server {
17
17
 
18
18
  server_name <%= config['Domain'] %>;
19
19
 
20
- access_log /var/log/nginx/jellyfin.access.log;
21
- error_log /var/log/nginx/jellyfin.error.log;
22
-
23
20
  include config-lmm/errors.conf;
24
21
  include config-lmm/ssl.conf;
25
22
 
@@ -14,7 +14,6 @@ module ConfigLMM
14
14
  def actionJellyfinDeploy(id, target, activeState, context, options)
15
15
  if !target['Location'] || target['Location'] == '@me'
16
16
  deployNginxConfig(id, target, activeState, context, options)
17
- activeState['Location'] = '@me'
18
17
  end
19
18
  end
20
19
 
@@ -7,48 +7,69 @@ module ConfigLMM
7
7
  CONFIG_DIR = '/etc/letsencrypt/'
8
8
 
9
9
  def actionLetsEncryptDeploy(id, target, activeState, context, options)
10
- self.ensurePackage(PACKAGE_NAME, target['Location'])
10
+ self.withConnection(target['Location'], target) do |connection|
11
+ Linux.withConnection(connection) do |linuxConnection|
12
+ linuxConnection.ensurePackage(PACKAGE_NAME, options)
11
13
 
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
- ssh.scp.upload!(__dir__ + '/rfc2136.ini', CONFIG_DIR)
18
- ssh.scp.upload!(__dir__ + '/renew-certificates.service', '/etc/systemd/system/')
19
- ssh.scp.upload!(__dir__ + '/renew-certificates.timer', '/etc/systemd/system/')
20
- self.class.exec("mkdir -p #{CONFIG_DIR}renewal-hooks/deploy", ssh)
14
+ linuxConnection.upload(__dir__ + '/rfc2136.ini', CONFIG_DIR, options)
15
+ linuxConnection.upload(__dir__ + '/renew-certificates.service', '/etc/systemd/system/', options)
16
+ linuxConnection.upload(__dir__ + '/renew-certificates.timer', '/etc/systemd/system/', options)
17
+ linuxConnection.createDirs(options, CONFIG_DIR + "renewal-hooks/deploy")
21
18
  target['Hooks'].to_a.each do |hook|
22
- ssh.scp.upload!(__dir__ + '/hooks/' + hook + '.sh', "#{CONFIG_DIR}renewal-hooks/deploy/")
19
+ linuxConnection.upload(__dir__ + '/hooks/' + hook + '.sh', "#{CONFIG_DIR}renewal-hooks/deploy/", options)
23
20
  end
24
- self.class.exec("chmod +x #{CONFIG_DIR}renewal-hooks/deploy/*.sh", ssh)
25
- self.class.exec("sed -i 's|$IP|#{target['DNS']['IP']}|' #{CONFIG_DIR}/rfc2136.ini", ssh)
26
- self.class.exec("sed -i 's|$SECRET|#{ENV['LETSENCRYPT_DNS_SECRET']}|' #{CONFIG_DIR}/rfc2136.ini", ssh)
27
- self.class.exec("chmod 600 #{CONFIG_DIR}/rfc2136.ini", ssh)
21
+ linuxConnection.exec("chmod +x #{CONFIG_DIR}renewal-hooks/deploy/*.sh", false, options)
22
+ linuxConnection.fileReplace(CONFIG_DIR + 'rfc2136.ini', '\$IP', target['DNS']['IP'] , options)
23
+
24
+ secretId, secretName = target['DNS']['SecretId'].to_s.split('.')
25
+ key = nil
26
+ key = context.secrets.load(secretId, secretName) if secretId && secretName
27
+ key = context.secrets.load('LETSENCRYPT', 'DNS_SECRET') if key.nil?
28
+ raise Framework::PluginProcessError.new('LetsEncrypt missing RFC2136 TSIG key! Specify DNS.SecretId or LETSENCRYPT_DNS_SECRET env variable') unless key
29
+
30
+ linuxConnection.fileReplace(CONFIG_DIR + 'rfc2136.ini', '\$SECRET', key, options)
31
+ linuxConnection.setPrivate(CONFIG_DIR + 'rfc2136.ini', options)
28
32
  if target['Domain']
29
- createCertificate('Wildcard', target['Domain'], target, ssh)
33
+ createCertificate('Wildcard', target['Domain'], target, linuxConnection, options)
30
34
  end
31
- target['Certificates'].to_h.each do |name, domain|
32
- createCertificate(name, domain, target, ssh)
35
+ target['Certificates'].to_h.each do |name, domains|
36
+ createCertificate(name, domains, target, linuxConnection, options)
33
37
  end
34
38
 
35
- self.class.exec("systemctl daemon-reload", ssh)
36
- self.class.exec("systemctl enable renew-certificates.timer", ssh)
37
- self.class.exec("systemctl start renew-certificates.timer", ssh)
39
+ linuxConnection.reloadServiceManager(options)
40
+ linuxConnection.ensureServiceAutoStart('renew-certificates.timer', options)
41
+ linuxConnection.startService('renew-certificates.timer', options)
42
+
43
+ target['Hooks'].to_a.each do |hook|
44
+ linuxConnection.exec("#{CONFIG_DIR}renewal-hooks/deploy/#{hook}.sh", false, options)
45
+ end
38
46
  end
39
- else
40
- # TODO
41
47
  end
42
48
  end
43
49
 
44
- def createCertificate(name, domain, target, ssh)
45
- domains = ['--domains "' + Addressable::IDNA.to_ascii(domain) + '"']
46
- if domain.start_with?('*.')
47
- domains << '--domains "' + Addressable::IDNA.to_ascii(domain[2..-1]) + '"'
50
+ def createCertificate(name, domains, target, connection, options)
51
+ return if connection.fileLink?("#{CONFIG_DIR}live/#{name}/fullchain.pem", options)
52
+ connection.exec("rm -rf #{CONFIG_DIR}live/#{name}", false, options)
53
+
54
+ domainList = []
55
+ domains = [domains] unless domains.is_a?(Array)
56
+ domains.each do |domain|
57
+ domainList << '--domains "' + Addressable::IDNA.to_ascii(domain) + '"'
58
+ if addBaseDomain?(domain, domains)
59
+ domainList << '--domains "' + Addressable::IDNA.to_ascii(domain[2..-1]) + '"'
60
+ end
48
61
  end
49
62
  extra = ''
50
63
  extra = '--dns-rfc2136-propagation-seconds ' + target['DNS']['Propagation'].to_s if target['DNS']['Propagation']
51
- self.class.exec("certbot certonly --dns-rfc2136 --dns-rfc2136-credentials=/etc/letsencrypt/rfc2136.ini #{extra} --non-interactive --agree-tos --email #{target['EMail']} --cert-name '#{name}' #{domains.join(' ')}", ssh)
64
+
65
+ connection.exec("certbot certonly --dns-rfc2136 --dns-rfc2136-credentials=#{CONFIG_DIR}rfc2136.ini #{extra} --non-interactive --agree-tos --email #{target['EMail']} --cert-name '#{name}' #{domainList.join(' ')}", false, options)
66
+ end
67
+
68
+ def addBaseDomain?(domain, domains)
69
+ return false unless domain.start_with?('*.')
70
+ match = '*.' + domain[2..-1].split('.')[1..].join('.')
71
+ return false if match == '*.' || domains.any? { |d| d.casecmp?(match) }
72
+ true
52
73
  end
53
74
 
54
75
  end
@@ -0,0 +1,21 @@
1
+
2
+ [Unit]
3
+ Description=LibreTranslate container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ ContainerName=LibreTranslate
8
+ Image=docker.io/libretranslate/libretranslate:latest
9
+ Exec=--host 0.0.0.0 $ARGS
10
+ PublishPort=127.0.0.1:15100:5000
11
+ UserNS=keep-id:uid=1032,gid=1032
12
+ Volume=/var/lib/libretranslate/.local:/home/libretranslate/.local
13
+ LogDriver=journald
14
+ AutoUpdate=registry
15
+
16
+ [Service]
17
+ TimeoutStartSec=32min
18
+ Restart=on-failure
19
+
20
+ [Install]
21
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,34 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class LibreTranslate < Framework::Plugin
5
+
6
+ USER = 'libretranslate'
7
+ HOME_DIR = '/var/lib/libretranslate'
8
+
9
+ def actionLibreTranslateDeploy(id, target, activeState, context, options)
10
+
11
+ self.withConnection(target['Location'], target) do |connection|
12
+ Linux.withConnection(connection) do |linuxConnection|
13
+ Podman.ensurePresent(linuxConnection, options)
14
+ Podman.createUser(USER, HOME_DIR, 'LibreTranslate', linuxConnection, options)
15
+
16
+ path = Podman.containersPath(HOME_DIR)
17
+
18
+ linuxConnection.upload(__dir__ + '/LibreTranslate.container', path, options)
19
+
20
+ args = ['--metrics']
21
+ linuxConnection.fileReplace("#{path}/LibreTranslate.container", '\$ARGS', args.join(' '), options)
22
+ if target['Listen']
23
+ linuxConnection.fileReplace("#{path}/LibreTranslate.container", '127.0.0.1', target['Listen'], options)
24
+ end
25
+
26
+ linuxConnection.reloadUserServices(USER, options)
27
+ linuxConnection.restartUserService(USER, 'LibreTranslate', options)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,81 @@
1
+ # Use an official Ruby image as a base
2
+ ARG RUBY_VERSION
3
+ FROM ruby:${RUBY_VERSION} AS base
4
+
5
+ # Install base packages
6
+ RUN apt-get update -qq && \
7
+ apt-get install --no-install-recommends -y curl libjemalloc2 libvips sqlite3 mariadb-client sendmail vim && \
8
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
9
+
10
+ # Latest releases available at https://github.com/aptible/supercronic/releases
11
+ ENV SUPERCRONIC_URL=https://github.com/aptible/supercronic/releases/download/v0.2.33/supercronic-linux-amd64 \
12
+ SUPERCRONIC_SHA1SUM=71b0d58cc53f6bd72cf2f293e09e294b79c666d8 \
13
+ SUPERCRONIC=supercronic-linux-amd64
14
+
15
+ RUN curl -fsSLO "$SUPERCRONIC_URL" \
16
+ && echo "${SUPERCRONIC_SHA1SUM} ${SUPERCRONIC}" | sha1sum -c - \
17
+ && chmod +x "$SUPERCRONIC" \
18
+ && mv "$SUPERCRONIC" "/usr/local/bin/${SUPERCRONIC}" \
19
+ && ln -s "/usr/local/bin/${SUPERCRONIC}" /usr/local/bin/supercronic
20
+
21
+ ENV BUNDLE_DEPLOYMENT="1" BUNDLE_PATH="/usr/local/bundle" BUNDLE_WITHOUT="development"
22
+
23
+ # Throw-away build stage to reduce size of final image
24
+ FROM base AS build
25
+
26
+ # Install packages needed to build gems
27
+ RUN apt-get update -qq && \
28
+ apt-get install --no-install-recommends -y build-essential git libyaml-dev pkg-config && \
29
+ rm -rf /var/lib/apt/lists /var/cache/apt/archives
30
+
31
+ # Set working directory
32
+ WORKDIR /lobsters
33
+
34
+ COPY . .
35
+
36
+ # Install application gems
37
+ RUN bundle install && \
38
+ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git
39
+
40
+ RUN mkdir -p /srv/lobste.rs/log && \
41
+ ln -sf /lobsters /srv/lobste.rs/http
42
+
43
+ # Temporary generate secrets
44
+ RUN RAILS_ENV=production ./bin/rails credentials:edit
45
+
46
+ # Precompiling assets for production without requiring secret RAILS_MASTER_KEY
47
+ RUN SECRET_KEY_BASE_DUMMY=1 RAILS_ENV=production ./bin/rails assets:precompile
48
+
49
+ # Remove secrets
50
+ RUN rm -rf ./config/credentials.yml.enc ./config/master.key ./config/database.yml ./tmp/* /srv/lobste.rs/log/*
51
+
52
+ # Final stage for app image
53
+ FROM base
54
+
55
+ WORKDIR /lobsters
56
+
57
+ # Copy built artifacts: gems, application
58
+ COPY --from=build "${BUNDLE_PATH}" "${BUNDLE_PATH}"
59
+ COPY --from=build /lobsters /lobsters
60
+ COPY --from=build /srv/lobste.rs /srv/lobste.rs
61
+
62
+ COPY crontab /etc/
63
+
64
+ RUN ln -sf /config/master.key /lobsters/config/master.key && \
65
+ ln -sf /config/credentials.yml.enc /lobsters/config/credentials.yml.enc && \
66
+ ln -sf /config/database.yml /lobsters/config/database.yml
67
+
68
+ RUN mv /lobsters/public /lobsters/public_source && ln -sf /srv/lobsters/public /lobsters/public
69
+
70
+ # Run and own only the runtime files as a non-root user for security
71
+ RUN groupadd --system --gid 1000 lobsters && \
72
+ useradd lobsters --uid 1000 --gid 1000 --create-home --shell /bin/bash && \
73
+ chown -R lobsters:lobsters /lobsters/tmp /srv/lobste.rs/log
74
+
75
+ ENV LD_PRELOAD="/usr/lib/x86_64-linux-gnu/libjemalloc.so.2"
76
+
77
+ # Expose port for Rails server
78
+ EXPOSE 9292
79
+
80
+ ENTRYPOINT ["/lobsters/entrypoint.sh"]
81
+ CMD ["server"]
@@ -0,0 +1,26 @@
1
+
2
+ [Unit]
3
+ Description=Lobsters tasks container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ ContainerName=LobstersTasks
8
+ Image=ConfigLM.moe/lobsters:master
9
+ EnvironmentFile=/var/lib/lobsters/.config/containers/systemd/Lobsters.env
10
+ Network=slirp4netns:allow_host_loopback=true
11
+ UserNS=keep-id:uid=1000,gid=1000
12
+ Exec=cron
13
+ Volume=/var/lib/lobsters/config:/config
14
+ Volume=/var/lib/lobsters/logs:/srv/lobste.rs/log
15
+ Volume=/var/lib/lobsters/cache:/srv/lobste.rs/cache
16
+ Volume=/var/lib/lobsters/storage:/srv/lobste.rs/storage
17
+ Volume=/var/lib/lobsters/queue:/srv/lobste.rs/queue
18
+ Volume=/var/lib/lobsters/tmp:/lobsters/tmp
19
+ Volume=/srv/lobsters:/srv/lobsters
20
+ LogDriver=journald
21
+
22
+ [Service]
23
+ Restart=on-failure
24
+
25
+ [Install]
26
+ WantedBy=multi-user.target default.target
@@ -0,0 +1,99 @@
1
+
2
+ upstream lobsters {
3
+ <% if config['Server'] %>
4
+ server <%= config['Server'] %>;
5
+ <% else %>
6
+ server 127.0.0.1:19292;
7
+ <% end %>
8
+ }
9
+
10
+ server {
11
+
12
+ <% if config['NginxVersion'] >= 1.25 %>
13
+ <% if !config['TLS'] %>
14
+ listen <%= config['Port'] %>;
15
+ listen [::]:<%= config['Port'] %>;
16
+ <% else %>
17
+ listen <%= config['Port'] %> ssl;
18
+ listen [::]:<%= config['Port'] %> ssl;
19
+
20
+ include config-lmm/ssl.conf;
21
+ <% end %>
22
+ http2 on;
23
+ http3 on;
24
+ quic_retry on;
25
+ add_header Alt-Svc 'h3=":443"; ma=86400';
26
+ <% else %>
27
+ <% if !config['TLS'] %>
28
+ listen <%= config['Port'] %>;
29
+ listen [::]:<%= config['Port'] %>;
30
+ <% else %>
31
+ listen <%= config['Port'] %> ssl http2;
32
+ listen [::]:<%= config['Port'] %> ssl http2;
33
+
34
+ include config-lmm/ssl.conf;
35
+ <% end %>
36
+ <% end %>
37
+
38
+ server_name <%= config['Domain'] %>;
39
+
40
+ root /srv/lobsters/public;
41
+
42
+ include config-lmm/errors.conf;
43
+
44
+ # max upload size for avatars (the only upload the site takes now)
45
+ client_max_body_size 2M;
46
+
47
+ location @lobsters {
48
+ proxy_pass http://lobsters;
49
+
50
+ include config-lmm/proxy.conf;
51
+ }
52
+
53
+ location ~ ^/assets/ {
54
+ gzip_static on;
55
+ expires max;
56
+ add_header Cache-Control public;
57
+ break;
58
+ }
59
+
60
+ location ~ ^/avatars/ {
61
+ expires max;
62
+ add_header Cache-Control public;
63
+ try_files $uri @lobsters;
64
+ break;
65
+ }
66
+
67
+ # file-based full-page caching, bypass if user has cookies
68
+ set $use_file_cache "";
69
+
70
+ if ($cookie_lobster_trap = "") {
71
+ set $use_file_cache "${use_file_cache}S"; # S = no session cookie
72
+ }
73
+ if ($cookie_tag_filters = "") {
74
+ set $use_file_cache "${use_file_cache}F"; # F = no filter cookie
75
+ }
76
+ if (-f $document_root/cache$uri/index.html) {
77
+ set $use_file_cache "${use_file_cache}I"; # I = index file cached
78
+ }
79
+ if ($use_file_cache = "SFI") {
80
+ rewrite (.*) /cache/$1/index.html break;
81
+ }
82
+ if (-f $document_root/cache$uri.html) {
83
+ set $use_file_cache "${use_file_cache}H"; # H = HTML file cached
84
+ }
85
+ if ($use_file_cache = "SFH") {
86
+ rewrite (.*) /cache/$1.html break;
87
+ }
88
+ if (-f $document_root/cache$uri) {
89
+ set $use_file_cache "${use_file_cache}O"; # O = other non-extentioned file cached
90
+ }
91
+ if ($use_file_cache = "SFO") {
92
+ rewrite (.*) /cache/$1 break;
93
+ }
94
+
95
+ location / {
96
+ try_files $uri @lobsters;
97
+ }
98
+
99
+ }
@@ -0,0 +1,27 @@
1
+
2
+ [Unit]
3
+ Description=Lobsters container
4
+ After=local-fs.target
5
+
6
+ [Container]
7
+ ContainerName=Lobsters
8
+ Image=ConfigLM.moe/lobsters:master
9
+ EnvironmentFile=/var/lib/lobsters/.config/containers/systemd/Lobsters.env
10
+ Network=slirp4netns:allow_host_loopback=true
11
+ UserNS=keep-id:uid=1000,gid=1000
12
+ PublishPort=127.0.0.1:19292:9292
13
+ Volume=/var/lib/lobsters/config:/config
14
+ Volume=/var/lib/lobsters/logs:/srv/lobste.rs/log
15
+ Volume=/var/lib/lobsters/cache:/srv/lobste.rs/cache
16
+ Volume=/var/lib/lobsters/storage:/srv/lobste.rs/storage
17
+ Volume=/var/lib/lobsters/queue:/srv/lobste.rs/queue
18
+ Volume=/var/lib/lobsters/tmp:/lobsters/tmp
19
+ Volume=/srv/lobsters:/srv/lobsters
20
+ LogDriver=journald
21
+
22
+ [Service]
23
+ TimeoutStartSec=6min
24
+ Restart=on-failure
25
+
26
+ [Install]
27
+ WantedBy=multi-user.target default.target