refactor: update nginx configuration and environment variables for improved routing and security
rabbitprincess committed
May 30, 2026 at 00:04 UTC
893ca3a879a3ba808b5f472f2bc36b005187f059
11 files changed
+259
-56
.env.example
+12
-7
@@ -1,14 +1,19 @@
1
# Public routing, discovery, and relay identity persistence
2
-PORTAL_URL=https://localhost:4017
3
-BOOTSTRAPS=https://localhost:4017
2
+PORTAL_URL=https://localhost
3
DISCOVERY=true
4
IDENTITY_PATH=/portal-certs
5
7
-# Listener ports
8
-FRONTEND_PORT=8080
9
-API_PORT=4017
10
-SNI_PORT=443
6
+# Public edge and internal listener ports.
7
+# nginx owns HTTP_PORT/HTTPS_PORT and forwards to the internal relay/frontend services.
8
+HTTP_PORT=80
9
+HTTPS_PORT=443
10
WIREGUARD_PORT=51820
11
+# Relay API and SNI TCP ports are fixed inside the Compose network at 4017 and 443.
12
+# If PORTAL_URL contains a path or a host alias, set PORTAL_HOST to the exact browser-facing host.
13
+PORTAL_HOST=
14
+# nginx reads these paths inside its container. Defaults map to ./.portal-certs on the host.
15
+NGINX_CERT_FILE=/etc/nginx/certs/fullchain.pem
16
+NGINX_CERT_KEY=/etc/nginx/certs/privatekey.pem
17
# Set when enabling public UDP or raw TCP lease ports.
18
MIN_PORT=0
19
MAX_PORT=0
@@ -54,7 +59,7 @@ ENS_GASLESS_ENABLED=false
59
ADMIN_WALLETS=
60
# Enable when the relay is behind nginx/ingress/load balancers and should trust forwarded client IP headers.
61
# Optionally restrict which proxy source ranges may supply those headers; leave empty for default private/loopback proxy ranges.
57
-TRUST_PROXY_HEADERS=false
62
+TRUST_PROXY_HEADERS=true
63
TRUSTED_PROXY_CIDRS=
64
65
# Frontend-owned presentation state.
docker-compose.yml
+43
-8
@@ -1,4 +1,43 @@
1
services:
2
+ nginx:
3
+ image: nginx:stable-alpine
4
+ depends_on:
5
+ - portal
6
+ - portal-frontend
7
+ - portal-api
8
+ ports:
9
+ - "${HTTP_PORT:-80}:80"
10
+ - "${HTTPS_PORT:-443}:443"
11
+ environment:
12
+ PORTAL_URL: ${PORTAL_URL:-https://localhost}
13
+ PORTAL_HOST: ${PORTAL_HOST:-}
14
+ NGINX_CERT_FILE: ${NGINX_CERT_FILE:-/etc/nginx/certs/fullchain.pem}
15
+ NGINX_CERT_KEY: ${NGINX_CERT_KEY:-/etc/nginx/certs/privatekey.pem}
16
+ volumes:
17
+ - ./nginx.conf.template:/etc/nginx/templates/nginx.conf.template:ro
18
+ - ./.portal-certs:/etc/nginx/certs:ro
19
+ command:
20
+ - /bin/sh
21
+ - -c
22
+ - |
23
+ portal_host="$${PORTAL_HOST:-$${PORTAL_URL#*://}}"
24
+ portal_host="$${portal_host%%/*}"
25
+ portal_host="$${portal_host%%:*}"
26
+ export PORTAL_HOST="$${portal_host:-localhost}"
27
+
28
+ export NGINX_CERT_FILE="$${NGINX_CERT_FILE:-/etc/nginx/certs/fullchain.pem}"
29
+ export NGINX_CERT_KEY="$${NGINX_CERT_KEY:-/etc/nginx/certs/privatekey.pem}"
30
+ envsubst '$$PORTAL_HOST $$NGINX_CERT_FILE $$NGINX_CERT_KEY' \
31
+ < /etc/nginx/templates/nginx.conf.template \
32
+ > /etc/nginx/nginx.conf
33
+
34
+ until [ -s "$$NGINX_CERT_FILE" ] && [ -s "$$NGINX_CERT_KEY" ]; do
35
+ echo "waiting for TLS certificate files: $$NGINX_CERT_FILE and $$NGINX_CERT_KEY"
36
+ sleep 1
37
+ done
38
+ exec nginx -g 'daemon off;'
39
+ restart: unless-stopped
40
+
41
# Optional: uncomment to enable auto-generated thumbnails for tunnel apps.
42
# See docs/src/routes/deployment/+page.md for details.
43
# headless-shell:
@@ -35,8 +74,6 @@ services:
74
depends_on:
75
- portal
76
- portal-api
38
- ports:
39
- - "${FRONTEND_PORT:-8080}:8080"
77
restart: unless-stopped
78
79
portal:
@@ -46,24 +83,22 @@ services:
83
dockerfile: Dockerfile
84
stop_grace_period: 30s
85
ports:
49
- - "${API_PORT:-4017}:4017"
50
- - "${SNI_PORT:-443}:${SNI_PORT:-443}"
86
- "${WIREGUARD_PORT:-51820}:${WIREGUARD_PORT:-51820}/udp"
87
# Uncomment for UDP backhaul, public UDP lease ports, and raw TCP lease ports as needed.
53
- # - "${SNI_PORT:-443}:${SNI_PORT:-443}/udp"
88
+ # - "443:443/udp"
89
# - "${MIN_PORT:-40000}-${MAX_PORT:-40009}:${MIN_PORT:-40000}-${MAX_PORT:-40009}/udp"
90
# - "${MIN_PORT:-40000}-${MAX_PORT:-40009}:${MIN_PORT:-40000}-${MAX_PORT:-40009}"
91
# Uncomment with PPROF_ENABLED=true and PPROF_ADDR=:6060 to inspect pprof from the host.
92
# - "${PPROF_PORT:-6060}:${PPROF_PORT:-6060}"
93
environment:
94
# Public routing, discovery, and relay identity persistence
60
- PORTAL_URL: ${PORTAL_URL:-https://localhost:${API_PORT:-4017}}
95
+ PORTAL_URL: ${PORTAL_URL:-https://localhost}
96
BOOTSTRAPS: ${BOOTSTRAPS:-}
97
DISCOVERY: ${DISCOVERY:-true}
98
IDENTITY_PATH: ${IDENTITY_PATH:-/portal-certs}
99
100
API_PORT: 4017
66
- SNI_PORT: ${SNI_PORT:-443}
101
+ SNI_PORT: 443
102
WIREGUARD_PORT: ${WIREGUARD_PORT:-51820}
103
104
# Shared lease port range.
@@ -74,7 +109,7 @@ services:
109
110
# Admin/auth configuration
111
ADMIN_WALLETS: ${ADMIN_WALLETS:-}
77
- TRUST_PROXY_HEADERS: ${TRUST_PROXY_HEADERS:-false}
112
+ TRUST_PROXY_HEADERS: ${TRUST_PROXY_HEADERS:-true}
113
TRUSTED_PROXY_CIDRS: ${TRUSTED_PROXY_CIDRS:-}
114
115
# Optional: relay-local x402 facilitator exposed under /x402
docs/src/routes/deployment/+page.md
+4
-4
@@ -20,7 +20,7 @@ The production deployment has four roles:
20
|---|---|---|---|
21
| Public edge | `nginx` | yes, `443/tcp` | Public TLS termination, path routing, wildcard SNI passthrough |
22
| Relay | `portal`, `ghcr.io/gosuda/portal` | no direct public API port | Relay API, wallet auth, policy enforcement, tunnel ingress |
23
-| Static frontend | `portal-frontend`, `ghcr.io/gosuda/portal-frontend` | no direct public port | SPA assets and same-origin frontend proxy |
23
+| Static frontend | `portal-frontend`, `ghcr.io/gosuda/portal-frontend` | no direct public port | SPA assets |
24
| Presentation API | `portal-api`, `ghcr.io/gosuda/portal-api` | no direct public port | Frontend-owned state, policy composition, service status, thumbnails |
25
26
Traffic should flow through one public HTTPS origin:
@@ -31,7 +31,7 @@ Browser
31
-> nginx public TLS edge
32
-> portal-frontend for SPA routes and assets
33
-> portal for relay-owned API paths
34
- -> portal-frontend -> portal-api for presentation-owned API paths
34
+ -> portal-api for presentation-owned API paths
35
36
Tunnel clients and public app visitors
37
-> https://*.portal.example.com
@@ -45,7 +45,7 @@ Tunnel clients and public app visitors
45
|---|---|---|
46
| `portal.example.com/`, `/admin`, SPA assets | Terminate TLS, HTTP proxy | `portal-frontend:8080` |
47
| `/admin/auth/*`, `/sdk/*`, `/install.*`, `/discovery`, `/discovery/*`, `/healthz`, `/v1/sign`, `/x402/*` | Terminate TLS, HTTP proxy | `portal:4017` over HTTPS |
48
-| `/state`, `/policy/*`, `/service/status`, `/thumbnail/*` | Terminate TLS, HTTP proxy | `portal-frontend:8080`, then `portal-api:8081` |
48
+| `/state`, `/policy/*`, `/service/status`, `/thumbnail/*` | Terminate TLS, HTTP proxy | `portal-api:8081` |
49
| `*.portal.example.com` | Raw TCP passthrough with `ssl_preread` | `portal` SNI listener |
50
51
The root relay host needs HTTP path routing, so it is not TCP-passthrough. Wildcard app hosts need TCP passthrough, so nginx must not terminate TLS for them.
@@ -67,7 +67,7 @@ To keep the same practical security level as the embedded frontend deployment:
67
68
- Public users reach the dashboard only through `https://portal.example.com`.
69
- `portal:4017`, `portal-frontend:8080`, and `portal-api:8081` are not exposed directly to the internet.
70
-- Root-host API paths are HTTP reverse-proxied by nginx to the relay API upstream.
70
+- Root-host API paths are HTTP reverse-proxied by nginx to either the relay API upstream or presentation API upstream.
71
- Wildcard app hosts are TCP-passthrough to the relay SNI listener.
72
- The nginx browser certificate and the relay API certificate are separate operational concerns unless you intentionally share the same certificate files.
73
docs/static/examples/nginx-proxy-multi-service/docker-compose.yaml
+1
@@ -6,6 +6,7 @@
6
# nginx:443 (L4 stream, ssl_preread)
7
# - portal.example.com -> nginx:8443 (L7 path split)
8
# - relay-owned API paths -> portal:${API_PORT:-4017} (portal, HTTPS, Docker network only)
9
+# - presentation API paths -> portal-api:8081 (HTTP)
10
# - frontend/UI paths -> portal-frontend:8080 (HTTP)
11
# - *.portal.example.com -> portal:443 (portal SNI passthrough, Docker network only)
12
# - everything else -> nginx:8443 (L7 for other apps)
docs/static/examples/nginx-proxy-multi-service/nginx.conf
+8
-4
@@ -79,6 +79,11 @@ http {
79
keepalive 16;
80
}
81
82
+ upstream portal_presentation_api {
83
+ server portal-api:8081;
84
+ keepalive 16;
85
+ }
86
+
87
upstream app_a_backend {
88
server app-a-api:8000;
89
keepalive 32;
@@ -141,10 +146,9 @@ http {
146
proxy_send_timeout 86400s;
147
}
148
144
- # Presentation-owned paths enter portal-frontend. Its internal nginx
145
- # forwards dynamic API requests to portal-api.
149
+ # Presentation-owned API paths belong to portal-api.
150
location = /state {
147
- proxy_pass http://portal_frontend;
151
+ proxy_pass http://portal_presentation_api;
152
proxy_http_version 1.1;
153
154
proxy_set_header Host $host;
@@ -157,7 +161,7 @@ http {
161
}
162
163
location ~ ^/(policy($|/)|service/status$|thumbnail/) {
160
- proxy_pass http://portal_frontend;
164
+ proxy_pass http://portal_presentation_api;
165
proxy_http_version 1.1;
166
167
proxy_set_header Host $host;
docs/static/examples/nginx-proxy/docker-compose.yaml
+3
@@ -5,6 +5,7 @@
5
# nginx:443/tcp (L4 stream, ssl_preread)
6
# - portal.example.com -> 127.0.0.1:8443 (nginx L7, TLS termination)
7
# - relay-owned API paths -> 127.0.0.1:${API_PORT:-4017} (portal, HTTPS, loopback only)
8
+# - presentation API paths -> 127.0.0.1:8081 (portal-api, HTTP, loopback only)
9
# - frontend/UI paths -> 127.0.0.1:8080 (portal-frontend, HTTP, loopback only)
10
# - *.portal.example.com -> 127.0.0.1:4443 (portal SNI, raw TCP passthrough)
11
# portal:443/udp (QUIC tunnel listener, only if UDP_ENABLED=true)
@@ -112,6 +113,8 @@ services:
113
- portal
114
# Uncomment with the headless-shell service above to enable generated screenshots.
115
# - headless-shell
116
+ ports:
117
+ - "127.0.0.1:8081:8081"
118
environment:
119
PORT: 8081
120
PORTAL_API_BASE_URL: "https://portal:${API_PORT:-4017}"
docs/static/examples/nginx-proxy/nginx.conf
+11
-6
@@ -8,8 +8,9 @@
8
# *.portal.example.com -> 127.0.0.1:4443 (portal SNI, raw TCP passthrough)
9
#
10
# L7 path routing on portal.example.com:
11
-# Relay API paths -> https://127.0.0.1:4017 (portal)
12
-# Frontend/UI paths -> http://127.0.0.1:8080 (portal-frontend)
11
+# Relay API paths -> https://127.0.0.1:4017 (portal)
12
+# Presentation API paths -> http://127.0.0.1:8081 (portal-api)
13
+# Frontend/UI paths -> http://127.0.0.1:8080 (portal-frontend)
14
15
events {
16
worker_connections 4096;
@@ -67,6 +68,11 @@ http {
68
keepalive 16;
69
}
70
71
+ upstream portal_presentation_api {
72
+ server 127.0.0.1:8081;
73
+ keepalive 16;
74
+ }
75
+
76
server {
77
listen 8443 ssl;
78
server_name portal.example.com;
@@ -103,10 +109,9 @@ http {
109
proxy_send_timeout 86400s;
110
}
111
106
- # Presentation-owned paths enter portal-frontend. Its internal nginx
107
- # forwards dynamic API requests to portal-api.
112
+ # Presentation-owned API paths belong to portal-api.
113
location = /state {
109
- proxy_pass http://portal_frontend;
114
+ proxy_pass http://portal_presentation_api;
115
proxy_http_version 1.1;
116
117
proxy_set_header Host $host;
@@ -119,7 +124,7 @@ http {
124
}
125
126
location ~ ^/(policy($|/)|service/status$|thumbnail/) {
122
- proxy_pass http://portal_frontend;
127
+ proxy_pass http://portal_presentation_api;
128
proxy_http_version 1.1;
129
130
proxy_set_header Host $host;
frontend/AGENTS.md
+1
-1
@@ -9,7 +9,7 @@ High-signal constraints for the relay-server frontend. Only items expensive to r
9
- Why: the Go relay is API-only. Do not reintroduce Go HTML data injection for public lease state.
10
11
2. **API path constants require dual maintenance.**
12
- Go relay definitions live in `../types/paths.go`; frontend facade paths live in `api/server.ts`, `nginx.conf`, and `src/lib/apiPaths.ts`.
12
+ Go relay definitions live in `../types/paths.go`; frontend facade paths live in `api/server.ts`, the edge nginx template, and `src/lib/apiPaths.ts`.
13
- Why: no codegen. A path mismatch produces 404s.
14
15
3. **API envelope shape must match across Go and TS.**
frontend/README.md
+5
-5
@@ -22,7 +22,7 @@ data.
22
- Public relay state is loaded from `/state`.
23
- Operator policy state is loaded from `/policy/state`.
24
- All JSON API responses use the `{ ok, data?, error? }` envelope parsed by `src/lib/apiClient.ts`.
25
-- `VITE_PORTAL_API_BASE_URL` points the frontend at the same API surface exposed by the frontend nginx/API service. Admin auth uses a bearer token returned by `/admin/auth/login`.
25
+- `VITE_PORTAL_API_BASE_URL` points the frontend at the same API surface exposed by the public edge nginx. Admin auth uses a bearer token returned by `/admin/auth/login`.
26
27
## Project Structure
28
@@ -84,9 +84,9 @@ VITE_PORTAL_API_BASE_URL=https://portal.example.com npm run dev
84
85
## Docker
86
87
-The frontend Docker image serves the built Vite app with nginx over HTTP,
88
-proxies relay-owned API paths to the HTTPS relay at `portal:4017`, and proxies
89
-presentation-owned paths to `portal-api:8081` in Docker Compose.
87
+The frontend Docker image serves the built Vite app with nginx over HTTP. It
88
+does not own API path routing; the public edge nginx routes relay-owned paths to
89
+`portal:4017` and presentation-owned paths to `portal-api:8081`.
90
TLS for public domains should live in the outer reverse proxy. The app uses
91
same-origin relative API paths, so it does not need runtime config file
92
generation.
@@ -129,6 +129,6 @@ state on top of relay data:
129
130
## Notes
131
132
-- Relay path constants live in Go (`types/paths.go`); frontend facade paths also need matching entries in `api/server.ts`, `nginx.conf`, and `src/lib/apiPaths.ts`.
132
+- Relay path constants live in Go (`types/paths.go`); frontend facade paths also need matching entries in `api/server.ts`, the edge nginx config, and `src/lib/apiPaths.ts`.
133
- Frontend API wire types live in `src/types/api.ts`.
134
- Radix Select values cannot be empty strings. Use stable values such as `"all"` and `"default"`.
frontend/nginx.conf
-21
@@ -5,27 +5,6 @@ server {
5
root /usr/share/nginx/html;
6
index index.html;
7
8
- location ~ ^/(state$|service/status$|policy(/|$)|thumbnail/) {
9
- proxy_http_version 1.1;
10
- proxy_set_header Host $host;
11
- proxy_set_header Authorization $http_authorization;
12
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
13
- proxy_set_header X-Forwarded-Host $host;
14
- proxy_set_header X-Forwarded-Proto $scheme;
15
- proxy_pass http://portal-api:8081;
16
- }
17
-
18
- location ~ ^/(admin/|sdk/|install\.sh$|install\.ps1$|install/bin/|discovery($|/)|healthz$|v1/sign$|x402(/|$)) {
19
- proxy_http_version 1.1;
20
- proxy_set_header Host $host;
21
- proxy_set_header Authorization $http_authorization;
22
- proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
23
- proxy_set_header X-Forwarded-Host $host;
24
- proxy_set_header X-Forwarded-Proto $scheme;
25
- proxy_ssl_verify off;
26
- proxy_pass https://portal:4017;
27
- }
28
-
8
location / {
9
try_files $uri $uri/ /index.html;
10
}
nginx.conf.template
new
+171
@@ -0,0 +1,171 @@
1
+# Portal relay + frontend edge nginx for the bundled Docker Compose stack.
2
+# docker-compose.yml renders this template from environment variables.
3
+#
4
+# Traffic flow:
5
+# :80 -> redirect to HTTPS
6
+# :443 -> L4 SNI inspection
7
+# ${PORTAL_HOST} -> nginx L7 TLS termination and path routing
8
+# *.${PORTAL_HOST} -> portal SNI listener, raw TCP passthrough
9
+#
10
+# The browser-facing certificate is read from ./.portal-certs by docker-compose.
11
+# That is the same default directory used by the relay certificate.
12
+
13
+include /usr/share/nginx/modules/*.conf;
14
+
15
+events {
16
+ worker_connections 4096;
17
+}
18
+
19
+stream {
20
+ map $ssl_preread_server_name $backend {
21
+ hostnames;
22
+ ${PORTAL_HOST} portal_web;
23
+ *.${PORTAL_HOST} portal_sni;
24
+ default portal_web;
25
+ }
26
+
27
+ upstream portal_web {
28
+ server 127.0.0.1:8443;
29
+ }
30
+
31
+ upstream portal_sni {
32
+ server portal:443;
33
+ }
34
+
35
+ server {
36
+ listen 443;
37
+ ssl_preread on;
38
+ proxy_pass $backend;
39
+ proxy_connect_timeout 5s;
40
+ proxy_timeout 86400s;
41
+ }
42
+}
43
+
44
+http {
45
+ sendfile on;
46
+ tcp_nopush on;
47
+ tcp_nodelay on;
48
+ keepalive_timeout 65;
49
+
50
+ include /etc/nginx/mime.types;
51
+ default_type application/octet-stream;
52
+
53
+ gzip on;
54
+ gzip_vary on;
55
+ gzip_min_length 1024;
56
+ gzip_types text/plain text/css application/json application/javascript
57
+ text/xml application/xml application/xml+rss text/javascript;
58
+
59
+ upstream portal_api {
60
+ server portal:4017;
61
+ keepalive 16;
62
+ }
63
+
64
+ upstream portal_presentation_api {
65
+ server portal-api:8081;
66
+ keepalive 16;
67
+ }
68
+
69
+ upstream portal_frontend {
70
+ server portal-frontend:8080;
71
+ keepalive 16;
72
+ }
73
+
74
+ server {
75
+ listen 8443 ssl;
76
+ server_name ${PORTAL_HOST};
77
+ server_tokens off;
78
+
79
+ ssl_certificate ${NGINX_CERT_FILE};
80
+ ssl_certificate_key ${NGINX_CERT_KEY};
81
+
82
+ ssl_protocols TLSv1.2 TLSv1.3;
83
+ ssl_ciphers HIGH:!aNULL:!MD5;
84
+ ssl_prefer_server_ciphers on;
85
+ ssl_session_cache shared:SSL:10m;
86
+ ssl_session_timeout 10m;
87
+
88
+ location = /sdk/connect {
89
+ proxy_pass https://portal_api;
90
+ proxy_ssl_verify off;
91
+ proxy_ssl_server_name on;
92
+ proxy_ssl_name $host;
93
+ proxy_http_version 1.1;
94
+
95
+ proxy_set_header Host $host;
96
+ proxy_set_header X-Real-IP $remote_addr;
97
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
98
+ proxy_set_header X-Forwarded-Proto https;
99
+ proxy_set_header Upgrade $http_upgrade;
100
+ proxy_set_header Connection $http_connection;
101
+
102
+ proxy_buffering off;
103
+ proxy_request_buffering off;
104
+ proxy_read_timeout 86400s;
105
+ proxy_send_timeout 86400s;
106
+ }
107
+
108
+ location = /state {
109
+ proxy_pass http://portal_presentation_api;
110
+ proxy_http_version 1.1;
111
+
112
+ proxy_set_header Host $host;
113
+ proxy_set_header X-Real-IP $remote_addr;
114
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
115
+ proxy_set_header X-Forwarded-Proto https;
116
+ proxy_set_header Connection "";
117
+
118
+ proxy_read_timeout 60s;
119
+ }
120
+
121
+ location ~ ^/(policy($|/)|service/status$|thumbnail/) {
122
+ proxy_pass http://portal_presentation_api;
123
+ proxy_http_version 1.1;
124
+
125
+ proxy_set_header Host $host;
126
+ proxy_set_header X-Real-IP $remote_addr;
127
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
128
+ proxy_set_header X-Forwarded-Proto https;
129
+ proxy_set_header Authorization $http_authorization;
130
+ proxy_set_header Connection "";
131
+
132
+ proxy_read_timeout 60s;
133
+ }
134
+
135
+ location ~ ^/(admin/|sdk/|install\.sh$|install\.ps1$|install/bin/|discovery($|/)|healthz$|v1/sign$|x402(/|$)) {
136
+ proxy_pass https://portal_api;
137
+ proxy_ssl_verify off;
138
+ proxy_ssl_server_name on;
139
+ proxy_ssl_name $host;
140
+ proxy_http_version 1.1;
141
+
142
+ proxy_set_header Host $host;
143
+ proxy_set_header X-Real-IP $remote_addr;
144
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
145
+ proxy_set_header X-Forwarded-Proto https;
146
+ proxy_set_header Authorization $http_authorization;
147
+ proxy_set_header Connection "";
148
+
149
+ proxy_read_timeout 60s;
150
+ }
151
+
152
+ location / {
153
+ proxy_pass http://portal_frontend;
154
+ proxy_http_version 1.1;
155
+
156
+ proxy_set_header Host $host;
157
+ proxy_set_header X-Real-IP $remote_addr;
158
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
159
+ proxy_set_header X-Forwarded-Proto https;
160
+ proxy_set_header Connection "";
161
+
162
+ proxy_read_timeout 60s;
163
+ }
164
+ }
165
+
166
+ server {
167
+ listen 80;
168
+ server_name _;
169
+ return 301 https://$host$request_uri;
170
+ }
171
+}