[{"data":1,"prerenderedAt":1372},["ShallowReactive",2],{"\u002Fdeploy\u002Fflask-environment-variables-and-secrets-setup":3},{"id":4,"title":5,"body":6,"description":1362,"extension":1363,"meta":1364,"navigation":122,"path":1368,"seo":1369,"stem":1370,"__hash__":1371},"content\u002Fdeploy\u002Fflask-environment-variables-and-secrets-setup.md","Flask Environment Variables and Secrets Setup",{"type":7,"value":8,"toc":1348},"minimark",[9,13,17,22,25,306,313,317,320,324,878,882,971,975,978,983,1142,1146,1175,1188,1192,1250,1257,1261,1281,1285,1299,1307,1315,1329,1337,1341,1344],[10,11,5],"h1",{"id":12},"flask-environment-variables-and-secrets-setup",[14,15,16],"p",{},"If you're trying to configure Flask environment variables and secrets for production, this guide shows you how to set them up safely and load them reliably with systemd and Gunicorn. The goal is to keep secrets out of source code and ensure your app reads the correct production settings on every deploy.",[18,19,21],"h2",{"id":20},"quick-fix-quick-setup","Quick Fix \u002F Quick Setup",[14,23,24],{},"Create a protected environment file, point your systemd service at it, then restart Gunicorn.",[26,27,32],"pre",{"className":28,"code":29,"language":30,"meta":31,"style":31},"language-bash shiki shiki-themes github-light github-dark","sudo mkdir -p \u002Fetc\u002Fmyflaskapp\nsudo tee \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env > \u002Fdev\u002Fnull \u003C\u003C'EOF'\nFLASK_ENV=production\nSECRET_KEY=replace-with-long-random-value\nDATABASE_URL=postgresql:\u002F\u002Fuser:password@127.0.0.1:5432\u002Fdbname\nEOF\nsudo chmod 600 \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\n\nsudo sed -i '\u002F^EnvironmentFile=\u002Fd' \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service\nsudo tee \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service > \u002Fdev\u002Fnull \u003C\u003C'EOF'\n[Unit]\nDescription=Gunicorn for myflaskapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fvar\u002Fwww\u002Fmyflaskapp\nEnvironmentFile=\u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\nExecStart=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn -w 3 -b unix:\u002Frun\u002Fmyflaskapp.sock wsgi:app\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\nEOF\n\nsudo systemctl daemon-reload\nsudo systemctl restart myflaskapp\nsudo systemctl status myflaskapp --no-pager\nsudo systemctl show myflaskapp --property=Environment\n","bash","",[33,34,35,55,79,85,91,97,103,117,124,141,159,165,171,177,182,188,194,200,206,212,218,224,229,235,241,246,251,262,275,291],"code",{"__ignoreMap":31},[36,37,40,44,48,52],"span",{"class":38,"line":39},"line",1,[36,41,43],{"class":42},"sScJk","sudo",[36,45,47],{"class":46},"sZZnC"," mkdir",[36,49,51],{"class":50},"sj4cs"," -p",[36,53,54],{"class":46}," \u002Fetc\u002Fmyflaskapp\n",[36,56,58,60,63,66,70,73,76],{"class":38,"line":57},2,[36,59,43],{"class":42},[36,61,62],{"class":46}," tee",[36,64,65],{"class":46}," \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env",[36,67,69],{"class":68},"szBVR"," >",[36,71,72],{"class":46}," \u002Fdev\u002Fnull",[36,74,75],{"class":68}," \u003C\u003C",[36,77,78],{"class":46},"'EOF'\n",[36,80,82],{"class":38,"line":81},3,[36,83,84],{"class":46},"FLASK_ENV=production\n",[36,86,88],{"class":38,"line":87},4,[36,89,90],{"class":46},"SECRET_KEY=replace-with-long-random-value\n",[36,92,94],{"class":38,"line":93},5,[36,95,96],{"class":46},"DATABASE_URL=postgresql:\u002F\u002Fuser:password@127.0.0.1:5432\u002Fdbname\n",[36,98,100],{"class":38,"line":99},6,[36,101,102],{"class":46},"EOF\n",[36,104,106,108,111,114],{"class":38,"line":105},7,[36,107,43],{"class":42},[36,109,110],{"class":46}," chmod",[36,112,113],{"class":50}," 600",[36,115,116],{"class":46}," \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\n",[36,118,120],{"class":38,"line":119},8,[36,121,123],{"emptyLinePlaceholder":122},true,"\n",[36,125,127,129,132,135,138],{"class":38,"line":126},9,[36,128,43],{"class":42},[36,130,131],{"class":46}," sed",[36,133,134],{"class":50}," -i",[36,136,137],{"class":46}," '\u002F^EnvironmentFile=\u002Fd'",[36,139,140],{"class":46}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service\n",[36,142,144,146,148,151,153,155,157],{"class":38,"line":143},10,[36,145,43],{"class":42},[36,147,62],{"class":46},[36,149,150],{"class":46}," \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service",[36,152,69],{"class":68},[36,154,72],{"class":46},[36,156,75],{"class":68},[36,158,78],{"class":46},[36,160,162],{"class":38,"line":161},11,[36,163,164],{"class":46},"[Unit]\n",[36,166,168],{"class":38,"line":167},12,[36,169,170],{"class":46},"Description=Gunicorn for myflaskapp\n",[36,172,174],{"class":38,"line":173},13,[36,175,176],{"class":46},"After=network.target\n",[36,178,180],{"class":38,"line":179},14,[36,181,123],{"emptyLinePlaceholder":122},[36,183,185],{"class":38,"line":184},15,[36,186,187],{"class":46},"[Service]\n",[36,189,191],{"class":38,"line":190},16,[36,192,193],{"class":46},"User=www-data\n",[36,195,197],{"class":38,"line":196},17,[36,198,199],{"class":46},"Group=www-data\n",[36,201,203],{"class":38,"line":202},18,[36,204,205],{"class":46},"WorkingDirectory=\u002Fvar\u002Fwww\u002Fmyflaskapp\n",[36,207,209],{"class":38,"line":208},19,[36,210,211],{"class":46},"EnvironmentFile=\u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\n",[36,213,215],{"class":38,"line":214},20,[36,216,217],{"class":46},"ExecStart=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn -w 3 -b unix:\u002Frun\u002Fmyflaskapp.sock wsgi:app\n",[36,219,221],{"class":38,"line":220},21,[36,222,223],{"class":46},"Restart=always\n",[36,225,227],{"class":38,"line":226},22,[36,228,123],{"emptyLinePlaceholder":122},[36,230,232],{"class":38,"line":231},23,[36,233,234],{"class":46},"[Install]\n",[36,236,238],{"class":38,"line":237},24,[36,239,240],{"class":46},"WantedBy=multi-user.target\n",[36,242,244],{"class":38,"line":243},25,[36,245,102],{"class":46},[36,247,249],{"class":38,"line":248},26,[36,250,123],{"emptyLinePlaceholder":122},[36,252,254,256,259],{"class":38,"line":253},27,[36,255,43],{"class":42},[36,257,258],{"class":46}," systemctl",[36,260,261],{"class":46}," daemon-reload\n",[36,263,265,267,269,272],{"class":38,"line":264},28,[36,266,43],{"class":42},[36,268,258],{"class":46},[36,270,271],{"class":46}," restart",[36,273,274],{"class":46}," myflaskapp\n",[36,276,278,280,282,285,288],{"class":38,"line":277},29,[36,279,43],{"class":42},[36,281,258],{"class":46},[36,283,284],{"class":46}," status",[36,286,287],{"class":46}," myflaskapp",[36,289,290],{"class":50}," --no-pager\n",[36,292,294,296,298,301,303],{"class":38,"line":293},30,[36,295,43],{"class":42},[36,297,258],{"class":46},[36,299,300],{"class":46}," show",[36,302,287],{"class":46},[36,304,305],{"class":50}," --property=Environment\n",[14,307,308,309,312],{},"Use an ",[33,310,311],{},"EnvironmentFile"," for production instead of exporting variables manually in a shell. Store the file outside the project directory, restrict permissions, and restart the service after changes.",[18,314,316],{"id":315},"whats-happening","What’s Happening",[14,318,319],{},"Flask reads configuration from process environment variables at startup. In production, Gunicorn usually runs under systemd, so variables exported in your interactive shell are not automatically available to the service. Secrets fail to load when they are defined in the wrong place, loaded too late, or blocked by file permission or service configuration issues.",[18,321,323],{"id":322},"step-by-step-guide","Step-by-Step Guide",[325,326,327,363,445,496,528,623,663,744,766,851,870],"ol",{},[328,329,330,334,337,338],"li",{},[331,332,333],"strong",{},"Decide which values must come from environment variables.",[335,336],"br",{},"Typical production values:",[339,340,341,346,351,354,357,360],"ul",{},[328,342,343],{},[33,344,345],{},"SECRET_KEY",[328,347,348],{},[33,349,350],{},"DATABASE_URL",[328,352,353],{},"mail credentials",[328,355,356],{},"API tokens",[328,358,359],{},"Flask config mode",[328,361,362],{},"feature flags",[328,364,365,368,370,371,374,375,378,379,435,437,438,441,442,378],{},[331,366,367],{},"Remove hardcoded secrets from Flask config.",[335,369],{},"Read values with ",[33,372,373],{},"os.environ"," or ",[33,376,377],{},"os.getenv",".",[26,380,384],{"className":381,"code":382,"language":383,"meta":31,"style":31},"language-python shiki shiki-themes github-light github-dark","from os import environ\n\nSECRET_KEY = environ[\"SECRET_KEY\"]\nSQLALCHEMY_DATABASE_URI = environ[\"DATABASE_URL\"]\n","python",[33,385,386,401,405,421],{"__ignoreMap":31},[36,387,388,391,395,398],{"class":38,"line":39},[36,389,390],{"class":68},"from",[36,392,394],{"class":393},"sVt8B"," os ",[36,396,397],{"class":68},"import",[36,399,400],{"class":393}," environ\n",[36,402,403],{"class":38,"line":57},[36,404,123],{"emptyLinePlaceholder":122},[36,406,407,409,412,415,418],{"class":38,"line":81},[36,408,345],{"class":50},[36,410,411],{"class":68}," =",[36,413,414],{"class":393}," environ[",[36,416,417],{"class":46},"\"SECRET_KEY\"",[36,419,420],{"class":393},"]\n",[36,422,423,426,428,430,433],{"class":38,"line":87},[36,424,425],{"class":50},"SQLALCHEMY_DATABASE_URI",[36,427,411],{"class":68},[36,429,414],{"class":393},[36,431,432],{"class":46},"\"DATABASE_URL\"",[36,434,420],{"class":393},[335,436],{},"If missing values should fail fast, use ",[33,439,440],{},"environ[...]",". If optional, use ",[33,443,444],{},"getenv",[328,446,447,450,474,476,477],{},[331,448,449],{},"Create a dedicated environment file outside the repository.",[26,451,453],{"className":28,"code":452,"language":30,"meta":31,"style":31},"sudo mkdir -p \u002Fetc\u002Fmyflaskapp\nsudo nano \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\n",[33,454,455,465],{"__ignoreMap":31},[36,456,457,459,461,463],{"class":38,"line":39},[36,458,43],{"class":42},[36,460,47],{"class":46},[36,462,51],{"class":50},[36,464,54],{"class":46},[36,466,467,469,472],{"class":38,"line":57},[36,468,43],{"class":42},[36,470,471],{"class":46}," nano",[36,473,116],{"class":46},[335,475],{},"Add:",[26,478,482],{"className":479,"code":480,"language":481,"meta":31,"style":31},"language-dotenv shiki shiki-themes github-light github-dark","FLASK_ENV=production\nSECRET_KEY=replace-with-long-random-value\nDATABASE_URL=postgresql:\u002F\u002Fuser:password@127.0.0.1:5432\u002Fdbname\n","dotenv",[33,483,484,488,492],{"__ignoreMap":31},[36,485,486],{"class":38,"line":39},[36,487,84],{},[36,489,490],{"class":38,"line":57},[36,491,90],{},[36,493,494],{"class":38,"line":81},[36,495,96],{},[328,497,498,501],{},[331,499,500],{},"Restrict permissions on the secrets file.",[26,502,504],{"className":28,"code":503,"language":30,"meta":31,"style":31},"sudo chown root:root \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\nsudo chmod 600 \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\n",[33,505,506,518],{"__ignoreMap":31},[36,507,508,510,513,516],{"class":38,"line":39},[36,509,43],{"class":42},[36,511,512],{"class":46}," chown",[36,514,515],{"class":46}," root:root",[36,517,116],{"class":46},[36,519,520,522,524,526],{"class":38,"line":57},[36,521,43],{"class":42},[36,523,110],{"class":46},[36,525,113],{"class":50},[36,527,116],{"class":46},[328,529,530,533,535,536,539,540,603,605,606],{},[331,531,532],{},"Configure systemd to load the environment file.",[335,534],{},"Edit ",[33,537,538],{},"\u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service",":",[26,541,545],{"className":542,"code":543,"language":544,"meta":31,"style":31},"language-ini shiki shiki-themes github-light github-dark","[Unit]\nDescription=Gunicorn for myflaskapp\nAfter=network.target\n\n[Service]\nUser=www-data\nGroup=www-data\nWorkingDirectory=\u002Fvar\u002Fwww\u002Fmyflaskapp\nEnvironmentFile=\u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\nExecStart=\u002Fvar\u002Fwww\u002Fmyflaskapp\u002Fvenv\u002Fbin\u002Fgunicorn -w 3 -b unix:\u002Frun\u002Fmyflaskapp.sock wsgi:app\nRestart=always\n\n[Install]\nWantedBy=multi-user.target\n","ini",[33,546,547,551,555,559,563,567,571,575,579,583,587,591,595,599],{"__ignoreMap":31},[36,548,549],{"class":38,"line":39},[36,550,164],{},[36,552,553],{"class":38,"line":57},[36,554,170],{},[36,556,557],{"class":38,"line":81},[36,558,176],{},[36,560,561],{"class":38,"line":87},[36,562,123],{"emptyLinePlaceholder":122},[36,564,565],{"class":38,"line":93},[36,566,187],{},[36,568,569],{"class":38,"line":99},[36,570,193],{},[36,572,573],{"class":38,"line":105},[36,574,199],{},[36,576,577],{"class":38,"line":119},[36,578,205],{},[36,580,581],{"class":38,"line":126},[36,582,211],{},[36,584,585],{"class":38,"line":143},[36,586,217],{},[36,588,589],{"class":38,"line":161},[36,590,223],{},[36,592,593],{"class":38,"line":167},[36,594,123],{"emptyLinePlaceholder":122},[36,596,597],{"class":38,"line":173},[36,598,234],{},[36,600,601],{"class":38,"line":179},[36,602,240],{},[335,604],{},"Ensure:",[339,607,608,614,620],{},[328,609,610,613],{},[33,611,612],{},"WorkingDirectory"," matches your app path",[328,615,616,619],{},[33,617,618],{},"ExecStart"," points to the correct virtualenv",[328,621,622],{},"the socket or bind target matches your Nginx config",[328,624,625,628],{},[331,626,627],{},"Reload systemd and restart the service.",[26,629,631],{"className":28,"code":630,"language":30,"meta":31,"style":31},"sudo systemctl daemon-reload\nsudo systemctl restart myflaskapp\nsudo systemctl status myflaskapp --no-pager\n",[33,632,633,641,651],{"__ignoreMap":31},[36,634,635,637,639],{"class":38,"line":39},[36,636,43],{"class":42},[36,638,258],{"class":46},[36,640,261],{"class":46},[36,642,643,645,647,649],{"class":38,"line":57},[36,644,43],{"class":42},[36,646,258],{"class":46},[36,648,271],{"class":46},[36,650,274],{"class":46},[36,652,653,655,657,659,661],{"class":38,"line":81},[36,654,43],{"class":42},[36,656,258],{"class":46},[36,658,284],{"class":46},[36,660,287],{"class":46},[36,662,290],{"class":50},[328,664,665,668],{},[331,666,667],{},"Verify the running service sees the variables.",[26,669,671],{"className":28,"code":670,"language":30,"meta":31,"style":31},"sudo systemctl show myflaskapp --property=Environment\nsudo cat \u002Fproc\u002F$(pgrep -f 'gunicorn.*myflaskapp' | head -n1)\u002Fenviron | tr '\\0' '\\n' | grep -E 'FLASK_ENV|DATABASE_URL|SECRET_KEY'\n",[33,672,673,685],{"__ignoreMap":31},[36,674,675,677,679,681,683],{"class":38,"line":39},[36,676,43],{"class":42},[36,678,258],{"class":46},[36,680,300],{"class":46},[36,682,287],{"class":46},[36,684,305],{"class":50},[36,686,687,689,692,695,698,701,704,707,710,713,716,719,722,724,727,730,733,735,738,741],{"class":38,"line":57},[36,688,43],{"class":42},[36,690,691],{"class":46}," cat",[36,693,694],{"class":46}," \u002Fproc\u002F",[36,696,697],{"class":393},"$(",[36,699,700],{"class":42},"pgrep",[36,702,703],{"class":50}," -f",[36,705,706],{"class":46}," 'gunicorn.*myflaskapp'",[36,708,709],{"class":68}," |",[36,711,712],{"class":42}," head",[36,714,715],{"class":50}," -n1",[36,717,718],{"class":393},")",[36,720,721],{"class":46},"\u002Fenviron",[36,723,709],{"class":68},[36,725,726],{"class":42}," tr",[36,728,729],{"class":46}," '\\0'",[36,731,732],{"class":46}," '\\n'",[36,734,709],{"class":68},[36,736,737],{"class":42}," grep",[36,739,740],{"class":50}," -E",[36,742,743],{"class":46}," 'FLASK_ENV|DATABASE_URL|SECRET_KEY'\n",[328,745,746,753,755,756,759,760,762,763,765],{},[331,747,748,749,752],{},"If you use ",[33,750,751],{},"python-dotenv",", keep it for development only unless explicitly needed in production.",[335,754],{},"For local development, ",[33,757,758],{},".env"," can be fine. For production, prefer systemd ",[33,761,311],{}," or a dedicated secret manager. Do not assume Gunicorn will read ",[33,764,758],{}," automatically.",[328,767,768,771,773,774,776,777],{},[331,769,770],{},"Load config before initializing extensions.",[335,772],{},"If you use an application factory, ensure environment-backed config is available before initializing extensions.",[335,775],{},"Example order:",[26,778,780],{"className":381,"code":779,"language":383,"meta":31,"style":31},"def create_app():\n    app = Flask(__name__)\n    app.config.from_object(\"config.ProductionConfig\")\n\n    db.init_app(app)\n    mail.init_app(app)\n    cache.init_app(app)\n\n    return app\n",[33,781,782,793,810,820,824,829,834,839,843],{"__ignoreMap":31},[36,783,784,787,790],{"class":38,"line":39},[36,785,786],{"class":68},"def",[36,788,789],{"class":42}," create_app",[36,791,792],{"class":393},"():\n",[36,794,795,798,801,804,807],{"class":38,"line":57},[36,796,797],{"class":393},"    app ",[36,799,800],{"class":68},"=",[36,802,803],{"class":393}," Flask(",[36,805,806],{"class":50},"__name__",[36,808,809],{"class":393},")\n",[36,811,812,815,818],{"class":38,"line":81},[36,813,814],{"class":393},"    app.config.from_object(",[36,816,817],{"class":46},"\"config.ProductionConfig\"",[36,819,809],{"class":393},[36,821,822],{"class":38,"line":87},[36,823,123],{"emptyLinePlaceholder":122},[36,825,826],{"class":38,"line":93},[36,827,828],{"class":393},"    db.init_app(app)\n",[36,830,831],{"class":38,"line":99},[36,832,833],{"class":393},"    mail.init_app(app)\n",[36,835,836],{"class":38,"line":105},[36,837,838],{"class":393},"    cache.init_app(app)\n",[36,840,841],{"class":38,"line":119},[36,842,123],{"emptyLinePlaceholder":122},[36,844,845,848],{"class":38,"line":126},[36,846,847],{"class":68},"    return",[36,849,850],{"class":393}," app\n",[328,852,853,856],{},[331,854,855],{},"Rotate secrets safely.",[339,857,858,861,864,867],{},[328,859,860],{},"edit the env file",[328,862,863],{},"restart Gunicorn",[328,865,866],{},"validate app health",[328,868,869],{},"remove old credentials only after confirming the new ones work",[328,871,872,875,877],{},[331,873,874],{},"For containers, keep the same variable names.",[335,876],{},"If you deploy with Docker or Compose, pass variables through container environment settings or secrets and keep names aligned with Flask config.",[18,879,881],{"id":880},"common-causes","Common Causes",[339,883,884,897,913,923,929,943,953,965],{},[328,885,886,889,890,374,893,896],{},[331,887,888],{},"Variables exported in a shell only"," → systemd does not inherit them → define ",[33,891,892],{},"EnvironmentFile=",[33,894,895],{},"Environment="," in the service unit.",[328,898,899,902,903,905,906,374,909,912],{},[331,900,901],{},"Wrong variable names in Flask config"," → app looks for ",[33,904,345],{}," but file defines ",[33,907,908],{},"SECRET",[33,910,911],{},"APP_SECRET"," → align names exactly.",[328,914,915,918,919,922],{},[331,916,917],{},"Environment file not readable by the service"," → permission denied or wrong path → set correct ownership, ",[33,920,921],{},"chmod 600",", and verify the path in systemd.",[328,924,925,928],{},[331,926,927],{},"Config loads too late in the app lifecycle"," → extensions initialize before env-backed settings are applied → load config before creating database, mail, cache, or login integrations.",[328,930,931,934,935,938,939,942],{},[331,932,933],{},"Invalid env file syntax"," → quotes, spaces, or ",[33,936,937],{},"export"," statements break parsing → keep one ",[33,940,941],{},"KEY=value"," pair per line without shell-specific syntax.",[328,944,945,948,949,952],{},[331,946,947],{},"Service not reloaded after changes"," → old values remain in memory → run ",[33,950,951],{},"daemon-reload"," when the unit changes and restart the service after env changes.",[328,954,955,961,962,964],{},[331,956,957,958,960],{},"Using ",[33,959,758],{}," in production without explicit loading"," → file exists but Flask never reads it → either load dotenv before app creation or use systemd ",[33,963,311],{}," instead.",[328,966,967,970],{},[331,968,969],{},"Secrets committed to Git"," → deployment works but creates a security risk → rotate exposed credentials and remove them from repository history if needed.",[18,972,974],{"id":973},"debugging-section","Debugging Section",[14,976,977],{},"Check service configuration, the running process environment, and startup logs.",[979,980,982],"h3",{"id":981},"commands","Commands",[26,984,986],{"className":28,"code":985,"language":30,"meta":31,"style":31},"sudo systemctl cat myflaskapp\nsudo systemctl show myflaskapp --property=Environment\nsudo systemctl status myflaskapp --no-pager\nsudo journalctl -u myflaskapp -n 100 --no-pager\nsudo grep -n 'EnvironmentFile' \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service\nsudo ls -l \u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env\nsudo cat \u002Fproc\u002F$(pgrep -f 'gunicorn.*myflaskapp' | head -n1)\u002Fenviron | tr '\\0' '\\n'\nsudo -u www-data env | sort\npython3 -c \"import os; print(os.getenv('SECRET_KEY')); print(os.getenv('DATABASE_URL'))\"\nsudo systemd-analyze verify \u002Fetc\u002Fsystemd\u002Fsystem\u002Fmyflaskapp.service\n",[33,987,988,998,1010,1022,1042,1055,1067,1102,1119,1130],{"__ignoreMap":31},[36,989,990,992,994,996],{"class":38,"line":39},[36,991,43],{"class":42},[36,993,258],{"class":46},[36,995,691],{"class":46},[36,997,274],{"class":46},[36,999,1000,1002,1004,1006,1008],{"class":38,"line":57},[36,1001,43],{"class":42},[36,1003,258],{"class":46},[36,1005,300],{"class":46},[36,1007,287],{"class":46},[36,1009,305],{"class":50},[36,1011,1012,1014,1016,1018,1020],{"class":38,"line":81},[36,1013,43],{"class":42},[36,1015,258],{"class":46},[36,1017,284],{"class":46},[36,1019,287],{"class":46},[36,1021,290],{"class":50},[36,1023,1024,1026,1029,1032,1034,1037,1040],{"class":38,"line":87},[36,1025,43],{"class":42},[36,1027,1028],{"class":46}," journalctl",[36,1030,1031],{"class":50}," -u",[36,1033,287],{"class":46},[36,1035,1036],{"class":50}," -n",[36,1038,1039],{"class":50}," 100",[36,1041,290],{"class":50},[36,1043,1044,1046,1048,1050,1053],{"class":38,"line":93},[36,1045,43],{"class":42},[36,1047,737],{"class":46},[36,1049,1036],{"class":50},[36,1051,1052],{"class":46}," 'EnvironmentFile'",[36,1054,140],{"class":46},[36,1056,1057,1059,1062,1065],{"class":38,"line":99},[36,1058,43],{"class":42},[36,1060,1061],{"class":46}," ls",[36,1063,1064],{"class":50}," -l",[36,1066,116],{"class":46},[36,1068,1069,1071,1073,1075,1077,1079,1081,1083,1085,1087,1089,1091,1093,1095,1097,1099],{"class":38,"line":105},[36,1070,43],{"class":42},[36,1072,691],{"class":46},[36,1074,694],{"class":46},[36,1076,697],{"class":393},[36,1078,700],{"class":42},[36,1080,703],{"class":50},[36,1082,706],{"class":46},[36,1084,709],{"class":68},[36,1086,712],{"class":42},[36,1088,715],{"class":50},[36,1090,718],{"class":393},[36,1092,721],{"class":46},[36,1094,709],{"class":68},[36,1096,726],{"class":42},[36,1098,729],{"class":46},[36,1100,1101],{"class":46}," '\\n'\n",[36,1103,1104,1106,1108,1111,1114,1116],{"class":38,"line":119},[36,1105,43],{"class":42},[36,1107,1031],{"class":50},[36,1109,1110],{"class":46}," www-data",[36,1112,1113],{"class":46}," env",[36,1115,709],{"class":68},[36,1117,1118],{"class":42}," sort\n",[36,1120,1121,1124,1127],{"class":38,"line":126},[36,1122,1123],{"class":42},"python3",[36,1125,1126],{"class":50}," -c",[36,1128,1129],{"class":46}," \"import os; print(os.getenv('SECRET_KEY')); print(os.getenv('DATABASE_URL'))\"\n",[36,1131,1132,1134,1137,1140],{"class":38,"line":143},[36,1133,43],{"class":42},[36,1135,1136],{"class":46}," systemd-analyze",[36,1138,1139],{"class":46}," verify",[36,1141,140],{"class":46},[979,1143,1145],{"id":1144},"what-to-look-for","What to look for",[339,1147,1148,1153,1156,1163,1166,1169],{},[328,1149,1150,1152],{},[33,1151,892],{}," is present in the active unit",[328,1154,1155],{},"systemd shows the expected environment variables",[328,1157,1158,1159,1162],{},"Gunicorn starts without ",[33,1160,1161],{},"KeyError"," or config import failures",[328,1164,1165],{},"the env file path exists and permissions are correct",[328,1167,1168],{},"variable names in Flask code exactly match variable names in the env file",[328,1170,1171,1172],{},"no invalid env file formatting such as ",[33,1173,1174],{},"export KEY=value",[14,1176,1177,1178,1183,1184,378],{},"If the service fails completely, check ",[1179,1180,1182],"a",{"href":1181},"\u002Ffix-issues\u002Fflask-gunicorn-service-failed-to-start","Flask Gunicorn Service Failed to Start",". If variables still do not appear inside the service, use ",[1179,1185,1187],{"href":1186},"\u002Ffix-issues\u002Fflask-environment-variables-not-loading-in-production","Flask Environment Variables Not Loading in Production",[18,1189,1191],{"id":1190},"checklist","Checklist",[339,1193,1196,1205,1211,1220,1226,1232,1238,1244],{"className":1194},[1195],"contains-task-list",[328,1197,1200,1204],{"className":1198},[1199],"task-list-item",[1201,1202],"input",{"disabled":122,"type":1203},"checkbox"," Secrets are not hardcoded in the Flask repository.",[328,1206,1208,1210],{"className":1207},[1199],[1201,1209],{"disabled":122,"type":1203}," Production variables are stored in a dedicated file or secret store outside the app codebase.",[328,1212,1214,1216,1217,1219],{"className":1213},[1199],[1201,1215],{"disabled":122,"type":1203}," ",[33,1218,311],{}," is present in the systemd service.",[328,1221,1223,1225],{"className":1222},[1199],[1201,1224],{"disabled":122,"type":1203}," File permissions on the secrets file are restricted.",[328,1227,1229,1231],{"className":1228},[1199],[1201,1230],{"disabled":122,"type":1203}," Gunicorn restarts successfully after config changes.",[328,1233,1235,1237],{"className":1234},[1199],[1201,1236],{"disabled":122,"type":1203}," The running process shows the expected environment variables.",[328,1239,1241,1243],{"className":1240},[1199],[1201,1242],{"disabled":122,"type":1203}," Flask connects successfully to the database and external services using those variables.",[328,1245,1247,1249],{"className":1246},[1199],[1201,1248],{"disabled":122,"type":1203}," Secret rotation procedure is documented and tested.",[14,1251,1252,1253,378],{},"For broader deployment validation, review ",[1179,1254,1256],{"href":1255},"\u002Fchecklist\u002Fflask-production-checklist-everything-you-must-do","Flask Production Checklist (Everything You Must Do)",[18,1258,1260],{"id":1259},"related-guides","Related Guides",[339,1262,1263,1269,1273,1277],{},[328,1264,1265],{},[1179,1266,1268],{"href":1267},"\u002Fdeploy\u002Fdeploy-flask-with-nginx-plus-gunicorn-step-by-step-guide","Deploy Flask with Nginx + Gunicorn (Step-by-Step Guide)",[328,1270,1271],{},[1179,1272,1182],{"href":1181},[328,1274,1275],{},[1179,1276,1187],{"href":1186},[328,1278,1279],{},[1179,1280,1256],{"href":1255},[18,1282,1284],{"id":1283},"faq","FAQ",[14,1286,1287,1293,1295,1296,378],{},[331,1288,1289,1290,1292],{},"Q: Should I store ",[33,1291,758],{}," inside the project directory in production?",[335,1294],{},"\nA: Prefer a root-owned file outside the repository, such as ",[33,1297,1298],{},"\u002Fetc\u002Fmyflaskapp\u002Fmyflaskapp.env",[14,1300,1301,1304,1306],{},[331,1302,1303],{},"Q: Does Nginx need these environment variables?",[335,1305],{},"\nA: Usually no. Gunicorn and the Flask app need them. Nginx mainly proxies requests.",[14,1308,1309,1312,1314],{},[331,1310,1311],{},"Q: Why do variables work in my shell but not in production?",[335,1313],{},"\nA: systemd services do not inherit your interactive shell exports unless you define them in the service configuration.",[14,1316,1317,1323,1325,1326,1328],{},[331,1318,1319,1320,1322],{},"Q: Can I use ",[33,1321,751],{}," in production?",[335,1324],{},"\nA: You can, but systemd ",[33,1327,311],{}," or a dedicated secret manager is more predictable for server deployments.",[14,1330,1331,1334,1336],{},[331,1332,1333],{},"Q: When do I need to restart the app?",[335,1335],{},"\nA: After changing environment variables or secrets, restart the Gunicorn service so Flask reloads config at startup.",[18,1338,1340],{"id":1339},"final-takeaway","Final Takeaway",[14,1342,1343],{},"Production Flask apps should load secrets from the process environment, not from source code. On a VPS, the most reliable pattern is a locked-down env file referenced by systemd and consumed by Gunicorn at startup. If variables are missing, debug from the running service context, not from your shell.",[1345,1346,1347],"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 .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}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}",{"title":31,"searchDepth":57,"depth":57,"links":1349},[1350,1351,1352,1353,1354,1358,1359,1360,1361],{"id":20,"depth":57,"text":21},{"id":315,"depth":57,"text":316},{"id":322,"depth":57,"text":323},{"id":880,"depth":57,"text":881},{"id":973,"depth":57,"text":974,"children":1355},[1356,1357],{"id":981,"depth":81,"text":982},{"id":1144,"depth":81,"text":1145},{"id":1190,"depth":57,"text":1191},{"id":1259,"depth":57,"text":1260},{"id":1283,"depth":57,"text":1284},{"id":1339,"depth":57,"text":1340},"Complete guide on flask environment variables and secrets setup for Flask production environments.","md",{"ogTitle":5,"ogDescription":1362,"twitterCard":1365,"robots":1366,"canonical":1367},"summary_large_image","index, follow","https:\u002F\u002Fflask-deployment.com\u002Fdeploy\u002Fflask-environment-variables-and-secrets-setup","\u002Fdeploy\u002Fflask-environment-variables-and-secrets-setup",{"title":5,"description":1362},"deploy\u002Fflask-environment-variables-and-secrets-setup","8UOCfSR0vOfdMBc51G8wpJKmT2iz87DkzWesD4KwHPc",1776805765845]