Nginx Reverse Proxy కాన్ఫిగరేషన్ ఎలా చేయాలి?
Nginx reverse proxy సర్వర్ బ్లాక్ను లైన్ బై లైన్ ఎలా నిర్మించాలో తెలుసుకోండి. proxy_pass, అవసరమైన హెడర్లు, websockets మరియు ఫైల్ అప్లోడ్ సెట్టింగ్ల గురించి పూర్తి వివరణ.
Nginx reverse proxy కాన్ఫిగరేషన్ ఏమి చేస్తుంది
Nginx reverse proxy అనేది port 80 మరియు port 443 లపై వచ్చే అభ్యర్థనలను స్వీకరించి, స్థానిక port లో వింటున్న (listening) అప్లికేషన్కు పంపిస్తుంది, ఆపై ఆ అప్లికేషన్ ఇచ్చే సమాధానాన్ని బ్రౌజర్కు తిరిగి పంపుతుంది. దీని కాన్ఫిగరేషన్ ఒకే ఒక server బ్లాక్గా ఉంటుంది మరియు ఆ బ్లాక్ చాలా చిన్నదిగా ఉంటుంది. అసలైన క్లయింట్ ఎవరు మరియు వారు ఏ ప్రోటోకాల్ను ఉపయోగించారో అప్లికేషన్కు తెలియజేసే ఐదు లేదా ఆరు లైన్ల అమరికలోనే దాదాపు అన్ని క్లిష్టతలు ఉంటాయి.
కింద ఉన్నదంతా Ubuntu 24.04 లో, డిస్ట్రిబ్యూషన్ నుండి వచ్చిన nginx ప్యాకేజీని ఉపయోగించి మొదటి నుండి నిర్మించబడింది. ప్రారంభ బిందువుగా, ఇప్పటికే 127.0.0.1:3000 వద్ద సమాధానమిచ్చే ఒక అప్లికేషన్ ఉందని భావించబడింది. మీరు ఇంకా ఏ proxy ని ఎంచుకోవాలో నిర్ణయించుకోకపోతే, nginx, Caddy మరియు Traefik ల మధ్య పోలిక అనే ఈ వ్యాసాన్ని ముందుగా చదవండి. Nginx ఇచ్చే సమాధానం ఎలా ఉంటుందో, లైన్ వారీగా కింద వివరించబడింది.
ఈ కాన్ఫిగరేషన్లను మీ స్వంత సర్వర్పై అమలు చేయండి. మీరు reload చేసే ముందు ప్రతి మార్పును sudo nginx -t తో పరీక్షించండి మరియు అది చూపే ఫలితాన్ని చదవండి.
Ubuntuలో nginx కాన్ఫిగరేషన్ ఎక్కడ ఉంటుంది
sudo apt update
sudo apt install -y nginx
ls -l /etc/nginx/sites-enabled/ప్రధాన ఫైల్ /etc/nginx/nginx.conf. ఇది http { } బ్లాక్ లోపల గ్లోబల్ ఆప్షన్లను సెట్ చేస్తుంది, ఆపై రెండు డైరెక్టరీలను తీసుకుంటుంది: /etc/nginx/conf.d/*.conf మరియు /etc/nginx/sites-enabled/*. Ubuntu మరియు Debian లలో, మీరు ప్రతి సైట్కు ఒక ఫైల్ను /etc/nginx/sites-available/ లో రాస్తారు మరియు /etc/nginx/sites-enabled/ లోకి ఒక symlink ద్వారా దానిని ఆన్ చేస్తారు. Symlink ను తొలగించడం ద్వారా సైట్ను డిసేబుల్ చేయవచ్చు, కానీ ఫైల్ అలాగే ఉంటుంది.
తర్వాత ఉపయోగించే రెండు డైరెక్టివ్లు http కాంటెక్స్ట్లో మాత్రమే పనిచేస్తాయి, server బ్లాక్ లోపల ఎప్పటికీ పనిచేయవు: అవి map మరియు upstream. వీటిని /etc/nginx/conf.d/ కింద ఉన్న వాటి స్వంత ఫైల్లో ఉంచండి, ఎందుకంటే ఆ డైరెక్టరీ http స్థాయిలో ఇంక్లూడ్ చేయబడుతుంది.
ఈ ప్యాకేజీ default అనే ఎనేబుల్ చేయబడిన సైట్తో వస్తుంది. ఇది default_server గా మార్క్ చేయబడి ఉంటుంది, అంటే మీ కాన్ఫిగరేషన్లో ఎక్కడా server_name లేని ఏ అభ్యర్థనకైనా (request) ఇది సమాధానం ఇస్తుంది, దీని Host హెడర్ సరిపోలదు. ఇది ఎనేబుల్ అయి ఉన్నంత వరకు, మీ అప్లికేషన్కు బదులుగా మీ పేర్లతో సరిపోలని అభ్యర్థనలు దీనికే చేరుతాయి. మీ స్వంత సైట్ పనిచేయడం ప్రారంభించిన తర్వాత ఆ symlink ను తొలగించండి.
sudo rm /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginxఒక అప్లికేషన్ను proxy చేసే అతి చిన్న సర్వర్ బ్లాక్
server {
listen 80;
listen [::]:80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}దీనిని /etc/nginx/sites-available/app.example.comగా సేవ్ చేయండి, ఆపై దానిని enable చేసి లోడ్ చేయండి.
sudo ln -s /etc/nginx/sites-available/app.example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
curl -sI -H 'Host: app.example.com' http://127.0.0.1/listen 80; అనేది IPv4ను, listen [::]:80; అనేది IPv6ను bind చేస్తుంది. రెండవ లైన్ను వదిలేస్తే, మీ సర్వర్ కోసం DNS (domain name system) lookup ద్వారా AAAA రికార్డును పొందే సందర్శకులకు connection refused అని వస్తుంది, అదే సమయంలో IPv4లో ఉన్న అందరికీ సైట్ పనిచేస్తుంది. మీకు వచ్చే బగ్ రిపోర్ట్ "it works for me" అని ఉంటుంది.
server_name అనేది బ్రౌజర్ పంపే Host హెడర్తో సరిపోల్చబడుతుంది. ఖాళీలతో వేరు చేస్తూ అనేక పేర్లను పేర్కొనవచ్చు. ఏ బ్లాక్ సరిపోలకపోతే, nginx అనేది default_serverగా ఉన్న బ్లాక్ను ఉపయోగిస్తుంది, అందుకే ప్యాకేజ్ చేయబడిన సైట్ను తొలగించాల్సి వచ్చింది.
location / అనేది రిక్వెస్ట్ పాత్పై prefix match చేస్తుంది, మరియు / ప్రతి పాత్ను సరిపోల్చుతుంది. proxy_pass అనేది nginx కనెక్షన్ను తెరిచే చిరునామా. అప్లికేషన్ను 127.0.0.1కి bind చేసి ఉంచండి, తద్వారా nginx ద్వారా మాత్రమే లోపలికి వెళ్లే మార్గం ఉంటుంది. అప్లికేషన్ కంటైనర్లో నడుస్తుంటే, దానిని 127.0.0.1:3000:3000గా publish చేయండి, 3000:3000గా వద్దు, ఎందుకంటే Docker తన సొంత నియమాలను రాస్తుంది మరియు ufw ని దాటి నేరుగా పోర్ట్లను publish చేస్తుంది, కాబట్టి మీ ఫైర్వాల్ ఏమని చెప్పినా, నేరుగా publish చేసిన పోర్ట్ ఇంటర్నెట్ నుండి అందుబాటులో ఉంటుంది.
curl లైన్ సర్వర్ నుండే సరైన Host హెడర్ను పంపుతుంది, కాబట్టి DNS ఎక్కడికైనా పాయింట్ చేయకముందే మీరు ఈ బ్లాక్ను పరీక్షించవచ్చు.
మీరు మరేమీ పేర్కొననప్పుడు nginx అప్స్ట్రీమ్కు ఏమి పంపుతుంది
proxy_pass స్వయంగా మీ అప్లికేషన్ నుండి నాలుగు విషయాలను దాచిపెడుతుంది.
nginx డిఫాల్ట్గా బ్యాకెండ్తో HTTP/1.0 ప్రోటోకాల్లో మాట్లాడుతుంది మరియు Connection: closeని పంపుతుంది, కాబట్టి ప్రతి అభ్యర్థన ఒక కొత్త అప్స్ట్రీమ్ కనెక్షన్ను తెరుస్తుంది మరియు ప్రోటోకాల్ అప్గ్రేడ్ సాధ్యం కాదు.
Host హెడర్ proxy_pass విలువకు తిరిగి వ్రాయబడుతుంది, ఇది 127.0.0.1:3000. Host నుండి అబ్సల్యూట్ లింక్లను నిర్మించే యాప్, ఇప్పుడు సర్వర్ వెలుపల ఎవరూ తెరవలేని లింక్లను సృష్టిస్తుంది.
యాప్కు చేరే కనెక్షన్ nginx నుండి వస్తుంది, కాబట్టి యాప్ క్లయింట్ అడ్రస్ను 127.0.0.1గా చూస్తుంది. అప్పుడు యాప్లోని ప్రతి లాగ్ లైన్ మరియు ప్రతి రేట్ లిమిట్ సందర్శకుడికి బదులుగా ప్రాక్సీని నమోదు చేస్తాయి.
బ్రౌజర్ HTTPSని ఉపయోగించిందని యాప్ గుర్తించలేదు, ఎందుకంటే అది అందుకున్న కనెక్షన్ లూప్బ్యాక్ అడ్రస్పై ఉన్న సాధారణ HTTP మాత్రమే.
నాలుగు లైన్లు వీటన్నింటినీ సరిచేస్తాయి.
సెట్ చేయాల్సిన నాలుగు హెడర్లు మరియు ప్రతి ఒక్కటి బ్యాకెండ్కు ఏమి చూపిస్తుంది
location / {
proxy_pass http://127.0.0.1:3000;
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;
}Host సందర్శకుడు టైప్ చేసిన పేరును కలిగి ఉంటుంది. $host అనేది అభ్యర్థనలోని పేరు, ఇందులో పోర్ట్ తొలగించబడి అక్షరాలు చిన్నవిగా (lowercase) మార్చబడతాయి. దీన్ని సెట్ చేస్తే మీ అప్లికేషన్ సరైన absolute URLలను నిర్మిస్తుంది: లాగిన్ తర్వాత రీడైరెక్ట్ అవ్వడం లేదా పాస్వర్డ్ రీసెట్ ఇమెయిల్లోని లింక్ వంటివి. దీన్ని వదిలేస్తే ఆ URLలు 127.0.0.1:3000ని సూచిస్తాయి, కాబట్టి లాగిన్ అయినప్పుడు బ్రౌజర్ కనెక్షన్ను తిరస్కరించే అడ్రస్కు వెళ్తుంది. మీ అప్లికేషన్కు పోర్ట్ కూడా అవసరమైతే, మీరు దాన్ని 8080లో సర్వ్ చేస్తున్నట్లయితే, $http_hostని ఉపయోగించండి, ఇది క్లయింట్ పంపిన హెడర్ను ఖచ్చితంగా కలిగి ఉంటుంది.
X-Real-IP ఒక విలువను కలిగి ఉంటుంది: $remote_addr, ఇది nginx కనెక్షన్ను స్వీకరించిన అడ్రస్. అప్లికేషన్లు తమ స్వంత access logs మరియు rate limiting కోసం దీన్ని చదువుతాయి.
X-Forwarded-For ఒక జాబితాను కలిగి ఉంటుంది. $proxy_add_x_forwarded_for అనేది క్లయింట్ ఇప్పటికే ఆ హెడర్లో ఉంచిన దానికి $remote_addrని జోడిస్తుంది, కాబట్టి విలువ కామాతో వేరు చేయబడి ఉంటుంది మరియు మీ nginx జోడించిన ఎంట్రీ చివరిదిగా ఉంటుంది. ఈ వివరమే హెడర్ను నమ్మవచ్చా లేదా అని నిర్ణయిస్తుంది: ఒక క్లయింట్ తనకు నచ్చిన ఏదైనా X-Forwarded-Forని పంపవచ్చు, కాబట్టి మొదటి ఎంట్రీని చదివే అప్లికేషన్ను ఏదైనా అడ్రస్ అని నమ్మించవచ్చు. nginx ఎడ్జ్ సర్వర్గా ఉన్నప్పుడు, $remote_addrని ఉపయోగించండి మరియు క్లయింట్ వెర్షన్ను విస్మరించండి. ముందు భాగంలో CDN లేదా మరొక ప్రాక్సీ ఉన్నప్పుడు, realip మాడ్యూల్ నుండి set_real_ip_from మరియు real_ip_headerని ఉపయోగించండి, తద్వారా $remote_addr స్వయంగా నిజమైన క్లయింట్ అడ్రస్గా మారుతుంది.
X-Forwarded-Proto http లేదా httpsని కలిగి ఉంటుంది. కుక్కీలను Secureగా మార్చాలా మరియు HTTPSకి రీడైరెక్ట్ను బలవంతం చేయాలా అని నిర్ణయించడానికి ఫ్రేమ్వర్క్లు దీన్ని చదువుతాయి. TLS సైట్లో దీన్ని వదిలేస్తే, HTTPSని బలవంతం చేయడానికి కాన్ఫిగర్ చేయబడిన అప్లికేషన్ httpని చూస్తుంది, HTTPS అడ్రస్కు రీడైరెక్ట్తో సమాధానం ఇస్తుంది, nginx ద్వారా తదుపరి అభ్యర్థనను అందుకుంటుంది, ఇప్పటికీ httpని చూస్తుంది మరియు మళ్ళీ రీడైరెక్ట్ చేస్తుంది. బ్రౌజర్ విసిగిపోయి ERR_TOO_MANY_REDIRECTSని చూపిస్తుంది.
ప్రతి locationలో ఆ నాలుగు లైన్లను మళ్ళీ మళ్ళీ రాయడం వల్ల అవి ఒకదానికొకటి భిన్నంగా మారే అవకాశం ఉంది. వాటిని ఒకే ఫైల్లో ఉంచి include చేయండి.
# /etc/nginx/snippets/proxy-headers.conf
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;location / {
include snippets/proxy-headers.conf;
proxy_pass http://127.0.0.1:3000;
}ఇక్కడ inheritance (వారసత్వం) విషయంలో ఒక చిక్కు ఉంది. ఒక location తన సొంత proxy_set_header డైరెక్టివ్లు ఏవీ లేనప్పుడు మాత్రమే దాని server block నుండి వాటిని వారసత్వంగా పొందుతుంది. location లోపల ఒక proxy_set_headerని జోడిస్తే, server స్థాయిలో నిర్వచించిన అన్ని హెడర్లు ఆ location కోసం తొలగించబడతాయి. కాబట్టి వాటన్నింటినీ ఒకే స్థాయిలో ఉంచండి లేదా ప్రాక్సీ చేసే ప్రతి locationలో ఆ స్నిప్పెట్ను include చేయండి.
నా WebSocket అప్లికేషన్ కనెక్ట్ అయ్యి వెంటనే ఎందుకు డిస్కనెక్ట్ అవుతోంది?
డిఫాల్ట్ సెట్టింగ్లు అప్గ్రేడ్ను అనుమతించవు మరియు డిఫాల్ట్ read timeout 60 సెకన్ల తర్వాత ఖాళీగా ఉన్న టన్నెల్ను మూసివేస్తుంది కాబట్టి ఇలా జరుగుతుంది. ఒక WebSocket అనేది Upgrade: websocket మరియు Connection: Upgrade కలిగి ఉన్న HTTP అభ్యర్థనగా ప్రారంభమవుతుంది. ఇవి hop-by-hop హెడర్లు, అంటే వీటిని ప్రాక్సీ స్వీకరించి ప్రాసెస్ చేయాలి, అంతే కానీ నేరుగా పంపకూడదు. అలాగే HTTP/1.0 లో అప్గ్రేడ్ మెకానిజం ఉండదు. కాబట్టి ఈ రెండింటినీ మాన్యువల్గా తిరిగి సెట్ చేయాలి.
ఈ మ్యాప్ http కాంటెక్స్ట్లో, దాని స్వంత ఫైల్లో ఉండాలి.
# /etc/nginx/conf.d/websocket.conf
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}ఆ తర్వాత location సెట్టింగ్.
location / {
include snippets/proxy-headers.conf;
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 3600s;
proxy_send_timeout 3600s;
}ఒకే location రెండు రకాల ట్రాఫిక్ను నిర్వహించడానికి ఈ మ్యాప్ ఉపయోగపడుతుంది. సాధారణ అభ్యర్థనలో $http_upgrade ఖాళీగా ఉంటుంది, కాబట్టి $connection_upgrade అనేది close అవుతుంది. అప్గ్రేడ్ అభ్యర్థనలో ఇది websocket ని కలిగి ఉంటుంది, కాబట్టి అప్స్ట్రీమ్కు పంపబడే హెడర్ Connection: upgrade అవుతుంది. proxy_set_header Connection "upgrade"; ని హార్డ్-కోడ్ చేస్తే, అది ప్రతి సాధారణ పేజీ అభ్యర్థనకు కూడా ఆ హెడర్ను పంపుతుంది, దీనివల్ల కొన్ని బ్యాకెండ్లు 400 ఎర్రర్ను ఇస్తాయి.
proxy_read_timeout వల్లనే "లోడ్ అవుతోంది, కానీ అప్డేట్ అవ్వడం ఆగిపోయింది" అనే సమస్యలు వస్తాయి. దీని డిఫాల్ట్ విలువ 60 సెకన్లు. ఇది కనెక్షన్ మొత్తం జీవితకాలం కాకుండా, బ్యాకెండ్ నుండి రెండు రీడ్ల మధ్య ఉన్న సమయాన్ని లెక్కిస్తుంది. 60 సెకన్ల పాటు ఎటువంటి డేటా లేని WebSocket ను nginx మూసివేస్తుంది, అప్పుడు బ్రౌజర్ కన్సోల్లో 1006 కోడ్తో సాకెట్ క్లోజ్ అయినట్లు కనిపిస్తుంది. నిమిషానికి ఒకసారి కంటే ఎక్కువసార్లు heartbeat పంపే అప్లికేషన్లకు ఈ సమస్య రాదు. అలా చేయని అప్లికేషన్లు నిమిషం తర్వాత ఆగిపోతాయి. లైవ్ ఎడిటర్లు మరియు డాష్బోర్డ్లలో ఇది మొదట కనిపిస్తుంది, HTTPS వెనుక ఉన్న self-hosted n8n instance దీనికి ఒక సాధారణ ఉదాహరణ.
proxy_pass లో చివరన ఉండే slash (/) నా URLలను ఎందుకు మారుస్తుంది?
ఈ నియమం చాలా సరళమైనది. ఒకవేళ proxy_pass ఒక URIతో ముగిస్తే (అది కేవలం ఒక / అయినా సరే), nginx అభ్యర్థనలోని path లో location prefix కి సరిపోయిన భాగాన్ని తొలగించి, ఆ స్థానంలో ఈ కొత్త URIని ఉంచుతుంది. ఒకవేళ proxy_pass కేవలం host మరియు port వద్దే ఆగిపోతే, అభ్యర్థనలోని path ఎటువంటి మార్పు లేకుండా అలాగే పంపబడుతుంది.
location /app/ {
proxy_pass http://127.0.0.1:3000/;
}/app/status కోసం వచ్చే అభ్యర్థన backend కి /status గా చేరుతుంది.
location /app/ {
proxy_pass http://127.0.0.1:3000;
}/app/status కోసం వచ్చే అభ్యర్థన backend కి /app/status గా చేరుతుంది.
మీకు ఏ పద్ధతి అవసరమనేది మీరు వాడుతున్న అప్లికేషన్ పై ఆధారపడి ఉంటుంది. base-path లేదా sub-folder సెట్టింగ్ ఉన్న అప్లికేషన్లకు రెండో పద్ధతి అవసరం, అప్పుడు ఆ సెట్టింగ్లో /app గురించి పేర్కొనాలి. prefix ల గురించి ఏమీ తెలియని అప్లికేషన్లకు మొదటి పద్ధతి అవసరం. మొదటి పద్ధతిలో ఒక సమస్య వెంటనే కనిపిస్తుంది: అప్లికేషన్ ఇచ్చే HTML లో /static/main.css వంటి absolute paths ఉంటాయి. బ్రౌజర్ వాటి కోసం site root ని అడుగుతుంది, అక్కడ ఏ location మ్యాచ్ అవ్వదు, ఫలితంగా styling లేని పేజీ కనిపిస్తుంది. బ్రౌజర్ లోని network tab లో ఆ asset అభ్యర్థనలు 404 error ని చూపిస్తాయి. దీనికి పరిష్కారం అప్లికేషన్ లోని base-path సెట్టింగ్ మార్చడం లేదా అదే backend కి పాయింట్ అయ్యేలా రెండో location /static/ ని జోడించడం.
Regex location లో proxy_pass తో పాటు URIని ఉంచడం సాధ్యం కాదు. అలా చేస్తే sudo nginx -t ఆ కాన్ఫిగరేషన్ను తిరస్కరించి, దానికి కారణాన్ని "proxy_pass" cannot have URI part in location given by regular expression, or inside named location, or inside "if" statement, or inside "limit_except" block అని చూపిస్తుంది.
ప్రతి అప్లికేషన్కు ఒక ప్రత్యేక పేరు, అంటే app.example.com ఉండి, దానిని location / నుండి proxy చేసినప్పుడు ఈ తరహా సమస్యలన్నీ తొలగిపోతాయి. DNS రికార్డులను జోడించడం సాధ్యం కానప్పుడు మాత్రమే sub-paths వాడటం మంచిది.
ఒకే పేరు వెనుక ఒకటి కంటే ఎక్కువ backendలను ఎలా ఉంచాలి?
దీని కోసం upstream బ్లాక్ను ఉపయోగించాలి. ఇది http కాంటెక్స్ట్కు చెందుతుంది, కాబట్టి దీన్ని అదే ఫైల్లో server బ్లాక్కు పైన రాయండి, లేదా /etc/nginx/conf.d/ లో ఉంచండి.
upstream app_backend {
least_conn;
server 127.0.0.1:3000 max_fails=3 fail_timeout=30s;
server 127.0.0.1:3001 max_fails=3 fail_timeout=30s;
keepalive 32;
}ఆ తర్వాత location దీనిని ఇలా సూచిస్తుంది: proxy_pass http://app_backend;.
డిఫాల్ట్ పద్ధతి round robin. least_conn ప్రతి అభ్యర్థనను తక్కువ active connections ఉన్న backendకు పంపుతుంది, ఇది అసమాన నిడివి గల అభ్యర్థనలకు బాగా సరిపోతుంది. ip_hash ఒక క్లయింట్ అడ్రస్ను ఒక నిర్దిష్ట backendకు అనుసంధానిస్తుంది. అప్లికేషన్ తన సొంత మెమరీలో సెషన్లను ఉంచుకున్నప్పుడు మీకు ip_hash అవసరం, ఎందుకంటే అటువంటి రెండు backendల మధ్య round robin వాడితే, అభ్యర్థనలు సెషన్ లేని instanceకు వెళ్ళినప్పుడు వినియోగదారులు అకస్మాత్తుగా లాగ్ అవుట్ అవుతారు. సెషన్లను shared storage లోకి మార్చడం దీనికి మెరుగైన పరిష్కారం.
max_fails=3 fail_timeout=30s అంటే 30 సెకన్లలో మూడుసార్లు విఫలమైతే, ఆ సర్వర్ను 30 సెకన్ల పాటు తొలగిస్తుంది. బ్లాక్లోని అన్ని సర్వర్లు ఆ స్థితిలో ఉన్నప్పుడు, క్లయింట్లకు 502 error వస్తుంది మరియు error log లో no live upstreams while connecting to upstream అని కనిపిస్తుంది.
keepalive 32 ప్రతి worker process కు 32 idle connections వరకు backendల వద్ద తెరిచి ఉంచుతుంది, ఇది చాలా అభ్యర్థనల నుండి TCP handshake అవసరాన్ని తొలగిస్తుంది. ఇది కేవలం proxy_http_version 1.1 తో మాత్రమే పనిచేస్తుంది మరియు upstream కు Connection: close లేనప్పుడు మాత్రమే పనిచేస్తుంది. ఒకవేళ అదే location లో WebSocket map కూడా వాడుతుంటే, empty case ను close నుండి ఖాళీ స్ట్రింగ్కు మార్చండి, తద్వారా సాధారణ అభ్యర్థనలు ఎటువంటి Connection హెడర్ను కలిగి ఉండవు మరియు pooled connection తిరిగి ఉపయోగించబడుతుంది.
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}upstream బ్లాక్లోని పేర్లు nginx ప్రారంభమైనప్పుడు resolve చేయబడతాయి. మీ backend ఒక container అయితే మరియు అది restart అయినప్పుడు కొత్త అడ్రస్ పొందితే, మీరు reload చేసే వరకు nginx పాత అడ్రస్నే వాడుతుంది. Docker network లోపల మీరు embedded resolver తో lookup ను request time కు మార్చవచ్చు.
resolver 127.0.0.11 valid=10s;
set $backend http://app:3000;
proxy_pass $backend;containers తరచుగా మారుతూ ఉండి, వాటిని ట్రాక్ చేయడానికి మీరు nginx ను ఎప్పటికప్పుడు ఎడిట్ చేయాల్సి వస్తుంటే, container labels ను చదవగలిగే proxy మెరుగైన సాధనం. అనేక Docker Compose అప్లికేషన్ల ముందు Traefik తన routes ను ఆ containers నుండే నిర్మించుకుంటుంది.
అప్లోడ్లు 413 Request Entity Too Large ఎర్రర్తో ఎందుకు విఫలమవుతాయి?
client_max_body_size డిఫాల్ట్గా 1 మెగాబైట్కు సెట్ చేయబడి ఉంటుంది. మీ అప్లికేషన్ అభ్యర్థనను చూడకముందే, అంతకంటే పెద్ద రిక్వెస్ట్ బాడీని nginx తిరస్కరిస్తుంది మరియు ఎర్రర్ లాగ్లో client intended to send too large body అని నమోదవుతుంది. సర్వర్ బ్లాక్లో లేదా అప్లోడ్లు జరిగే లొకేషన్లో దీని పరిమితిని పెంచండి.
client_max_body_size 512m;0 విలువను సెట్ చేయడం ద్వారా ఈ తనిఖీని పూర్తిగా నిలిపివేయవచ్చు. అప్లికేషన్కు కూడా సొంత పరిమితి ఉంటుంది, కాబట్టి ఈ మార్పు తర్వాత కూడా 413 ఎర్రర్ వస్తుంటే, అది బ్యాకెండ్ నుండి వస్తున్నట్లు అర్థం. అప్పుడు అప్లికేషన్ యొక్క సొంత అప్లోడ్ సెట్టింగ్లను తనిఖీ చేయాలి.
డిఫాల్ట్గా, అప్స్ట్రీమ్ కనెక్షన్ను తెరవకముందే nginx మొత్తం రిక్వెస్ట్ బాడీని చదువుతుంది మరియు పెద్ద ఫైళ్లను డిస్క్లోని తాత్కాలిక ఫైల్లోకి రాస్తుంది. ఇది నెమ్మదిగా ఉండే క్లయింట్ల నుండి అప్లికేషన్ను రక్షిస్తుంది, ఎందుకంటే బ్యాకెండ్ అప్లోడ్ను పూర్తి లోకల్ వేగంతో అందుకుంటుంది. చాలా పెద్ద అప్లోడ్ల కోసం మీరు స్ట్రీమింగ్ పద్ధతిని ఉపయోగించవచ్చు.
proxy_request_buffering off;అప్పుడు బ్యాకెండ్ బాడీని అది అందుతున్న కొద్దీ స్వీకరిస్తుంది, కాబట్టి బ్యాకెండ్ దాన్ని హ్యాండిల్ చేయగలగాలి. బాడీ ఇప్పటికే పంపబడింది కాబట్టి, మరొక అప్స్ట్రీమ్కు రిక్వెస్ట్ను మళ్ళీ పంపే (retry) సామర్థ్యాన్ని nginx కోల్పోతుంది.
client_body_timeout, ఇది డిఫాల్ట్గా 60 సెకన్లు ఉంటుంది, ఇది మొత్తం అప్లోడ్ సమయానికి కాకుండా, బాడీని చదివే రెండు వరుస రీడ్ల మధ్య సమయానికి వర్తిస్తుంది. నెమ్మదిగా ఉన్నప్పటికీ స్థిరంగా జరిగే అప్లోడ్ దీనివల్ల ఆగిపోదు. కానీ అప్లోడ్ ఆగిపోతే (stalled), కనెక్షన్ తొలగించబడుతుంది.
ప్రతిస్పందన బఫరింగ్ (Response buffering), మరియు లైవ్ అవుట్పుట్ను నిలిపివేసే సెట్టింగ్
proxy_buffering డిఫాల్ట్గా ఆన్లో ఉంటుంది మరియు సాధారణంగా ఇది మీకు అవసరమైన సెట్టింగ్. మీ అప్లికేషన్ ఎంత వేగంగా డేటాను పంపగలదో, Nginx అంత వేగంగా ప్రతిస్పందనను చదివి, దానిని నిల్వ ఉంచుతుంది. ఆ తర్వాత నెమ్మదిగా ఉన్న క్లయింట్కు వారి వేగానికి అనుగుణంగా డేటాను అందిస్తుంది. దీనివల్ల, నెమ్మదిగా జరిగే డౌన్లోడ్ కోసం అప్లికేషన్ వర్కర్ వేచి ఉండాల్సిన అవసరం లేకుండా, త్వరగా తన పనిని పూర్తి చేస్తుంది.
ఇది స్ట్రీమింగ్ ప్రతిస్పందనలను (streaming responses) నిలిపివేస్తుంది. సర్వర్-పంపిన ఈవెంట్లు (Server-sent events) మరియు లైవ్ లాగ్ అవుట్పుట్, బఫర్ నిండే వరకు రీడర్కు ఏమీ చూపించవు. అటువంటి సందర్భాల్లో, ఆ లొకేషన్లో మాత్రమే బఫరింగ్ను ఆఫ్ చేయండి.
proxy_buffering off;మీరు అప్లికేషన్ను నియంత్రిస్తున్నట్లయితే, స్ట్రీమింగ్ ప్రతిస్పందనలకు మాత్రమే X-Accel-Buffering: no హెడర్ను పంపడం మంచి పద్ధతి. Nginx ప్రతి ప్రతిస్పందన కోసం ఆ హెడర్ను చదివి, కేవలం దానికి మాత్రమే బఫరింగ్ను నిలిపివేస్తుంది. తద్వారా సాధారణ పేజీలు బఫరింగ్ ప్రయోజనాలను పొందుతూనే ఉంటాయి.
ఎర్రర్ లాగ్లో upstream sent too big header while reading response header from upstream అని కనిపిస్తే, ప్రతిస్పందన హెడర్లు ఒకే బఫర్లో సరిపోలేదని అర్థం. proxy_buffer_size డిఫాల్ట్గా ఒక మెమరీ పేజీ పరిమాణంలో ఉంటుంది (ప్లాట్ఫారమ్ను బట్టి 4 లేదా 8 కిలోబైట్లు). పొడవైన కుక్కీలు లేదా పెద్ద అథెంటికేషన్ హెడర్లు ఉన్నప్పుడు ఇది నిండిపోతుంది. అప్పుడు ఈ రెండు విలువలను పెంచండి.
proxy_buffer_size 16k;
proxy_buffers 8 16k;ఈ కాన్ఫిగరేషన్లో TLS ఎక్కడ ఉండాలి?
Nginx వద్ద, పైన పేర్కొన్న అన్నింటికీ ముందుగా ఉండాలి. TLS (transport layer security) ప్రాక్సీ వద్ద ముగుస్తుంది (terminates). Nginx నుండి అప్లికేషన్కు ఉండే కనెక్షన్ loopback అడ్రస్ ద్వారా సాధారణ HTTP గానే ఉంటుంది, దీనిని నెట్వర్క్లో మరెవరూ చదవలేరు. సందర్శకుడు HTTPS ఉపయోగించాడని అప్లికేషన్ X-Forwarded-Proto ద్వారా తెలుసుకుంటుంది, ఇది నాలుగు హెడర్లలో నాలుగవది.
సర్టిఫికేట్ పాత్లను మాన్యువల్గా రాయవద్దు. DNS రికార్డును సర్వర్కు పాయింట్ చేయండి, ఫైర్వాల్ను ఓపెన్ చేయండి, మరియు ఈ సర్వర్ బ్లాక్ను Certbot ద్వారా ఎడిట్ చేయనివ్వండి: ఇది ssl_certificate పాత్లతో కూడిన listen 443 ssl లైన్ను, అలాగే పోర్ట్ 80 నుండి రీడైరెక్ట్ను జోడిస్తుంది. Certbot తో nginx కోసం Let's Encrypt సర్టిఫికేట్ను జారీ చేయడం అనే విభాగం జారీ ప్రక్రియ మరియు రెన్యూవల్ టైమర్ గురించి వివరిస్తుంది.
sudo ufw allow 'Nginx Full'
sudo ufw statusNginx Full అనేది nginx ప్యాకేజీ ఇన్స్టాల్ చేసే ఒక అప్లికేషన్ ప్రొఫైల్, ఇది పోర్ట్ 80 మరియు పోర్ట్ 443 రెండింటినీ ఒకేసారి ఓపెన్ చేస్తుంది. సందర్శకులందరినీ HTTPS కి రీడైరెక్ట్ చేసిన తర్వాత కూడా, HTTP-01 రెన్యూవల్ ఛాలెంజ్ కోసం పోర్ట్ 80 ఓపెన్గానే ఉండాలి.
కాన్ఫిగరేషన్ను పరీక్షించి, ఆపై రీలోడ్ చేయండి
sudo nginx -t
sudo systemctl reload nginxnginx -t ప్రతి ఇంక్లూడ్ చేసిన ఫైల్ను పార్స్ చేస్తుంది మరియు పరీక్ష విజయవంతమైందో లేదో తెలియజేస్తుంది, లేదా అది ఎక్కడ ఆగిపోయిందో ఆ ఫైల్ మరియు లైన్ నంబర్ను ప్రింట్ చేస్తుంది. మీరు రీలోడ్ చేసే ముందు ఆ అవుట్పుట్ను చదవండి. లోపభూయిష్టమైన కాన్ఫిగరేషన్తో రీలోడ్ చేస్తే అది వర్తించదు: nginx పాత కాన్ఫిగరేషన్తోనే సేవలను కొనసాగిస్తుంది, కాబట్టి మీరు చేసిన మార్పు ఏ ప్రభావం చూపకపోయినా సైట్ అందుబాటులోనే ఉంటుంది. systemctl restart భిన్నంగా మరియు మరింత ప్రమాదకరంగా ప్రవర్తిస్తుంది, ఎందుకంటే రీస్టార్ట్ చేసేటప్పుడు నడుస్తున్న సర్వర్ను ముందుగా ఆపివేస్తుంది, కాబట్టి కాన్ఫిగరేషన్ లోపం ఉంటే nginx అస్సలు రన్ అవ్వదు. డిఫాల్ట్గా రీలోడ్ చేయండి, మరియు రీస్టార్ట్ అవసరమయ్యే అరుదైన మార్పుల కోసం మాత్రమే దానిని ఉపయోగించండి.
sudo tail -f /var/log/nginx/error.log
sudo ss -lntp | grep -E ':(80|443|3000)'ss లైన్ ఏ ప్రాసెస్ ఏ పోర్ట్ను కలిగి ఉందో చూపిస్తుంది, కాబట్టి proxy_pass దేనిని సూచిస్తుందో అక్కడ అప్లికేషన్ నిజంగా వింటోందో లేదో మీరు నిర్ధారించుకోవచ్చు.
మీరు ఎదుర్కొనే వాస్తవ వైఫల్యాలు
502 Bad Gateway, error log లో connect() failed (111: Connection refused) while connecting to upstream తో. proxy_pass లో ఉన్న చిరునామా వద్ద ఏదీ వినడం లేదు (listening). అప్లికేషన్ ఆగిపోయి ఉండవచ్చు, వేరే పోర్ట్కు బైండ్ అయి ఉండవచ్చు, లేదా హోస్ట్ చేరుకోలేని కంటైనర్-అంతర్గత చిరునామాకు బైండ్ అయి ఉండవచ్చు.
no live upstreams while connecting to upstream తో 502 ఎర్రర్. upstream బ్లాక్లోని ప్రతి సర్వర్ ప్రస్తుతం max_fails ద్వారా విఫలమైనట్లుగా గుర్తించబడింది. బ్యాకెండ్లను సరిచేయండి. fail_timeout గడువు ముగిసిన తర్వాత Nginx వాటిని మళ్ళీ ప్రయత్నిస్తుంది.
504 Gateway Time-out, upstream timed out (110: Connection timed out) while reading response header from upstream తో. బ్యాకెండ్ కనెక్షన్ను అంగీకరించింది, కానీ proxy_read_timeout సెకన్ల పాటు ఏ సమాచారాన్ని పంపలేదు. నిజంగా నెమ్మదిగా ఉండే రిపోర్ట్ కోసం టైమ్అవుట్ను పెంచడం సరైనదే, కానీ అప్లికేషన్ నిలిచిపోయినప్పుడు (stuck) ఇది తప్పు.
ప్రతి పాత్ (path) అప్లికేషన్ నుండి 404ని ఇస్తోంది. ట్రైలింగ్ స్లాష్ (trailing slash) నియమం పాత్ను తిరిగి రాసింది. అప్లికేషన్ లాగ్ చేసే పాత్ను, మీరు అభ్యర్థించిన పాత్తో పోల్చి చూడండి.
వేరే సైట్ సమాధానం ఇస్తోంది. server_name అనేది Host హెడర్తో సరిపోలడం లేదు, కాబట్టి అభ్యర్థన default_server బ్లాక్కు వెళ్ళింది.
పేజీ లోడ్ అవుతుంది, కానీ ఒక నిమిషం తర్వాత ఇంటర్ఫేస్ ఫ్రీజ్ అవుతుంది. ఇది WebSocket కి సంబంధించిన సమస్య: Upgrade హ్యాండ్లింగ్ లేదు, లేదా proxy_read_timeout ఇంకా 60 సెకన్ల వద్దే ఉంది.
FAQ
proxy_pass జోడించిన తర్వాత nginx ఎందుకు 502 Bad Gateway అని చూపిస్తుంది?
proxy_pass లో పేర్కొన్న చిరునామాకు కనెక్షన్ను తెరవడంలో nginx విఫలమైంది. /var/log/nginx/error.log వద్ద ఉన్న error log కారణాన్ని తెలియజేస్తుంది: connect() failed (111: Connection refused) while connecting to upstream అంటే అక్కడ ఏ సేవ వినడం లేదని అర్థం, మరియు no live upstreams అంటే upstream బ్లాక్లోని ప్రతి సర్వర్ విఫలమైనట్లు గుర్తించబడిందని అర్థం. ఏ ప్రాసెస్ ఆ పోర్ట్ను కలిగి ఉందో మరియు అది ఏ చిరునామాకు బంధించబడిందో చూడటానికి sudo ss -lntp | grep 3000 కమాండ్ను రన్ చేయండి. కంటైనర్-అంతర్గత చిరునామాకు లేదా మీరు రాసిన పోర్ట్ కాకుండా వేరే పోర్ట్కు బంధించబడిన అప్లికేషన్ ప్రతిసారీ ఈ లోపాన్ని ఇస్తుంది.
nginx వెనుక ఉన్న నా అప్లికేషన్ సుమారు ఒక నిమిషం తర్వాత ఎందుకు డిస్కనెక్ట్ అవుతుంది?
ఆ కనెక్షన్ ఒక WebSocket మరియు proxy_read_timeout దాని డిఫాల్ట్ విలువ 60 సెకన్ల వద్ద ఉంది, ఇది బ్యాకెండ్ నుండి రెండు రీడ్ల మధ్య సమయాన్ని లెక్కిస్తుంది. నిశ్శబ్దంగా ఉన్న సాకెట్ను nginx మూసివేస్తుంది మరియు బ్రౌజర్ కన్సోల్ 1006 క్లోజ్ కోడ్ను చూపుతుంది. proxy_http_version 1.1 ని సెట్ చేయండి, map ద్వారా $http_upgrade పై Upgrade మరియు Connection లను పంపండి, మరియు proxy_read_timeout విలువను 3600s వంటి దానికి పెంచండి. Upgrade హెడర్ లేకపోతే అప్గ్రేడ్ జరగదు, దీనివల్ల అప్లికేషన్ పోలింగ్కు మారుతుంది లేదా లైవ్ అప్డేట్లను చూపదు.
proxy_pass లో చివరన ఉండే స్లాష్ (/) ముఖ్యమా?
అవును, ఇది మీ బ్యాకెండ్కు అందే పాత్ను మారుస్తుంది. location /app/ మరియు proxy_pass http://127.0.0.1:3000/ ఉన్నప్పుడు, /app/status కోసం వచ్చే అభ్యర్థన బ్యాకెండ్కు /status గా చేరుతుంది, ఎందుకంటే హోస్ట్ మరియు పోర్ట్ తర్వాత ఉన్న ఏదైనా URI, మ్యాచ్ అయిన లొకేషన్ ప్రిఫిక్స్ను భర్తీ చేస్తుంది. ఆ చివరి స్లాష్ను తొలగిస్తే, అదే అభ్యర్థన /app/status గా చేరుతుంది. ప్రిఫిక్స్ను తొలగించడం వల్ల అప్లికేషన్ యొక్క అసెట్ లింకులు విచ్ఛిన్నం కావచ్చు, అవి అబ్సల్యూట్గా ఉండి సైట్ రూట్ వద్ద 404 లోపాన్ని ఇస్తాయి. కాబట్టి, బేస్-పాత్ సెట్టింగ్ ఉన్న అప్లికేషన్కు పాత్ను అలాగే పంపే పద్ధతి ఉత్తమం.
నా అప్లికేషన్ ప్రతి సందర్శకుడి IP చిరునామాను 127.0.0.1 అని ఎందుకు లాగ్ చేస్తుంది?
ఎందుకంటే అప్లికేషన్ అందుకునే కనెక్షన్ నిజానికి లూప్బ్యాక్ చిరునామా నుండి nginx ద్వారా వస్తుంది. సందర్శకుడి చిరునామా మీరు సెట్ చేసిన హెడర్ ద్వారా మాత్రమే అప్లికేషన్కు చేరుతుంది: ఒకే విలువ కోసం proxy_set_header X-Real-IP $remote_addr;, మరియు జోడించిన చైన్ కోసం proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;. ఆ హెడర్లను నమ్మేలా అప్లికేషన్ను కాన్ఫిగర్ చేయాలి. క్లయింట్ తన సొంత X-Forwarded-For ని పంపగలదని గుర్తుంచుకోండి, కాబట్టి nginx ఎడ్జ్ సర్వర్గా ఉన్నప్పుడు, దాన్ని అపెండ్ చేయడానికి బదులుగా $remote_addr తో ఓవర్రైట్ చేయండి.
nginx మరియు నా అప్లికేషన్ మధ్య కనెక్షన్కు TLS అవసరమా?
అప్లికేషన్ ఒకే సర్వర్పై నడుస్తూ 127.0.0.1 కి బంధించబడినప్పుడు అవసరం లేదు, ఎందుకంటే ఆ ట్రాఫిక్ మెషీన్ బయటకు వెళ్లదు. TLS ను nginx వద్ద ముగించండి, proxy_pass ని లూప్బ్యాక్ ద్వారా సాధారణ HTTP లో ఉంచండి, మరియు సందర్శకుడు HTTPS ఉపయోగించాడని అప్లికేషన్కు తెలియజేయడానికి X-Forwarded-Proto $scheme ని పంపండి. ఒకవేళ బ్యాకెండ్ మీరు నియంత్రించని నెట్వర్క్ ద్వారా వేరే హోస్ట్లో ఉంటే, ఆ కనెక్షన్కు రక్షణ అవసరం, అంటే బ్యాకెండ్కు HTTPS లేదా రెండు మెషీన్ల మధ్య ప్రైవేట్ టన్నెల్ ఉండాలి.