autoreg-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
124
skills/reseller-api-gateway/references/nginx-config.md
Normal file
124
skills/reseller-api-gateway/references/nginx-config.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Nginx Config — API Gateway (HTTP/2 + Gzip + Error Masking)
|
||||
|
||||
Production config for `api.<domain>` on nginx 1.28.3.
|
||||
|
||||
## Server block (SSL + HTTP/2)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
listen [::]:443 ssl;
|
||||
http2 on;
|
||||
server_name api.[REDACTED-NAME].loc.cc;
|
||||
server_tokens off;
|
||||
|
||||
ssl_certificate /etc/letsencrypt/live/[REDACTED-NAME].loc.cc/fullchain.pem;
|
||||
ssl_certificate_key /etc/letsencrypt/live/[REDACTED-NAME].loc.cc/privkey.pem;
|
||||
include /etc/letsencrypt/options-ssl-nginx.conf;
|
||||
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
|
||||
|
||||
client_max_body_size 25m;
|
||||
gzip on;
|
||||
gzip_min_length 256;
|
||||
gzip_types application/json text/event-stream;
|
||||
gzip_comp_level 1;
|
||||
gzip_vary on;
|
||||
|
||||
location / {
|
||||
proxy_pass http://[REDACTED-NAME];
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
proxy_set_header X-Forwarded-Proto $scheme;
|
||||
proxy_set_header X-Request-ID $request_id;
|
||||
proxy_set_header Connection "";
|
||||
proxy_connect_timeout 10s;
|
||||
proxy_read_timeout 600s;
|
||||
proxy_send_timeout 600s;
|
||||
proxy_request_buffering off;
|
||||
proxy_buffering off;
|
||||
proxy_cache off;
|
||||
proxy_socket_keepalive on;
|
||||
proxy_intercept_errors on;
|
||||
}
|
||||
|
||||
# Error masking: ALL upstream/nginx errors → neutral JSON
|
||||
error_page 400 408 411 414 431 = @invalid_request;
|
||||
error_page 405 = @method_not_allowed;
|
||||
error_page 413 = @request_too_large;
|
||||
error_page 500 502 503 504 = @service_unavailable;
|
||||
|
||||
location @invalid_request {
|
||||
internal;
|
||||
default_type application/json;
|
||||
return 400 '{"error":{"message":"Invalid request","type":"gateway_error","code":"invalid_request"}}';
|
||||
}
|
||||
|
||||
location @method_not_allowed {
|
||||
internal;
|
||||
default_type application/json;
|
||||
return 405 '{"error":{"message":"Method not allowed","type":"gateway_error","code":"method_not_allowed"}}';
|
||||
}
|
||||
|
||||
location @request_too_large {
|
||||
internal;
|
||||
default_type application/json;
|
||||
return 413 '{"error":{"message":"Request body is too large","type":"gateway_error","code":"request_too_large"}}';
|
||||
}
|
||||
|
||||
location @service_unavailable {
|
||||
internal;
|
||||
default_type application/json;
|
||||
return 502 '{"error":{"message":"Service temporarily unavailable","type":"gateway_error","code":"service_unavailable"}}';
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Upstream block
|
||||
|
||||
```nginx
|
||||
upstream [REDACTED-NAME] {
|
||||
zone [REDACTED-NAME] 64k;
|
||||
server 127.0.0.1:18181;
|
||||
keepalive 64;
|
||||
}
|
||||
```
|
||||
|
||||
## HTTP → HTTPS redirect
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name [REDACTED-NAME].loc.cc www.[REDACTED-NAME].loc.cc api.[REDACTED-NAME].loc.cc;
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
||||
```
|
||||
|
||||
## Echo/legacy paths (block on old domain)
|
||||
|
||||
```nginx
|
||||
server {
|
||||
listen 443 ssl;
|
||||
server_name [REDACTED-NAME].loc.cc www.[REDACTED-NAME].loc.cc;
|
||||
# ... SSL ...
|
||||
location ^~ /echo/ {
|
||||
default_type application/json;
|
||||
return 404 '{"error":{"message":"Not found","type":"gateway_error","code":"not_found"}}';
|
||||
}
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:18080;
|
||||
# ... proxy ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Key decisions
|
||||
|
||||
- `gzip_comp_level 1` — minimal CPU cost, sufficient compression for JSON
|
||||
- `proxy_buffering off` — required for SSE streaming
|
||||
- `proxy_socket_keepalive on` — reduce TIME_WAIT on localhost
|
||||
- `http2 on;` (not `listen ... http2`) — nginx 1.28 deprecation
|
||||
- `proxy_intercept_errors on` — enables error_page for upstream errors
|
||||
- `proxy_set_header Connection ""` — prevents hop-by-hop forwarding
|
||||
Reference in New Issue
Block a user