ConfigLMM 0.3.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 (250) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +70 -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 +20 -0
  13. data/Plugins/Apps/Authentik/Authentik-Server.container +7 -1
  14. data/Plugins/Apps/Authentik/Authentik-Worker.container +7 -1
  15. data/Plugins/Apps/Authentik/Authentik.conf.erb +18 -6
  16. data/Plugins/Apps/Authentik/Authentik.lmm.rb +232 -45
  17. data/Plugins/Apps/BookStack/BookStack.conf.erb +38 -0
  18. data/Plugins/Apps/BookStack/BookStack.container +20 -0
  19. data/Plugins/Apps/BookStack/BookStack.lmm.rb +91 -0
  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 +22 -0
  28. data/Plugins/Apps/Discourse/Discourse.conf.erb +38 -0
  29. data/Plugins/Apps/Discourse/Discourse.container +21 -0
  30. data/Plugins/Apps/Discourse/Discourse.lmm.rb +156 -0
  31. data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +87 -52
  32. data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +24 -0
  33. data/Plugins/Apps/ERPNext/ERPNext-Queue.container +22 -0
  34. data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +22 -0
  35. data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +24 -0
  36. data/Plugins/Apps/ERPNext/ERPNext.container +23 -0
  37. data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +204 -0
  38. data/Plugins/Apps/ERPNext/ERPNext.network +12 -0
  39. data/Plugins/Apps/ERPNext/sites/apps.json +10 -0
  40. data/Plugins/Apps/ERPNext/sites/apps.txt +3 -0
  41. data/Plugins/Apps/ERPNext/sites/common_site_config.json +11 -0
  42. data/Plugins/Apps/GitLab/GitLab.container +9 -2
  43. data/Plugins/Apps/GitLab/GitLab.lmm.rb +52 -33
  44. data/Plugins/Apps/Homepage/Homepage.conf.erb +86 -0
  45. data/Plugins/Apps/Homepage/Homepage.container +19 -0
  46. data/Plugins/Apps/Homepage/Homepage.lmm.rb +54 -0
  47. data/Plugins/Apps/IPFS/IPFS.conf.erb +0 -3
  48. data/Plugins/Apps/IPFS/IPFS.lmm.rb +0 -1
  49. data/Plugins/Apps/InfluxDB/InfluxDB.conf.erb +0 -3
  50. data/Plugins/Apps/InfluxDB/InfluxDB.lmm.rb +0 -1
  51. data/Plugins/Apps/Jackett/Jackett.conf.erb +0 -3
  52. data/Plugins/Apps/Jackett/Jackett.lmm.rb +0 -1
  53. data/Plugins/Apps/Jellyfin/Jellyfin.conf.erb +0 -3
  54. data/Plugins/Apps/Jellyfin/Jellyfin.lmm.rb +0 -1
  55. data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +78 -0
  56. data/Plugins/Apps/LetsEncrypt/hooks/dovecot.sh +2 -0
  57. data/Plugins/Apps/LetsEncrypt/hooks/nginx.sh +2 -0
  58. data/Plugins/Apps/LetsEncrypt/hooks/postfix.sh +2 -0
  59. data/Plugins/Apps/LetsEncrypt/renew-certificates.service +7 -0
  60. data/Plugins/Apps/LetsEncrypt/renew-certificates.timer +12 -0
  61. data/Plugins/Apps/LetsEncrypt/rfc2136.ini +11 -0
  62. data/Plugins/Apps/LibreTranslate/LibreTranslate.container +21 -0
  63. data/Plugins/Apps/LibreTranslate/LibreTranslate.lmm.rb +34 -0
  64. data/Plugins/Apps/Lobsters/Containerfile +81 -0
  65. data/Plugins/Apps/Lobsters/Lobsters-Tasks.container +26 -0
  66. data/Plugins/Apps/Lobsters/Lobsters.conf.erb +99 -0
  67. data/Plugins/Apps/Lobsters/Lobsters.container +27 -0
  68. data/Plugins/Apps/Lobsters/Lobsters.lmm.rb +196 -0
  69. data/Plugins/Apps/Lobsters/crontab +3 -0
  70. data/Plugins/Apps/Lobsters/database.yml +26 -0
  71. data/Plugins/Apps/Lobsters/entrypoint.sh +30 -0
  72. data/Plugins/Apps/Lobsters/generateCredentials.rb +19 -0
  73. data/Plugins/Apps/Lobsters/lobsters-cron.sh +25 -0
  74. data/Plugins/Apps/Lobsters/lobsters-daily.sh +23 -0
  75. data/Plugins/Apps/Lobsters/puma.rb +49 -0
  76. data/Plugins/Apps/MariaDB/Connection.rb +55 -0
  77. data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +122 -0
  78. data/Plugins/Apps/Mastodon/Mastodon-Sidekiq.container +22 -0
  79. data/Plugins/Apps/Mastodon/Mastodon-Streaming.container +20 -0
  80. data/Plugins/Apps/Mastodon/Mastodon.conf.erb +34 -45
  81. data/Plugins/Apps/Mastodon/Mastodon.container +28 -0
  82. data/Plugins/Apps/Mastodon/Mastodon.lmm.rb +240 -5
  83. data/Plugins/Apps/Mastodon/configlmm.rake +30 -0
  84. data/Plugins/Apps/Mastodon/entrypoint.sh +16 -0
  85. data/Plugins/Apps/Matrix/Element.container +19 -0
  86. data/Plugins/Apps/Matrix/Matrix.conf.erb +47 -9
  87. data/Plugins/Apps/Matrix/Matrix.lmm.rb +119 -5
  88. data/Plugins/Apps/Matrix/Synapse.container +22 -0
  89. data/Plugins/Apps/Matrix/config.json +50 -0
  90. data/Plugins/Apps/Matrix/homeserver.yaml +70 -0
  91. data/Plugins/Apps/Matrix/log.config +30 -0
  92. data/Plugins/Apps/Netdata/Netdata.conf.erb +0 -3
  93. data/Plugins/Apps/Netdata/Netdata.lmm.rb +0 -1
  94. data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +3 -4
  95. data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +155 -48
  96. data/Plugins/Apps/Nextcloud/autoconfig.php +13 -0
  97. data/Plugins/Apps/Nextcloud/config.php +10 -1
  98. data/Plugins/Apps/Nextcloud/nextcloudcron.service +8 -0
  99. data/Plugins/Apps/Nextcloud/nextcloudcron.timer +10 -0
  100. data/Plugins/Apps/Nginx/Connection.rb +93 -0
  101. data/Plugins/Apps/Nginx/conf.d/configlmm.conf +54 -4
  102. data/Plugins/Apps/Nginx/conf.d/languages.conf +21 -0
  103. data/Plugins/Apps/Nginx/config-lmm/errors.conf +33 -22
  104. data/Plugins/Apps/Nginx/config-lmm/gateway-errors.conf +20 -0
  105. data/Plugins/Apps/Nginx/config-lmm/proxy.conf +6 -2
  106. data/Plugins/Apps/Nginx/main.conf.erb +7 -3
  107. data/Plugins/Apps/Nginx/nginx.conf +2 -2
  108. data/Plugins/Apps/Nginx/nginx.lmm.rb +103 -81
  109. data/Plugins/Apps/Nginx/proxy.conf.erb +24 -6
  110. data/Plugins/Apps/Odoo/Odoo.conf.erb +0 -3
  111. data/Plugins/Apps/Odoo/Odoo.container +7 -1
  112. data/Plugins/Apps/Odoo/Odoo.lmm.rb +4 -5
  113. data/Plugins/Apps/Ollama/Ollama.container +26 -0
  114. data/Plugins/Apps/Ollama/Ollama.lmm.rb +73 -0
  115. data/Plugins/Apps/OpenTelemetry/Config/config.yaml +704 -0
  116. data/Plugins/Apps/OpenTelemetry/OpenTelemetry.lmm.rb +154 -0
  117. data/Plugins/Apps/OpenVidu/Ingress.container +23 -0
  118. data/Plugins/Apps/{GitLab/GitLab.conf.erb → OpenVidu/OpenVidu.conf.erb} +8 -3
  119. data/Plugins/Apps/OpenVidu/OpenVidu.container +21 -0
  120. data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +94 -0
  121. data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +32 -0
  122. data/Plugins/Apps/OpenVidu/OpenViduCall.container +20 -0
  123. data/Plugins/Apps/OpenVidu/ingress.yaml +10 -0
  124. data/Plugins/Apps/OpenVidu/livekit.yaml +13 -0
  125. data/Plugins/Apps/PHP-FPM/Connection.rb +91 -0
  126. data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +31 -4
  127. data/Plugins/Apps/Peppermint/Peppermint.conf.erb +2 -9
  128. data/Plugins/Apps/Peppermint/Peppermint.container +7 -1
  129. data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +29 -33
  130. data/Plugins/Apps/Perplexica/Perplexica.container +25 -0
  131. data/Plugins/Apps/Perplexica/Perplexica.lmm.rb +92 -0
  132. data/Plugins/Apps/Perplexica/config.toml +26 -0
  133. data/Plugins/Apps/Podman/Connection.rb +24 -0
  134. data/Plugins/Apps/Podman/Podman.lmm.rb +80 -0
  135. data/Plugins/Apps/Podman/storage.conf +6 -0
  136. data/Plugins/Apps/Postfix/Postfix.lmm.rb +249 -145
  137. data/Plugins/Apps/PostgreSQL/Connection.rb +97 -0
  138. data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +204 -99
  139. data/Plugins/Apps/Pterodactyl/Pterodactyl.conf.erb +0 -3
  140. data/Plugins/Apps/Pterodactyl/Pterodactyl.lmm.rb +0 -2
  141. data/Plugins/Apps/Pterodactyl/Wings.conf.erb +0 -3
  142. data/Plugins/Apps/RVM/RVM.lmm.rb +57 -0
  143. data/Plugins/Apps/Roundcube/Roundcube.conf.erb +72 -0
  144. data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +141 -0
  145. data/Plugins/Apps/SSH/SSH.lmm.rb +9 -15
  146. data/Plugins/Apps/SearXNG/SearXNG.container +22 -0
  147. data/Plugins/Apps/SearXNG/SearXNG.lmm.rb +79 -0
  148. data/Plugins/Apps/SearXNG/limiter.toml +40 -0
  149. data/Plugins/Apps/SearXNG/settings.yml +2 -0
  150. data/Plugins/Apps/SigNoz/Config/alerts.yml +11 -0
  151. data/Plugins/Apps/SigNoz/Config/otel-collector-config.yaml +110 -0
  152. data/Plugins/Apps/SigNoz/Config/otel-collector-opamp-config.yaml +1 -0
  153. data/Plugins/Apps/SigNoz/Config/prometheus.yml +18 -0
  154. data/Plugins/Apps/SigNoz/SigNoz-Collector.container +23 -0
  155. data/Plugins/Apps/SigNoz/SigNoz-Migrator.container +17 -0
  156. data/Plugins/Apps/SigNoz/SigNoz.conf.erb +61 -0
  157. data/Plugins/Apps/SigNoz/SigNoz.container +26 -0
  158. data/Plugins/Apps/SigNoz/SigNoz.lmm.rb +319 -0
  159. data/Plugins/Apps/Solr/log4j2.xml +89 -0
  160. data/Plugins/Apps/Solr/solr.lmm.rb +82 -0
  161. data/Plugins/Apps/Sunshine/Sunshine.conf.erb +0 -3
  162. data/Plugins/Apps/Sunshine/Sunshine.lmm.rb +0 -1
  163. data/Plugins/Apps/Tunnel/tunnel.lmm.rb +59 -0
  164. data/Plugins/Apps/Tunnel/tunnelTCP.service +9 -0
  165. data/Plugins/Apps/Tunnel/tunnelTCP.socket +9 -0
  166. data/Plugins/Apps/Tunnel/tunnelUDP.service +9 -0
  167. data/Plugins/Apps/Tunnel/tunnelUDP.socket +9 -0
  168. data/Plugins/Apps/UVdesk/UVdesk.conf.erb +0 -3
  169. data/Plugins/Apps/Umami/Umami.container +19 -0
  170. data/Plugins/Apps/Umami/Umami.lmm.rb +108 -0
  171. data/Plugins/Apps/Valkey/Valkey.lmm.rb +64 -20
  172. data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +9 -6
  173. data/Plugins/Apps/Vaultwarden/Vaultwarden.container +7 -1
  174. data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +67 -28
  175. data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +39 -0
  176. data/Plugins/Apps/Wiki.js/Wiki.js.container +20 -0
  177. data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +55 -0
  178. data/Plugins/Apps/YaCy/YaCy.conf.erb +93 -0
  179. data/Plugins/Apps/YaCy/YaCy.container +21 -0
  180. data/Plugins/Apps/YaCy/YaCy.lmm.rb +160 -0
  181. data/Plugins/Apps/ZooKeeper/ZooKeeper.container +24 -0
  182. data/Plugins/Apps/ZooKeeper/ZooKeeper.lmm.rb +68 -0
  183. data/Plugins/Apps/bitmagnet/bitmagnet.conf.erb +0 -3
  184. data/Plugins/Apps/bitmagnet/bitmagnet.lmm.rb +0 -1
  185. data/Plugins/Apps/gollum/gollum.conf.erb +40 -4
  186. data/Plugins/Apps/gollum/gollum.container +10 -1
  187. data/Plugins/Apps/gollum/gollum.lmm.rb +56 -47
  188. data/Plugins/Apps/llama.cpp/llama.cpp.container +28 -0
  189. data/Plugins/Apps/llama.cpp/llama.cpp.lmm.rb +90 -0
  190. data/Plugins/Apps/vLLM/vLLM.container +32 -0
  191. data/Plugins/Apps/vLLM/vLLM.lmm.rb +89 -0
  192. data/Plugins/OS/General/Utils.lmm.rb +26 -0
  193. data/Plugins/OS/Linux/Connection.rb +472 -0
  194. data/Plugins/OS/Linux/Debian/preseed.cfg.erb +81 -0
  195. data/Plugins/OS/Linux/Distributions.yaml +32 -0
  196. data/Plugins/OS/Linux/Flavours.yaml +24 -0
  197. data/Plugins/OS/Linux/Grub/grub.cfg +10 -0
  198. data/Plugins/OS/Linux/HTTP.rb +32 -0
  199. data/Plugins/OS/Linux/Linux.lmm.rb +708 -174
  200. data/Plugins/OS/Linux/Packages.yaml +67 -3
  201. data/Plugins/OS/Linux/Proxmox/answer.toml.erb +30 -0
  202. data/Plugins/OS/Linux/Services.yaml +8 -0
  203. data/Plugins/OS/Linux/Shell.rb +70 -0
  204. data/Plugins/OS/Linux/Syslinux/default +8 -0
  205. data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +93 -40
  206. data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +3 -0
  207. data/Plugins/OS/Linux/openSUSE/autoinst.xml.erb +29 -3
  208. data/Plugins/OS/Linux/systemd/systemd.lmm.rb +13 -11
  209. data/Plugins/OS/Routers/Aruba/ArubaInstant.lmm.rb +6 -5
  210. data/Plugins/Platforms/GitHub.lmm.rb +73 -28
  211. data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +10 -7
  212. data/Plugins/Platforms/Proxmox/Proxmox.lmm.rb +402 -0
  213. data/Plugins/Platforms/Proxmox/XTerm.rb +321 -0
  214. data/Plugins/Platforms/libvirt/libvirt.lmm.rb +41 -15
  215. data/Plugins/Platforms/porkbun.lmm.rb +12 -2
  216. data/Plugins/Platforms/porkbun_spec.rb +2 -2
  217. data/Plugins/Services/DNS/AmberBit.lmm.rb +1 -1
  218. data/Plugins/Services/DNS/ArubaItDNS.lmm.rb +1 -1
  219. data/Plugins/Services/DNS/NICLV.lmm.rb +1 -1
  220. data/Plugins/Services/DNS/PowerDNS.lmm.rb +130 -41
  221. data/Plugins/Services/DNS/tonic.lmm.rb +22 -12
  222. data/bootstrap.sh +41 -3
  223. data/lib/ConfigLMM/Framework/plugins/dns.rb +4 -3
  224. data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +187 -144
  225. data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +54 -6
  226. data/lib/ConfigLMM/Framework/plugins/plugin.rb +68 -140
  227. data/lib/ConfigLMM/Framework/plugins/store.rb +4 -4
  228. data/lib/ConfigLMM/Framework/variables.rb +75 -0
  229. data/lib/ConfigLMM/Framework.rb +1 -0
  230. data/lib/ConfigLMM/cli.rb +13 -5
  231. data/lib/ConfigLMM/commands/cleanup.rb +1 -0
  232. data/lib/ConfigLMM/commands/configsCommand.rb +38 -5
  233. data/lib/ConfigLMM/commands/diff.rb +33 -9
  234. data/lib/ConfigLMM/context.rb +22 -3
  235. data/lib/ConfigLMM/io/configList.rb +85 -7
  236. data/lib/ConfigLMM/io/connection.rb +143 -0
  237. data/lib/ConfigLMM/io/dhcp.rb +330 -0
  238. data/lib/ConfigLMM/io/http.rb +78 -0
  239. data/lib/ConfigLMM/io/local.rb +207 -0
  240. data/lib/ConfigLMM/io/pxe.rb +92 -0
  241. data/lib/ConfigLMM/io/ssh.rb +156 -0
  242. data/lib/ConfigLMM/io/tftp.rb +105 -0
  243. data/lib/ConfigLMM/io.rb +2 -0
  244. data/lib/ConfigLMM/secrets/envStore.rb +39 -0
  245. data/lib/ConfigLMM/secrets/fileStore.rb +43 -0
  246. data/lib/ConfigLMM/state.rb +12 -3
  247. data/lib/ConfigLMM/version.rb +2 -1
  248. data/lib/ConfigLMM.rb +1 -0
  249. data/{Examples → scripts}/configlmmAuth.sh +7 -5
  250. metadata +257 -9
@@ -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
@@ -0,0 +1,196 @@
1
+
2
+
3
+ module ConfigLMM
4
+ module LMM
5
+ class Lobsters < Framework::Plugin
6
+
7
+ USER = 'lobsters'
8
+ HOME_DIR = '/var/lib/lobsters'
9
+ GIT_REPO = 'https://github.com/lobsters/lobsters.git'
10
+ IMAGE_ID = 'ConfigLM.moe/lobsters:master'
11
+
12
+ def actionLobstersBuild(id, target, activeState, context, options)
13
+ buildContainer(id, target, options)
14
+ end
15
+
16
+ def buildContainer(id, target, options)
17
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
18
+ Linux.withConnection(local) do |localLinux|
19
+ begin
20
+ localLinux.ensurePackages(['git', 'Podman'], options) unless localLinux.hasBinaries?(['git', 'podman'], options)
21
+ rescue RuntimeError => error
22
+ prompt.say(error, :color => :red)
23
+ end
24
+ lobstersDir = File.expand_path(REPOS_CACHE + '/lobsters')
25
+ if !File.exist?(lobstersDir)
26
+ localLinux.createDirs(options, File.expand_path(REPOS_CACHE))
27
+ gitRepo = GIT_REPO
28
+ gitRepo = target['Repository'] if target['Repository']
29
+ localLinux.exec("cd #{REPOS_CACHE} && git clone --quiet #{gitRepo} lobsters", false, options)
30
+ else
31
+ localLinux.exec("cd #{lobstersDir} && git checkout . --quiet && git pull --quiet", false, options)
32
+ end
33
+ localLinux.exec("cd #{lobstersDir} && git checkout . --quiet", false, options)
34
+
35
+ if !IO::Connection.cmdSuccess?("podman image exists #{IMAGE_ID}")
36
+ # if you see error like "newuidmap 5227 0 1000 1 1 100000 65536: newuidmap: write to uid_map failed: Operation not permitted"
37
+ # then for LXC you need to set idmap like:
38
+ # LXC:
39
+ # - idmap: u 0 100000 165536
40
+ # - idmap: g 0 100000 165536
41
+ localLinux.upload(__dir__ + '/entrypoint.sh', lobstersDir, options)
42
+ localLinux.upload(__dir__ + '/Containerfile', lobstersDir, options)
43
+ localLinux.upload(__dir__ + '/crontab', lobstersDir, options)
44
+ localLinux.upload(__dir__ + '/puma.rb', lobstersDir + '/config/', options)
45
+ localLinux.upload(__dir__ + '/database.yml', lobstersDir + '/config/', options)
46
+ localLinux.upload(__dir__ + '/lobsters-cron.sh', lobstersDir + '/script/', options)
47
+ localLinux.upload(__dir__ + '/lobsters-daily.sh', lobstersDir + '/script/', options)
48
+ localLinux.upload(__dir__ + '/generateCredentials.rb', lobstersDir + '/script/', options)
49
+
50
+ localLinux.exec("cd #{lobstersDir} && git rev-parse HEAD > id.txt", false, options)
51
+
52
+ localLinux.exec("sed -i 's|lobste\\.rs|#{target['Domain']}|' #{lobstersDir}/config/application.rb #{lobstersDir}/config/sitemap.rb #{lobstersDir}/public/opensearch.xml", false, options)
53
+ localLinux.exec("sed -i 's|lobste\\.rs|#{target['Domain']}|' #{lobstersDir}/app/models/comment.rb #{lobstersDir}/app/controllers/keybase_proofs_controller.rb", false, options)
54
+
55
+ localLinux.exec("sed -i 's|email: \"inactive-user@example.com\"|email: \"inactive-user@#{target['Domain']}\"|' #{lobstersDir}/db/seeds.rb", false, options)
56
+
57
+ if target['Admin'].to_h['Username']
58
+ localLinux.exec("sed -i 's|username: \"test\"|username: \"#{target['Admin']['Username']}\"|' #{lobstersDir}/db/seeds.rb", false, options)
59
+ end
60
+
61
+ if target['Admin'].to_h['EMail']
62
+ localLinux.exec("sed -i 's|email: \"test@example.com\"|email: \"#{target['Admin']['EMail']}\"|' #{lobstersDir}/db/seeds.rb", false, options)
63
+ end
64
+
65
+ adminPassword = SecureRandom.alphanumeric(20)
66
+ localLinux.exec(" sed -i 's|password: \"test\"|password: \"#{adminPassword}\"|' #{lobstersDir}/db/seeds.rb", false, { **options, hide: true })
67
+ localLinux.exec(" sed -i 's|password_confirmation: \"test\"|password_confirmation: \"#{adminPassword}\"|' #{lobstersDir}/db/seeds.rb", false, { **options, hide: true })
68
+
69
+ #localLinux.fileReplace("#{REPOS_CACHE}/lobsters/Dockerfile.dev", 'COPY Gemfile.*', 'COPY . ./', options)
70
+ rubyVersion = localLinux.fileRead("#{REPOS_CACHE}/lobsters/.ruby-version", options).strip
71
+ localLinux.exec("cd #{REPOS_CACHE}/lobsters && podman build --tag=#{IMAGE_ID} --build-arg RUBY_VERSION=#{rubyVersion} --file Containerfile .", false, options)
72
+ end
73
+ end
74
+ end
75
+
76
+ def actionLobstersDeploy(id, target, activeState, context, options)
77
+ raise Framework::PluginProcessError.new('Domain field must be set!') unless target['Domain']
78
+
79
+ target['Database'] ||= {}
80
+ self.withConnection(target['Location'], target) do |connection|
81
+ Linux.withConnection(connection) do |linuxConnection|
82
+
83
+ dbPassword = self.configureMariaDB(target['Database'], activeState, linuxConnection, options)
84
+
85
+ Podman.ensurePresent(linuxConnection, options)
86
+ Podman.createUser(USER, HOME_DIR, 'Lobsters', linuxConnection, options)
87
+
88
+ cmd = IO::SSH.cmd(target['Location'])
89
+ local.exec("podman image save #{IMAGE_ID} | #{cmd} 'cat > #{HOME_DIR}/lobsters.tar'", false, options)
90
+
91
+ linuxConnection.withUserShell(USER) do |shell|
92
+ shell.createDirs(options, '~/config', '~/logs', '~/cache', '~/storage', '~/queue', '~/tmp')
93
+ Podman.loadImage(shell, 'lobsters.tar', options)
94
+ end
95
+
96
+ linuxConnection.exec("rm -f #{HOME_DIR}/lobsters.tar", false, options)
97
+
98
+ linuxConnection.createDirs(options, '/srv/lobsters')
99
+ linuxConnection.setUserGroup('/srv/lobsters', USER, USER, options)
100
+
101
+ path = Podman.containersPath(HOME_DIR)
102
+
103
+ linuxConnection.fileWrite(path + '/Lobsters.env', 'RAILS_ENV=production', options)
104
+ if target['SMTP'] && target['SMTP']['Host']
105
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_HOST=' + target['SMTP']['Host'], options)
106
+ if target['SMTP']['Port']
107
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_PORT=' + target['SMTP']['Port'].to_s, options)
108
+ end
109
+ if target['SMTP']['Username']
110
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_USERNAME=' + target['SMTP']['Username'], options)
111
+ end
112
+ if target['SMTP']['SecretId']
113
+ smtpPassword = context.secrets.load(target['SMTP']['SecretId'], target['SMTP']['Username'].upcase + '_PASSWORD')
114
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_PASSWORD=' + smtpPassword.to_s, { **options, hide: true })
115
+ end
116
+ if target['SMTP']['TLS'] || target['SMTP']['Port'].to_s == '465'
117
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_TLS=true', options)
118
+ end
119
+ else
120
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_HOST=10.0.2.2', options)
121
+ end
122
+ linuxConnection.fileAppend(path + '/Lobsters.env', 'SMTP_STARTTLS_AUTO=true', options)
123
+
124
+ linuxConnection.exec("chown #{USER}:#{USER} #{path}/Lobsters.env", false, options)
125
+ linuxConnection.exec("chmod 600 #{path}/Lobsters.env", false, options)
126
+
127
+ linuxConnection.upload(__dir__ + '/database.yml', HOME_DIR + '/config/', options)
128
+
129
+ if target['Database'] && target['Database']['HostName'] && target['Database']['HostName'] != 'localhost'
130
+ linuxConnection.fileReplace(HOME_DIR + '/config/database.yml', '10.0.2.2', target['Database']['HostName'], options)
131
+ end
132
+ linuxConnection.exec("sed -i 's|password:.*|password: #{dbPassword}|' #{HOME_DIR}/config/database.yml", false, options)
133
+
134
+ linuxConnection.upload(__dir__ + '/Lobsters.container', path, options)
135
+ linuxConnection.upload(__dir__ + '/Lobsters-Tasks.container', path, options)
136
+
137
+ linuxConnection.reloadUserServices(USER, options)
138
+ linuxConnection.restartUserService(USER, 'Lobsters', options)
139
+ linuxConnection.restartUserService(USER, 'Lobsters-Tasks', options)
140
+
141
+ Nginx.withConnection(linuxConnection) do |nginxConnection|
142
+ nginxConnection.writeConfig(__dir__, 'Lobsters', target, state, context, options)
143
+ nginxConnection.deployAllConfigs(target, activeState, context, options)
144
+ end
145
+ end
146
+ end
147
+ end
148
+
149
+ def configureMariaDB(settings, activeState, linuxConnection, options)
150
+ password = SecureRandom.alphanumeric(20)
151
+ MariaDB.withConnection(settings, linuxConnection) do |mariaConnection|
152
+ mariaConnection.createUserAndDB(USER, password, nil, options)
153
+ end
154
+ password
155
+ end
156
+
157
+ def cleanup(configs, state, context, options)
158
+ cleanupType(:Lobsters, configs, state, context, options) do |item, id, state, context, options, connection|
159
+ Linux.withConnection(connection) do |linuxConnection|
160
+
161
+ Nginx.withConnection(linuxConnection) do |nginxConnection|
162
+ nginxConnection.cleanupConfig('Lobsters', context, options)
163
+ nginxConnection.reload(options)
164
+ end
165
+
166
+ linuxConnection.stopUserService(USER, 'Lobsters-Tasks', options)
167
+ linuxConnection.stopUserService(USER, 'Lobsters', options)
168
+
169
+ path = Podman.containersPath(HOME_DIR)
170
+ linuxConnection.rm(path + 'Lobsters.container', options[:dry])
171
+ linuxConnection.rm(path + 'Lobsters-Tasks.container', options[:dry])
172
+ linuxConnection.rm('/srv/lobsters', options[:dry])
173
+
174
+ linuxConnection.withUserShell(USER) do |shell|
175
+ Podman.removeImage(shell, IMAGE_ID, options)
176
+ end
177
+
178
+ state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
179
+
180
+ if options[:destroy]
181
+ item['Config']['Database'] ||= {}
182
+ MariaDB.withConnection(item['Config']['Database'], linuxConnection) do |connectionDB|
183
+ connectionDB.dropDB(USER, options)
184
+ end
185
+ linuxConnection.deleteUserAndGroup(USER, options)
186
+ linuxConnection.rm(HOME_DIR, options[:dry])
187
+
188
+ state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
189
+ end
190
+ end
191
+ end
192
+ end
193
+
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,3 @@
1
+ */5 * * * * /srv/lobste.rs/http/script/lobsters-cron.sh
2
+ 0 0 * * * /srv/lobste.rs/http/script/lobsters-daily.sh
3
+ * * * * * /srv/lobste.rs/http/script/expire_page_cache
@@ -0,0 +1,26 @@
1
+ ---
2
+ trilogy: &trilogy
3
+ adapter: trilogy
4
+ encoding: utf8mb4
5
+ host: 10.0.2.2
6
+ port: 3306
7
+ pool: 5
8
+
9
+ sqlite3: &sqlite3
10
+ adapter: sqlite3
11
+ timeout: 5000
12
+
13
+ production:
14
+ primary:
15
+ <<: *trilogy
16
+ database: lobsters
17
+ username: lobsters
18
+ password:
19
+ cache:
20
+ <<: *sqlite3
21
+ database: /srv/lobste.rs/cache/cache.sqlite3
22
+ migrations_paths: db/cache_migrate
23
+ queue:
24
+ <<: *sqlite3
25
+ database: /srv/lobste.rs/queue/queue.sqlite3
26
+ migrations_paths: db/queue_migrate
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/sh
2
+
3
+ set -o errexit
4
+ set -o nounset
5
+
6
+ cmd="/lobsters/bin/rails"
7
+
8
+ if [ $# -gt 0 ]; then
9
+ if [ "$1" = "cron" ]; then
10
+ shift
11
+ cmd="/usr/local/bin/supercronic /etc/crontab"
12
+ elif [ "$1" = "server" ]; then
13
+ status=0
14
+ cmp --quiet "/lobsters/id.txt" "/srv/lobsters/id.txt" || status=$?
15
+ if [ $status -ne 0 ]; then
16
+ rm -rf /srv/lobsters/*
17
+ mkdir -p /srv/lobsters/public
18
+ cp -R /lobsters/public_source/* /srv/lobsters/public/
19
+ cp -R /lobsters/public_source/.* /srv/lobsters/public/
20
+ cp "/lobsters/id.txt" "/srv/lobsters/"
21
+ fi
22
+
23
+ if [ ! -f "/config/credentials.yml.enc" ]; then
24
+ bundle exec /lobsters/script/generateCredentials.rb
25
+ fi
26
+ /lobsters/bin/rails db:prepare
27
+ fi
28
+ fi
29
+
30
+ exec $cmd "$@"
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'rails/generators'
4
+ require 'rails/generators/rails/encryption_key_file/encryption_key_file_generator'
5
+ require 'rails/generators/rails/credentials/credentials_generator'
6
+
7
+ content_path = '/config/credentials.yml.enc'
8
+ key_path = '/config/master.key'
9
+
10
+ Rails::Generators::EncryptionKeyFileGenerator.new([], quiet: true).add_key_file(key_path)
11
+
12
+ Rails::Generators::CredentialsGenerator.new(
13
+ [content_path, key_path],
14
+ skip_secret_key_base: false,
15
+ quiet: true
16
+ ).invoke_all
17
+
18
+ # TODO
19
+ # should apply config/credentials.yml.enc.sample to config
@@ -0,0 +1,25 @@
1
+ #!/bin/bash
2
+
3
+ err=0
4
+ report() {
5
+ err=1
6
+ echo -n "error at line ${BASH_LINENO[0]}, in call to "
7
+ sed -n ${BASH_LINENO[0]}p $0
8
+ } >&2
9
+ trap report ERR
10
+
11
+ cd /srv/lobste.rs/http
12
+
13
+ if [ -f public/maintenance.html ];
14
+ then
15
+ exit 0
16
+ fi
17
+
18
+ bundle exec ruby script/fill_flagged_cache.rb &
19
+ bundle exec ruby script/mail_new_activity.rb &
20
+ #bundle exec ruby script/mastodon_post.rb &
21
+ #bundle exec ruby script/mastodon_sync_users.rb &
22
+ #bundle exec ruby script/send_new_webmentions &
23
+ bundle exec ruby script/traffic_range &
24
+
25
+ exit $err
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ err=0
4
+ report() {
5
+ err=1
6
+ echo -n "error at line ${BASH_LINENO[0]}, in call to "
7
+ sed -n ${BASH_LINENO[0]}p $0
8
+ } >&2
9
+ trap report ERR
10
+
11
+ cd /srv/lobste.rs/http
12
+
13
+ if [ -f public/maintenance.html ];
14
+ then
15
+ exit 0
16
+ fi
17
+
18
+ bundle exec rails daily_maintenance
19
+ bundle exec rails sitemap:refresh -s
20
+
21
+ find /srv/lobste.rs/http/tmp -type f -name 'rack%3A%3Aattack*' -mtime +2 -delete
22
+
23
+ exit $err
@@ -0,0 +1,49 @@
1
+ # typed: false
2
+
3
+ require "etc"
4
+
5
+ # Puma can serve each request in a thread from an internal thread pool.
6
+ # The `threads` method setting takes two numbers: a minimum and maximum.
7
+ # Any libraries that use thread pools should be configured to match
8
+ # the maximum value specified for Puma. Default is set to 5 threads for minimum
9
+ # and maximum; this matches the default thread size of Active Record.
10
+ #
11
+ threads_count = ENV.fetch("RAILS_MAX_THREADS") { 4 }
12
+ threads threads_count, threads_count
13
+
14
+ # Specifies the `port` that Puma will listen on to receive requests; default is 3000.
15
+ # port ENV.fetch("PORT") { 3000 }
16
+ # bind 'tcp://127.0.0.1:3000'
17
+
18
+ # Specifies the `environment` that Puma will run in.
19
+ environment ENV.fetch("RAILS_ENV") { "development" }
20
+
21
+ # Specifies the `pidfile` that Puma will use.
22
+ #pidfile ENV.fetch("PIDFILE") {
23
+ # "tmp/puma.pid"
24
+ #}
25
+
26
+ # Specifies the number of `workers` to boot in clustered mode.
27
+ # Workers are forked webserver processes. If using threads and workers together
28
+ # the concurrency of the application would be max `threads` * `workers`.
29
+ # Workers do not work on JRuby or Windows (both of which do not support
30
+ # processes).
31
+ workers ENV.fetch("PUMA_WORKERS") { 3 }
32
+
33
+ # Use the `preload_app!` method when specifying a `workers` number.
34
+ # This directive tells Puma to first boot the application and load code
35
+ # before forking the application. This takes advantage of Copy On Write
36
+ # process behavior so workers use less memory.
37
+ if ENV.fetch("RAILS_ENV") == "production"
38
+
39
+ # phased restarts
40
+ # https://github.com/puma/puma/blob/master/docs/restart.md
41
+ prune_bundler
42
+
43
+ # old hot restart config; will need ansible change to tell systemctl to restart instead of reload
44
+ # preload_app!
45
+ end
46
+
47
+ # Allow puma to be restarted by `rails restart` command.
48
+ plugin :tmp_restart
49
+
@@ -0,0 +1,55 @@
1
+
2
+ module ConfigLMM
3
+ module LMM
4
+ class MariaDBConnection
5
+
6
+ attr_reader :connection
7
+
8
+ def initialize(connection, settings)
9
+ @connection = connection
10
+ @settings = settings
11
+ end
12
+
13
+ def exec(sql, db = nil, allowFailure = false, options = {})
14
+ cmd = "mariadb #{db ? db.shellescape : ''} --execute=#{sql.shellescape}"
15
+ @connection.exec(cmd, allowFailure, options)
16
+ end
17
+
18
+ def createUserAndDB(user, password, host = nil, options = {})
19
+ if host.nil?
20
+ if @settings['HostName'] == 'localhost'
21
+ host = 'localhost'
22
+ else
23
+ host = '%'
24
+ end
25
+ end
26
+ self.exec("CREATE USER '#{user}'@'#{host}'", nil, true, options)
27
+ self.exec("ALTER USER '#{user}'@'#{host}' IDENTIFIED BY '#{password}'", nil, false, { **options, hide: true })
28
+ self.exec("CREATE DATABASE #{user}", nil, true, options)
29
+ self.exec("GRANT ALL PRIVILEGES ON #{user}.* TO '#{user}'@'#{host}'", nil, false, options)
30
+ end
31
+
32
+ def dropDB(db, options = {})
33
+ self.exec("DROP DATABASE #{db}", nil, true, options)
34
+ end
35
+
36
+ def createAdmin(options = {})
37
+ self.exec("CREATE USER 'admin'@'%'", nil, true, options)
38
+ password = SecureRandom.alphanumeric(20)
39
+ self.exec("ALTER USER 'admin'@'%' IDENTIFIED BY '#{password}'", nil, false, { **options, hide: true })
40
+ self.exec("GRANT ALL PRIVILEGES ON *.* TO 'admin'@'%' WITH GRANT OPTION", nil, false, options)
41
+ password
42
+ end
43
+
44
+ def dropAdmin(options = {})
45
+ self.exec("DROP USER 'admin'@'%'", nil, true, options)
46
+ end
47
+
48
+ def tableExist?(db, table, options = {})
49
+ table = self.exec("SHOW TABLES LIKE '#{table}'", db, false, options).strip
50
+ !table.empty?
51
+ end
52
+
53
+ end
54
+ end
55
+ end