8000 Merge pull request #2561 from nginx-proxy/fix/proto-with-multiports · nginx-proxy/nginx-proxy@dfbff1e · GitHub
[go: up one dir, main page]

65EB
Skip to content

Commit dfbff1e

Browse files
authored
Merge pull request #2561 from nginx-proxy/fix/proto-with-multiports
fix: add proto to VIRTUAL_HOST_MULTIPORTS
2 parents 691724c + 34a33a2 commit dfbff1e

File tree

8 files changed

+213
-18
lines changed

8 files changed

+213
-18
lines changed

docs/README.md

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ For each host defined into `VIRTUAL_HOST`, the associated virtual port is retrie
5656

5757
### Multiple ports
5858

59-
If your container expose more than one service on different ports and those services need to be proxied, you'll need to use the `VIRTUAL_HOST_MULTIPORTS` environment variable. This variable takes virtual host, path, port and dest definition in YAML (or JSON) form, and completely override the `VIRTUAL_HOST`, `VIRTUAL_PORT`, `VIRTUAL_PATH` and `VIRTUAL_DEST` environment variables on this container.
59+
If your container expose more than one service on different ports and those services need to be proxied, you'll need to use the `VIRTUAL_HOST_MULTIPORTS` environment variable. This variable takes virtual host, path, port and dest definition in YAML (or JSON) form, and completely override the `VIRTUAL_HOST`, `VIRTUAL_PORT`, `VIRTUAL_PROTO`, `VIRTUAL_PATH` and `VIRTUAL_DEST` environment variables on this container.
6060

6161
The YAML syntax should be easier to write on Docker compose files, while the JSON syntax can be used for CLI invocation.
6262

@@ -66,19 +66,21 @@ The expected format is the following:
6666
hostname:
6767
path:
6868
port: int
69+
proto: string
6970
dest: string
7071
```
7172
72-
For each hostname entry, `path`, `port` and `dest` are optional and are assigned default values when missing:
73+
For each hostname entry, `path`, `port`, `proto` and `dest` are optional and are assigned default values when missing:
7374

7475
- `path` = "/"
7576
- `port` = default port
77+
- `proto` = "http"
7678
- `dest` = ""
7779

78-
The following examples use an hypothetical container running services on port 80, 8000 and 9000:
79-
8080
#### Multiple ports routed to different hostnames
8181

82+
The following example use an hypothetical container running services over HTTP on port 80, 8000 and 9000:
83+
8284
```yaml
8385
services:
8486
multiport-container:
@@ -111,12 +113,14 @@ services:
111113

112114
This would result in the following proxy config:
113115

114-
- `www.example.org` -> `multiport-container:80`
115-
- `service1.example.org` -> `multiport-container:8000`
116-
- `service2.example.org` -> `multiport-container:9000`
116+
- `www.example.org` -> `multiport-container:80` over `HTTP`
117+
- `service1.example.org` -> `multiport-container:8000` over `HTTP`
118+
- `service2.example.org` -> `multiport-container:9000` over `HTTP`
117119

118120
#### Multiple ports routed to same hostname and different paths
119121

122+
The following example use an hypothetical container running services over HTTP on port 80 and 8000 and over HTTPS on port 9443:
123+
120124
```yaml
121125
services:
122126
multiport-container:
@@ -130,28 +134,29 @@ services:
130134
port: 8000
131135
dest: "/"
132136
"/service2":
133-
port: 9000
137+
port: 9443
138+
proto: "https"
134139
dest: "/"
135140
136-
# port and dest are not specified on the / path, so this path is routed
137-
# to the default port with the default dest value (empty string)
141+
# port and dest are not specified on the / path, so this path is routed to the
142+
# default port with the default dest value (empty string) and default proto (http)
138143
139144
# JSON equivalent:
140145
# VIRTUAL_HOST_MULTIPORTS: |-
141146
# {
142147
# "www.example.org": {
143148
# "/": {},
144149
# "/service1": { "port": 8000, "dest": "/" },
145-
# "/service2": { "port": 9000, "dest": "/" }
150+
# "/service2": { "port": 9443, "proto": "https", "dest": "/" }
146151
# }
147152
# }
148153
```
149154

150155
This would result in the following proxy config:
151156

152-
- `www.example.org` -> `multiport-container:80`
153-
- `www.example.org/service1` -> `multiport-container:8000`
154-
- `www.example.org/service2` -> `multiport-container:9000`
157+
- `www.example.org` -> `multiport-container:80` over `HTTP`
158+
- `www.example.org/service1` -> `multiport-container:8000` over `HTTP`
159+
- `www.example.org/service2` -> `multiport-container:9443` over `HTTPS`
155160

156161
⬆️ [back to table of contents](#table-of-contents)
157162

nginx.tmpl

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -589,18 +589,31 @@ proxy_set_header Proxy "";
589589

590590
{{- range $path, $vpath := $vhost }}
591591
{{- if (empty $vpath) }}
592-
{{- $vpath = dict "dest" "" "port" "default" }}
592+
{{- $vpath = dict
593+
"dest" ""
594+
"port" "default"
595+
"proto" "http"
596+
}}
593597
{{- end }}
598+
594599
{{- $dest := $vpath.dest | default "" }}
595600
{{- $port := $vpath.port | default "default" | toString }}
601+
{{- $proto := $vpath.proto | default "http" }}
602+
596603
{{- $path_data := get $paths $path | default (dict) }}
597604
{{- $path_ports := $path_data.ports | default (dict) }}
598605
{{- $path_port_containers := get $path_ports $port | default (list) | concat $containers }}
599606
{{- $_ := set $path_ports $port $path_port_containers }}
600607
{{- $_ := set $path_data "ports" $path_ports }}
608+
601609
{{- if (not (hasKey $path_data "dest")) }}
602610
{{- $_ := set $path_data "dest" $dest }}
603611
{{- end }}
612+
613+
{{- if (not (hasKey $path_data "proto")) }}
614+
{{- $_ := set $path_data "proto" $proto }}
615+
{{- end }}
616+
604617
{{- $_ := set $paths $path $path_data }}
605618
{{- end }}
606619
{{- $_ := set $vhost_data "paths" $paths }}
@@ -635,16 +648,24 @@ proxy_set_header Proxy "";
635648

636649
{{- range $path, $containers := $tmp_paths }}
637650
{{- $dest := groupByKeys $containers "Env.VIRTUAL_DEST" | first | default "" }}
651+
{{- $proto := groupByKeys $containers "Env.VIRTUAL_PROTO" | first | default "http" | trim }}
652+
638653
{{- $path_data := get $paths $path | default (dict) }}
639654
{{- $path_ports := $path_data.ports | default (dict) }}
640655
{{- range $port, $containers := groupByWithDefault $containers "Env.VIRTUAL_PORT" "default" }}
641656
{{- $path_port_containers := get $path_ports $port | default (list) | concat $containers }}
642657
{{- $_ := set $path_ports $port $path_port_containers }}
643658
{{- end }}
644659
{{- $_ := set $path_data "ports" $path_ports }}
660+
645661
{{- if (not (hasKey $path_data "dest")) }}
646662
{{- $_ := set $path_data "dest" $dest }}
647663
{{- end }}
664+
665+
{{- if (not (hasKey $path_data "proto")) }}
666+
{{- $_ := set $path_data "proto" $proto }}
667+
{{- end }}
668+
648669
{{- $_ := set $paths $path $path_data }}
649670
{{- end }}
650671
{{- $_ := set $vhost_data "paths" $paths }}
@@ -664,8 +685,6 @@ proxy_set_header Proxy "";
664685
{{ $vpath_containers = concat $vpath_containers $vport_containers }}
665686
{{- end }}
666687

667-
{{- /* Get the VIRTUAL_PROTO defined by containers w/ the same vhost-vpath, falling back to "http". */}}
668-
{{- $proto := groupByKeys $vpath_containers "Env.VIRTUAL_PROTO" | first | default "http" | trim }}
669688
{{- /* Get the NETWORK_ACCESS defined by containers w/ the same vhost, falling back to "external". */}}
670689
{{- $network_tag := groupByKeys $vpath_containers "Env.NETWORK_ACCESS" | first | default "external" }}
671690

@@ -678,7 +697,6 @@ proxy_set_header Proxy "";
678697
{{- $upstream = printf "%s-%s" $upstream $sum }}
679698
{{- end }}
680699

681-
{{- $_ := set $vpath_data "proto" $proto }}
682700
{{- $_ := set $vpath_data "network_tag" $network_tag }}
683701
{{- $_ := set $vpath_data "upstream" $upstream }}
684702
{{- $_ := set $vpath_data "loadbalance" $loadbalance }}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
Certificate:
2+
Data:
3+
Version: 3 (0x2)
4+
Serial Number: 4096 (0x1000)
5+
Signature Algorithm: sha256WithRSAEncryption
6+
Issuer: O=nginx-proxy test suite, CN=www.nginx-proxy.tld
7+
Validity
8+
Not Before: Jan 10 00:08:52 2017 GMT
9+
Not After : May 28 00:08:52 2044 GMT
10+
Subject: CN=*.nginx-proxy.tld
11+
Subject Public Key Info:
12+
Public Key Algorithm: rsaEncryption
13+
Public-Key: (2048 bit)
14+
Modulus:
15+
00:cb:45:f4:14:9b:fe:64:85:79:4a:36:8d:3d:d1:
16+
27:d0:7c:36:28:30:e6:73:80:6f:7c:49:23:d0:6c:
17+
17:e4:44:c0:77:4d:9a:c2:bc:24:84:e3:a5:4d:ba:
18+
d2:da:51:7b:a1:2a:12:d4:c0:19:55:69:2c:22:27:
19+
2d:1a:f6:fc:4b:7f:e9:cb:a8:3c:e8:69:b8:d2:4f:
20+
de:4e:50:e2:d0:74:30:7c:42:5a:ae:aa:85:a5:b1:
21+
71:4d:c9:7e:86:8b:62:8c:3e:0d:e3:3b:c3:f5:81:
22+
0b:8c:68:79:fe:bf:10:fb:ae:ec:11:49:6d:64:5e:
23+
1a:7d:b3:92:93:4e:96:19:3a:98:04:a7:66:b2:74:
24+
61:2d:41:13:0c:a4:54:0d:2c:78:fd:b4:a3:e8:37:
25+
78:9a:de:fa:bc:2e:a8:0f:67:14:58:ce:c3:87:d5:
26+
14:0e:8b:29:7d:48:19:b2:a9:f5:b4:e8:af:32:21:
27+
67:15:7e: 10000 43:52:8b:20:cf:9f:38:43:bf:fd:c8:24:
28+
7f:52:a3:88:f2:f1:4a:14:91:2a:6e:91:6f:fb:7d:
29+
6a:78:c6:6d:2e:dd:1e:4c:2b:63:bb:3a:43:9c:91:
30+
f9:df:d3:08:13:63:86:7d:ce:e8:46:cf:f1:6c:1f:
31+
ca:f7:4c:de:d8:4b:e0:da:bc:06:d9:87:0f:ff:96:
32+
45:85
33+
Exponent: 65537 (0x10001)
34+
X509v3 extensions:
35+
X509v3 Subject Alternative Name:
36+
DNS:*.nginx-proxy.tld
37+
Signature Algorithm: sha256WithRSAEncryption
38+
6e:a5:0e:e4:d3:cc:d5:b7:fc:34:75:89:4e:98:8c:e7:08:06:
39+
a8:5b:ec:13:7d:83:99:a2:61:b8:d5:12:6e:c5:b4:53:4e:9a:
40+
22:cd:ad:14:30:6a:7d:58:d7:23:d9:a4:2a:96:a0:40:9e:50:
41+
9f:ce:f2:fe:8c:dd:9a:ac:99:39:5b:89:2d:ca:e5:3e:c3:bc:
42+
03:04:1c:12:d9:6e:b8:9f:f0:3a:be:12:44:7e:a4:21:86:73:
43+
af:d5:00:51:3f:2c:56:70:34:8f:26:b0:7f:b0:cf:cf:7f:f9:
44+
40:6f:00:29:c4:cf:c3:b7:c2:49:3d:3f:b0:26:78:87:b9:c7:
45+
6c:1b:aa:6a:1a:dd:c5:eb:f2:69:ba:6d:46:0b:92:49:b5:11:
46+
3c:eb:48:c7:2f:fb:33:a6:6a:82:a2:ab:f8:1e:5f:7d:e3:b7:
47+
f2:fd:f5:88:a5:09:4d:a0:bc:f4:3b:cd:d2:8b:d7:57:1f:86:
48+
3b:d2:3e:a4:92:21:b0:02:0b:e9:e0:c4:1c:f1:78:e2:58:a7:
49+
26:5f:4c:29:c8:23:f0:6e:12:3f:bd:ad:44:7b:0b:bd:db:ba:
50+
63:8d:07:c6:9d:dc:46:cc:63:40:ba:5e:45:82:dd:9a:e5:50:
51+
e8:e7:d7:27:88:fc:6f:1d:8a:e7:5c:49:28:aa:10:29:75:28:
52+
c7:52:de:f9
53+
-----BEGIN CERTIFICATE-----
54+
MIIC9zCCAd+gAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwPzEfMB0GA1UECgwWbmdp
55+
bngtcHJveHkgdGVzdCBzdWl0ZTEcMBoGA1UEAwwTd3d3Lm5naW54LXByb3h5LnRs
56+
ZDAeFw0xNzAxMTAwMDA4NTJaFw00NDA1MjgwMDA4NTJaMBwxGjAYBgNVBAMMESou
57+
bmdpbngtcHJveHkudGxkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
58+
y0X0FJv+ZIV5SjaNPdEn0Hw2KDDmc4BvfEkj0GwX5ETAd02awrwkhOOlTbrS2lF7
59+
oSoS1MAZVWksIictGvb8S3/py6g86Gm40k/eTlDi0HQwfEJarqqFpbFxTcl+hoti
60+
jD4N4zvD9YELjGh5/r8Q+67sEUltZF4afbOSk06WGTqYBKdmsnRhLUETDKRUDSx4
61+
/bSj6Dd4mt76vC6oD2cUWM7Dh9UUDospfUgZsqn1tOivMiFnFX5DUosgz584Q7/9
62+
yCR/UqOI8vFKFJEqbpFv+31qeMZtLt0eTCtjuzpDnJH539MIE2OGfc7oRs/xbB/K
63+
90ze2Evg2rwG2YcP/5ZFhQIDAQABoyAwHjAcBgNVHREEFTATghEqLm5naW54LXBy
64+
b3h5LnRsZDANBgkqhkiG9w0BAQsFAAOCAQEAbqUO5NPM1bf8NHWJTpiM5wgGqFvs
65+
E32DmaJhuNUSbsW0U06aIs2tFDBqfVjXI9mkKpagQJ5Qn87y/ozdmqyZOVuJLcrl
66+
PsO8AwQcEtluuJ/wOr4SRH6kIYZzr9UAUT8sVnA0jyawf7DPz3/5QG8AKcTPw7fC
67+
ST0/sCZ4h7nHbBuqahrdxevyabptRguSSbURPOtIxy/7M6ZqgqKr+B5ffeO38v31
68+
iKUJTaC89DvN0ovXVx+GO9I+pJIhsAIL6eDEHPF44linJl9MKcgj8G4SP72tRHsL
69+
vdu6Y40Hxp3cRsxjQLpeRYLdmuVQ6OfXJ4j8bx2K51xJKKoQKXUox1Le+Q==
70+
-----END CERTIFICATE-----
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
-----BEGIN RSA PRIVATE KEY-----
2+
MIIEowIBAAKCAQEAy0X0FJv+ZIV5SjaNPdEn0Hw2KDDmc4BvfEkj0GwX5ETAd02a
3+
wrwkhOOlTbrS2lF7oSoS1MAZVWksIictGvb8S3/py6g86Gm40k/eTlDi0HQwfEJa
4+
rqqFpbFxTcl+hotijD4N4zvD9YELjGh5/r8Q+67sEUltZF4afbOSk06WGTqYBKdm
5+
snRhLUETDKRUDSx4/bSj6Dd4mt76vC6oD2cUWM7Dh9UUDospfUgZsqn1tOivMiFn
6+
FX5DUosgz584Q7/9yCR/UqOI8vFKFJEqbpFv+31qeMZtLt0eTCtjuzpDnJH539MI
7+
E2OGfc7oRs/xbB/K90ze2Evg2rwG2YcP/5ZFhQIDAQABAoIBAQCjAro2PNLJMfCO
8+
fyjNRgmzu6iCmpR0U68T8GN0JPsT576g7e8J828l0pkhuIyW33lRSThIvLSUNf9a
9+
dChL032H3lBTLduKVh4NKleQXnVFzaeEPoISSFVdButiAhAhPW4OIUVp0OfY3V+x
10+
fac3j2nDLAfL5SKAtqZv363Py9m66EBYm5BmGTQqT/frQWeCEBvlErQef5RIaU8p
11+
e2zMWgSNNojVai8U3nKNRvYHWeWXM6Ck7lCvkHhMF+RpbmCZuqhbEARVnehU/Jdn
12+
QHJ3nxeA2OWpoWKXvAHtSnno49yxq1UIstiQvY+ng5C5i56UlB60UiU2NJ6doZkB
13+
uQ7/1MaBAoGBAORdcFtgdgRALjXngFWhpCp0CseyUehn1KhxDCG+D1pJ142/ymcf
14+
oJOzKJPMRNDdDUBMnR1GBfy7rmwvYevI/SMNy2Qs7ofcXPbdtwwvTCToZ1V9/54k
15+
VfuPBFT+3QzWRvG1tjTV3E4L2VV3nrl2qNPhE5DlfIaU3nQq5Fl0HprJAoGBAOPf
16+
MWOTGev61CdODO5KN3pLAoamiPs5lEUlz3kM3L1Q52YLITxNDjRj9hWBUATJZOS2
17+
pLOoYRwmhD7vrnimMc41+NuuFX+4T7hWPc8uSuOxX0VijYtULyNRK57mncG1Fq9M
18+
RMLbOJ7FD+8jdXNsSMqpQ+pxLJRX/A10O2fOQnbdAoGAL5hV4YWSM0KZHvz332EI
19+
ER0MXiCJN7HkPZMKH0I4eu3m8hEmAyYxVndBnsQ1F37q0xrkqAQ/HTSUntGlS/og
20+
4Bxw5pkCwegoq/77tpto+ExDtSrEitYx4XMmSPyxX4qNULU5m3tzJgUML+b1etwD
21+
Rd2kMU/TC02dq4KBAy/TbRkCgYAl1xN5iJz+XenLGR/2liZ+TWR+/bqzlU006mF4
22+
pZUmbv/uJxz+yYD5XDwqOA4UrWjuvhG9r9FoflDprp2XdWnB556KxG7XhcDfSJr9
23+
A5/2DadXe1Ur9O/a+oi2228JEsxQkea9QPA3FVxfBtFjOHEiDlez39VaUP4PMeUH
24+
iO3qlQKBgFQhdTb7HeYnApYIDHLmd1PvjRvp8XKR1CpEN0nkw8HpHcT1q1MUjQCr
25+
iT6FQupULEvGmO3frQsgVeRIQDbEdZK3C5xCtn6qOw70sYATVf361BbTtidmU9yV
26+
THFxwDSVLiVZgFryoY/NtAc27sVdJnGsPRjjaeVgALAsLbmZ1K/H
27+
-----END RSA PRIVATE KEY-----
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
server {
2+
listen 80;
3+
server_name web2.nginx-proxy.tld;
4+
5+
location / {
6+
default_type text/plain;
7+
return 200 'This is web2.nginx-proxy.tld';
8+
}
9+
}
10+
11+
server {
12+
listen 443 ssl;
13+
server_name web3.nginx-proxy.tld;
14+
15+
ssl_certificate /etc/nginx/certs/server.crt;
16+
ssl_certificate_key /etc/nginx/certs/server.key;
17+
18+
ssl_protocols TLSv1.2 TLSv1.3;
19+
ssl_prefer_server_ciphers off;
20+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305';
21+
22+
location / {
23+
default_type text/plain;
24+
return 200 'This is web3.nginx-proxy.tld';
25+
}
26+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
server {
2+
listen 443 ssl;
3+
server_name web1.nginx-proxy.tld;
4+
5+
ssl_certificate /etc/nginx/certs/server.crt;
6+
ssl_certificate_key /etc/nginx/certs/server.key;
7+
8+
ssl_protocols TLSv1.2 TLSv1.3;
9+
ssl_prefer_server_ciphers off;
10+
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305';
11+
12+
location / {
13+
default_type text/plain;
14+
return 200 'This is web1.nginx-proxy.tld';
15+
}
16+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import pytest
2+
3+
4+
@pytest.mark.parametrize('subdomain', ['web1', 'web2', 'web3'])
5+
def test_upstream_with_https_virtual_proto(docker_compose, nginxproxy, subdomain):
6+
r = nginxproxy.get(f"http://{subdomain}.nginx-proxy.tld")
7+
assert r.status_code == 200
8+
assert r.text == f"This is {subdomain}.nginx-proxy.tld"
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
services:
2+
ssl-app-single-port:
3+
image: nginx:alpine
4+
volumes:
5+
- ${PYTEST_MODULE_PATH}/ssl-app-single-port.conf:/etc/nginx/conf.d/default.conf:ro
6+
- ${PYTEST_MODULE_PATH}/nginx-proxy.tld.crt:/etc/nginx/certs/server.crt:ro
7+
- ${PYTEST_MODULE_PATH}/nginx-proxy.tld.key:/etc/nginx/certs/server.key:ro
8+
environment:
9+
VIRTUAL_HOST: "web1.nginx-proxy.tld"
10+
VIRTUAL_PROTO: "https"
11+
VIRTUAL_PORT: "443"
12+
13+
ssl-app-multi-ports:
14+
image: nginx:alpine
15+
volumes:
16+
- ${PYTEST_MODULE_PATH}/ssl-app-multi-ports.conf:/etc/nginx/conf.d/default.conf:ro
17+
- ${PYTEST_MODULE_PATH}/nginx-proxy.tld.crt:/etc/nginx/certs/server.crt:ro
18+
- ${PYTEST_MODULE_PATH}/nginx-proxy.tld.key:/etc/nginx/certs/server.key:ro
19+
environment:
20+
VIRTUAL_HOST_MULTIPORTS: |-
21+
web2.nginx-proxy.tld:
22+
web3.nginx-proxy.tld:
23+
"/":
24+
port: 443
25+
proto: "https"

0 commit comments

Comments
 (0)
0