[{"data":1,"prerenderedAt":1999},["ShallowReactive",2],{"\u002Fdeploy\u002Fdeploy-flask-on-ubuntu-vps-step-by-step":3},{"id":4,"title":5,"body":6,"description":1989,"extension":1990,"meta":1991,"navigation":143,"path":1995,"seo":1996,"stem":1997,"__hash__":1998},"content\u002Fdeploy\u002Fdeploy-flask-on-ubuntu-vps-step-by-step.md","Deploy Flask on Ubuntu VPS (Step-by-Step)",{"type":7,"value":8,"toc":1946},"minimark",[9,13,17,22,25,542,549,553,556,579,582,586,591,638,642,686,690,709,716,720,773,780,784,791,812,815,830,833,861,865,884,887,891,894,907,914,920,924,929,992,995,1015,1018,1027,1031,1057,1061,1081,1084,1088,1093,1149,1152,1161,1165,1184,1188,1206,1210,1234,1238,1276,1287,1291,1304,1307,1321,1325,1328,1347,1350,1369,1377,1381,1384,1387,1401,1405,1494,1498,1501,1505,1559,1562,1579,1583,1623,1625,1643,1647,1679,1686,1690,1717,1720,1724,1737,1741,1763,1766,1777,1784,1788,1867,1872,1876,1890,1894,1898,1901,1905,1908,1912,1915,1919,1928,1932,1935,1939,1942],[10,11,5],"h1",{"id":12},"deploy-flask-on-ubuntu-vps-step-by-step",[14,15,16],"p",{},"If you're trying to deploy a Flask app on an Ubuntu VPS, this guide shows you how to set up a production-ready stack step-by-step. The outcome is a running Flask application behind Gunicorn and Nginx, managed by systemd and reachable through your server domain or IP.",[18,19,21],"h2",{"id":20},"quick-setup","Quick Setup",[14,23,24],{},"Use this on a fresh Ubuntu VPS to validate the stack end-to-end:",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","sudo apt update && sudo apt install -y python3 python3-venv python3-pip nginx\nsudo mkdir -p \u002Fvar\u002Fwww\u002Fflaskapp && cd \u002Fvar\u002Fwww\u002Fflaskapp\npython3 -m venv venv\nsource venv\u002Fbin\u002Factivate\npip install flask gunicorn\n\ncat > app.py \u003C\u003C'EOF'\nfrom flask import Flask\napp = Flask(__name__)\n\n@app.route('\u002F')\ndef index():\n    return 'Flask app is running on Ubuntu VPS'\nEOF\n\ncat > wsgi.py \u003C\u003C'EOF'\nfrom app import app\nEOF\n\nsudo tee \u002Fetc\u002Fsystemd\u002Fsystem\u002Fflaskapp.service > \u002Fdev\u002Fnull \u003C\u003C'EOF'\n[Unit]\nDescription=Gunicorn instance for flaskapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fvar\u002Fwww\u002Fflaskapp\nEnvironment=\"PATH=\u002Fvar\u002Fwww\u002Fflaskapp\u002Fvenv\u002Fbin\"\nExecStart=\u002Fvar\u002Fwww\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsudo systemctl daemon-reload\nsudo systemctl enable --now flaskapp\n\nsudo tee \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp > \u002Fdev\u002Fnull \u003C\u003C'EOF'\nserver {\n    listen 80;\n    server_name _;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\nEOF\n\nsudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fflaskapp\nsudo nginx -t && sudo systemctl reload nginx\n\ncurl -I http:\u002F\u002F127.0.0.1:8000\ncurl -I http:\u002F\u002FYOUR_SERVER_IP\n","bash","",[33,34,35,78,100,115,124,138,145,164,170,176,181,187,193,199,205,210,224,230,235,240,260,266,272,278,283,289,295,301,307,313,319,324,330,336,341,346,357,373,378,396,402,408,414,419,425,431,437,443,449,455,461,467,472,477,493,515,520,532],"code",{"__ignoreMap":31},[36,37,40,44,48,51,55,57,59,62,66,69,72,75],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sScJk","sudo",[36,45,47],{"class":46},"sZZnC"," apt",[36,49,50],{"class":46}," update",[36,52,54],{"class":53},"sVt8B"," && ",[36,56,43],{"class":42},[36,58,47],{"class":46},[36,60,61],{"class":46}," install",[36,63,65],{"class":64},"sj4cs"," -y",[36,67,68],{"class":46}," python3",[36,70,71],{"class":46}," python3-venv",[36,73,74],{"class":46}," python3-pip",[36,76,77],{"class":46}," nginx\n",[36,79,81,83,86,89,92,94,97],{"class":38,"line":80},2,[36,82,43],{"class":42},[36,84,85],{"class":46}," mkdir",[36,87,88],{"class":64}," -p",[36,90,91],{"class":46}," \u002Fvar\u002Fwww\u002Fflaskapp",[36,93,54],{"class":53},[36,95,96],{"class":64},"cd",[36,98,99],{"class":46}," \u002Fvar\u002Fwww\u002Fflaskapp\n",[36,101,103,106,109,112],{"class":38,"line":102},3,[36,104,105],{"class":42},"python3",[36,107,108],{"class":64}," -m",[36,110,111],{"class":46}," venv",[36,113,114],{"class":46}," venv\n",[36,116,118,121],{"class":38,"line":117},4,[36,119,120],{"class":64},"source",[36,122,123],{"class":46}," venv\u002Fbin\u002Factivate\n",[36,125,127,130,132,135],{"class":38,"line":126},5,[36,128,129],{"class":42},"pip",[36,131,61],{"class":46},[36,133,134],{"class":46}," flask",[36,136,137],{"class":46}," gunicorn\n",[36,139,141],{"class":38,"line":140},6,[36,142,144],{"emptyLinePlaceholder":143},true,"\n",[36,146,148,151,155,158,161],{"class":38,"line":147},7,[36,149,150],{"class":42},"cat",[36,152,154],{"class":153},"szBVR"," >",[36,156,157],{"class":46}," app.py",[36,159,160],{"class":153}," \u003C\u003C",[36,162,163],{"class":46},"'EOF'\n",[36,165,167],{"class":38,"line":166},8,[36,168,169],{"class":46},"from flask import Flask\n",[36,171,173],{"class":38,"line":172},9,[36,174,175],{"class":46},"app = Flask(__name__)\n",[36,177,179],{"class":38,"line":178},10,[36,180,144],{"emptyLinePlaceholder":143},[36,182,184],{"class":38,"line":183},11,[36,185,186],{"class":46},"@app.route('\u002F')\n",[36,188,190],{"class":38,"line":189},12,[36,191,192],{"class":46},"def index():\n",[36,194,196],{"class":38,"line":195},13,[36,197,198],{"class":46},"    return 'Flask app is running on Ubuntu VPS'\n",[36,200,202],{"class":38,"line":201},14,[36,203,204],{"class":46},"EOF\n",[36,206,208],{"class":38,"line":207},15,[36,209,144],{"emptyLinePlaceholder":143},[36,211,213,215,217,220,222],{"class":38,"line":212},16,[36,214,150],{"class":42},[36,216,154],{"class":153},[36,218,219],{"class":46}," wsgi.py",[36,221,160],{"class":153},[36,223,163],{"class":46},[36,225,227],{"class":38,"line":226},17,[36,228,229],{"class":46},"from app import app\n",[36,231,233],{"class":38,"line":232},18,[36,234,204],{"class":46},[36,236,238],{"class":38,"line":237},19,[36,239,144],{"emptyLinePlaceholder":143},[36,241,243,245,248,251,253,256,258],{"class":38,"line":242},20,[36,244,43],{"class":42},[36,246,247],{"class":46}," tee",[36,249,250],{"class":46}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fflaskapp.service",[36,252,154],{"class":153},[36,254,255],{"class":46}," \u002Fdev\u002Fnull",[36,257,160],{"class":153},[36,259,163],{"class":46},[36,261,263],{"class":38,"line":262},21,[36,264,265],{"class":46},"[Unit]\n",[36,267,269],{"class":38,"line":268},22,[36,270,271],{"class":46},"Description=Gunicorn instance for flaskapp\n",[36,273,275],{"class":38,"line":274},23,[36,276,277],{"class":46},"After=network.target\n",[36,279,281],{"class":38,"line":280},24,[36,282,144],{"emptyLinePlaceholder":143},[36,284,286],{"class":38,"line":285},25,[36,287,288],{"class":46},"[Service]\n",[36,290,292],{"class":38,"line":291},26,[36,293,294],{"class":46},"User=www-data\n",[36,296,298],{"class":38,"line":297},27,[36,299,300],{"class":46},"Group=www-data\n",[36,302,304],{"class":38,"line":303},28,[36,305,306],{"class":46},"WorkingDirectory=\u002Fvar\u002Fwww\u002Fflaskapp\n",[36,308,310],{"class":38,"line":309},29,[36,311,312],{"class":46},"Environment=\"PATH=\u002Fvar\u002Fwww\u002Fflaskapp\u002Fvenv\u002Fbin\"\n",[36,314,316],{"class":38,"line":315},30,[36,317,318],{"class":46},"ExecStart=\u002Fvar\u002Fwww\u002Fflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n",[36,320,322],{"class":38,"line":321},31,[36,323,144],{"emptyLinePlaceholder":143},[36,325,327],{"class":38,"line":326},32,[36,328,329],{"class":46},"[Install]\n",[36,331,333],{"class":38,"line":332},33,[36,334,335],{"class":46},"WantedBy=multi-user.target\n",[36,337,339],{"class":38,"line":338},34,[36,340,204],{"class":46},[36,342,344],{"class":38,"line":343},35,[36,345,144],{"emptyLinePlaceholder":143},[36,347,349,351,354],{"class":38,"line":348},36,[36,350,43],{"class":42},[36,352,353],{"class":46}," systemctl",[36,355,356],{"class":46}," daemon-reload\n",[36,358,360,362,364,367,370],{"class":38,"line":359},37,[36,361,43],{"class":42},[36,363,353],{"class":46},[36,365,366],{"class":46}," enable",[36,368,369],{"class":64}," --now",[36,371,372],{"class":46}," flaskapp\n",[36,374,376],{"class":38,"line":375},38,[36,377,144],{"emptyLinePlaceholder":143},[36,379,381,383,385,388,390,392,394],{"class":38,"line":380},39,[36,382,43],{"class":42},[36,384,247],{"class":46},[36,386,387],{"class":46}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fflaskapp",[36,389,154],{"class":153},[36,391,255],{"class":46},[36,393,160],{"class":153},[36,395,163],{"class":46},[36,397,399],{"class":38,"line":398},40,[36,400,401],{"class":46},"server {\n",[36,403,405],{"class":38,"line":404},41,[36,406,407],{"class":46},"    listen 80;\n",[36,409,411],{"class":38,"line":410},42,[36,412,413],{"class":46},"    server_name _;\n",[36,415,417],{"class":38,"line":416},43,[36,418,144],{"emptyLinePlaceholder":143},[36,420,422],{"class":38,"line":421},44,[36,423,424],{"class":46},"    location \u002F {\n",[36,426,428],{"class":38,"line":427},45,[36,429,430],{"class":46},"        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n",[36,432,434],{"class":38,"line":433},46,[36,435,436],{"class":46},"        proxy_set_header Host $host;\n",[36,438,440],{"class":38,"line":439},47,[36,441,442],{"class":46},"        proxy_set_header X-Real-IP $remote_addr;\n",[36,444,446],{"class":38,"line":445},48,[36,447,448],{"class":46},"        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n",[36,450,452],{"class":38,"line":451},49,[36,453,454],{"class":46},"        proxy_set_header X-Forwarded-Proto $scheme;\n",[36,456,458],{"class":38,"line":457},50,[36,459,460],{"class":46},"    }\n",[36,462,464],{"class":38,"line":463},51,[36,465,466],{"class":46},"}\n",[36,468,470],{"class":38,"line":469},52,[36,471,204],{"class":46},[36,473,475],{"class":38,"line":474},53,[36,476,144],{"emptyLinePlaceholder":143},[36,478,480,482,485,488,490],{"class":38,"line":479},54,[36,481,43],{"class":42},[36,483,484],{"class":46}," ln",[36,486,487],{"class":64}," -s",[36,489,387],{"class":46},[36,491,492],{"class":46}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fflaskapp\n",[36,494,496,498,501,504,506,508,510,513],{"class":38,"line":495},55,[36,497,43],{"class":42},[36,499,500],{"class":46}," nginx",[36,502,503],{"class":64}," -t",[36,505,54],{"class":53},[36,507,43],{"class":42},[36,509,353],{"class":46},[36,511,512],{"class":46}," reload",[36,514,77],{"class":46},[36,516,518],{"class":38,"line":517},56,[36,519,144],{"emptyLinePlaceholder":143},[36,521,523,526,529],{"class":38,"line":522},57,[36,524,525],{"class":42},"curl",[36,527,528],{"class":64}," -I",[36,530,531],{"class":46}," http:\u002F\u002F127.0.0.1:8000\n",[36,533,535,537,539],{"class":38,"line":534},58,[36,536,525],{"class":42},[36,538,528],{"class":64},[36,540,541],{"class":46}," http:\u002F\u002FYOUR_SERVER_IP\n",[14,543,544,545,548],{},"Replace the sample app, ",[33,546,547],{},"server_name",", paths, and service settings before production launch.",[18,550,552],{"id":551},"whats-happening","What’s Happening",[14,554,555],{},"A standard Flask deployment on Ubuntu uses:",[557,558,559,567,573],"ul",{},[560,561,562,566],"li",{},[563,564,565],"strong",{},"Gunicorn"," to run the Flask app as the WSGI server",[560,568,569,572],{},[563,570,571],{},"systemd"," to start, stop, and restart Gunicorn reliably",[560,574,575,578],{},[563,576,577],{},"Nginx"," to accept public traffic and proxy requests to Gunicorn",[14,580,581],{},"Most failures come from bad paths, incorrect import targets, missing dependencies, or an Nginx upstream that does not match the Gunicorn bind address.",[18,583,585],{"id":584},"step-by-step-guide","Step-by-Step Guide",[587,588,590],"h3",{"id":589},"_1-update-ubuntu-and-install-required-packages","1. Update Ubuntu and install required packages",[26,592,594],{"className":28,"code":593,"language":30,"meta":31,"style":31},"sudo apt update\nsudo apt upgrade -y\nsudo apt install -y python3 python3-venv python3-pip nginx git\n",[33,595,596,605,617],{"__ignoreMap":31},[36,597,598,600,602],{"class":38,"line":39},[36,599,43],{"class":42},[36,601,47],{"class":46},[36,603,604],{"class":46}," update\n",[36,606,607,609,611,614],{"class":38,"line":80},[36,608,43],{"class":42},[36,610,47],{"class":46},[36,612,613],{"class":46}," upgrade",[36,615,616],{"class":64}," -y\n",[36,618,619,621,623,625,627,629,631,633,635],{"class":38,"line":102},[36,620,43],{"class":42},[36,622,47],{"class":46},[36,624,61],{"class":46},[36,626,65],{"class":64},[36,628,68],{"class":46},[36,630,71],{"class":46},[36,632,74],{"class":46},[36,634,500],{"class":46},[36,636,637],{"class":46}," git\n",[587,639,641],{"id":640},"_2-create-the-application-directory","2. Create the application directory",[26,643,645],{"className":28,"code":644,"language":30,"meta":31,"style":31},"sudo mkdir -p \u002Fvar\u002Fwww\u002Fmyflaskapp\nsudo chown -R $USER:$USER \u002Fvar\u002Fwww\u002Fmyflaskapp\ncd \u002Fvar\u002Fwww\u002Fmyflaskapp\n",[33,646,647,658,680],{"__ignoreMap":31},[36,648,649,651,653,655],{"class":38,"line":39},[36,650,43],{"class":42},[36,652,85],{"class":46},[36,654,88],{"class":64},[36,656,657],{"class":46}," \u002Fvar\u002Fwww\u002Fmyflaskapp\n",[36,659,660,662,665,668,671,674,677],{"class":38,"line":80},[36,661,43],{"class":42},[36,663,664],{"class":46}," chown",[36,666,667],{"class":64}," -R",[36,669,670],{"class":53}," $USER",[36,672,673],{"class":46},":",[36,675,676],{"class":53},"$USER ",[36,678,679],{"class":46},"\u002Fvar\u002Fwww\u002Fmyflaskapp\n",[36,681,682,684],{"class":38,"line":102},[36,683,96],{"class":64},[36,685,657],{"class":46},[587,687,689],{"id":688},"_3-copy-or-clone-your-flask-project","3. Copy or clone your Flask project",[26,691,693],{"className":28,"code":692,"language":30,"meta":31,"style":31},"git clone YOUR_REPO_URL .\n",[33,694,695],{"__ignoreMap":31},[36,696,697,700,703,706],{"class":38,"line":39},[36,698,699],{"class":42},"git",[36,701,702],{"class":46}," clone",[36,704,705],{"class":46}," YOUR_REPO_URL",[36,707,708],{"class":46}," .\n",[14,710,711,712,715],{},"If the app already exists locally, copy it into ",[33,713,714],{},"\u002Fvar\u002Fwww\u002Fmyflaskapp",".",[587,717,719],{"id":718},"_4-create-a-virtual-environment-and-install-dependencies","4. Create a virtual environment and install dependencies",[26,721,723],{"className":28,"code":722,"language":30,"meta":31,"style":31},"python3 -m venv venv\nsource venv\u002Fbin\u002Factivate\npip install --upgrade pip\npip install -r requirements.txt\npip install gunicorn\n",[33,724,725,735,741,753,765],{"__ignoreMap":31},[36,726,727,729,731,733],{"class":38,"line":39},[36,728,105],{"class":42},[36,730,108],{"class":64},[36,732,111],{"class":46},[36,734,114],{"class":46},[36,736,737,739],{"class":38,"line":80},[36,738,120],{"class":64},[36,740,123],{"class":46},[36,742,743,745,747,750],{"class":38,"line":102},[36,744,129],{"class":42},[36,746,61],{"class":46},[36,748,749],{"class":64}," --upgrade",[36,751,752],{"class":46}," pip\n",[36,754,755,757,759,762],{"class":38,"line":117},[36,756,129],{"class":42},[36,758,61],{"class":46},[36,760,761],{"class":64}," -r",[36,763,764],{"class":46}," requirements.txt\n",[36,766,767,769,771],{"class":38,"line":126},[36,768,129],{"class":42},[36,770,61],{"class":46},[36,772,137],{"class":46},[14,774,775,776,779],{},"If you do not have a ",[33,777,778],{},"requirements.txt"," yet, install your app dependencies manually.",[587,781,783],{"id":782},"_5-create-or-verify-the-wsgi-entry-point","5. Create or verify the WSGI entry point",[14,785,786,787,790],{},"Create ",[33,788,789],{},"wsgi.py"," in the project root:",[26,792,796],{"className":793,"code":794,"language":795,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","from yourapp import app\n","python",[33,797,798],{"__ignoreMap":31},[36,799,800,803,806,809],{"class":38,"line":39},[36,801,802],{"class":153},"from",[36,804,805],{"class":53}," yourapp ",[36,807,808],{"class":153},"import",[36,810,811],{"class":53}," app\n",[14,813,814],{},"If your Flask app object is in another module or package, adjust it accordingly. Examples:",[26,816,817],{"className":793,"code":229,"language":795,"meta":31,"style":31},[33,818,819],{"__ignoreMap":31},[36,820,821,823,826,828],{"class":38,"line":39},[36,822,802],{"class":153},[36,824,825],{"class":53}," app ",[36,827,808],{"class":153},[36,829,811],{"class":53},[14,831,832],{},"or:",[26,834,836],{"className":793,"code":835,"language":795,"meta":31,"style":31},"from project import create_app\napp = create_app()\n",[33,837,838,850],{"__ignoreMap":31},[36,839,840,842,845,847],{"class":38,"line":39},[36,841,802],{"class":153},[36,843,844],{"class":53}," project ",[36,846,808],{"class":153},[36,848,849],{"class":53}," create_app\n",[36,851,852,855,858],{"class":38,"line":80},[36,853,854],{"class":53},"app ",[36,856,857],{"class":153},"=",[36,859,860],{"class":53}," create_app()\n",[587,862,864],{"id":863},"_6-test-gunicorn-directly-before-configuring-systemd","6. Test Gunicorn directly before configuring systemd",[26,866,868],{"className":28,"code":867,"language":30,"meta":31,"style":31},"\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn --bind 127.0.0.1:8000 wsgi:app\n",[33,869,870],{"__ignoreMap":31},[36,871,872,875,878,881],{"class":38,"line":39},[36,873,874],{"class":42},"\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn",[36,876,877],{"class":64}," --bind",[36,879,880],{"class":46}," 127.0.0.1:8000",[36,882,883],{"class":46}," wsgi:app\n",[14,885,886],{},"If it starts without import errors, leave it running temporarily.",[587,888,890],{"id":889},"_7-verify-the-app-responds-on-the-local-gunicorn-port","7. Verify the app responds on the local Gunicorn port",[14,892,893],{},"In another shell:",[26,895,897],{"className":28,"code":896,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002F127.0.0.1:8000\n",[33,898,899],{"__ignoreMap":31},[36,900,901,903,905],{"class":38,"line":39},[36,902,525],{"class":42},[36,904,528],{"class":64},[36,906,531],{"class":46},[14,908,909,910,913],{},"Expected result: an HTTP response such as ",[33,911,912],{},"200 OK"," or your app’s normal redirect\u002Fstatus.",[14,915,916,917,715],{},"Stop Gunicorn after the test with ",[33,918,919],{},"Ctrl+C",[587,921,923],{"id":922},"_8-create-the-systemd-service","8. Create the systemd service",[14,925,786,926,673],{},[33,927,928],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service",[26,930,934],{"className":931,"code":932,"language":933,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=Gunicorn instance for myflaskapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fvar\u002Fwww\u002Fmyflaskapp\nEnvironment=\"PATH=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\"\nExecStart=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n\n[Install]\nWantedBy=multi-user.target\n","ini",[33,935,936,940,945,949,953,957,961,965,970,975,980,984,988],{"__ignoreMap":31},[36,937,938],{"class":38,"line":39},[36,939,265],{},[36,941,942],{"class":38,"line":80},[36,943,944],{},"Description=Gunicorn instance for myflaskapp\n",[36,946,947],{"class":38,"line":102},[36,948,277],{},[36,950,951],{"class":38,"line":117},[36,952,144],{"emptyLinePlaceholder":143},[36,954,955],{"class":38,"line":126},[36,956,288],{},[36,958,959],{"class":38,"line":140},[36,960,294],{},[36,962,963],{"class":38,"line":147},[36,964,300],{},[36,966,967],{"class":38,"line":166},[36,968,969],{},"WorkingDirectory=\u002Fvar\u002Fwww\u002Fmyflaskapp\n",[36,971,972],{"class":38,"line":172},[36,973,974],{},"Environment=\"PATH=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\"\n",[36,976,977],{"class":38,"line":178},[36,978,979],{},"ExecStart=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind 127.0.0.1:8000 wsgi:app\n",[36,981,982],{"class":38,"line":183},[36,983,144],{"emptyLinePlaceholder":143},[36,985,986],{"class":38,"line":189},[36,987,329],{},[36,989,990],{"class":38,"line":195},[36,991,335],{},[14,993,994],{},"If your app needs environment variables, add them here:",[26,996,998],{"className":931,"code":997,"language":933,"meta":31,"style":31},"Environment=\"FLASK_ENV=production\"\nEnvironment=\"SECRET_KEY=replace-me\"\nEnvironment=\"DATABASE_URL=postgresql:\u002F\u002Fuser:pass@host\u002Fdbname\"\n",[33,999,1000,1005,1010],{"__ignoreMap":31},[36,1001,1002],{"class":38,"line":39},[36,1003,1004],{},"Environment=\"FLASK_ENV=production\"\n",[36,1006,1007],{"class":38,"line":80},[36,1008,1009],{},"Environment=\"SECRET_KEY=replace-me\"\n",[36,1011,1012],{"class":38,"line":102},[36,1013,1014],{},"Environment=\"DATABASE_URL=postgresql:\u002F\u002Fuser:pass@host\u002Fdbname\"\n",[14,1016,1017],{},"Or use an environment file:",[26,1019,1021],{"className":931,"code":1020,"language":933,"meta":31,"style":31},"EnvironmentFile=\u002Fetc\u002Fmyflaskapp.env\n",[33,1022,1023],{"__ignoreMap":31},[36,1024,1025],{"class":38,"line":39},[36,1026,1020],{},[587,1028,1030],{"id":1029},"_9-reload-systemd-and-start-the-service","9. Reload systemd and start the service",[26,1032,1034],{"className":28,"code":1033,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl enable --now myflaskapp\n",[33,1035,1036,1044],{"__ignoreMap":31},[36,1037,1038,1040,1042],{"class":38,"line":39},[36,1039,43],{"class":42},[36,1041,353],{"class":46},[36,1043,356],{"class":46},[36,1045,1046,1048,1050,1052,1054],{"class":38,"line":80},[36,1047,43],{"class":42},[36,1049,353],{"class":46},[36,1051,366],{"class":46},[36,1053,369],{"class":64},[36,1055,1056],{"class":46}," myflaskapp\n",[587,1058,1060],{"id":1059},"_10-check-service-status","10. Check service status",[26,1062,1064],{"className":28,"code":1063,"language":30,"meta":31,"style":31},"sudo systemctl status myflaskapp --no-pager\n",[33,1065,1066],{"__ignoreMap":31},[36,1067,1068,1070,1072,1075,1078],{"class":38,"line":39},[36,1069,43],{"class":42},[36,1071,353],{"class":46},[36,1073,1074],{"class":46}," status",[36,1076,1077],{"class":46}," myflaskapp",[36,1079,1080],{"class":64}," --no-pager\n",[14,1082,1083],{},"If the service does not stay active, go to the Debugging section below.",[587,1085,1087],{"id":1086},"_11-create-the-nginx-server-block","11. Create the Nginx server block",[14,1089,786,1090,673],{},[33,1091,1092],{},"\u002Fetc\u002Fnginx\u002Fsites-available\u002Fmyflaskapp",[26,1094,1098],{"className":1095,"code":1096,"language":1097,"meta":31,"style":31},"language-nginx shiki shiki-themes github-light github-dark","server {\n    listen 80;\n    server_name YOUR_DOMAIN_OR_IP;\n\n    location \u002F {\n        proxy_pass http:\u002F\u002F127.0.0.1:8000;\n        proxy_set_header Host $host;\n        proxy_set_header X-Real-IP $remote_addr;\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n        proxy_set_header X-Forwarded-Proto $scheme;\n    }\n}\n","nginx",[33,1099,1100,1104,1108,1113,1117,1121,1125,1129,1133,1137,1141,1145],{"__ignoreMap":31},[36,1101,1102],{"class":38,"line":39},[36,1103,401],{},[36,1105,1106],{"class":38,"line":80},[36,1107,407],{},[36,1109,1110],{"class":38,"line":102},[36,1111,1112],{},"    server_name YOUR_DOMAIN_OR_IP;\n",[36,1114,1115],{"class":38,"line":117},[36,1116,144],{"emptyLinePlaceholder":143},[36,1118,1119],{"class":38,"line":126},[36,1120,424],{},[36,1122,1123],{"class":38,"line":140},[36,1124,430],{},[36,1126,1127],{"class":38,"line":147},[36,1128,436],{},[36,1130,1131],{"class":38,"line":166},[36,1132,442],{},[36,1134,1135],{"class":38,"line":172},[36,1136,448],{},[36,1138,1139],{"class":38,"line":178},[36,1140,454],{},[36,1142,1143],{"class":38,"line":183},[36,1144,460],{},[36,1146,1147],{"class":38,"line":189},[36,1148,466],{},[14,1150,1151],{},"If you are deploying with IP only for the first test, use:",[26,1153,1155],{"className":1095,"code":1154,"language":1097,"meta":31,"style":31},"server_name _;\n",[33,1156,1157],{"__ignoreMap":31},[36,1158,1159],{"class":38,"line":39},[36,1160,1154],{},[587,1162,1164],{"id":1163},"_12-enable-the-site","12. Enable the site",[26,1166,1168],{"className":28,"code":1167,"language":30,"meta":31,"style":31},"sudo ln -s \u002Fetc\u002Fnginx\u002Fsites-available\u002Fmyflaskapp \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fmyflaskapp\n",[33,1169,1170],{"__ignoreMap":31},[36,1171,1172,1174,1176,1178,1181],{"class":38,"line":39},[36,1173,43],{"class":42},[36,1175,484],{"class":46},[36,1177,487],{"class":64},[36,1179,1180],{"class":46}," \u002Fetc\u002Fnginx\u002Fsites-available\u002Fmyflaskapp",[36,1182,1183],{"class":46}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fmyflaskapp\n",[587,1185,1187],{"id":1186},"_13-disable-the-default-nginx-site-if-needed","13. Disable the default Nginx site if needed",[26,1189,1191],{"className":28,"code":1190,"language":30,"meta":31,"style":31},"sudo rm -f \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fdefault\n",[33,1192,1193],{"__ignoreMap":31},[36,1194,1195,1197,1200,1203],{"class":38,"line":39},[36,1196,43],{"class":42},[36,1198,1199],{"class":46}," rm",[36,1201,1202],{"class":64}," -f",[36,1204,1205],{"class":46}," \u002Fetc\u002Fnginx\u002Fsites-enabled\u002Fdefault\n",[587,1207,1209],{"id":1208},"_14-validate-and-reload-nginx","14. Validate and reload Nginx",[26,1211,1213],{"className":28,"code":1212,"language":30,"meta":31,"style":31},"sudo nginx -t\nsudo systemctl reload nginx\n",[33,1214,1215,1224],{"__ignoreMap":31},[36,1216,1217,1219,1221],{"class":38,"line":39},[36,1218,43],{"class":42},[36,1220,500],{"class":46},[36,1222,1223],{"class":64}," -t\n",[36,1225,1226,1228,1230,1232],{"class":38,"line":80},[36,1227,43],{"class":42},[36,1229,353],{"class":46},[36,1231,512],{"class":46},[36,1233,77],{"class":46},[587,1235,1237],{"id":1236},"_15-open-firewall-rules-if-ufw-is-enabled","15. Open firewall rules if UFW is enabled",[26,1239,1241],{"className":28,"code":1240,"language":30,"meta":31,"style":31},"sudo ufw allow 'Nginx Full'\nsudo ufw allow OpenSSH\nsudo ufw status\n",[33,1242,1243,1256,1267],{"__ignoreMap":31},[36,1244,1245,1247,1250,1253],{"class":38,"line":39},[36,1246,43],{"class":42},[36,1248,1249],{"class":46}," ufw",[36,1251,1252],{"class":46}," allow",[36,1254,1255],{"class":46}," 'Nginx Full'\n",[36,1257,1258,1260,1262,1264],{"class":38,"line":80},[36,1259,43],{"class":42},[36,1261,1249],{"class":46},[36,1263,1252],{"class":46},[36,1265,1266],{"class":46}," OpenSSH\n",[36,1268,1269,1271,1273],{"class":38,"line":102},[36,1270,43],{"class":42},[36,1272,1249],{"class":46},[36,1274,1275],{"class":46}," status\n",[14,1277,1278,1279,1282,1283,1286],{},"If your provider has a cloud firewall, allow ports ",[33,1280,1281],{},"80"," and ",[33,1284,1285],{},"443"," there as well.",[587,1288,1290],{"id":1289},"_16-test-the-public-endpoint","16. Test the public endpoint",[26,1292,1294],{"className":28,"code":1293,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002FYOUR_SERVER_IP\n",[33,1295,1296],{"__ignoreMap":31},[36,1297,1298,1300,1302],{"class":38,"line":39},[36,1299,525],{"class":42},[36,1301,528],{"class":64},[36,1303,541],{"class":46},[14,1305,1306],{},"If DNS is already configured:",[26,1308,1310],{"className":28,"code":1309,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002FYOUR_DOMAIN\n",[33,1311,1312],{"__ignoreMap":31},[36,1313,1314,1316,1318],{"class":38,"line":39},[36,1315,525],{"class":42},[36,1317,528],{"class":64},[36,1319,1320],{"class":46}," http:\u002F\u002FYOUR_DOMAIN\n",[587,1322,1324],{"id":1323},"_17-add-static-file-handling-if-needed","17. Add static file handling if needed",[14,1326,1327],{},"Do not serve production static files through Flask unless required. Add an Nginx location block:",[26,1329,1331],{"className":1095,"code":1330,"language":1097,"meta":31,"style":31},"location \u002Fstatic\u002F {\n    alias \u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fstatic\u002F;\n}\n",[33,1332,1333,1338,1343],{"__ignoreMap":31},[36,1334,1335],{"class":38,"line":39},[36,1336,1337],{},"location \u002Fstatic\u002F {\n",[36,1339,1340],{"class":38,"line":80},[36,1341,1342],{},"    alias \u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fstatic\u002F;\n",[36,1344,1345],{"class":38,"line":102},[36,1346,466],{},[14,1348,1349],{},"For uploads or media:",[26,1351,1353],{"className":1095,"code":1352,"language":1097,"meta":31,"style":31},"location \u002Fuploads\u002F {\n    alias \u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fuploads\u002F;\n}\n",[33,1354,1355,1360,1365],{"__ignoreMap":31},[36,1356,1357],{"class":38,"line":39},[36,1358,1359],{},"location \u002Fuploads\u002F {\n",[36,1361,1362],{"class":38,"line":80},[36,1363,1364],{},"    alias \u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fuploads\u002F;\n",[36,1366,1367],{"class":38,"line":102},[36,1368,466],{},[14,1370,1371,1372,715],{},"If static files are not loading, see ",[1373,1374,1376],"a",{"href":1375},"\u002Ffix-issues\u002Fflask-static-files-not-loading-in-production","Flask Static Files Not Loading in Production",[587,1378,1380],{"id":1379},"_18-add-a-domain-and-https-after-http-works","18. Add a domain and HTTPS after HTTP works",[14,1382,1383],{},"Once the application works by IP or plain HTTP, configure your domain and DNS, then add TLS.",[14,1385,1386],{},"See:",[557,1388,1389,1395],{},[560,1390,1391],{},[1373,1392,1394],{"href":1393},"\u002Fdeploy\u002Fflask-domain-and-dns-setup-for-production","Flask Domain and DNS Setup for Production",[560,1396,1397],{},[1373,1398,1400],{"href":1399},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1402,1404],{"id":1403},"common-causes","Common Causes",[557,1406,1407,1422,1439,1449,1462,1468,1474,1488],{},[560,1408,1409,1416,1417,1419,1420,715],{},[563,1410,1411,1412,1415],{},"Wrong ",[33,1413,1414],{},"WorkingDirectory"," in systemd"," → Gunicorn cannot import the app → point ",[33,1418,1414],{}," to the folder containing your code and ",[33,1421,789],{},[560,1423,1424,1427,1428,1431,1432,1435,1436,715],{},[563,1425,1426],{},"Wrong WSGI module path"," → ",[33,1429,1430],{},"ModuleNotFoundError"," or service exits immediately → use the correct target such as ",[33,1433,1434],{},"wsgi:app"," or ",[33,1437,1438],{},"package_name.wsgi:app",[560,1440,1441,1444,1445,1448],{},[563,1442,1443],{},"Virtual environment not used"," → dependencies appear missing in production → set ",[33,1446,1447],{},"Environment=\"PATH=\u002Fpath\u002Fto\u002Fvenv\u002Fbin\""," and use the venv Gunicorn binary.",[560,1450,1451,1427,1454,1457,1458,1461],{},[563,1452,1453],{},"Nginx upstream mismatch",[33,1455,1456],{},"502 Bad Gateway"," or connection refused → make ",[33,1459,1460],{},"proxy_pass"," match the Gunicorn bind address or socket.",[560,1463,1464,1467],{},[563,1465,1466],{},"Port blocked by firewall"," → app works locally but not externally → allow HTTP and HTTPS in UFW or provider firewall rules.",[560,1469,1470,1473],{},[563,1471,1472],{},"Permissions issue on app files"," → Gunicorn cannot read code or write runtime files → ensure the service user can access the application directory.",[560,1475,1476,1479,1480,1483,1484,1487],{},[563,1477,1478],{},"Missing environment variables"," → app fails during import or startup → define ",[33,1481,1482],{},"Environment="," lines or ",[33,1485,1486],{},"EnvironmentFile="," in systemd and restart.",[560,1489,1490,1493],{},[563,1491,1492],{},"Default Nginx site still active"," → wrong site responds or config conflicts → remove or disable the default site.",[18,1495,1497],{"id":1496},"debugging","Debugging",[14,1499,1500],{},"Check these in order.",[587,1502,1504],{"id":1503},"systemd-service-status-and-logs","systemd service status and logs",[26,1506,1508],{"className":28,"code":1507,"language":30,"meta":31,"style":31},"sudo systemctl status myflaskapp --no-pager -l\nsudo journalctl -u myflaskapp -n 100 --no-pager\nsudo journalctl -u myflaskapp -f\n",[33,1509,1510,1526,1546],{"__ignoreMap":31},[36,1511,1512,1514,1516,1518,1520,1523],{"class":38,"line":39},[36,1513,43],{"class":42},[36,1515,353],{"class":46},[36,1517,1074],{"class":46},[36,1519,1077],{"class":46},[36,1521,1522],{"class":64}," --no-pager",[36,1524,1525],{"class":64}," -l\n",[36,1527,1528,1530,1533,1536,1538,1541,1544],{"class":38,"line":80},[36,1529,43],{"class":42},[36,1531,1532],{"class":46}," journalctl",[36,1534,1535],{"class":64}," -u",[36,1537,1077],{"class":46},[36,1539,1540],{"class":64}," -n",[36,1542,1543],{"class":64}," 100",[36,1545,1080],{"class":64},[36,1547,1548,1550,1552,1554,1556],{"class":38,"line":102},[36,1549,43],{"class":42},[36,1551,1532],{"class":46},[36,1553,1535],{"class":64},[36,1555,1077],{"class":46},[36,1557,1558],{"class":64}," -f\n",[14,1560,1561],{},"Look for:",[557,1563,1564,1567,1570,1573,1576],{},[560,1565,1566],{},"import errors",[560,1568,1569],{},"missing packages",[560,1571,1572],{},"bad paths",[560,1574,1575],{},"permission denied",[560,1577,1578],{},"environment variable errors",[587,1580,1582],{"id":1581},"nginx-configuration-and-logs","Nginx configuration and logs",[26,1584,1586],{"className":28,"code":1585,"language":30,"meta":31,"style":31},"sudo nginx -t\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\nsudo tail -n 100 \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\n",[33,1587,1588,1596,1610],{"__ignoreMap":31},[36,1589,1590,1592,1594],{"class":38,"line":39},[36,1591,43],{"class":42},[36,1593,500],{"class":46},[36,1595,1223],{"class":64},[36,1597,1598,1600,1603,1605,1607],{"class":38,"line":80},[36,1599,43],{"class":42},[36,1601,1602],{"class":46}," tail",[36,1604,1540],{"class":64},[36,1606,1543],{"class":64},[36,1608,1609],{"class":46}," \u002Fvar\u002Flog\u002Fnginx\u002Ferror.log\n",[36,1611,1612,1614,1616,1618,1620],{"class":38,"line":102},[36,1613,43],{"class":42},[36,1615,1602],{"class":46},[36,1617,1540],{"class":64},[36,1619,1543],{"class":64},[36,1621,1622],{"class":46}," \u002Fvar\u002Flog\u002Fnginx\u002Faccess.log\n",[14,1624,1561],{},[557,1626,1627,1630,1635,1638],{},[560,1628,1629],{},"upstream connection refused",[560,1631,1632,1633],{},"bad ",[33,1634,1460],{},[560,1636,1637],{},"syntax errors",[560,1639,1640,1641],{},"wrong ",[33,1642,547],{},[587,1644,1646],{"id":1645},"test-gunicorn-directly","Test Gunicorn directly",[26,1648,1650],{"className":28,"code":1649,"language":30,"meta":31,"style":31},"curl -I http:\u002F\u002F127.0.0.1:8000\nsudo ss -ltnp | grep 8000\n",[33,1651,1652,1660],{"__ignoreMap":31},[36,1653,1654,1656,1658],{"class":38,"line":39},[36,1655,525],{"class":42},[36,1657,528],{"class":64},[36,1659,531],{"class":46},[36,1661,1662,1664,1667,1670,1673,1676],{"class":38,"line":80},[36,1663,43],{"class":42},[36,1665,1666],{"class":46}," ss",[36,1668,1669],{"class":64}," -ltnp",[36,1671,1672],{"class":153}," |",[36,1674,1675],{"class":42}," grep",[36,1677,1678],{"class":64}," 8000\n",[14,1680,1681,1682,1685],{},"If nothing is listening on ",[33,1683,1684],{},"127.0.0.1:8000",", Gunicorn is not running or is bound somewhere else.",[587,1687,1689],{"id":1688},"verify-the-app-imports-from-the-deployment-directory","Verify the app imports from the deployment directory",[26,1691,1693],{"className":28,"code":1692,"language":30,"meta":31,"style":31},"cd \u002Fvar\u002Fwww\u002Fmyflaskapp\nsource venv\u002Fbin\u002Factivate\npython -c \"from wsgi import app; print(app)\"\n",[33,1694,1695,1701,1707],{"__ignoreMap":31},[36,1696,1697,1699],{"class":38,"line":39},[36,1698,96],{"class":64},[36,1700,657],{"class":46},[36,1702,1703,1705],{"class":38,"line":80},[36,1704,120],{"class":64},[36,1706,123],{"class":46},[36,1708,1709,1711,1714],{"class":38,"line":102},[36,1710,795],{"class":42},[36,1712,1713],{"class":64}," -c",[36,1715,1716],{"class":46}," \"from wsgi import app; print(app)\"\n",[14,1718,1719],{},"If this fails, fix the Python import path before troubleshooting Nginx.",[587,1721,1723],{"id":1722},"check-installed-packages-in-the-virtual-environment","Check installed packages in the virtual environment",[26,1725,1727],{"className":28,"code":1726,"language":30,"meta":31,"style":31},"\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fpip freeze\n",[33,1728,1729],{"__ignoreMap":31},[36,1730,1731,1734],{"class":38,"line":39},[36,1732,1733],{"class":42},"\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fpip",[36,1735,1736],{"class":46}," freeze\n",[587,1738,1740],{"id":1739},"if-using-a-unix-socket-instead-of-a-port","If using a Unix socket instead of a port",[26,1742,1744],{"className":28,"code":1743,"language":30,"meta":31,"style":31},"ls -lah \u002Frun\u002F | grep gunicorn\n",[33,1745,1746],{"__ignoreMap":31},[36,1747,1748,1751,1754,1757,1759,1761],{"class":38,"line":39},[36,1749,1750],{"class":42},"ls",[36,1752,1753],{"class":64}," -lah",[36,1755,1756],{"class":46}," \u002Frun\u002F",[36,1758,1672],{"class":153},[36,1760,1675],{"class":42},[36,1762,137],{"class":46},[14,1764,1765],{},"Check:",[557,1767,1768,1771,1774],{},[560,1769,1770],{},"socket file exists",[560,1772,1773],{},"Nginx points to the same socket",[560,1775,1776],{},"socket permissions allow Nginx access",[14,1778,1779,1780,715],{},"If Nginx returns a 502, see ",[1373,1781,1783],{"href":1782},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",[18,1785,1787],{"id":1786},"checklist","Checklist",[557,1789,1792,1801,1807,1813,1819,1825,1834,1840,1846,1855,1861],{"className":1790},[1791],"contains-task-list",[560,1793,1796,1800],{"className":1794},[1795],"task-list-item",[1797,1798],"input",{"disabled":143,"type":1799},"checkbox"," Ubuntu packages are installed and updated",[560,1802,1804,1806],{"className":1803},[1795],[1797,1805],{"disabled":143,"type":1799}," Project files are present in the deployment directory",[560,1808,1810,1812],{"className":1809},[1795],[1797,1811],{"disabled":143,"type":1799}," Virtual environment exists and all dependencies are installed",[560,1814,1816,1818],{"className":1815},[1795],[1797,1817],{"disabled":143,"type":1799}," Gunicorn starts successfully with the correct WSGI target",[560,1820,1822,1824],{"className":1821},[1795],[1797,1823],{"disabled":143,"type":1799}," systemd service is enabled and running",[560,1826,1828,1830,1831],{"className":1827},[1795],[1797,1829],{"disabled":143,"type":1799}," Nginx config passes ",[33,1832,1833],{},"sudo nginx -t",[560,1835,1837,1839],{"className":1836},[1795],[1797,1838],{"disabled":143,"type":1799}," Nginx proxies to the correct Gunicorn port or socket",[560,1841,1843,1845],{"className":1842},[1795],[1797,1844],{"disabled":143,"type":1799}," Firewall allows HTTP or HTTPS traffic",[560,1847,1849,1851,1852,1854],{"className":1848},[1795],[1797,1850],{"disabled":143,"type":1799}," ",[33,1853,525],{}," to localhost and the public endpoint returns the expected response",[560,1856,1858,1860],{"className":1857},[1795],[1797,1859],{"disabled":143,"type":1799}," App environment variables are loaded in production",[560,1862,1864,1866],{"className":1863},[1795],[1797,1865],{"disabled":143,"type":1799}," Static and media handling is configured separately if needed",[14,1868,1869,1870,715],{},"For final hardening and launch checks, use ",[1373,1871,1400],{"href":1399},[18,1873,1875],{"id":1874},"related-guides","Related Guides",[557,1877,1878,1882,1886],{},[560,1879,1880],{},[1373,1881,1783],{"href":1782},[560,1883,1884],{},[1373,1885,1400],{"href":1399},[560,1887,1888],{},[1373,1889,1394],{"href":1393},[18,1891,1893],{"id":1892},"faq","FAQ",[587,1895,1897],{"id":1896},"what-is-the-minimum-production-stack-for-flask-on-ubuntu","What is the minimum production stack for Flask on Ubuntu?",[14,1899,1900],{},"Gunicorn to run the app, systemd to manage the service, and Nginx to reverse proxy public traffic.",[587,1902,1904],{"id":1903},"should-i-use-a-port-or-a-unix-socket-for-gunicorn","Should I use a port or a Unix socket for Gunicorn?",[14,1906,1907],{},"Either works. A local TCP port is simpler to debug first. A Unix socket is common after the app is stable.",[587,1909,1911],{"id":1910},"why-am-i-getting-a-502-after-deployment","Why am I getting a 502 after deployment?",[14,1913,1914],{},"Usually Nginx cannot reach Gunicorn because the service is down, the bind target is wrong, or permissions prevent access.",[587,1916,1918],{"id":1917},"where-do-i-put-environment-variables","Where do I put environment variables?",[14,1920,1921,1922,1924,1925,1927],{},"In the systemd service with ",[33,1923,1482],{}," entries or an ",[33,1926,1486],{}," referenced by the service.",[587,1929,1931],{"id":1930},"do-i-need-https-before-testing-deployment","Do I need HTTPS before testing deployment?",[14,1933,1934],{},"No. Validate the app over HTTP first, then add a domain and HTTPS once the stack is working.",[18,1936,1938],{"id":1937},"final-takeaway","Final Takeaway",[14,1940,1941],{},"A reliable Flask deployment on an Ubuntu VPS depends on four aligned pieces: application path, Python environment, Gunicorn service definition, and Nginx upstream configuration. If the app runs correctly under Gunicorn and systemd manages it cleanly, Nginx becomes straightforward to validate and expose publicly.",[1943,1944,1945],"style",{},"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);}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 .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}",{"title":31,"searchDepth":80,"depth":80,"links":1947},[1948,1949,1950,1970,1971,1979,1980,1981,1988],{"id":20,"depth":80,"text":21},{"id":551,"depth":80,"text":552},{"id":584,"depth":80,"text":585,"children":1951},[1952,1953,1954,1955,1956,1957,1958,1959,1960,1961,1962,1963,1964,1965,1966,1967,1968,1969],{"id":589,"depth":102,"text":590},{"id":640,"depth":102,"text":641},{"id":688,"depth":102,"text":689},{"id":718,"depth":102,"text":719},{"id":782,"depth":102,"text":783},{"id":863,"depth":102,"text":864},{"id":889,"depth":102,"text":890},{"id":922,"depth":102,"text":923},{"id":1029,"depth":102,"text":1030},{"id":1059,"depth":102,"text":1060},{"id":1086,"depth":102,"text":1087},{"id":1163,"depth":102,"text":1164},{"id":1186,"depth":102,"text":1187},{"id":1208,"depth":102,"text":1209},{"id":1236,"depth":102,"text":1237},{"id":1289,"depth":102,"text":1290},{"id":1323,"depth":102,"text":1324},{"id":1379,"depth":102,"text":1380},{"id":1403,"depth":80,"text":1404},{"id":1496,"depth":80,"text":1497,"children":1972},[1973,1974,1975,1976,1977,1978],{"id":1503,"depth":102,"text":1504},{"id":1581,"depth":102,"text":1582},{"id":1645,"depth":102,"text":1646},{"id":1688,"depth":102,"text":1689},{"id":1722,"depth":102,"text":1723},{"id":1739,"depth":102,"text":1740},{"id":1786,"depth":80,"text":1787},{"id":1874,"depth":80,"text":1875},{"id":1892,"depth":80,"text":1893,"children":1982},[1983,1984,1985,1986,1987],{"id":1896,"depth":102,"text":1897},{"id":1903,"depth":102,"text":1904},{"id":1910,"depth":102,"text":1911},{"id":1917,"depth":102,"text":1918},{"id":1930,"depth":102,"text":1931},{"id":1937,"depth":80,"text":1938},"Complete guide on deploy flask on ubuntu vps (step-by-step) for Flask production environments.","md",{"ogTitle":5,"ogDescription":1989,"twitterCard":1992,"robots":1993,"canonical":1994},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Fdeploy\u002Fdeploy-flask-on-ubuntu-vps-step-by-step","\u002Fdeploy\u002Fdeploy-flask-on-ubuntu-vps-step-by-step",{"title":5,"description":1989},"deploy\u002Fdeploy-flask-on-ubuntu-vps-step-by-step","lD8-7NDr0vXgCX-N_iGwY6q3W4NGmkpQajvLD2ijriU",1776805765065]