[{"data":1,"prerenderedAt":1544},["ShallowReactive",2],{"\u002Fdeploy\u002Fflask-systemd-plus-gunicorn-service-setup":3},{"id":4,"title":5,"body":6,"description":1534,"extension":1535,"meta":1536,"navigation":91,"path":1540,"seo":1541,"stem":1542,"__hash__":1543},"content\u002Fdeploy\u002Fflask-systemd-plus-gunicorn-service-setup.md","Flask systemd + Gunicorn Service Setup",{"type":7,"value":8,"toc":1523},"minimark",[9,13,22,27,30,225,240,244,265,269,633,667,677,697,700,713,723,750,753,775,782,810,817,842,852,875,884,888,1003,1007,1010,1027,1030,1050,1053,1071,1074,1090,1093,1115,1118,1135,1138,1150,1153,1169,1172,1195,1198,1222,1225,1240,1243,1272,1284,1288,1365,1372,1376,1394,1398,1410,1422,1434,1445,1462,1470,1478,1490,1504,1512,1516,1519],[10,11,5],"h1",{"id":12},"flask-systemd-gunicorn-service-setup",[14,15,16,17,21],"p",{},"If you're trying to run a Flask app under Gunicorn as a managed Linux service, this guide shows you how to set up systemd step-by-step. The goal is a reliable service that starts on boot, restarts on failure, and can be controlled with standard ",[18,19,20],"code",{},"systemctl"," commands.",[23,24,26],"h2",{"id":25},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,28,29],{},"Create a basic systemd unit, reload systemd, start the service, and verify the socket:",[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\u002Fsystemd\u002Fsystem\u002Fmyflask.service > \u002Fdev\u002Fnull \u003C\u003C'EOF'\n[Unit]\nDescription=Gunicorn service for Flask app\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fsrv\u002Fmyflask\nEnvironment=\"PATH=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\"\nExecStart=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind unix:\u002Frun\u002Fmyflask.sock wsgi:app\nRestart=always\nRestartSec=3\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsudo systemctl daemon-reload\nsudo systemctl enable --now myflask\nsudo systemctl status myflask --no-pager\nls -l \u002Frun\u002Fmyflask.sock\n","bash","",[18,38,39,68,74,80,86,93,99,105,111,117,123,129,135,141,146,152,158,164,169,180,197,213],{"__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\u002Fsystemd\u002Fsystem\u002Fmyflask.service",[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},"[Unit]\n",[40,75,77],{"class":42,"line":76},3,[40,78,79],{"class":50},"Description=Gunicorn service for Flask app\n",[40,81,83],{"class":42,"line":82},4,[40,84,85],{"class":50},"After=network.target\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},"[Service]\n",[40,100,102],{"class":42,"line":101},7,[40,103,104],{"class":50},"User=www-data\n",[40,106,108],{"class":42,"line":107},8,[40,109,110],{"class":50},"Group=www-data\n",[40,112,114],{"class":42,"line":113},9,[40,115,116],{"class":50},"WorkingDirectory=\u002Fsrv\u002Fmyflask\n",[40,118,120],{"class":42,"line":119},10,[40,121,122],{"class":50},"Environment=\"PATH=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\"\n",[40,124,126],{"class":42,"line":125},11,[40,127,128],{"class":50},"ExecStart=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind unix:\u002Frun\u002Fmyflask.sock wsgi:app\n",[40,130,132],{"class":42,"line":131},12,[40,133,134],{"class":50},"Restart=always\n",[40,136,138],{"class":42,"line":137},13,[40,139,140],{"class":50},"RestartSec=3\n",[40,142,144],{"class":42,"line":143},14,[40,145,92],{"emptyLinePlaceholder":91},[40,147,149],{"class":42,"line":148},15,[40,150,151],{"class":50},"[Install]\n",[40,153,155],{"class":42,"line":154},16,[40,156,157],{"class":50},"WantedBy=multi-user.target\n",[40,159,161],{"class":42,"line":160},17,[40,162,163],{"class":50},"EOF\n",[40,165,167],{"class":42,"line":166},18,[40,168,92],{"emptyLinePlaceholder":91},[40,170,172,174,177],{"class":42,"line":171},19,[40,173,47],{"class":46},[40,175,176],{"class":50}," systemctl",[40,178,179],{"class":50}," daemon-reload\n",[40,181,183,185,187,190,194],{"class":42,"line":182},20,[40,184,47],{"class":46},[40,186,176],{"class":50},[40,188,189],{"class":50}," enable",[40,191,193],{"class":192},"sj4cs"," --now",[40,195,196],{"class":50}," myflask\n",[40,198,200,202,204,207,210],{"class":42,"line":199},21,[40,201,47],{"class":46},[40,203,176],{"class":50},[40,205,206],{"class":50}," status",[40,208,209],{"class":50}," myflask",[40,211,212],{"class":192}," --no-pager\n",[40,214,216,219,222],{"class":42,"line":215},22,[40,217,218],{"class":46},"ls",[40,220,221],{"class":192}," -l",[40,223,224],{"class":50}," \u002Frun\u002Fmyflask.sock\n",[14,226,227,228,231,232,235,236,239],{},"Replace ",[18,229,230],{},"\u002Fsrv\u002Fmyflask",", the virtualenv path, service name, socket path, and ",[18,233,234],{},"wsgi:app"," with your actual project values. Use a TCP bind like ",[18,237,238],{},"127.0.0.1:8000"," instead of a Unix socket if that matches your Nginx setup.",[23,241,243],{"id":242},"whats-happening","What’s Happening",[245,246,247,254,257,262],"ul",{},[248,249,250,253],"li",{},[18,251,252],{},"systemd"," runs Gunicorn as a managed background service.",[248,255,256],{},"Gunicorn serves the Flask WSGI app and listens on a Unix socket or local TCP port.",[248,258,259,261],{},[18,260,252],{}," handles startup order, restarts, logs, and boot-time enablement.",[248,263,264],{},"Most failures come from incorrect paths, wrong WSGI entrypoint, missing virtualenv dependencies, or socket permission mismatches.",[23,266,268],{"id":267},"step-by-step-guide","Step-by-Step Guide",[270,271,272,320,366,401,421,501,569,587,608,628],"ol",{},[248,273,274,278,281,282,317,319],{},[275,276,277],"strong",{},"Verify the Flask app runs manually",[279,280],"br",{},"Confirm the app works before introducing systemd:",[31,283,285],{"className":33,"code":284,"language":35,"meta":36,"style":36},"source \u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Factivate\ncd \u002Fsrv\u002Fmyflask\ngunicorn --bind 127.0.0.1:8000 wsgi:app\n",[18,286,287,295,303],{"__ignoreMap":36},[40,288,289,292],{"class":42,"line":43},[40,290,291],{"class":192},"source",[40,293,294],{"class":50}," \u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Factivate\n",[40,296,297,300],{"class":42,"line":70},[40,298,299],{"class":192},"cd",[40,301,302],{"class":50}," \u002Fsrv\u002Fmyflask\n",[40,304,305,308,311,314],{"class":42,"line":76},[40,306,307],{"class":46},"gunicorn",[40,309,310],{"class":192}," --bind",[40,312,313],{"class":50}," 127.0.0.1:8000",[40,315,316],{"class":50}," wsgi:app\n",[279,318],{},"If this fails, fix the app import or dependencies first.",[248,321,322,325,327,328,331,332,354,356,357],{},[275,323,324],{},"Create or verify the WSGI entrypoint",[279,326],{},"Example ",[18,329,330],{},"wsgi.py",":",[31,333,337],{"className":334,"code":335,"language":336,"meta":36,"style":36},"language-python shiki shiki-themes github-light github-dark","from app import app\n","python",[18,338,339],{"__ignoreMap":36},[40,340,341,344,348,351],{"class":42,"line":43},[40,342,343],{"class":57},"from",[40,345,347],{"class":346},"sVt8B"," app ",[40,349,350],{"class":57},"import",[40,352,353],{"class":346}," app\n",[279,355],{},"Your Gunicorn target must match this file and object:",[31,358,360],{"className":33,"code":359,"language":35,"meta":36,"style":36},"wsgi:app\n",[18,361,362],{"__ignoreMap":36},[40,363,364],{"class":42,"line":43},[40,365,359],{"class":46},[248,367,368,371,373,374,376,377,386,388,389,398,400],{},[275,369,370],{},"Choose a bind method",[279,372],{},"Use one of these:",[279,375],{},"Unix socket:",[31,378,380],{"className":33,"code":379,"language":35,"meta":36,"style":36},"unix:\u002Frun\u002Fmyflask.sock\n",[18,381,382],{"__ignoreMap":36},[40,383,384],{"class":42,"line":43},[40,385,379],{"class":46},[279,387],{},"TCP:",[31,390,392],{"className":33,"code":391,"language":35,"meta":36,"style":36},"127.0.0.1:8000\n",[18,393,394],{"__ignoreMap":36},[40,395,396],{"class":42,"line":43},[40,397,391],{"class":46},[279,399],{},"Match this exactly in your Nginx upstream configuration.",[248,402,403,406],{},[275,404,405],{},"Create the systemd unit file",[31,407,409],{"className":33,"code":408,"language":35,"meta":36,"style":36},"sudo nano \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflask.service\n",[18,410,411],{"__ignoreMap":36},[40,412,413,415,418],{"class":42,"line":43},[40,414,47],{"class":46},[40,416,417],{"class":50}," nano",[40,419,420],{"class":50}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflask.service\n",[248,422,423,426,428,429],{},[275,424,425],{},"Add the unit configuration",[279,427],{},"Recommended example:",[31,430,434],{"className":431,"code":432,"language":433,"meta":36,"style":36},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=Gunicorn service for Flask app\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fsrv\u002Fmyflask\nEnvironment=\"PATH=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\"\nEnvironment=\"FLASK_ENV=production\"\nExecStart=\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn --workers 3 --bind unix:\u002Frun\u002Fmyflask.sock wsgi:app\nRestart=always\nRestartSec=3\n\n[Install]\nWantedBy=multi-user.target\n","ini",[18,435,436,440,444,448,452,456,460,464,468,472,477,481,485,489,493,497],{"__ignoreMap":36},[40,437,438],{"class":42,"line":43},[40,439,73],{},[40,441,442],{"class":42,"line":70},[40,443,79],{},[40,445,446],{"class":42,"line":76},[40,447,85],{},[40,449,450],{"class":42,"line":82},[40,451,92],{"emptyLinePlaceholder":91},[40,453,454],{"class":42,"line":88},[40,455,98],{},[40,457,458],{"class":42,"line":95},[40,459,104],{},[40,461,462],{"class":42,"line":101},[40,463,110],{},[40,465,466],{"class":42,"line":107},[40,467,116],{},[40,469,470],{"class":42,"line":113},[40,471,122],{},[40,473,474],{"class":42,"line":119},[40,475,476],{},"Environment=\"FLASK_ENV=production\"\n",[40,478,479],{"class":42,"line":125},[40,480,128],{},[40,482,483],{"class":42,"line":131},[40,484,134],{},[40,486,487],{"class":42,"line":137},[40,488,140],{},[40,490,491],{"class":42,"line":143},[40,492,92],{"emptyLinePlaceholder":91},[40,494,495],{"class":42,"line":148},[40,496,151],{},[40,498,499],{"class":42,"line":154},[40,500,157],{},[248,502,503,506,508,509,512,513,515,516,552,554,555],{},[275,504,505],{},"Add environment variables if needed",[279,507],{},"If your app depends on secrets or database settings, use inline ",[18,510,511],{},"Environment="," values or an environment file.",[279,514],{},"Example environment file:",[31,517,519],{"className":33,"code":518,"language":35,"meta":36,"style":36},"sudo tee \u002Fetc\u002Fmyflask.env > \u002Fdev\u002Fnull \u003C\u003C'EOF'\nSECRET_KEY=change-me\nDATABASE_URL=postgresql:\u002F\u002Fuser:pass@localhost\u002Fdbname\nEOF\n",[18,520,521,538,543,548],{"__ignoreMap":36},[40,522,523,525,527,530,532,534,536],{"class":42,"line":43},[40,524,47],{"class":46},[40,526,51],{"class":50},[40,528,529],{"class":50}," \u002Fetc\u002Fmyflask.env",[40,531,58],{"class":57},[40,533,61],{"class":50},[40,535,64],{"class":57},[40,537,67],{"class":50},[40,539,540],{"class":42,"line":70},[40,541,542],{"class":50},"SECRET_KEY=change-me\n",[40,544,545],{"class":42,"line":76},[40,546,547],{"class":50},"DATABASE_URL=postgresql:\u002F\u002Fuser:pass@localhost\u002Fdbname\n",[40,549,550],{"class":42,"line":82},[40,551,163],{"class":50},[279,553],{},"Then update the service:",[31,556,558],{"className":431,"code":557,"language":433,"meta":36,"style":36},"[Service]\nEnvironmentFile=\u002Fetc\u002Fmyflask.env\n",[18,559,560,564],{"__ignoreMap":36},[40,561,562],{"class":42,"line":43},[40,563,98],{},[40,565,566],{"class":42,"line":70},[40,567,568],{},"EnvironmentFile=\u002Fetc\u002Fmyflask.env\n",[248,570,571,574],{},[275,572,573],{},"Reload systemd",[31,575,577],{"className":33,"code":576,"language":35,"meta":36,"style":36},"sudo systemctl daemon-reload\n",[18,578,579],{"__ignoreMap":36},[40,580,581,583,585],{"class":42,"line":43},[40,582,47],{"class":46},[40,584,176],{"class":50},[40,586,179],{"class":50},[248,588,589,592],{},[275,590,591],{},"Start the service",[31,593,595],{"className":33,"code":594,"language":35,"meta":36,"style":36},"sudo systemctl start myflask\n",[18,596,597],{"__ignoreMap":36},[40,598,599,601,603,606],{"class":42,"line":43},[40,600,47],{"class":46},[40,602,176],{"class":50},[40,604,605],{"class":50}," start",[40,607,196],{"class":50},[248,609,610,613],{},[275,611,612],{},"Enable the service at boot",[31,614,616],{"className":33,"code":615,"language":35,"meta":36,"style":36},"sudo systemctl enable myflask\n",[18,617,618],{"__ignoreMap":36},[40,619,620,622,624,626],{"class":42,"line":43},[40,621,47],{"class":46},[40,623,176],{"class":50},[40,625,189],{"class":50},[40,627,196],{"class":50},[248,629,630],{},[275,631,632],{},"Verify the service state",[31,634,636],{"className":33,"code":635,"language":35,"meta":36,"style":36},"sudo systemctl status myflask --no-pager\nps aux | grep gunicorn\n",[18,637,638,650],{"__ignoreMap":36},[40,639,640,642,644,646,648],{"class":42,"line":43},[40,641,47],{"class":46},[40,643,176],{"class":50},[40,645,206],{"class":50},[40,647,209],{"class":50},[40,649,212],{"class":192},[40,651,652,655,658,661,664],{"class":42,"line":70},[40,653,654],{"class":46},"ps",[40,656,657],{"class":50}," aux",[40,659,660],{"class":57}," |",[40,662,663],{"class":46}," grep",[40,665,666],{"class":50}," gunicorn\n",[270,668,669],{"start":125},[248,670,671,674,676],{},[275,672,673],{},"Verify the listener",[279,675],{},"For TCP:",[31,678,680],{"className":33,"code":679,"language":35,"meta":36,"style":36},"ss -ltnp | grep 8000\n",[18,681,682],{"__ignoreMap":36},[40,683,684,687,690,692,694],{"class":42,"line":43},[40,685,686],{"class":46},"ss",[40,688,689],{"class":192}," -ltnp",[40,691,660],{"class":57},[40,693,663],{"class":46},[40,695,696],{"class":192}," 8000\n",[14,698,699],{},"For Unix socket:",[31,701,703],{"className":33,"code":702,"language":35,"meta":36,"style":36},"ls -l \u002Frun\u002Fmyflask.sock\n",[18,704,705],{"__ignoreMap":36},[40,706,707,709,711],{"class":42,"line":43},[40,708,218],{"class":46},[40,710,221],{"class":192},[40,712,224],{"class":50},[270,714,715],{"start":131},[248,716,717,720,722],{},[275,718,719],{},"Confirm Nginx points to the same upstream",[279,721],{},"Example Nginx upstream for Unix socket:",[31,724,728],{"className":725,"code":726,"language":727,"meta":36,"style":36},"language-nginx shiki shiki-themes github-light github-dark","location \u002F {\n    proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fmyflask.sock;\n    include proxy_params;\n}\n","nginx",[18,729,730,735,740,745],{"__ignoreMap":36},[40,731,732],{"class":42,"line":43},[40,733,734],{},"location \u002F {\n",[40,736,737],{"class":42,"line":70},[40,738,739],{},"    proxy_pass http:\u002F\u002Funix:\u002Frun\u002Fmyflask.sock;\n",[40,741,742],{"class":42,"line":76},[40,743,744],{},"    include proxy_params;\n",[40,746,747],{"class":42,"line":82},[40,748,749],{},"}\n",[14,751,752],{},"Example Nginx upstream for TCP:",[31,754,756],{"className":725,"code":755,"language":727,"meta":36,"style":36},"location \u002F {\n    proxy_pass http:\u002F\u002F127.0.0.1:8000;\n    include proxy_params;\n}\n",[18,757,758,762,767,771],{"__ignoreMap":36},[40,759,760],{"class":42,"line":43},[40,761,734],{},[40,763,764],{"class":42,"line":70},[40,765,766],{},"    proxy_pass http:\u002F\u002F127.0.0.1:8000;\n",[40,768,769],{"class":42,"line":76},[40,770,744],{},[40,772,773],{"class":42,"line":82},[40,774,749],{},[270,776,777],{"start":137},[248,778,779],{},[275,780,781],{},"Test restart behavior",[31,783,785],{"className":33,"code":784,"language":35,"meta":36,"style":36},"sudo systemctl restart myflask\nsudo systemctl status myflask --no-pager\n",[18,786,787,798],{"__ignoreMap":36},[40,788,789,791,793,796],{"class":42,"line":43},[40,790,47],{"class":46},[40,792,176],{"class":50},[40,794,795],{"class":50}," restart",[40,797,196],{"class":50},[40,799,800,802,804,806,808],{"class":42,"line":70},[40,801,47],{"class":46},[40,803,176],{"class":50},[40,805,206],{"class":50},[40,807,209],{"class":50},[40,809,212],{"class":192},[270,811,812],{"start":143},[248,813,814],{},[275,815,816],{},"Review logs for startup and import errors",[31,818,820],{"className":33,"code":819,"language":35,"meta":36,"style":36},"sudo journalctl -u myflask -n 100 --no-pager\n",[18,821,822],{"__ignoreMap":36},[40,823,824,826,829,832,834,837,840],{"class":42,"line":43},[40,825,47],{"class":46},[40,827,828],{"class":50}," journalctl",[40,830,831],{"class":192}," -u",[40,833,209],{"class":50},[40,835,836],{"class":192}," -n",[40,838,839],{"class":192}," 100",[40,841,212],{"class":192},[270,843,844],{"start":148},[248,845,846,849,851],{},[275,847,848],{},"Apply updates safely after unit changes",[279,850],{},"If you edit the service file again:",[31,853,855],{"className":33,"code":854,"language":35,"meta":36,"style":36},"sudo systemctl daemon-reload\nsudo systemctl restart myflask\n",[18,856,857,865],{"__ignoreMap":36},[40,858,859,861,863],{"class":42,"line":43},[40,860,47],{"class":46},[40,862,176],{"class":50},[40,864,179],{"class":50},[40,866,867,869,871,873],{"class":42,"line":70},[40,868,47],{"class":46},[40,870,176],{"class":50},[40,872,795],{"class":50},[40,874,196],{"class":50},[14,876,877,878,883],{},"For full reverse proxy setup, see ",[879,880,882],"a",{"href":881},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",".",[23,885,887],{"id":886},"common-causes","Common Causes",[245,889,890,909,923,934,946,956,970,982],{},[248,891,892,899,900],{},[275,893,894,895,898],{},"Wrong ",[18,896,897],{},"ExecStart"," path"," → systemd cannot find Gunicorn → use the full virtualenv binary path such as:",[31,901,903],{"className":33,"code":902,"language":35,"meta":36,"style":36},"\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn\n",[18,904,905],{"__ignoreMap":36},[40,906,907],{"class":42,"line":43},[40,908,902],{"class":46},[248,910,911,914,915],{},[275,912,913],{},"Incorrect WSGI target"," → Gunicorn cannot import the app → verify the module and object, for example:",[31,916,917],{"className":33,"code":359,"language":35,"meta":36,"style":36},[18,918,919],{"__ignoreMap":36},[40,920,921],{"class":42,"line":43},[40,922,359],{"class":46},[248,924,925,930,931,933],{},[275,926,894,927],{},[18,928,929],{},"WorkingDirectory"," → relative imports or file paths fail → point ",[18,932,929],{}," to the project root.",[248,935,936,939,940,942,943,883],{},[275,937,938],{},"Environment variables missing under systemd"," → app starts manually but fails as a service → add ",[18,941,511],{}," lines or ",[18,944,945],{},"EnvironmentFile=",[248,947,948,951,952,883],{},[275,949,950],{},"Socket path mismatch with Nginx"," → service runs but Nginx returns 502 → make the Gunicorn bind path match the Nginx upstream exactly. See ",[879,953,955],{"href":954},"\u002Ffix-issues\u002Ffix-flask-502-bad-gateway-step-by-step-guide","Fix Flask 502 Bad Gateway (Step-by-Step Guide)",[248,957,958,961,962,965,966,969],{},[275,959,960],{},"Permission issue on Unix socket or app files"," → Nginx or Gunicorn cannot access required paths → align ",[18,963,964],{},"User",", ",[18,967,968],{},"Group",", and file permissions.",[248,971,972,975,976,979,980,883],{},[275,973,974],{},"Virtualenv dependencies not installed"," → worker boot fails with ",[18,977,978],{},"ModuleNotFoundError"," → install dependencies inside the same virtualenv used by ",[18,981,897],{},[248,983,984,990,991],{},[275,985,986,987],{},"Service edited without ",[18,988,989],{},"daemon-reload"," → changes do not apply → run:",[31,992,993],{"className":33,"code":576,"language":35,"meta":36,"style":36},[18,994,995],{"__ignoreMap":36},[40,996,997,999,1001],{"class":42,"line":43},[40,998,47],{"class":46},[40,1000,176],{"class":50},[40,1002,179],{"class":50},[23,1004,1006],{"id":1005},"debugging-section","Debugging Section",[14,1008,1009],{},"Check service status:",[31,1011,1013],{"className":33,"code":1012,"language":35,"meta":36,"style":36},"sudo systemctl status myflask --no-pager\n",[18,1014,1015],{"__ignoreMap":36},[40,1016,1017,1019,1021,1023,1025],{"class":42,"line":43},[40,1018,47],{"class":46},[40,1020,176],{"class":50},[40,1022,206],{"class":50},[40,1024,209],{"class":50},[40,1026,212],{"class":192},[14,1028,1029],{},"Read recent logs:",[31,1031,1032],{"className":33,"code":819,"language":35,"meta":36,"style":36},[18,1033,1034],{"__ignoreMap":36},[40,1035,1036,1038,1040,1042,1044,1046,1048],{"class":42,"line":43},[40,1037,47],{"class":46},[40,1039,828],{"class":50},[40,1041,831],{"class":192},[40,1043,209],{"class":50},[40,1045,836],{"class":192},[40,1047,839],{"class":192},[40,1049,212],{"class":192},[14,1051,1052],{},"Follow logs live:",[31,1054,1056],{"className":33,"code":1055,"language":35,"meta":36,"style":36},"sudo journalctl -u myflask -f\n",[18,1057,1058],{"__ignoreMap":36},[40,1059,1060,1062,1064,1066,1068],{"class":42,"line":43},[40,1061,47],{"class":46},[40,1063,828],{"class":50},[40,1065,831],{"class":192},[40,1067,209],{"class":50},[40,1069,1070],{"class":192}," -f\n",[14,1072,1073],{},"Show the loaded service file:",[31,1075,1077],{"className":33,"code":1076,"language":35,"meta":36,"style":36},"sudo systemctl cat myflask\n",[18,1078,1079],{"__ignoreMap":36},[40,1080,1081,1083,1085,1088],{"class":42,"line":43},[40,1082,47],{"class":46},[40,1084,176],{"class":50},[40,1086,1087],{"class":50}," cat",[40,1089,196],{"class":50},[14,1091,1092],{},"Reload and restart after changes:",[31,1094,1095],{"className":33,"code":854,"language":35,"meta":36,"style":36},[18,1096,1097,1105],{"__ignoreMap":36},[40,1098,1099,1101,1103],{"class":42,"line":43},[40,1100,47],{"class":46},[40,1102,176],{"class":50},[40,1104,179],{"class":50},[40,1106,1107,1109,1111,1113],{"class":42,"line":70},[40,1108,47],{"class":46},[40,1110,176],{"class":50},[40,1112,795],{"class":50},[40,1114,196],{"class":50},[14,1116,1117],{},"Check running Gunicorn processes:",[31,1119,1121],{"className":33,"code":1120,"language":35,"meta":36,"style":36},"ps aux | grep gunicorn\n",[18,1122,1123],{"__ignoreMap":36},[40,1124,1125,1127,1129,1131,1133],{"class":42,"line":43},[40,1126,654],{"class":46},[40,1128,657],{"class":50},[40,1130,660],{"class":57},[40,1132,663],{"class":46},[40,1134,666],{"class":50},[14,1136,1137],{},"Check Unix socket:",[31,1139,1140],{"className":33,"code":702,"language":35,"meta":36,"style":36},[18,1141,1142],{"__ignoreMap":36},[40,1143,1144,1146,1148],{"class":42,"line":43},[40,1145,218],{"class":46},[40,1147,221],{"class":192},[40,1149,224],{"class":50},[14,1151,1152],{},"Check TCP listener:",[31,1154,1155],{"className":33,"code":679,"language":35,"meta":36,"style":36},[18,1156,1157],{"__ignoreMap":36},[40,1158,1159,1161,1163,1165,1167],{"class":42,"line":43},[40,1160,686],{"class":46},[40,1162,689],{"class":192},[40,1164,660],{"class":57},[40,1166,663],{"class":46},[40,1168,696],{"class":192},[14,1170,1171],{},"Test as the service user:",[31,1173,1175],{"className":33,"code":1174,"language":35,"meta":36,"style":36},"sudo -u www-data \u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn --bind 127.0.0.1:8000 wsgi:app\n",[18,1176,1177],{"__ignoreMap":36},[40,1178,1179,1181,1183,1186,1189,1191,1193],{"class":42,"line":43},[40,1180,47],{"class":46},[40,1182,831],{"class":192},[40,1184,1185],{"class":50}," www-data",[40,1187,1188],{"class":50}," \u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fgunicorn",[40,1190,310],{"class":192},[40,1192,313],{"class":50},[40,1194,316],{"class":50},[14,1196,1197],{},"Test Python import directly:",[31,1199,1201],{"className":33,"code":1200,"language":35,"meta":36,"style":36},"cd \u002Fsrv\u002Fmyflask && \u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fpython -c \"import wsgi; print(wsgi.app)\"\n",[18,1202,1203],{"__ignoreMap":36},[40,1204,1205,1207,1210,1213,1216,1219],{"class":42,"line":43},[40,1206,299],{"class":192},[40,1208,1209],{"class":50}," \u002Fsrv\u002Fmyflask",[40,1211,1212],{"class":346}," && ",[40,1214,1215],{"class":46},"\u002Fsrv\u002Fmyflask\u002Fvenv\u002Fbin\u002Fpython",[40,1217,1218],{"class":192}," -c",[40,1220,1221],{"class":50}," \"import wsgi; print(wsgi.app)\"\n",[14,1223,1224],{},"Validate Nginx config:",[31,1226,1228],{"className":33,"code":1227,"language":35,"meta":36,"style":36},"sudo nginx -t\n",[18,1229,1230],{"__ignoreMap":36},[40,1231,1232,1234,1237],{"class":42,"line":43},[40,1233,47],{"class":46},[40,1235,1236],{"class":50}," nginx",[40,1238,1239],{"class":192}," -t\n",[14,1241,1242],{},"What to look for:",[245,1244,1245,1250,1256,1261,1264,1267],{},[248,1246,1247,1249],{},[18,1248,978],{}," or import errors",[248,1251,1252,1255],{},[18,1253,1254],{},"Permission denied"," on app files or socket paths",[248,1257,1258,1259],{},"wrong ",[18,1260,929],{},[248,1262,1263],{},"missing environment variables",[248,1265,1266],{},"socket or port mismatch between Gunicorn and Nginx",[248,1268,1269,1270],{},"immediate restart loops in ",[18,1271,252],{},[14,1273,1274,1275,1279,1280,883],{},"If the unit refuses to start, see ",[879,1276,1278],{"href":1277},"\u002Ffix-issues\u002Fflask-gunicorn-service-failed-to-start","Flask Gunicorn Service Failed to Start",". For systemd behavior and unit syntax, see ",[879,1281,1283],{"href":1282},"\u002Freference\u002Fsystemd-basics-for-flask-deployments","systemd Basics for Flask Deployments",[23,1285,1287],{"id":1286},"checklist","Checklist",[245,1289,1292,1304,1313,1321,1327,1338,1344,1350,1356],{"className":1290},[1291],"contains-task-list",[248,1293,1296,1300,1301],{"className":1294},[1295],"task-list-item",[1297,1298],"input",{"disabled":91,"type":1299},"checkbox"," Service file is saved in ",[18,1302,1303],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002F",[248,1305,1307,1309,1310,1312],{"className":1306},[1295],[1297,1308],{"disabled":91,"type":1299}," ",[18,1311,929],{}," points to the project root",[248,1314,1316,1309,1318,1320],{"className":1315},[1295],[1297,1317],{"disabled":91,"type":1299},[18,1319,897],{}," uses the full path to the Gunicorn binary in the virtualenv",[248,1322,1324,1326],{"className":1323},[1295],[1297,1325],{"disabled":91,"type":1299}," WSGI module path matches the real app entrypoint",[248,1328,1330,1309,1332,1334,1335,1337],{"className":1329},[1295],[1297,1331],{"disabled":91,"type":1299},[18,1333,964],{}," and ",[18,1336,968],{}," can read the app files",[248,1339,1341,1343],{"className":1340},[1295],[1297,1342],{"disabled":91,"type":1299}," Socket or TCP bind matches the Nginx upstream",[248,1345,1347,1349],{"className":1346},[1295],[1297,1348],{"disabled":91,"type":1299}," systemd daemon was reloaded after unit changes",[248,1351,1353,1355],{"className":1352},[1295],[1297,1354],{"disabled":91,"type":1299}," Service is enabled and running",[248,1357,1359,1309,1361,1364],{"className":1358},[1295],[1297,1360],{"disabled":91,"type":1299},[18,1362,1363],{},"journalctl"," shows no import or permission errors",[14,1366,1367,1368,883],{},"Before go-live, validate against ",[879,1369,1371],{"href":1370},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[23,1373,1375],{"id":1374},"related-guides","Related Guides",[245,1377,1378,1382,1386,1390],{},[248,1379,1380],{},[879,1381,882],{"href":881},[248,1383,1384],{},[879,1385,955],{"href":954},[248,1387,1388],{},[879,1389,1278],{"href":1277},[248,1391,1392],{},[879,1393,1371],{"href":1370},[23,1395,1397],{"id":1396},"faq","FAQ",[14,1399,1400,1403,1405,1406,1409],{},[275,1401,1402],{},"Q: Should I run Gunicorn as root?",[279,1404],{},"\nA: No. Run it as a non-root service user such as ",[18,1407,1408],{},"www-data"," or a dedicated app user.",[14,1411,1412,1415,1417,1418,1421],{},[275,1413,1414],{},"Q: Where should the service file go?",[279,1416],{},"\nA: Use ",[18,1419,1420],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002F\u003Cservice>.service"," for a custom system service.",[14,1423,1424,1427,1429,1430,1433],{},[275,1425,1426],{},"Q: How do I apply changes to the service file?",[279,1428],{},"\nA: Run ",[18,1431,1432],{},"sudo systemctl daemon-reload"," and then restart the service.",[14,1435,1436,1442,1444],{},[275,1437,1438,1439,1441],{},"Q: What is the correct ",[18,1440,897],{}," format?",[279,1443],{},"\nA: Use the full Gunicorn binary path, bind option, and WSGI target, for example:",[31,1446,1448],{"className":33,"code":1447,"language":35,"meta":36,"style":36},"\u002Fpath\u002Fto\u002Fvenv\u002Fbin\u002Fgunicorn --bind unix:\u002Frun\u002Fapp.sock wsgi:app\n",[18,1449,1450],{"__ignoreMap":36},[40,1451,1452,1455,1457,1460],{"class":42,"line":43},[40,1453,1454],{"class":46},"\u002Fpath\u002Fto\u002Fvenv\u002Fbin\u002Fgunicorn",[40,1456,310],{"class":192},[40,1458,1459],{"class":50}," unix:\u002Frun\u002Fapp.sock",[40,1461,316],{"class":50},[14,1463,1464,1467,1469],{},[275,1465,1466],{},"Q: Should Gunicorn bind to a socket or a TCP port?",[279,1468],{},"\nA: Either works. Unix sockets are common with local Nginx reverse proxy setups; TCP is simpler to debug.",[14,1471,1472,1475,1477],{},[275,1473,1474],{},"Q: Why use systemd instead of running Gunicorn manually?",[279,1476],{},"\nA: systemd handles boot startup, restarts, logging, and service management.",[14,1479,1480,1483,1485,1486,1489],{},[275,1481,1482],{},"Q: Why does the service work manually but fail under systemd?",[279,1484],{},"\nA: systemd uses a different environment, working directory, and ",[18,1487,1488],{},"PATH"," than your interactive shell.",[14,1491,1492,1498,1500,1501,1503],{},[275,1493,1494,1495,1497],{},"Q: Do I need ",[18,1496,989],{}," after editing the unit?",[279,1499],{},"\nA: Yes. Run ",[18,1502,1432],{}," before restarting the service.",[14,1505,1506,1509,1511],{},[275,1507,1508],{},"Q: Why does Nginx still return 502 after the service starts?",[279,1510],{},"\nA: Usually the upstream in Nginx does not match the Gunicorn socket or port, or the socket permissions are wrong.",[23,1513,1515],{"id":1514},"final-takeaway","Final Takeaway",[14,1517,1518],{},"A correct systemd unit makes Gunicorn predictable in production. Most setup failures are caused by wrong paths, wrong app import target, or mismatched socket settings. Validate the service manually first, then lock in the unit file, enable it, and confirm logs are clean.",[1520,1521,1522],"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 .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 .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":36,"searchDepth":70,"depth":70,"links":1524},[1525,1526,1527,1528,1529,1530,1531,1532,1533],{"id":25,"depth":70,"text":26},{"id":242,"depth":70,"text":243},{"id":267,"depth":70,"text":268},{"id":886,"depth":70,"text":887},{"id":1005,"depth":70,"text":1006},{"id":1286,"depth":70,"text":1287},{"id":1374,"depth":70,"text":1375},{"id":1396,"depth":70,"text":1397},{"id":1514,"depth":70,"text":1515},"Complete guide on flask systemd + gunicorn service setup for Flask production environments.","md",{"ogTitle":5,"ogDescription":1534,"twitterCard":1537,"robots":1538,"canonical":1539},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Fdeploy\u002Fflask-systemd-plus-gunicorn-service-setup","\u002Fdeploy\u002Fflask-systemd-plus-gunicorn-service-setup",{"title":5,"description":1534},"deploy\u002Fflask-systemd-plus-gunicorn-service-setup","sgaGs6PamUHobGOZODyWu6pMpTkMrkCObdDkOqSFtHw",1776805765813]