[{"data":1,"prerenderedAt":1725},["ShallowReactive",2],{"\u002Freference\u002Fnginx-reverse-proxy-for-flask-explained":3},{"id":4,"title":5,"body":6,"description":1715,"extension":1716,"meta":1717,"navigation":91,"path":1721,"seo":1722,"stem":1723,"__hash__":1724},"content\u002Freference\u002Fnginx-reverse-proxy-for-flask-explained.md","Nginx Reverse Proxy for Flask Explained",{"type":7,"value":8,"toc":1691},"minimark",[9,13,17,22,30,249,252,263,266,275,282,286,289,293,857,862,922,926,952,956,1111,1115,1118,1122,1134,1137,1149,1153,1170,1172,1183,1187,1203,1205,1216,1220,1223,1240,1243,1270,1272,1280,1284,1296,1298,1303,1307,1321,1323,1331,1335,1369,1371,1391,1395,1434,1436,1447,1451,1475,1478,1492,1509,1513,1573,1577,1599,1603,1611,1619,1630,1641,1656,1664,1672,1680,1684,1687],[10,11,5],"h1",{"id":12},"nginx-reverse-proxy-for-flask-explained",[14,15,16],"p",{},"If you're trying to understand how Nginx sits in front of Flask or need a working reverse proxy setup, this guide shows you how to configure it step-by-step. The outcome is a Flask app served through Gunicorn with Nginx handling client traffic, headers, and static delivery.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24,25,29],{},"Use this minimal Nginx server block if Gunicorn is already listening on ",[26,27,28],"code",{},"127.0.0.1:8000",":",[31,32,37],"pre",{"className":33,"code":34,"language":35,"meta":36,"style":36},"language-bash shiki shiki-themes github-light github-dark","sudo tee \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp >\u002Fdev\u002Fnull \u003C\u003C'EOF'\nserver {\n    listen 80;\n    server_name example.com www.example.com;\n\n    location \u002Fstatic\u002F {\n        alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n    }\n\n    location \u002F {\n        include proxy_params;\n        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n        proxy_redirect off;\n    }\n}\nEOF\n\nsudo ln -sf \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fflaskapp\nsudo nginx -t\nsudo systemctl reload nginx\n\n# Test Gunicorn first\ncurl -I http:\u002F\u002F127.0.0.1:8000\n\n# Test through Nginx\ncurl -I http:\u002F\u002Fexample.com\n","bash","",[26,38,39,68,74,80,86,93,99,105,111,116,122,128,134,140,145,151,157,162,179,190,204,209,216,228,233,239],{"__ignoreMap":36},[40,41,44,48,52,55,59,62,65],"span",{"class":42,"line":43},"line",1,[40,45,47],{"class":46},"sScJk","sudo",[40,49,51],{"class":50},"sZZnC"," tee",[40,53,54],{"class":50}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp",[40,56,58],{"class":57},"szBVR"," >",[40,60,61],{"class":50},"\u002Fdev\u002Fnull",[40,63,64],{"class":57}," \u003C\u003C",[40,66,67],{"class":50},"'EOF'\n",[40,69,71],{"class":42,"line":70},2,[40,72,73],{"class":50},"server {\n",[40,75,77],{"class":42,"line":76},3,[40,78,79],{"class":50},"    listen 80;\n",[40,81,83],{"class":42,"line":82},4,[40,84,85],{"class":50},"    server_name example.com www.example.com;\n",[40,87,89],{"class":42,"line":88},5,[40,90,92],{"emptyLinePlaceholder":91},true,"\n",[40,94,96],{"class":42,"line":95},6,[40,97,98],{"class":50},"    location \u002Fstatic\u002F {\n",[40,100,102],{"class":42,"line":101},7,[40,103,104],{"class":50},"        alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n",[40,106,108],{"class":42,"line":107},8,[40,109,110],{"class":50},"    }\n",[40,112,114],{"class":42,"line":113},9,[40,115,92],{"emptyLinePlaceholder":91},[40,117,119],{"class":42,"line":118},10,[40,120,121],{"class":50},"    location \u002F {\n",[40,123,125],{"class":42,"line":124},11,[40,126,127],{"class":50},"        include proxy_params;\n",[40,129,131],{"class":42,"line":130},12,[40,132,133],{"class":50},"        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n",[40,135,137],{"class":42,"line":136},13,[40,138,139],{"class":50},"        proxy_redirect off;\n",[40,141,143],{"class":42,"line":142},14,[40,144,110],{"class":50},[40,146,148],{"class":42,"line":147},15,[40,149,150],{"class":50},"}\n",[40,152,154],{"class":42,"line":153},16,[40,155,156],{"class":50},"EOF\n",[40,158,160],{"class":42,"line":159},17,[40,161,92],{"emptyLinePlaceholder":91},[40,163,165,167,170,174,176],{"class":42,"line":164},18,[40,166,47],{"class":46},[40,168,169],{"class":50}," ln",[40,171,173],{"class":172},"sj4cs"," -sf",[40,175,54],{"class":50},[40,177,178],{"class":50}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fflaskapp\n",[40,180,182,184,187],{"class":42,"line":181},19,[40,183,47],{"class":46},[40,185,186],{"class":50}," nginx",[40,188,189],{"class":172}," -t\n",[40,191,193,195,198,201],{"class":42,"line":192},20,[40,194,47],{"class":46},[40,196,197],{"class":50}," systemctl",[40,199,200],{"class":50}," reload",[40,202,203],{"class":50}," nginx\n",[40,205,207],{"class":42,"line":206},21,[40,208,92],{"emptyLinePlaceholder":91},[40,210,212],{"class":42,"line":211},22,[40,213,215],{"class":214},"sJ8bj","# Test Gunicorn first\n",[40,217,219,222,225],{"class":42,"line":218},23,[40,220,221],{"class":46},"curl",[40,223,224],{"class":172}," -I",[40,226,227],{"class":50}," http:\u002F\u002F127.0.0.1:8000\n",[40,229,231],{"class":42,"line":230},24,[40,232,92],{"emptyLinePlaceholder":91},[40,234,236],{"class":42,"line":235},25,[40,237,238],{"class":214},"# Test through Nginx\n",[40,240,242,244,246],{"class":42,"line":241},26,[40,243,221],{"class":46},[40,245,224],{"class":172},[40,247,248],{"class":50}," http:\u002F\u002Fexample.com\n",[14,250,251],{},"If Gunicorn uses a Unix socket, replace:",[31,253,257],{"className":254,"code":255,"language":256,"meta":36,"style":36},"language-nginx shiki shiki-themes github-light github-dark","proxy_pass http:\u002F\u002F127.0.0.1:8000;\n","nginx",[26,258,259],{"__ignoreMap":36},[40,260,261],{"class":42,"line":43},[40,262,255],{},[14,264,265],{},"with:",[31,267,269],{"className":254,"code":268,"language":256,"meta":36,"style":36},"proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fgunicorn.sock;\n",[26,270,271],{"__ignoreMap":36},[40,272,273],{"class":42,"line":43},[40,274,268],{},[14,276,277,278,281],{},"This assumes static files exist at ",[26,279,280],{},"\u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F",".",[18,283,285],{"id":284},"whats-happening","What’s Happening",[14,287,288],{},"Nginx accepts incoming client requests and acts as the public web server. It forwards dynamic requests to Gunicorn, which runs the Flask WSGI app, and it can serve static files directly without involving Flask. Most failures happen when the upstream target, socket permissions, headers, or static file paths do not match the running app.",[18,290,292],{"id":291},"step-by-step-guide","Step-by-Step Guide",[294,295,296,352,387,476,519,540,560,581,694,718,768,796],"ol",{},[297,298,299,303,306,307,309,310,329,331,332],"li",{},[300,301,302],"strong",{},"Start or verify Gunicorn first",[304,305],"br",{},"Confirm your Flask app is running behind Gunicorn before configuring Nginx.",[304,308],{},"Example:",[31,311,313],{"className":33,"code":312,"language":35,"meta":36,"style":36},"gunicorn --bind 127.0.0.1:8000 wsgi:app\n",[26,314,315],{"__ignoreMap":36},[40,316,317,320,323,326],{"class":42,"line":43},[40,318,319],{"class":46},"gunicorn",[40,321,322],{"class":172}," --bind",[40,324,325],{"class":50}," 127.0.0.1:8000",[40,327,328],{"class":50}," wsgi:app\n",[304,330],{},"If using systemd, verify the service:",[31,333,335],{"className":33,"code":334,"language":35,"meta":36,"style":36},"sudo systemctl status gunicorn --no-pager\n",[26,336,337],{"__ignoreMap":36},[40,338,339,341,343,346,349],{"class":42,"line":43},[40,340,47],{"class":46},[40,342,197],{"class":50},[40,344,345],{"class":50}," status",[40,347,348],{"class":50}," gunicorn",[40,350,351],{"class":172}," --no-pager\n",[297,353,354,357,359,360,373,375,376,379,380,379,383,386],{},[300,355,356],{},"Test Gunicorn directly on the local machine",[304,358],{},"Do not add Nginx until the upstream works.",[31,361,363],{"className":33,"code":362,"language":35,"meta":36,"style":36},"curl -I http:\u002F\u002F127.0.0.1:8000\n",[26,364,365],{"__ignoreMap":36},[40,366,367,369,371],{"class":42,"line":43},[40,368,221],{"class":46},[40,370,224],{"class":172},[40,372,227],{"class":50},[304,374],{},"Expected result: ",[26,377,378],{},"200",", ",[26,381,382],{},"301",[26,384,385],{},"302",", or your expected app response.",[297,388,389,392,394,395,29,398,459,461,462],{},[300,390,391],{},"Create an Nginx server block",[304,393],{},"Create ",[26,396,397],{},"\u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp",[31,399,401],{"className":254,"code":400,"language":256,"meta":36,"style":36},"server {\n    listen 80;\n    server_name example.com www.example.com;\n\n    location \u002Fstatic\u002F {\n        alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n    }\n\n    location \u002F {\n        include proxy_params;\n        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n        proxy_redirect off;\n    }\n}\n",[26,402,403,407,411,415,419,423,427,431,435,439,443,447,451,455],{"__ignoreMap":36},[40,404,405],{"class":42,"line":43},[40,406,73],{},[40,408,409],{"class":42,"line":70},[40,410,79],{},[40,412,413],{"class":42,"line":76},[40,414,85],{},[40,416,417],{"class":42,"line":82},[40,418,92],{"emptyLinePlaceholder":91},[40,420,421],{"class":42,"line":88},[40,422,98],{},[40,424,425],{"class":42,"line":95},[40,426,104],{},[40,428,429],{"class":42,"line":101},[40,430,110],{},[40,432,433],{"class":42,"line":107},[40,434,92],{"emptyLinePlaceholder":91},[40,436,437],{"class":42,"line":113},[40,438,121],{},[40,440,441],{"class":42,"line":118},[40,442,127],{},[40,444,445],{"class":42,"line":124},[40,446,133],{},[40,448,449],{"class":42,"line":130},[40,450,139],{},[40,452,453],{"class":42,"line":136},[40,454,110],{},[40,456,457],{"class":42,"line":142},[40,458,150],{},[304,460],{},"Replace:",[463,464,465,471],"ul",{},[297,466,467,470],{},[26,468,469],{},"example.com www.example.com"," with your real domain",[297,472,473,475],{},[26,474,280],{}," with your actual static directory",[297,477,478,481,498,500,501],{},[300,479,480],{},"Enable the site",[31,482,484],{"className":33,"code":483,"language":35,"meta":36,"style":36},"sudo ln -sf \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fflaskapp\n",[26,485,486],{"__ignoreMap":36},[40,487,488,490,492,494,496],{"class":42,"line":43},[40,489,47],{"class":46},[40,491,169],{"class":50},[40,493,173],{"class":172},[40,495,54],{"class":50},[40,497,178],{"class":50},[304,499],{},"If the default site conflicts, disable it:",[31,502,504],{"className":33,"code":503,"language":35,"meta":36,"style":36},"sudo rm -f \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fdefault\n",[26,505,506],{"__ignoreMap":36},[40,507,508,510,513,516],{"class":42,"line":43},[40,509,47],{"class":46},[40,511,512],{"class":50}," rm",[40,514,515],{"class":172}," -f",[40,517,518],{"class":50}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fdefault\n",[297,520,521,524,537,539],{},[300,522,523],{},"Validate Nginx configuration",[31,525,527],{"className":33,"code":526,"language":35,"meta":36,"style":36},"sudo nginx -t\n",[26,528,529],{"__ignoreMap":36},[40,530,531,533,535],{"class":42,"line":43},[40,532,47],{"class":46},[40,534,186],{"class":50},[40,536,189],{"class":172},[304,538],{},"Fix any reported syntax errors before reloading.",[297,541,542,545],{},[300,543,544],{},"Reload Nginx",[31,546,548],{"className":33,"code":547,"language":35,"meta":36,"style":36},"sudo systemctl reload nginx\n",[26,549,550],{"__ignoreMap":36},[40,551,552,554,556,558],{"class":42,"line":43},[40,553,47],{"class":46},[40,555,197],{"class":50},[40,557,200],{"class":50},[40,559,203],{"class":50},[297,561,562,565,578,580],{},[300,563,564],{},"Test the public Nginx path",[31,566,568],{"className":33,"code":567,"language":35,"meta":36,"style":36},"curl -I http:\u002F\u002Fexample.com\n",[26,569,570],{"__ignoreMap":36},[40,571,572,574,576],{"class":42,"line":43},[40,573,221],{"class":46},[40,575,224],{"class":172},[40,577,248],{"class":50},[304,579],{},"Also test in a browser.",[297,582,583,586,588,589,605,607,608,670,672,673,691,693],{},[300,584,585],{},"Optional: use a Unix socket instead of TCP",[304,587],{},"If Gunicorn is bound to a socket:",[31,590,592],{"className":33,"code":591,"language":35,"meta":36,"style":36},"gunicorn --bind unix:\u002Frun\u002Fgunicorn.sock wsgi:app\n",[26,593,594],{"__ignoreMap":36},[40,595,596,598,600,603],{"class":42,"line":43},[40,597,319],{"class":46},[40,599,322],{"class":172},[40,601,602],{"class":50}," unix:\u002Frun\u002Fgunicorn.sock",[40,604,328],{"class":50},[304,606],{},"Update the Nginx server block:",[31,609,611],{"className":254,"code":610,"language":256,"meta":36,"style":36},"server {\n    listen 80;\n    server_name example.com www.example.com;\n\n    location \u002Fstatic\u002F {\n        alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n    }\n\n    location \u002F {\n        include proxy_params;\n        proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fgunicorn.sock;\n        proxy_redirect off;\n    }\n}\n",[26,612,613,617,621,625,629,633,637,641,645,649,653,658,662,666],{"__ignoreMap":36},[40,614,615],{"class":42,"line":43},[40,616,73],{},[40,618,619],{"class":42,"line":70},[40,620,79],{},[40,622,623],{"class":42,"line":76},[40,624,85],{},[40,626,627],{"class":42,"line":82},[40,628,92],{"emptyLinePlaceholder":91},[40,630,631],{"class":42,"line":88},[40,632,98],{},[40,634,635],{"class":42,"line":95},[40,636,104],{},[40,638,639],{"class":42,"line":101},[40,640,110],{},[40,642,643],{"class":42,"line":107},[40,644,92],{"emptyLinePlaceholder":91},[40,646,647],{"class":42,"line":113},[40,648,121],{},[40,650,651],{"class":42,"line":118},[40,652,127],{},[40,654,655],{"class":42,"line":124},[40,656,657],{},"        proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fgunicorn.sock;\n",[40,659,660],{"class":42,"line":130},[40,661,139],{},[40,663,664],{"class":42,"line":136},[40,665,110],{},[40,667,668],{"class":42,"line":142},[40,669,150],{},[304,671],{},"Then verify the socket exists:",[31,674,676],{"className":33,"code":675,"language":35,"meta":36,"style":36},"sudo ls -l \u002Frun\u002Fgunicorn.sock\n",[26,677,678],{"__ignoreMap":36},[40,679,680,682,685,688],{"class":42,"line":43},[40,681,47],{"class":46},[40,683,684],{"class":50}," ls",[40,686,687],{"class":172}," -l",[40,689,690],{"class":50}," \u002Frun\u002Fgunicorn.sock\n",[304,692],{},"Nginx must be able to read the socket.",[297,695,696,699,701,702,711,713,714,717],{},[300,697,698],{},"Verify forwarded headers are included",[304,700],{},"This line is important:",[31,703,705],{"className":254,"code":704,"language":256,"meta":36,"style":36},"include proxy_params;\n",[26,706,707],{"__ignoreMap":36},[40,708,709],{"class":42,"line":43},[40,710,704],{},[304,712],{},"It forwards standard proxy headers such as ",[26,715,716],{},"Host"," and client IP metadata. Without it, Flask may generate incorrect URLs or mis-handle scheme and host information when additional proxy layers or HTTPS are added.",[297,719,720,723,725,726,729,730,749,751,752],{},[300,721,722],{},"Serve static files directly from Nginx",[304,724],{},"Use ",[26,727,728],{},"alias"," for static assets:",[31,731,733],{"className":254,"code":732,"language":256,"meta":36,"style":36},"location \u002Fstatic\u002F {\n    alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n}\n",[26,734,735,740,745],{"__ignoreMap":36},[40,736,737],{"class":42,"line":43},[40,738,739],{},"location \u002Fstatic\u002F {\n",[40,741,742],{"class":42,"line":70},[40,743,744],{},"    alias \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F;\n",[40,746,747],{"class":42,"line":76},[40,748,150],{},[304,750],{},"Confirm the files exist:",[31,753,755],{"className":33,"code":754,"language":35,"meta":36,"style":36},"ls -lah \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F\n",[26,756,757],{"__ignoreMap":36},[40,758,759,762,765],{"class":42,"line":43},[40,760,761],{"class":46},"ls",[40,763,764],{"class":172}," -lah",[40,766,767],{"class":50}," \u002Fvar\u002Fwww\u002Fflaskapp\u002Fstatic\u002F\n",[297,769,770,773,775,776,778,779],{},[300,771,772],{},"Harden the deployment baseline",[304,774],{},"Keep Gunicorn private to the local machine unless you explicitly need external access.",[304,777],{},"Recommended:",[463,780,781,790,793],{},[297,782,783,784,786,787],{},"bind Gunicorn to ",[26,785,28],{}," or ",[26,788,789],{},"\u002Frun\u002Fgunicorn.sock",[297,791,792],{},"remove the default Nginx site",[297,794,795],{},"add HTTPS after HTTP proxying is confirmed working",[297,797,798,801,803,804],{},[300,799,800],{},"Validate end-to-end behavior",[304,802],{},"Check all layers:",[31,805,807],{"className":33,"code":806,"language":35,"meta":36,"style":36},"curl -I http:\u002F\u002F127.0.0.1:8000\ncurl -I http:\u002F\u002Fexample.com\nsudo nginx -t\nsudo systemctl status nginx --no-pager\nsudo systemctl status gunicorn --no-pager\n",[26,808,809,817,825,833,845],{"__ignoreMap":36},[40,810,811,813,815],{"class":42,"line":43},[40,812,221],{"class":46},[40,814,224],{"class":172},[40,816,227],{"class":50},[40,818,819,821,823],{"class":42,"line":70},[40,820,221],{"class":46},[40,822,224],{"class":172},[40,824,248],{"class":50},[40,826,827,829,831],{"class":42,"line":76},[40,828,47],{"class":46},[40,830,186],{"class":50},[40,832,189],{"class":172},[40,834,835,837,839,841,843],{"class":42,"line":82},[40,836,47],{"class":46},[40,838,197],{"class":50},[40,840,345],{"class":50},[40,842,186],{"class":50},[40,844,351],{"class":172},[40,846,847,849,851,853,855],{"class":42,"line":88},[40,848,47],{"class":46},[40,850,197],{"class":50},[40,852,345],{"class":50},[40,854,348],{"class":50},[40,856,351],{"class":172},[858,859,861],"h3",{"id":860},"minimal-nginx-server-block-example","Minimal Nginx Server Block Example",[31,863,864],{"className":254,"code":400,"language":256,"meta":36,"style":36},[26,865,866,870,874,878,882,886,890,894,898,902,906,910,914,918],{"__ignoreMap":36},[40,867,868],{"class":42,"line":43},[40,869,73],{},[40,871,872],{"class":42,"line":70},[40,873,79],{},[40,875,876],{"class":42,"line":76},[40,877,85],{},[40,879,880],{"class":42,"line":82},[40,881,92],{"emptyLinePlaceholder":91},[40,883,884],{"class":42,"line":88},[40,885,98],{},[40,887,888],{"class":42,"line":95},[40,889,104],{},[40,891,892],{"class":42,"line":101},[40,893,110],{},[40,895,896],{"class":42,"line":107},[40,897,92],{"emptyLinePlaceholder":91},[40,899,900],{"class":42,"line":113},[40,901,121],{},[40,903,904],{"class":42,"line":118},[40,905,127],{},[40,907,908],{"class":42,"line":124},[40,909,133],{},[40,911,912],{"class":42,"line":130},[40,913,139],{},[40,915,916],{"class":42,"line":136},[40,917,110],{},[40,919,920],{"class":42,"line":142},[40,921,150],{},[858,923,925],{"id":924},"when-to-use-tcp-vs-unix-socket","When to Use TCP vs Unix Socket",[463,927,928,936,942,945],{},[297,929,725,930,932,933,935],{},[26,931,28],{}," for a simpler first deployment and easier ",[26,934,221],{}," testing.",[297,937,938,939,941],{},"Use a Unix socket such as ",[26,940,789],{}," for local-only communication and tighter process coupling.",[297,943,944],{},"If using a socket, permission and ownership issues are a common failure point.",[297,946,947,948,951],{},"If using TCP, do not expose Gunicorn publicly on ",[26,949,950],{},"0.0.0.0"," unless that is intentional and firewalled.",[18,953,955],{"id":954},"common-causes","Common Causes",[463,957,958,989,1034,1057,1066,1075,1088,1098],{},[297,959,960,963,964],{},[300,961,962],{},"Gunicorn not running"," → Nginx has no upstream to connect to → start or restart Gunicorn and retest locally.",[31,965,967],{"className":33,"code":966,"language":35,"meta":36,"style":36},"sudo systemctl restart gunicorn\ncurl -I http:\u002F\u002F127.0.0.1:8000\n",[26,968,969,981],{"__ignoreMap":36},[40,970,971,973,975,978],{"class":42,"line":43},[40,972,47],{"class":46},[40,974,197],{"class":50},[40,976,977],{"class":50}," restart",[40,979,980],{"class":50}," gunicorn\n",[40,982,983,985,987],{"class":42,"line":70},[40,984,221],{"class":46},[40,986,224],{"class":172},[40,988,227],{"class":50},[297,990,991,998,999],{},[300,992,993,994,997],{},"Wrong ",[26,995,996],{},"proxy_pass"," target"," → Nginx points to the wrong port or socket → match Nginx to the actual Gunicorn bind.",[31,1000,1002],{"className":33,"code":1001,"language":35,"meta":36,"style":36},"ss -ltnp | grep 8000\nss -lx | grep gunicorn\n",[26,1003,1004,1021],{"__ignoreMap":36},[40,1005,1006,1009,1012,1015,1018],{"class":42,"line":43},[40,1007,1008],{"class":46},"ss",[40,1010,1011],{"class":172}," -ltnp",[40,1013,1014],{"class":57}," |",[40,1016,1017],{"class":46}," grep",[40,1019,1020],{"class":172}," 8000\n",[40,1022,1023,1025,1028,1030,1032],{"class":42,"line":70},[40,1024,1008],{"class":46},[40,1026,1027],{"class":172}," -lx",[40,1029,1014],{"class":57},[40,1031,1017],{"class":46},[40,1033,980],{"class":50},[297,1035,1036,1039,1040,1042,1043],{},[300,1037,1038],{},"Socket permission mismatch"," → Nginx cannot access ",[26,1041,789],{}," → fix service user, group, and socket permissions.",[31,1044,1045],{"className":33,"code":675,"language":35,"meta":36,"style":36},[26,1046,1047],{"__ignoreMap":36},[40,1048,1049,1051,1053,1055],{"class":42,"line":43},[40,1050,47],{"class":46},[40,1052,684],{"class":50},[40,1054,687],{"class":172},[40,1056,690],{"class":50},[297,1058,1059,1065],{},[300,1060,1061,1062],{},"Missing ",[26,1063,1064],{},"include proxy_params"," → forwarded headers are incomplete → add the standard proxy parameters include.",[297,1067,1068,1074],{},[300,1069,1070,1071],{},"Incorrect ",[26,1072,1073],{},"server_name"," → requests hit the wrong server block → update the domain list and reload Nginx.",[297,1076,1077,1080,1081,1084,1085,1087],{},[300,1078,1079],{},"Bad static alias path"," → app works but static files return ",[26,1082,1083],{},"404"," → point ",[26,1086,728],{}," to the real static directory.",[297,1089,1090,1093,1094,1097],{},[300,1091,1092],{},"Nginx syntax error"," → reload fails or old config remains active → run ",[26,1095,1096],{},"nginx -t"," and fix the reported line.",[297,1099,1100,1106,1107,1110],{},[300,1101,1102,1103,1105],{},"Gunicorn bound to ",[26,1104,950],{}," unexpectedly"," → direct exposure bypasses Nginx and weakens the setup → bind to ",[26,1108,1109],{},"127.0.0.1"," or a Unix socket.",[18,1112,1114],{"id":1113},"debugging-section","Debugging Section",[14,1116,1117],{},"Run these checks in order.",[858,1119,1121],{"id":1120},"_1-validate-nginx-configuration","1. Validate Nginx configuration",[31,1123,1124],{"className":33,"code":526,"language":35,"meta":36,"style":36},[26,1125,1126],{"__ignoreMap":36},[40,1127,1128,1130,1132],{"class":42,"line":43},[40,1129,47],{"class":46},[40,1131,186],{"class":50},[40,1133,189],{"class":172},[14,1135,1136],{},"Look for:",[463,1138,1139,1144],{},[297,1140,1141],{},[26,1142,1143],{},"syntax is ok",[297,1145,1146],{},[26,1147,1148],{},"test is successful",[858,1150,1152],{"id":1151},"_2-check-nginx-service-status","2. Check Nginx service status",[31,1154,1156],{"className":33,"code":1155,"language":35,"meta":36,"style":36},"sudo systemctl status nginx --no-pager\n",[26,1157,1158],{"__ignoreMap":36},[40,1159,1160,1162,1164,1166,1168],{"class":42,"line":43},[40,1161,47],{"class":46},[40,1163,197],{"class":50},[40,1165,345],{"class":50},[40,1167,186],{"class":50},[40,1169,351],{"class":172},[14,1171,1136],{},[463,1173,1174,1180],{},[297,1175,1176,1177],{},"service is ",[26,1178,1179],{},"active (running)",[297,1181,1182],{},"no recent config or bind errors",[858,1184,1186],{"id":1185},"_3-check-gunicorn-service-status","3. Check Gunicorn service status",[31,1188,1189],{"className":33,"code":334,"language":35,"meta":36,"style":36},[26,1190,1191],{"__ignoreMap":36},[40,1192,1193,1195,1197,1199,1201],{"class":42,"line":43},[40,1194,47],{"class":46},[40,1196,197],{"class":50},[40,1198,345],{"class":50},[40,1200,348],{"class":50},[40,1202,351],{"class":172},[14,1204,1136],{},[463,1206,1207,1210,1213],{},[297,1208,1209],{},"service is running",[297,1211,1212],{},"no import errors",[297,1214,1215],{},"no worker boot failures",[858,1217,1219],{"id":1218},"_4-confirm-gunicorn-is-listening","4. Confirm Gunicorn is listening",[14,1221,1222],{},"For TCP:",[31,1224,1226],{"className":33,"code":1225,"language":35,"meta":36,"style":36},"ss -ltnp | grep 8000\n",[26,1227,1228],{"__ignoreMap":36},[40,1229,1230,1232,1234,1236,1238],{"class":42,"line":43},[40,1231,1008],{"class":46},[40,1233,1011],{"class":172},[40,1235,1014],{"class":57},[40,1237,1017],{"class":46},[40,1239,1020],{"class":172},[14,1241,1242],{},"For Unix sockets:",[31,1244,1246],{"className":33,"code":1245,"language":35,"meta":36,"style":36},"ss -lx | grep gunicorn\nsudo ls -l \u002Frun\u002Fgunicorn.sock\n",[26,1247,1248,1260],{"__ignoreMap":36},[40,1249,1250,1252,1254,1256,1258],{"class":42,"line":43},[40,1251,1008],{"class":46},[40,1253,1027],{"class":172},[40,1255,1014],{"class":57},[40,1257,1017],{"class":46},[40,1259,980],{"class":50},[40,1261,1262,1264,1266,1268],{"class":42,"line":70},[40,1263,47],{"class":46},[40,1265,684],{"class":50},[40,1267,687],{"class":172},[40,1269,690],{"class":50},[14,1271,1136],{},[463,1273,1274,1277],{},[297,1275,1276],{},"expected port or socket exists",[297,1278,1279],{},"correct ownership and permissions",[858,1281,1283],{"id":1282},"_5-test-the-upstream-directly","5. Test the upstream directly",[31,1285,1286],{"className":33,"code":362,"language":35,"meta":36,"style":36},[26,1287,1288],{"__ignoreMap":36},[40,1289,1290,1292,1294],{"class":42,"line":43},[40,1291,221],{"class":46},[40,1293,224],{"class":172},[40,1295,227],{"class":50},[14,1297,1136],{},[463,1299,1300],{},[297,1301,1302],{},"direct success before testing through Nginx",[858,1304,1306],{"id":1305},"_6-test-through-nginx","6. Test through Nginx",[31,1308,1310],{"className":33,"code":1309,"language":35,"meta":36,"style":36},"curl -I http:\u002F\u002Fyour-domain\n",[26,1311,1312],{"__ignoreMap":36},[40,1313,1314,1316,1318],{"class":42,"line":43},[40,1315,221],{"class":46},[40,1317,224],{"class":172},[40,1319,1320],{"class":50}," http:\u002F\u002Fyour-domain\n",[14,1322,1136],{},[463,1324,1325,1328],{},[297,1326,1327],{},"expected response code",[297,1329,1330],{},"if direct Gunicorn works but Nginx fails, the issue is in Nginx configuration or routing",[858,1332,1334],{"id":1333},"_7-inspect-nginx-logs","7. Inspect Nginx logs",[31,1336,1338],{"className":33,"code":1337,"language":35,"meta":36,"style":36},"sudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\n",[26,1339,1340,1356],{"__ignoreMap":36},[40,1341,1342,1344,1347,1350,1353],{"class":42,"line":43},[40,1343,47],{"class":46},[40,1345,1346],{"class":50}," tail",[40,1348,1349],{"class":172}," -n",[40,1351,1352],{"class":172}," 100",[40,1354,1355],{"class":50}," \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\n",[40,1357,1358,1360,1362,1364,1366],{"class":42,"line":70},[40,1359,47],{"class":46},[40,1361,1346],{"class":50},[40,1363,1349],{"class":172},[40,1365,1352],{"class":172},[40,1367,1368],{"class":50}," \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\n",[14,1370,1136],{},[463,1372,1373,1378,1383,1388],{},[297,1374,1375],{},[26,1376,1377],{},"connect() failed",[297,1379,1380],{},[26,1381,1382],{},"permission denied",[297,1384,1385],{},[26,1386,1387],{},"no such file or directory",[297,1389,1390],{},"requests hitting the expected server block",[858,1392,1394],{"id":1393},"_8-inspect-journald-logs","8. Inspect journald logs",[31,1396,1398],{"className":33,"code":1397,"language":35,"meta":36,"style":36},"sudo journalctl -u nginx -n 100 --no-pager\nsudo journalctl -u gunicorn -n 100 --no-pager\n",[26,1399,1400,1418],{"__ignoreMap":36},[40,1401,1402,1404,1407,1410,1412,1414,1416],{"class":42,"line":43},[40,1403,47],{"class":46},[40,1405,1406],{"class":50}," journalctl",[40,1408,1409],{"class":172}," -u",[40,1411,186],{"class":50},[40,1413,1349],{"class":172},[40,1415,1352],{"class":172},[40,1417,351],{"class":172},[40,1419,1420,1422,1424,1426,1428,1430,1432],{"class":42,"line":70},[40,1421,47],{"class":46},[40,1423,1406],{"class":50},[40,1425,1409],{"class":172},[40,1427,348],{"class":50},[40,1429,1349],{"class":172},[40,1431,1352],{"class":172},[40,1433,351],{"class":172},[14,1435,1136],{},[463,1437,1438,1441,1444],{},[297,1439,1440],{},"startup failures",[297,1442,1443],{},"path errors",[297,1445,1446],{},"Python import or dependency failures",[858,1448,1450],{"id":1449},"_9-dump-active-nginx-configuration","9. Dump active Nginx configuration",[31,1452,1454],{"className":33,"code":1453,"language":35,"meta":36,"style":36},"sudo nginx -T | sed -n '\u002Fserver_name example.com\u002F,\u002F}\u002Fp'\n",[26,1455,1456],{"__ignoreMap":36},[40,1457,1458,1460,1462,1465,1467,1470,1472],{"class":42,"line":43},[40,1459,47],{"class":46},[40,1461,186],{"class":50},[40,1463,1464],{"class":172}," -T",[40,1466,1014],{"class":57},[40,1468,1469],{"class":46}," sed",[40,1471,1349],{"class":172},[40,1473,1474],{"class":50}," '\u002Fserver_name example.com\u002F,\u002F}\u002Fp'\n",[14,1476,1477],{},"Use this to confirm:",[463,1479,1480,1485,1489],{},[297,1481,1482,1483],{},"the active ",[26,1484,1073],{},[297,1486,1482,1487],{},[26,1488,996],{},[297,1490,1491],{},"no conflicting config is overriding your site",[14,1493,1494,1495,1498,1499,1504,1505,281],{},"If requests fail with ",[26,1496,1497],{},"502",", continue with ",[1500,1501,1503],"a",{"href":1502},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",". If static assets fail, continue with ",[1500,1506,1508],{"href":1507},"\u002Ffix-issues\u002Fflask-static-files-not-loading-in-production","Flask Static Files Not Loading in Production",[18,1510,1512],{"id":1511},"checklist","Checklist",[463,1514,1517,1526,1532,1541,1547,1555,1561,1567],{"className":1515},[1516],"contains-task-list",[297,1518,1521,1525],{"className":1519},[1520],"task-list-item",[1522,1523],"input",{"disabled":91,"type":1524},"checkbox"," Gunicorn is running and bound to localhost TCP or a valid Unix socket",[297,1527,1529,1531],{"className":1528},[1520],[1522,1530],{"disabled":91,"type":1524}," Nginx server block points to the correct upstream",[297,1533,1535,1537,1538,1540],{"className":1534},[1520],[1522,1536],{"disabled":91,"type":1524}," ",[26,1539,1073],{}," matches the domain or server IP being tested",[297,1542,1544,1546],{"className":1543},[1520],[1522,1545],{"disabled":91,"type":1524}," Static file alias path exists if Nginx serves static assets",[297,1548,1550,1537,1552,1554],{"className":1549},[1520],[1522,1551],{"disabled":91,"type":1524},[26,1553,1096],{}," passes without errors",[297,1556,1558,1560],{"className":1557},[1520],[1522,1559],{"disabled":91,"type":1524}," Nginx reloaded successfully",[297,1562,1564,1566],{"className":1563},[1520],[1522,1565],{"disabled":91,"type":1524}," Direct Gunicorn test works before Nginx test",[297,1568,1570,1572],{"className":1569},[1520],[1522,1571],{"disabled":91,"type":1524}," Domain request reaches the Flask app through Nginx",[18,1574,1576],{"id":1575},"related-guides","Related Guides",[463,1578,1579,1585,1589,1593],{},[297,1580,1581],{},[1500,1582,1584],{"href":1583},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[297,1586,1587],{},[1500,1588,1503],{"href":1502},[297,1590,1591],{},[1500,1592,1508],{"href":1507},[297,1594,1595],{},[1500,1596,1598],{"href":1597},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1600,1602],{"id":1601},"faq","FAQ",[14,1604,1605,1608,1610],{},[300,1606,1607],{},"Q: What is the reverse proxy layer doing in a Flask deployment?",[304,1609],{},"\nA: It accepts client requests, handles web-server concerns, and forwards application traffic to Gunicorn.",[14,1612,1613,1616,1618],{},[300,1614,1615],{},"Q: Does Nginx run Flask directly?",[304,1617],{},"\nA: No. Nginx proxies requests to Gunicorn or another WSGI server running the Flask app.",[14,1620,1621,1624,1626,1627,1629],{},[300,1622,1623],{},"Q: Should I start with a port or a Unix socket?",[304,1625],{},"\nA: Start with ",[26,1628,28],{}," for easier testing, then switch to a socket if needed.",[14,1631,1632,1638,1640],{},[300,1633,1634,1635,1637],{},"Q: Should ",[26,1636,996],{}," point to localhost or a socket?",[304,1639],{},"\nA: Either works. TCP is simpler to debug; Unix sockets are common in production.",[14,1642,1643,1646,1648,1649,1652,1653,1655],{},[300,1644,1645],{},"Q: Can Nginx serve static files without Flask?",[304,1647],{},"\nA: Yes. Use a ",[26,1650,1651],{},"location"," block with ",[26,1654,728],{}," to serve static assets directly.",[14,1657,1658,1661,1663],{},[300,1659,1660],{},"Q: Why serve static files from Nginx instead of Flask?",[304,1662],{},"\nA: Nginx is more efficient for static file delivery and keeps Gunicorn focused on dynamic requests.",[14,1665,1666,1669,1671],{},[300,1667,1668],{},"Q: Why do I get 502 Bad Gateway after adding Nginx?",[304,1670],{},"\nA: The upstream Gunicorn service is usually down, misbound, or inaccessible due to socket or permission issues.",[14,1673,1674,1677,1679],{},[300,1675,1676],{},"Q: Is this enough for HTTPS?",[304,1678],{},"\nA: No. Add TLS certificates and an HTTPS server block or use Certbot after the proxy is working.",[18,1681,1683],{"id":1682},"final-takeaway","Final Takeaway",[14,1685,1686],{},"An Nginx reverse proxy for Flask means Nginx handles client traffic and forwards app requests to Gunicorn. In practice, most setup issues come from an incorrect upstream target, missing proxy headers, broken static paths, or socket permission problems. Start with a simple localhost Gunicorn bind, verify it directly, then add Nginx, static files, and HTTPS in stages.",[1688,1689,1690],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":36,"searchDepth":70,"depth":70,"links":1692},[1693,1694,1695,1699,1700,1711,1712,1713,1714],{"id":20,"depth":70,"text":21},{"id":284,"depth":70,"text":285},{"id":291,"depth":70,"text":292,"children":1696},[1697,1698],{"id":860,"depth":76,"text":861},{"id":924,"depth":76,"text":925},{"id":954,"depth":70,"text":955},{"id":1113,"depth":70,"text":1114,"children":1701},[1702,1703,1704,1705,1706,1707,1708,1709,1710],{"id":1120,"depth":76,"text":1121},{"id":1151,"depth":76,"text":1152},{"id":1185,"depth":76,"text":1186},{"id":1218,"depth":76,"text":1219},{"id":1282,"depth":76,"text":1283},{"id":1305,"depth":76,"text":1306},{"id":1333,"depth":76,"text":1334},{"id":1393,"depth":76,"text":1394},{"id":1449,"depth":76,"text":1450},{"id":1511,"depth":70,"text":1512},{"id":1575,"depth":70,"text":1576},{"id":1601,"depth":70,"text":1602},{"id":1682,"depth":70,"text":1683},"Complete guide on nginx reverse proxy for flask explained for Flask production environments.","md",{"ogTitle":5,"ogDescription":1715,"twitterCard":1718,"robots":1719,"canonical":1720},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Freference\u002Fnginx-reverse-proxy-for-flask-explained","\u002Freference\u002Fnginx-reverse-proxy-for-flask-explained",{"title":5,"description":1715},"reference\u002Fnginx-reverse-proxy-for-flask-explained","KxgTK67fOl_BX1TQ7aV78eLJ78f0ZuJXt1fZi6ei15Y",1776805765079]