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