ConfigLMM 0.2.0 → 0.4.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +67 -0
- data/Examples/Implemented.mm.yaml +75 -1
- data/Plugins/Apps/Authentik/Authentik-ProxyOutpost.container +14 -0
- data/Plugins/Apps/Authentik/Authentik-Server.container +19 -0
- data/Plugins/Apps/Authentik/Authentik-Worker.container +18 -0
- data/Plugins/Apps/Authentik/Authentik.conf.erb +42 -0
- data/Plugins/Apps/Authentik/Authentik.lmm.rb +95 -0
- data/Plugins/Apps/BookStack/BookStack.conf.erb +41 -0
- data/Plugins/Apps/BookStack/BookStack.container +15 -0
- data/Plugins/Apps/BookStack/BookStack.lmm.rb +80 -0
- data/Plugins/Apps/Cassandra/Cassandra.lmm.rb +41 -0
- data/Plugins/Apps/Discourse/Discourse-Sidekiq.container +17 -0
- data/Plugins/Apps/Discourse/Discourse.conf.erb +41 -0
- data/Plugins/Apps/Discourse/Discourse.container +17 -0
- data/Plugins/Apps/Discourse/Discourse.lmm.rb +95 -0
- data/Plugins/Apps/Dovecot/Dovecot.lmm.rb +171 -0
- data/Plugins/Apps/ERPNext/ERPNext-Frontend.container +19 -0
- data/Plugins/Apps/ERPNext/ERPNext-Queue.container +17 -0
- data/Plugins/Apps/ERPNext/ERPNext-Scheduler.container +17 -0
- data/Plugins/Apps/ERPNext/ERPNext-Websocket.container +19 -0
- data/Plugins/Apps/ERPNext/ERPNext.container +18 -0
- data/Plugins/Apps/ERPNext/ERPNext.lmm.rb +193 -0
- data/Plugins/Apps/ERPNext/ERPNext.network +12 -0
- data/Plugins/Apps/ERPNext/sites/apps.json +10 -0
- data/Plugins/Apps/ERPNext/sites/apps.txt +3 -0
- data/Plugins/Apps/ERPNext/sites/common_site_config.json +11 -0
- data/Plugins/Apps/GitLab/GitLab.container +18 -0
- data/Plugins/Apps/GitLab/GitLab.lmm.rb +100 -0
- data/Plugins/Apps/LetsEncrypt/LetsEncrypt.lmm.rb +57 -0
- data/Plugins/Apps/LetsEncrypt/hooks/dovecot.sh +2 -0
- data/Plugins/Apps/LetsEncrypt/hooks/nginx.sh +2 -0
- data/Plugins/Apps/LetsEncrypt/hooks/postfix.sh +2 -0
- data/Plugins/Apps/LetsEncrypt/renew-certificates.service +7 -0
- data/Plugins/Apps/LetsEncrypt/renew-certificates.timer +12 -0
- data/Plugins/Apps/LetsEncrypt/rfc2136.ini +11 -0
- data/Plugins/Apps/MariaDB/MariaDB.lmm.rb +115 -0
- data/Plugins/Apps/Matrix/Element.container +14 -0
- data/Plugins/Apps/Matrix/Matrix.conf.erb +49 -5
- data/Plugins/Apps/Matrix/Matrix.lmm.rb +86 -1
- data/Plugins/Apps/Matrix/Synapse.container +17 -0
- data/Plugins/Apps/Matrix/config.json +50 -0
- data/Plugins/Apps/Matrix/homeserver.yaml +70 -0
- data/Plugins/Apps/Matrix/log.config +30 -0
- data/Plugins/Apps/Nextcloud/Nextcloud.conf.erb +48 -10
- data/Plugins/Apps/Nextcloud/Nextcloud.lmm.rb +83 -1
- data/Plugins/Apps/Nextcloud/config.php +18 -0
- data/Plugins/Apps/Nginx/conf.d/configlmm.conf +71 -0
- data/Plugins/Apps/Nginx/config-lmm/errors.conf +11 -5
- data/Plugins/Apps/Nginx/config-lmm/proxy.conf +5 -1
- data/Plugins/Apps/Nginx/main.conf.erb +31 -0
- data/Plugins/Apps/Nginx/nginx.conf +3 -68
- data/Plugins/Apps/Nginx/nginx.lmm.rb +83 -22
- data/Plugins/Apps/Nginx/proxy.conf.erb +13 -3
- data/Plugins/Apps/Odoo/Odoo.conf.erb +30 -13
- data/Plugins/Apps/Odoo/Odoo.container +18 -0
- data/Plugins/Apps/Odoo/Odoo.lmm.rb +62 -2
- data/Plugins/Apps/Odoo/odoo.conf +37 -0
- data/Plugins/Apps/OpenVidu/Ingress.container +18 -0
- data/Plugins/Apps/OpenVidu/OpenVidu.conf.erb +34 -0
- data/Plugins/Apps/OpenVidu/OpenVidu.container +16 -0
- data/Plugins/Apps/OpenVidu/OpenVidu.lmm.rb +90 -0
- data/Plugins/Apps/OpenVidu/OpenViduCall.conf.erb +35 -0
- data/Plugins/Apps/OpenVidu/OpenViduCall.container +15 -0
- data/Plugins/Apps/OpenVidu/ingress.yaml +10 -0
- data/Plugins/Apps/OpenVidu/livekit.yaml +13 -0
- data/Plugins/Apps/PHP-FPM/PHP-FPM.lmm.rb +95 -0
- data/Plugins/Apps/Peppermint/Peppermint.conf.erb +60 -0
- data/Plugins/Apps/Peppermint/Peppermint.container +15 -0
- data/Plugins/Apps/Peppermint/Peppermint.lmm.rb +58 -0
- data/Plugins/Apps/Postfix/Postfix.lmm.rb +165 -31
- data/Plugins/Apps/Postfix/smtpd.conf +3 -0
- data/Plugins/Apps/PostgreSQL/PostgreSQL.lmm.rb +242 -24
- data/Plugins/Apps/Roundcube/Roundcube.conf.erb +75 -0
- data/Plugins/Apps/Roundcube/Roundcube.lmm.rb +145 -0
- data/Plugins/Apps/SSH/SSH.lmm.rb +51 -0
- data/Plugins/Apps/Tunnel/tunnel.lmm.rb +63 -0
- data/Plugins/Apps/Tunnel/tunnelTCP.service +9 -0
- data/Plugins/Apps/Tunnel/tunnelTCP.socket +9 -0
- data/Plugins/Apps/Tunnel/tunnelUDP.service +9 -0
- data/Plugins/Apps/Tunnel/tunnelUDP.socket +9 -0
- data/Plugins/Apps/UVdesk/UVdesk.conf.erb +52 -0
- data/Plugins/Apps/UVdesk/UVdesk.lmm.rb +85 -0
- data/Plugins/Apps/Valkey/Valkey.lmm.rb +34 -1
- data/Plugins/Apps/Vaultwarden/Vaultwarden.conf.erb +35 -18
- data/Plugins/Apps/Vaultwarden/Vaultwarden.container +16 -0
- data/Plugins/Apps/Vaultwarden/Vaultwarden.lmm.rb +46 -3
- data/Plugins/Apps/Wiki.js/Wiki.js.conf.erb +42 -0
- data/Plugins/Apps/Wiki.js/Wiki.js.container +15 -0
- data/Plugins/Apps/Wiki.js/Wiki.js.lmm.rb +61 -0
- data/Plugins/Apps/gollum/gollum.conf.erb +84 -19
- data/Plugins/Apps/gollum/gollum.container +15 -0
- data/Plugins/Apps/gollum/gollum.lmm.rb +48 -11
- data/Plugins/OS/Linux/Debian/preseed.cfg.erb +62 -0
- data/Plugins/OS/Linux/Distributions.yaml +42 -0
- data/Plugins/OS/Linux/Flavours.yaml +11 -0
- data/Plugins/OS/Linux/Linux.lmm.rb +362 -41
- data/Plugins/OS/Linux/Packages.yaml +88 -5
- data/Plugins/OS/Linux/Proxmox/answer.toml.erb +30 -0
- data/Plugins/OS/Linux/WireGuard/WireGuard.lmm.rb +137 -0
- data/Plugins/OS/Linux/WireGuard/wg0.conf.erb +15 -0
- data/Plugins/OS/Linux/systemd/systemd.lmm.rb +28 -0
- data/Plugins/OS/Linux/systemd/user-0.slice +9 -0
- data/Plugins/OS/Linux/systemd/user@.service.d/delegate.conf +3 -0
- data/Plugins/Platforms/GoDaddy/GoDaddy.lmm.rb +7 -3
- data/Plugins/Platforms/libvirt/libvirt.lmm.rb +3 -2
- data/Plugins/Services/DNS/PowerDNS.lmm.rb +158 -8
- data/README.md +6 -0
- data/bootstrap.sh +92 -0
- data/lib/ConfigLMM/Framework/plugins/dns.rb +1 -2
- data/lib/ConfigLMM/Framework/plugins/linuxApp.rb +249 -45
- data/lib/ConfigLMM/Framework/plugins/nginxApp.rb +56 -7
- data/lib/ConfigLMM/Framework/plugins/plugin.rb +112 -16
- data/lib/ConfigLMM/cli.rb +3 -1
- data/lib/ConfigLMM/commands/cleanup.rb +1 -0
- data/lib/ConfigLMM/commands/configsCommand.rb +3 -1
- data/lib/ConfigLMM/io/configList.rb +3 -1
- data/lib/ConfigLMM/state.rb +10 -2
- data/lib/ConfigLMM/version.rb +1 -1
- metadata +82 -3
- data/Plugins/Apps/Nginx/main.conf +0 -30
@@ -0,0 +1,30 @@
|
|
1
|
+
version: 1
|
2
|
+
|
3
|
+
formatters:
|
4
|
+
precise:
|
5
|
+
|
6
|
+
format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s'
|
7
|
+
|
8
|
+
handlers:
|
9
|
+
|
10
|
+
console:
|
11
|
+
class: logging.StreamHandler
|
12
|
+
formatter: precise
|
13
|
+
|
14
|
+
loggers:
|
15
|
+
# This is just here so we can leave `loggers` in the config regardless of whether
|
16
|
+
# we configure other loggers below (avoid empty yaml dict error).
|
17
|
+
_placeholder:
|
18
|
+
level: "INFO"
|
19
|
+
|
20
|
+
synapse.storage.SQL:
|
21
|
+
# beware: increasing this to DEBUG will make synapse log sensitive
|
22
|
+
# information such as access tokens.
|
23
|
+
level: INFO
|
24
|
+
|
25
|
+
root:
|
26
|
+
level: INFO
|
27
|
+
handlers: [console]
|
28
|
+
|
29
|
+
|
30
|
+
disable_existing_loggers: false
|
@@ -1,9 +1,11 @@
|
|
1
1
|
|
2
|
-
|
3
|
-
|
4
2
|
upstream nextcloud
|
5
3
|
{
|
4
|
+
<% if config['Server'] %>
|
5
|
+
server <%= config['Server'] %>;
|
6
|
+
<% else %>
|
6
7
|
server unix:/run/php-fpm/nextcloud.sock;
|
8
|
+
<% end %>
|
7
9
|
}
|
8
10
|
|
9
11
|
server
|
@@ -12,13 +14,22 @@ server
|
|
12
14
|
listen <%= config['Port'] %>;
|
13
15
|
listen [::]:<%= config['Port'] %>;
|
14
16
|
<% else %>
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
<% if config['NginxVersion'] >= 1.25 %>
|
18
|
+
listen <%= config['Port'] %> ssl;
|
19
|
+
listen [::]:<%= config['Port'] %> ssl;
|
20
|
+
http2 on;
|
21
|
+
http3 on;
|
22
|
+
quic_retry on;
|
23
|
+
add_header Alt-Svc 'h3=":<%= config['Port'] %>"; ma=86400';
|
24
|
+
<% else %>
|
25
|
+
listen <%= config['Port'] %> ssl http2;
|
26
|
+
listen [::]:<%= config['Port'] %> ssl http2;
|
27
|
+
<% end %>
|
28
|
+
|
18
29
|
include config-lmm/ssl.conf;
|
19
30
|
<% end %>
|
20
31
|
|
21
|
-
<%= config['Domain'] %>;
|
32
|
+
server_name <%= config['Domain'] %>;
|
22
33
|
|
23
34
|
access_log /var/log/nginx/nextcloud.access.log;
|
24
35
|
error_log /var/log/nginx/nextcloud.error.log;
|
@@ -133,17 +144,23 @@ server
|
|
133
144
|
fastcgi_max_temp_file_size 0;
|
134
145
|
}
|
135
146
|
|
147
|
+
# Rule borrowed from `.htaccess`
|
148
|
+
location /remote {
|
149
|
+
return 301 /remote.php$request_uri;
|
150
|
+
}
|
151
|
+
|
136
152
|
# Serve static files
|
137
153
|
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
|
138
154
|
try_files $uri /index.php$request_uri;
|
139
155
|
# HTTP response headers borrowed from Nextcloud `.htaccess`
|
140
|
-
add_header Cache-Control "public, max-age=15778463$assetImmutable";
|
141
156
|
add_header Referrer-Policy "no-referrer" always;
|
142
157
|
add_header X-Content-Type-Options "nosniff" always;
|
143
158
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
144
159
|
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
145
160
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
146
161
|
add_header X-XSS-Protection "1; mode=block" always;
|
162
|
+
add_header Cache-Control "public, max-age=15778463$assetImmutable";
|
163
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
147
164
|
access_log off; # Optional: Don't log access to assets
|
148
165
|
}
|
149
166
|
|
@@ -153,9 +170,30 @@ server
|
|
153
170
|
access_log off; # Optional: Don't log access to assets
|
154
171
|
}
|
155
172
|
|
156
|
-
|
157
|
-
|
158
|
-
|
173
|
+
location /wapps/ {
|
174
|
+
alias /var/lib/nextcloud/apps/;
|
175
|
+
|
176
|
+
# Serve static files
|
177
|
+
location ~ \.(?:css|js|mjs|svg|gif|png|jpg|ico|wasm|tflite|map|ogg|flac)$ {
|
178
|
+
try_files $uri /index.php$request_uri;
|
179
|
+
# HTTP response headers borrowed from Nextcloud `.htaccess`
|
180
|
+
add_header Referrer-Policy "no-referrer" always;
|
181
|
+
add_header X-Content-Type-Options "nosniff" always;
|
182
|
+
add_header X-Frame-Options "SAMEORIGIN" always;
|
183
|
+
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
184
|
+
add_header X-Robots-Tag "noindex, nofollow" always;
|
185
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
186
|
+
add_header Cache-Control "public, max-age=15778463$assetImmutable";
|
187
|
+
add_header X-XSS-Protection "1; mode=block" always;
|
188
|
+
access_log off; # Optional: Don't log access to assets
|
189
|
+
}
|
190
|
+
|
191
|
+
location ~ \.woff2?$ {
|
192
|
+
try_files $uri /index.php$request_uri;
|
193
|
+
expires 7d; # Cache-Control policy borrowed from `.htaccess`
|
194
|
+
access_log off; # Optional: Don't log access to assets
|
195
|
+
}
|
196
|
+
|
159
197
|
}
|
160
198
|
|
161
199
|
location / {
|
@@ -3,6 +3,10 @@ module ConfigLMM
|
|
3
3
|
module LMM
|
4
4
|
class Nextcloud < Framework::NginxApp
|
5
5
|
|
6
|
+
USER = 'nextcloud'
|
7
|
+
HOME_DIR = '/var/lib/nextcloud'
|
8
|
+
PACKAGE_NAME = 'Nextcloud'
|
9
|
+
|
6
10
|
def actionNextcloudBuild(id, target, state, context, options)
|
7
11
|
writeNginxConfig(__dir__, 'Nextcloud', id, target, state, context, options)
|
8
12
|
end
|
@@ -12,10 +16,88 @@ module ConfigLMM
|
|
12
16
|
end
|
13
17
|
|
14
18
|
def actionNextcloudDeploy(id, target, activeState, context, options)
|
15
|
-
if
|
19
|
+
if target['Location'] && target['Location'] != '@me'
|
20
|
+
uri = Addressable::URI.parse(target['Location'])
|
21
|
+
raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
|
22
|
+
self.class.sshStart(uri) do |ssh|
|
23
|
+
Framework::LinuxApp.ensurePackages([PHP_FPM::PHPFPM_PACKAGE], ssh)
|
24
|
+
Framework::LinuxApp.ensureServiceAutoStartOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
|
25
|
+
distroInfo = Framework::LinuxApp.ensurePackages([PACKAGE_NAME], ssh)
|
26
|
+
addUserCmd = "#{distroInfo['CreateServiceUser']} --home-dir '#{HOME_DIR}' --create-home --comment 'Nextcloud' #{USER}"
|
27
|
+
self.class.sshExec!(ssh, addUserCmd, true)
|
28
|
+
self.class.sshExec!(ssh, "mkdir -p /var/log/php/ /var/lib/nextcloud/apps/ /var/lib/nextcloud/data/")
|
29
|
+
self.class.sshExec!(ssh, "touch /var/log/php/nextcloud.errors.log")
|
30
|
+
self.class.sshExec!(ssh, "touch /var/log/php/nextcloud.mail.log")
|
31
|
+
self.class.sshExec!(ssh, "chown #{USER}:#{USER} /var/log/php/nextcloud.errors.log")
|
32
|
+
self.class.sshExec!(ssh, "chown #{USER}:#{USER} /var/log/php/nextcloud.mail.log")
|
33
|
+
PHP_FPM::fixConfigFileOverSSH(distroInfo, ssh)
|
34
|
+
|
35
|
+
webappsDir = PHP_FPM::webappsDir(distroInfo)
|
36
|
+
configDir = webappsDir + 'nextcloud/config/'
|
37
|
+
if !self.class.remoteFilePresent?(configDir + 'config.php', ssh)
|
38
|
+
self.class.uploadNotPresent(__dir__ + '/config.php', configDir, ssh)
|
39
|
+
self.class.sshExec!(ssh, "sed -i \"s|'instanceid' .*|'instanceid' => '#{SecureRandom.alphanumeric(10)}',|\" #{configDir}config.php")
|
40
|
+
self.class.sshExec!(ssh, "touch #{configDir}CAN_INSTALL")
|
41
|
+
self.class.sshExec!(ssh, "sed -i 's|/usr/share/webapps/|#{webappsDir}|' #{configDir}config.php")
|
42
|
+
end
|
43
|
+
self.class.sshExec!(ssh, "chown -R nextcloud:nextcloud #{configDir}")
|
44
|
+
self.class.sshExec!(ssh, "chown -R nextcloud:nextcloud /var/lib/nextcloud/")
|
45
|
+
|
46
|
+
target['Database'] ||= {}
|
47
|
+
if !target['Database']['Type'] || target['Database']['Type'] == 'pgsql'
|
48
|
+
PostgreSQL.createRemoteUserAndDBOverSSH(target['Database'], USER, nil, ssh)
|
49
|
+
end
|
50
|
+
|
51
|
+
target['User'] = USER unless target['User']
|
52
|
+
name = 'nextcloud'
|
53
|
+
self.updateRemoteFile(ssh, PHP_FPM.configDir(distroInfo) + name + '.conf', options, false, ';') do |configLines|
|
54
|
+
PHP_FPM.writeConfig(name, target, distroInfo, configLines)
|
55
|
+
end
|
56
|
+
|
57
|
+
Framework::LinuxApp.startServiceOverSSH(PHP_FPM::PHPFPM_SERVICE, ssh)
|
58
|
+
|
59
|
+
self.class.ensurePackage(ssh)
|
60
|
+
self.class.prepareNginxConfig(target, ssh)
|
61
|
+
self.writeNginxConfig(__dir__, 'Nextcloud', id, target, state, context, options)
|
62
|
+
distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
|
63
|
+
webappsDir = PHP_FPM::webappsDir(distroInfo)
|
64
|
+
nginxFile = options['output'] + '/nginx/servers-lmm/Nextcloud.conf'
|
65
|
+
`sed -i 's|root .*|root #{webappsDir}nextcloud;|' #{nginxFile}`
|
66
|
+
deployNginxConfig(id, target, activeState, context, options)
|
67
|
+
Framework::LinuxApp.startService(NGINX_PACKAGE, ssh)
|
68
|
+
self.class.reload(ssh)
|
69
|
+
end
|
70
|
+
else
|
16
71
|
deployNginxConfig(id, target, activeState, context, options)
|
17
72
|
activeState['Location'] = '@me'
|
18
73
|
end
|
74
|
+
activeState['Status'] = State::STATUS_DEPLOYED
|
75
|
+
end
|
76
|
+
|
77
|
+
def cleanup(configs, state, context, options)
|
78
|
+
cleanupType(:Nextcloud, configs, state, context, options) do |item, id, state, context, options, ssh|
|
79
|
+
self.cleanupNginxConfig('Nextcloud', id, state, context, options, ssh)
|
80
|
+
self.class.reload(ssh, options[:dry])
|
81
|
+
distroInfo = Framework::LinuxApp.currentDistroInfo(ssh)
|
82
|
+
rm(PHP_FPM.configDir(distroInfo) + 'nextcloud.conf', options[:dry], ssh)
|
83
|
+
Framework::LinuxApp.reloadService(PHP_FPM::PHPFPM_SERVICE, ssh, options[:dry])
|
84
|
+
Framework::LinuxApp.removePackage(PACKAGE_NAME, ssh, options[:dry])
|
85
|
+
state.item(id)['Status'] = State::STATUS_DELETED unless options[:dry]
|
86
|
+
if options[:destroy]
|
87
|
+
rm(PHP_FPM::webappsDir(distroInfo) + 'nextcloud', options[:dry], ssh)
|
88
|
+
item['Database'] ||= {}
|
89
|
+
if !item['Database']['Type'] || item['Database']['Type'] == 'pgsql'
|
90
|
+
PostgreSQL.dropUserAndDB(item['Database'], USER, ssh, options[:dry])
|
91
|
+
end
|
92
|
+
Framework::LinuxApp.deleteUserAndGroup(USER, ssh, options[:dry])
|
93
|
+
rm('/var/log/php/nextcloud.access.log', options[:dry], ssh)
|
94
|
+
rm('/var/log/php/nextcloud.errors.log', options[:dry], ssh)
|
95
|
+
rm('/var/log/php/nextcloud.mail.log', options[:dry], ssh)
|
96
|
+
rm('/var/log/nginx/nextcloud.access.log', options[:dry], ssh)
|
97
|
+
rm('/var/log/nginx/nextcloud.error.log', options[:dry], ssh)
|
98
|
+
state.item(id)['Status'] = State::STATUS_DESTROYED unless options[:dry]
|
99
|
+
end
|
100
|
+
end
|
19
101
|
end
|
20
102
|
|
21
103
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
<?php
|
2
|
+
|
3
|
+
$CONFIG = [
|
4
|
+
'instanceid' => '',
|
5
|
+
'datadirectory' => '/var/lib/nextcloud/data/',
|
6
|
+
'apps_paths' => [
|
7
|
+
[
|
8
|
+
'path'=> '/usr/share/webapps/nextcloud/apps',
|
9
|
+
'url' => '/apps',
|
10
|
+
'writable' => false,
|
11
|
+
],
|
12
|
+
[
|
13
|
+
'path'=> '/var/lib/nextcloud/apps',
|
14
|
+
'url' => '/wapps',
|
15
|
+
'writable' => true,
|
16
|
+
],
|
17
|
+
]
|
18
|
+
];
|
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
server_tokens off;
|
3
|
+
|
4
|
+
tcp_nopush on;
|
5
|
+
|
6
|
+
# Needed for OCSP stapling
|
7
|
+
resolver 127.0.0.53;
|
8
|
+
|
9
|
+
|
10
|
+
# types_hash_max_size 4096;
|
11
|
+
# types_hash_bucket_size 64;
|
12
|
+
# proxy_headers_hash_max_size 512;
|
13
|
+
# proxy_headers_hash_bucket_size 128;
|
14
|
+
|
15
|
+
|
16
|
+
gzip on;
|
17
|
+
gzip_vary on;
|
18
|
+
gzip_proxied any;
|
19
|
+
gzip_comp_level 6;
|
20
|
+
gzip_min_length 256;
|
21
|
+
|
22
|
+
# do not remove ETag headers
|
23
|
+
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
24
|
+
|
25
|
+
gzip_types application/atom+xml text/javascript text/xml application/xml+rss application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
26
|
+
|
27
|
+
|
28
|
+
charset utf-8;
|
29
|
+
charset_types text/css text/plain text/xml text/javascript text/vnd.wap.wml application/json application/javascript application/xml application/xml+rss application/rss+xm image/svg+xml;
|
30
|
+
proxy_intercept_errors on;
|
31
|
+
fastcgi_intercept_errors on;
|
32
|
+
|
33
|
+
map '' $WithHost {
|
34
|
+
default '';
|
35
|
+
}
|
36
|
+
|
37
|
+
map "$WithHost" $ProxyHost {
|
38
|
+
default $host;
|
39
|
+
~. $WithHost;
|
40
|
+
}
|
41
|
+
|
42
|
+
map $http_accept $errorExtension
|
43
|
+
{
|
44
|
+
default html;
|
45
|
+
~application/json json;
|
46
|
+
~application/activity+json json;
|
47
|
+
}
|
48
|
+
|
49
|
+
map $http_upgrade $connectionUpgrade
|
50
|
+
{
|
51
|
+
default upgrade;
|
52
|
+
'' '';
|
53
|
+
}
|
54
|
+
|
55
|
+
# Set the `immutable` cache control options only for assets with a cache busting `v` argument
|
56
|
+
map $arg_v $assetImmutable
|
57
|
+
{
|
58
|
+
"" "";
|
59
|
+
default ", immutable";
|
60
|
+
}
|
61
|
+
|
62
|
+
root /srv/www/root;
|
63
|
+
|
64
|
+
ssl_certificate "/etc/letsencrypt/live/Wildcard/fullchain.pem";
|
65
|
+
ssl_certificate_key "/etc/letsencrypt/live/Wildcard/privkey.pem";
|
66
|
+
ssl_trusted_certificate "/etc/letsencrypt/live/Wildcard/chain.pem";
|
67
|
+
|
68
|
+
# Load modular configuration files from the /etc/nginx/servers directory.
|
69
|
+
# See http://nginx.org/en/docs/ngx_core_module.html#include
|
70
|
+
# for more information.
|
71
|
+
include servers-lmm/*.conf;
|
@@ -1,7 +1,13 @@
|
|
1
1
|
|
2
2
|
# add one directive for each http status code
|
3
3
|
error_page 301 /_errors_/HTTP301.$errorExtension;
|
4
|
-
|
4
|
+
|
5
|
+
# Looks like enabling custom 302 can be problematic
|
6
|
+
# due to apps using multiple Set-Cookie headers
|
7
|
+
# for example this breaks BookStack
|
8
|
+
# so lets not use it by default
|
9
|
+
#error_page 302 /_errors_/HTTP302.$errorExtension;
|
10
|
+
|
5
11
|
error_page 303 /_errors_/HTTP303.$errorExtension;
|
6
12
|
error_page 307 /_errors_/HTTP307.$errorExtension;
|
7
13
|
error_page 308 /_errors_/HTTP308.$errorExtension;
|
@@ -23,9 +29,9 @@ error_page 533 /_errors_/HTTP533.$errorExtension;
|
|
23
29
|
location /_errors_/ {
|
24
30
|
include config-lmm/public.conf;
|
25
31
|
|
26
|
-
|
32
|
+
add_header Location $upstream_http_location;
|
33
|
+
add_header Set-Cookie $upstream_http_set_cookie;
|
34
|
+
|
35
|
+
alias /srv/www/errors/;
|
27
36
|
internal;
|
28
37
|
}
|
29
|
-
|
30
|
-
add_header Location $upstream_http_location;
|
31
|
-
add_header Set-Cookie $upstream_http_set_cookie;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
|
2
2
|
proxy_http_version 1.1;
|
3
3
|
|
4
|
-
proxy_set_header Host $
|
4
|
+
proxy_set_header Host $ProxyHost;
|
5
5
|
proxy_set_header X-Real-IP $remote_addr;
|
6
6
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
7
7
|
proxy_set_header X-Forwarded-Proto $scheme;
|
@@ -13,3 +13,7 @@ proxy_set_header Connection $connectionUpgrade;
|
|
13
13
|
|
14
14
|
# proxy_set_header Proxy "";
|
15
15
|
proxy_pass_header Server;
|
16
|
+
|
17
|
+
proxy_ssl_protocols TLSv1.2 TLSv1.3;
|
18
|
+
|
19
|
+
proxy_connect_timeout 2s;
|
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
server {
|
3
|
+
listen 80 default_server;
|
4
|
+
listen [::]:80 default_server;
|
5
|
+
server_name _;
|
6
|
+
|
7
|
+
include config-lmm/errors.conf;
|
8
|
+
|
9
|
+
deny all;
|
10
|
+
}
|
11
|
+
|
12
|
+
server {
|
13
|
+
<% if config['NginxVersion'] >= 1.25 %>
|
14
|
+
listen 443 default_server ssl reuseport;
|
15
|
+
listen [::]:443 default_server ssl reuseport;
|
16
|
+
http2 on;
|
17
|
+
<% else %>
|
18
|
+
listen 443 default_server ssl reuseport http2;
|
19
|
+
listen [::]:443 default_server ssl reuseport http2;
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
server_name _;
|
23
|
+
|
24
|
+
deny all;
|
25
|
+
|
26
|
+
ssl_early_data on;
|
27
|
+
|
28
|
+
include config-lmm/errors.conf;
|
29
|
+
include config-lmm/security.conf;
|
30
|
+
include config-lmm/ssl.conf;
|
31
|
+
}
|
@@ -1,90 +1,25 @@
|
|
1
1
|
|
2
|
-
load_module "/usr/lib/nginx/modules/ngx_http_passenger_module.so";
|
3
|
-
#load_module "/usr/lib/nginx/modules/ngx_http_stub_status_module.so";
|
4
|
-
|
5
|
-
#user http;
|
6
2
|
worker_processes 4;
|
7
3
|
|
8
|
-
#error_log logs/error.log;
|
9
|
-
#error_log logs/error.log notice;
|
10
|
-
#error_log logs/error.log info;
|
11
4
|
error_log /var/log/nginx/error.log info;
|
12
5
|
|
13
|
-
#pid logs/nginx.pid;
|
14
|
-
|
15
|
-
|
16
6
|
events {
|
17
7
|
worker_connections 1024;
|
8
|
+
use epoll;
|
18
9
|
}
|
19
10
|
|
20
|
-
|
21
11
|
http {
|
22
12
|
include mime.types;
|
23
13
|
default_type application/octet-stream;
|
24
|
-
server_tokens off;
|
25
|
-
|
26
|
-
types_hash_max_size 4096;
|
27
|
-
types_hash_bucket_size 64;
|
28
|
-
proxy_headers_hash_max_size 512;
|
29
|
-
proxy_headers_hash_bucket_size 128;
|
30
|
-
|
31
|
-
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
32
|
-
# '$status $body_bytes_sent "$http_referer" '
|
33
|
-
# '"$http_user_agent" "$http_x_forwarded_for"';
|
34
|
-
|
35
|
-
#access_log logs/access.log main;
|
36
14
|
|
37
15
|
sendfile on;
|
38
|
-
tcp_nopush on;
|
39
|
-
resolver 127.0.0.53;
|
40
|
-
|
41
|
-
gzip on;
|
42
|
-
gzip_vary on;
|
43
|
-
gzip_proxied any;
|
44
|
-
gzip_comp_level 6;
|
45
|
-
gzip_min_length 256;
|
46
|
-
|
47
|
-
# do not remove ETag headers
|
48
|
-
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
|
49
|
-
|
50
|
-
gzip_types application/atom+xml text/javascript text/xml application/xml+rss application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/wasm application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
|
51
|
-
|
52
|
-
|
53
|
-
charset utf-8;
|
54
|
-
charset_types text/css text/plain text/xml text/javascript text/vnd.wap.wml application/json application/javascript application/xml application/xml+rss application/rss+xm image/svg+xml;
|
55
|
-
proxy_intercept_errors on;
|
56
|
-
fastcgi_intercept_errors on;
|
57
|
-
|
58
|
-
map $http_accept $errorExtension
|
59
|
-
{
|
60
|
-
default html;
|
61
|
-
~application/json json;
|
62
|
-
~application/activity+json json;
|
63
|
-
}
|
64
|
-
|
65
|
-
map $http_upgrade $connectionUpgrade
|
66
|
-
{
|
67
|
-
default upgrade;
|
68
|
-
'' '';
|
69
|
-
}
|
70
|
-
|
71
|
-
# Set the `immutable` cache control options only for assets with a cache busting `v` argument
|
72
|
-
map $arg_v $assetImmutable
|
73
|
-
{
|
74
|
-
"" "";
|
75
|
-
default ", immutable";
|
76
|
-
}
|
77
|
-
|
78
|
-
passenger_ruby /usr/bin/ruby;
|
79
|
-
passenger_root /usr/lib/passenger;
|
80
16
|
|
81
|
-
|
17
|
+
include conf.d/*.conf;
|
82
18
|
|
83
19
|
include /etc/nginx/main.conf;
|
84
20
|
|
85
21
|
# Load modular configuration files from the /etc/nginx/servers directory.
|
86
22
|
# See http://nginx.org/en/docs/ngx_core_module.html#include
|
87
23
|
# for more information.
|
88
|
-
include
|
89
|
-
include /etc/nginx/servers-lmm/*.conf;
|
24
|
+
include vhosts.d/*.conf;
|
90
25
|
}
|
@@ -2,19 +2,20 @@
|
|
2
2
|
module ConfigLMM
|
3
3
|
module LMM
|
4
4
|
class Nginx < Framework::NginxApp
|
5
|
-
|
6
|
-
|
7
|
-
HTTP_DIR = '/srv/http/'
|
5
|
+
CERTBOT_PACKAGE = 'CertBotNginx'
|
6
|
+
ERROR_PAGES_REPO = 'https://github.com/HttpErrorPages/HttpErrorPages.git'
|
8
7
|
|
9
8
|
def actionNginxBuild(id, target, activeState, context, options)
|
9
|
+
|
10
10
|
dir = options['output'] + '/nginx/'
|
11
|
-
mkdir(dir, options[:dry])
|
11
|
+
mkdir(dir + 'conf.d', options[:dry])
|
12
|
+
mkdir(dir + 'servers-lmm', options[:dry])
|
12
13
|
copy(__dir__ + '/config-lmm', dir, options[:dry])
|
13
|
-
# TODO, maybe evaluate them as template?
|
14
14
|
copy(__dir__ + '/nginx.conf', dir, options[:dry])
|
15
|
-
copy(__dir__ + '/
|
16
|
-
|
17
|
-
mkdir(options['output'] +
|
15
|
+
copy(__dir__ + '/conf.d/configlmm.conf', dir + 'conf.d/', options[:dry])
|
16
|
+
|
17
|
+
mkdir(options['output'] + WWW_DIR + 'root', options[:dry])
|
18
|
+
mkdir(options['output'] + WWW_DIR + 'errors', options[:dry])
|
18
19
|
end
|
19
20
|
|
20
21
|
# TODO
|
@@ -25,13 +26,68 @@ module ConfigLMM
|
|
25
26
|
def actionNginxDeploy(id, target, activeState, context, options)
|
26
27
|
dir = options['output'] + '/nginx/'
|
27
28
|
|
28
|
-
if
|
29
|
+
if target['Location'] && target['Location'] != '@me'
|
30
|
+
uri = Addressable::URI.parse(target['Location'])
|
31
|
+
raise Framework::PluginProcessError.new("Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
|
32
|
+
self.class.sshStart(uri) do |ssh|
|
33
|
+
Framework::LinuxApp.ensurePackages([CERTBOT_PACKAGE], ssh)
|
34
|
+
self.class.prepareNginxConfig(target, ssh)
|
35
|
+
|
36
|
+
self.class.sshExec!(ssh, "mkdir -p #{CONFIG_DIR}conf.d")
|
37
|
+
self.class.sshExec!(ssh, "mkdir -p #{WWW_DIR}root")
|
38
|
+
self.class.sshExec!(ssh, "mkdir -p #{WWW_DIR}errors")
|
39
|
+
ssh.scp.upload!(dir + 'nginx.conf', CONFIG_DIR + 'nginx.conf')
|
40
|
+
ssh.scp.upload!(dir + 'conf.d/configlmm.conf', CONFIG_DIR + 'conf.d/configlmm.conf')
|
41
|
+
resolverIP = self.class.sshExec!(ssh, "cat /etc/resolv.conf | grep 'nameserver' | grep -v ':' | head -n 1 | cut -d ' ' -f 2").strip
|
42
|
+
self.class.sshExec!(ssh, "sed -i 's|^resolver .*|resolver #{resolverIP};|' /etc/nginx/conf.d/configlmm.conf")
|
43
|
+
|
44
|
+
self.class.uploadFolder(dir + 'config-lmm', CONFIG_DIR, ssh)
|
45
|
+
self.class.uploadFolder(dir + 'servers-lmm', CONFIG_DIR, ssh)
|
46
|
+
|
47
|
+
template = ERB.new(File.read(__dir__ + '/main.conf.erb'))
|
48
|
+
renderTemplate(template, target, dir + 'main.conf', options)
|
49
|
+
ssh.scp.upload!(dir + 'main.conf', CONFIG_DIR + 'main.conf')
|
50
|
+
|
51
|
+
if !self.class.remoteFilePresent?(WWW_DIR + 'errors/HTTP500.html', ssh)
|
52
|
+
errorPages = File.expand_path(REPOS_CACHE + '/HttpErrorPages')
|
53
|
+
if !File.exist?(errorPages)
|
54
|
+
mkdir(File.expand_path(REPOS_CACHE), false)
|
55
|
+
begin
|
56
|
+
Framework::LinuxApp.ensurePackages(['git', 'Yarn'], '@me')
|
57
|
+
rescue RuntimeError => error
|
58
|
+
prompt.say(error, :color => :red)
|
59
|
+
end
|
60
|
+
`cd #{REPOS_CACHE} && git clone --quiet #{ERROR_PAGES_REPO} > /dev/null`
|
61
|
+
end
|
62
|
+
`cd #{errorPages} && yarn install --silent`
|
63
|
+
`cd #{errorPages} && yarn run static config-dist.json > /dev/null`
|
64
|
+
`cd #{errorPages} && cp -R dist errors`
|
65
|
+
self.class.uploadFolder(errorPages + '/errors', WWW_DIR, ssh)
|
66
|
+
end
|
67
|
+
|
68
|
+
Framework::LinuxApp.createCertificateOverSSH(ssh)
|
69
|
+
end
|
70
|
+
else
|
71
|
+
self.class.prepareNginxConfig(target, nil)
|
72
|
+
|
29
73
|
copy(dir + '/config-lmm', CONFIG_DIR, options[:dry])
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
mkdir(
|
34
|
-
mkdir(
|
74
|
+
copy(dir + '/nginx.conf', CONFIG_DIR, options[:dry])
|
75
|
+
|
76
|
+
copy(dir + '/servers-lmm', CONFIG_DIR, options['dry'])
|
77
|
+
mkdir(WWW_DIR + 'root', options[:dry])
|
78
|
+
mkdir(WWW_DIR + 'errors', options[:dry])
|
79
|
+
|
80
|
+
template = ERB.new(File.read(__dir__ + '/main.conf.erb'))
|
81
|
+
renderTemplate(template, target, dir + 'main.conf', options)
|
82
|
+
copy(dir + '/main.conf', CONFIG_DIR, options[:dry])
|
83
|
+
|
84
|
+
dir = "/etc/letsencrypt/live/Wildcard/"
|
85
|
+
`mkdir -p #{dir}`
|
86
|
+
if !File.exist?(dir + 'fullchain.pem')
|
87
|
+
`openssl req -x509 -noenc -days 90 -newkey rsa:2048 -keyout #{dir}privkey.pem -out #{dir}fullchain.pem -subj "/C=US/O=ConfigLMM/CN=Wildcard"`
|
88
|
+
`cp #{dir}fullchain.pem #{dir}chain.pem`
|
89
|
+
end
|
90
|
+
|
35
91
|
end
|
36
92
|
# Consider:
|
37
93
|
# * Deploy on current host
|
@@ -42,18 +98,23 @@ module ConfigLMM
|
|
42
98
|
end
|
43
99
|
|
44
100
|
def actionNginxProxyBuild(id, target, activeState, context, options)
|
45
|
-
|
46
|
-
|
47
|
-
template = ERB.new(File.read(__dir__ + '/proxy.conf.erb'))
|
48
|
-
renderTemplate(template, target, options['output'] + '/nginx/servers-lmm/' + target['Name'] + '.conf', options)
|
49
|
-
|
101
|
+
target['ConfigName'] = target['Name']
|
102
|
+
writeNginxConfig(__dir__, 'proxy', id, target, activeState, context, options)
|
50
103
|
actionNginxBuild(id, target, activeState, context, options)
|
51
104
|
end
|
52
105
|
|
53
106
|
def actionNginxProxyDeploy(id, target, activeState, context, options)
|
54
|
-
|
55
|
-
|
56
|
-
|
107
|
+
raise Framework::PluginProcessError.new('Proxy field must be set!') unless target['Proxy']
|
108
|
+
|
109
|
+
target['ConfigName'] = target['Name']
|
110
|
+
if target['Location'] && target['Location'] != '@me'
|
111
|
+
uri = Addressable::URI.parse(target['Location'])
|
112
|
+
raise Framework::PluginProcessError.new("#{id}: Unknown Protocol: #{uri.scheme}!") if uri.scheme != 'ssh'
|
113
|
+
self.class.sshStart(uri) do |ssh|
|
114
|
+
useNginxProxy(__dir__, 'proxy', id, target, activeState, state, context, options, ssh)
|
115
|
+
end
|
116
|
+
else
|
117
|
+
useNginxProxy(__dir__, 'proxy', id, target, activeState, state, context, options, ssh)
|
57
118
|
end
|
58
119
|
end
|
59
120
|
|
@@ -6,9 +6,18 @@ server {
|
|
6
6
|
listen <%= config['Port'] %>;
|
7
7
|
listen [::]:<%= config['Port'] %>;
|
8
8
|
<% else %>
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
<% if config['NginxVersion'] >= 1.25 %>
|
10
|
+
listen <%= config['Port'] %> ssl;
|
11
|
+
listen [::]:<%= config['Port'] %> ssl;
|
12
|
+
http2 on;
|
13
|
+
http3 on;
|
14
|
+
quic_retry on;
|
15
|
+
add_header Alt-Svc 'h3=":<%= config['Port'] %>"; ma=86400';
|
16
|
+
<% else %>
|
17
|
+
listen <%= config['Port'] %> ssl http2;
|
18
|
+
listen [::]:<%= config['Port'] %> ssl http2;
|
19
|
+
<% end %>
|
20
|
+
|
12
21
|
include config-lmm/ssl.conf;
|
13
22
|
<% end %>
|
14
23
|
|
@@ -18,6 +27,7 @@ server {
|
|
18
27
|
error_log /var/log/nginx/<%= config['Name'].downcase %>.error.log;
|
19
28
|
|
20
29
|
include config-lmm/errors.conf;
|
30
|
+
include config-lmm/security.conf;
|
21
31
|
|
22
32
|
<% if config['Private'] %>
|
23
33
|
include config-lmm/private.conf;
|