nginx.tmpl: use closest vhost.d and htpasswd files (#1309)

Add logic to find the closest matching files for vhost.d, vhost.d
_include and htpasswd files.

This allows multiple hosts to share these files, similar to wildcard
certificate files, but not limited to just 1 subdomain depth.

The match is anchored to the end of the string filename, so a largest
suffix match is found.

For example, 'vhost.d/b.c' will match a 'a.b.c' virtual host.
But 'a.b' will not match 'a.b.c'.
This is stricter than the "closest" match function that certificate
files used in the past, which would also match in the 2nd case.

This is a WIP, unfinished sections are marked with TODO.
This commit is contained in:
Jernej Jakob 2025-01-11 00:27:45 +01:00
parent 691724c81f
commit 8adc2eb146
No known key found for this signature in database
GPG key ID: 1E936484FFE8BA69

View file

@ -280,6 +280,7 @@
{{- define "location" }} {{- define "location" }}
{{- $vpath := .VPath }} {{- $vpath := .VPath }}
{{- /* TODO: largest suffix match location_override (same as for include_file and htpasswd_file) */}}
{{- $override := printf "/etc/nginx/vhost.d/%s_%s_location_override" .Host (sha1 .Path) }} {{- $override := printf "/etc/nginx/vhost.d/%s_%s_location_override" .Host (sha1 .Path) }}
{{- if and (eq .Path "/") (not (exists $override)) }} {{- if and (eq .Path "/") (not (exists $override)) }}
{{- $override = printf "/etc/nginx/vhost.d/%s_location_override" .Host }} {{- $override = printf "/etc/nginx/vhost.d/%s_location_override" .Host }}
@ -322,14 +323,16 @@
set $upstream_keepalive {{ if ne $keepalive "disabled" }}true{{ else }}false{{ end }}; set $upstream_keepalive {{ if ne $keepalive "disabled" }}true{{ else }}false{{ end }};
{{- end }} {{- end }}
{{- /* TODO: largest suffix match for host_sha1path too? */}}
{{- if (exists (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path) )) }} {{- if (exists (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path) )) }}
auth_basic "Restricted {{ .Host }}{{ .Path }}"; auth_basic "Restricted {{ .Host }}{{ .Path }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path)) }}; auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s_%s" .Host (sha1 .Path)) }};
{{- else if (exists (printf "/etc/nginx/htpasswd/%s" .Host)) }} {{- else if (ne .HtpasswdFile "") }}
auth_basic "Restricted {{ .HostIsRegexp | ternary "access" .Host }}"; auth_basic "Restricted {{ .HostIsRegexp | ternary "access" .Host }}";
auth_basic_user_file {{ (printf "/etc/nginx/htpasswd/%s" .Host) }}; auth_basic_user_file {{ .HtpasswdFile }};
{{- end }} {{- end }}
{{- /* TODO: largest suffix match location_override (same as for include_file and htpasswd_file) */}}
{{- if (exists (printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) )) }} {{- if (exists (printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) )) }}
include {{ printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) }}; include {{ printf "/etc/nginx/vhost.d/%s_%s_location" .Host (sha1 .Path) }};
{{- else if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }} {{- else if (exists (printf "/etc/nginx/vhost.d/%s_location" .Host)) }}
@ -739,6 +742,36 @@ proxy_set_header Proxy "";
{{- /* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}} {{- /* Get the VIRTUAL_ROOT By containers w/ use fastcgi root */}}
{{- $vhost_root := groupByKeys $vhost_containers "Env.VIRTUAL_ROOT" | first | default "/var/www/public" }} {{- $vhost_root := groupByKeys $vhost_containers "Env.VIRTUAL_ROOT" | first | default "/var/www/public" }}
{{- /* Get the best matching vhost.d include file */}}
{{- $include_file := "" }}
{{- range (dir "/etc/nginx/vhost.d") }}
{{- if (and (hasSuffix . $hostname) (gt (len .) (len $include_file))) }}
{{- $include_file = . }}
{{- end }}
{{- end }}
{{- $include_file = when (ne $include_file "") (print "/etc/nginx/vhost.d/" $include_file) "" }}
{{- $include_file = when (exists $include_file) $include_file "" }}
{{- /* Get the best matching vhost.d location include file */}}
{{- $location_file := "" }}
{{- range (dir "/etc/nginx/vhost.d") }}
{{- if (and (hasSuffix . (print $hostname "_location")) (gt (len .) (len $location_file))) }}
{{- $location_file = . }}
{{- end }}
{{- end }}
{{- $location_file = when (ne $location_file "") (print "/etc/nginx/vhost.d/" $location_file) "" }}
{{- $location_file = when (exists $location_file) $location_file "" }}
{{- /* Get the best matching htpasswd file */}}
{{- $htpasswd_file := "" }}
{{- range (dir "/etc/nginx/htpasswd") }}
{{- if (and (hasSuffix . $hostname) (gt (len .) (len $htpasswd_file))) }}
{{- $htpasswd_file = . }}
{{- end }}
{{- end }}
{{- $htpasswd_file = when (ne $htpasswd_file "") (print "/etc/nginx/htpasswd/" $htpasswd_file) "" }}
{{- $htpasswd_file = when (exists $htpasswd_file) $htpasswd_file "" }}
{{- $vhost_data = merge $vhost_data (dict {{- $vhost_data = merge $vhost_data (dict
"cert" $cert "cert" $cert
"cert_ok" $cert_ok "cert_ok" $cert_ok
@ -756,6 +789,9 @@ proxy_set_header Proxy "";
"trust_default_cert" $trust_default_cert "trust_default_cert" $trust_default_cert
"upstream_name" $upstream_name "upstream_name" $upstream_name
"vhost_root" $vhost_root "vhost_root" $vhost_root
"include_file" $include_file
"location_file" $location_file
"htpasswd_file" $htpasswd_file
) }} ) }}
{{- $_ := set $globals.vhosts $hostname $vhost_data }} {{- $_ := set $globals.vhosts $hostname $vhost_data }}
{{- end }} {{- end }}
@ -897,6 +933,7 @@ server {
server { server {
{{- if $vhost.is_regexp }} {{- if $vhost.is_regexp }}
{{- /* TODO: largest suffix match? what does this if-block even do? */}}
{{- if or {{- if or
(printf "/etc/nginx/vhost.d/%s" $hostname | exists) (printf "/etc/nginx/vhost.d/%s" $hostname | exists)
(printf "/etc/nginx/vhost.d/%s_location" $hostname | exists) (printf "/etc/nginx/vhost.d/%s_location" $hostname | exists)
@ -988,10 +1025,10 @@ server {
{{- end }} {{- end }}
{{- end }} {{- end }}
{{- $vhostFileName := $vhost.is_regexp | ternary (sha1 $hostname) $hostname }} {{- $vhostFileName := $vhost.is_regexp | ternary (print "/etc/nginx/vhost.d/" (sha1 $hostname)) $vhost.include_file }}
{{- if (exists (printf "/etc/nginx/vhost.d/%s" $vhostFileName)) }} {{- if (ne $vhostFileName "") }}
include {{ printf "/etc/nginx/vhost.d/%s" $vhostFileName }}; include {{ $vhostFileName }};
{{- else if (exists "/etc/nginx/vhost.d/default") }} {{- else if (exists "/etc/nginx/vhost.d/default") }}
include /etc/nginx/vhost.d/default; include /etc/nginx/vhost.d/default;
{{- end }} {{- end }}
@ -1003,10 +1040,12 @@ server {
{{- range $path, $vpath := $vhost.paths }} {{- range $path, $vpath := $vhost.paths }}
{{- template "location" (dict {{- template "location" (dict
"Path" $path "Path" $path
"Host" $vhostFileName "Host" ($vhost.is_regexp | ternary (sha1 $hostname) $hostname)
"HostIsRegexp" $vhost.is_regexp "HostIsRegexp" $vhost.is_regexp
"VhostRoot" $vhost.vhost_root "VhostRoot" $vhost.vhost_root
"VPath" $vpath "VPath" $vpath
"LocationFile" $vhost.location_file
"HtpasswdFile" $vhost.htpasswd_file
) }} ) }}
{{- end }} {{- end }}