26

I'm currently having difficulty passing environment variables into Gunicorn for my Django project. I'm on the latest 19.1 version. I have a wsgi.py file like so:

import os
import sys
from django.core.wsgi import get_wsgi_application

BASE_DIR = os.path.dirname(os.path.abspath(__file__))
PROJECT_DIR = os.path.abspath(os.path.join(BASE_DIR, '..'))

sys.path.append(PROJECT_DIR)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "app.settings")

def application(environ, start_response):
    _application = get_wsgi_application()
    os.environ['SERVER_ENV'] = environ['SERVER_ENV']
    os.environ['SERVER_ID'] = environ['SERVER_ID']
    return _application(environ, start_response)

When I run gunicorn from the command line as:

SERVER_ENV=TEST SERVER_ID=TEST gunicorn -b 127.0.0.1:8080 --error-logfile - --access-logfile - app.wsgi:application

and I then pass a request to gunicorn I keep getting:

2014-08-01 08:39:17 [21462] [ERROR] Error handling request
Traceback (most recent call last):
  File "/opt/virtualenv/python-2.7.5/django-1.5.5/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 93, in handle
    self.handle_request(listener, req, client, addr)
  File "/opt/virtualenv/python-2.7.5/django-1.5.5/lib/python2.7/site-packages/gunicorn/workers/sync.py", line 134, in handle_request
    respiter = self.wsgi(environ, resp.start_response)
  File "/opt/sites/itracker/wsgi.py", line 18, in application
    os.environ['SERVER_ENV'] = environ['SERVER_ENV']
KeyError: 'SERVER_ENV'

Printing out the environ values confirms that the environment variables are not being passed in. I've tried setting the environment variables in the virtualenv activation script and also in a dedicated gunicorn shell script and also by setting the environment variables using the --env flag but nothing seems to work.

Any ideas?

Huw
  • 533
  • 1
  • 7
  • 15

4 Answers4

36

I got a similar problem when deploying gunicorn.service. And I passed environment variables to it by a file:

<on gunicorn.service>
[Service]
...
EnvironmentFile=/pathto/somefilewith_secrets
...

For example (cat /etc/systemd/system/gunicorn.service)

[Unit]  
Description=gunicorn daemon  
After=network.target  
  
[Service]  
User=ubuntu
Group=ubuntu
WorkingDirectory=/home/ubuntu/10008/digichainOpen
EnvironmentFile=/home/ubuntu/10008/digichainOpen/.env
ExecStart=/home/ubuntu/.local/share/virtualenvs/digichainOpen-Zk2Jnvjv/bin/gunicorn \
          --worker-class=gevent --workers 4 \
          --bind unix:/home/ubuntu/10008/digichainOpen/gunicorn.sock digichainOpen.wsgi:application
            
[Install]  
WantedBy=multi-user.target  

and the .env file can be:

my_var=someValue
some_secret=secretvalue
another_secret=blah
pyjavo
  • 1,598
  • 2
  • 23
  • 41
Waket Zheng
  • 5,065
  • 2
  • 17
  • 30
  • 4
    I did not immediately realize the variables in the env file need to be set like `MY_VAR=someValue` not `export MY_VAR=someValue`. In case anyone else runs into a similar issue – johnchase Mar 21 '20 at 18:35
  • Does WorkingDirectory and EnvironmentFile's directory have to be same? – Bagghi Daku Jun 03 '20 at 20:23
  • 1
    @AnuroopSingh EnvironmentFile is read by systemd, it may be anywhere. – temoto Jul 28 '20 at 15:31
  • Do you think the PATH variable should be set here? Or does gunicorn inherit the environ variables that are set in .bash files in the home dir of the User that it is using? – Francesco Pegoraro Jan 11 '21 at 21:48
11

You just have to export your environment variable.

export SERVER_ENV=TEST
export SERVER_ID=TEST
gunicorn -b 127.0.0.1:8080 --error-logfile - --access-logfile - app.wsgi:application

And in your code you can get them like that

os.getenv('SERVER_ENV')
Uhsac
  • 769
  • 1
  • 6
  • 13
  • Why ```os.environ.get('SERVER_ENV')``` doesn't work? – Patrick Bassut Aug 31 '14 at 14:09
  • No, it does. Was using the ```def application(environ, start_response)``` django calls when setting up wsgi – Patrick Bassut Aug 31 '14 at 14:11
  • Isn't this the same thing as the OP demonstrates? Setting env vars at the start of a command I think would have the same affect, so if that isn't working for the OP, I wouldn't think that this would either. – CryptoFool Jun 09 '23 at 04:07
5

If you want to run Django using gunicorn config file:

Write a config.py file

command = 'venv/bin/gunicorn'
pythonpath = 'venv'
bind = '127.0.0.1:8000'
workers = 2
raw_env = ["VARIABLE_HERE=VARIABLE_VALUE_HERE"]
wsgi_app = "project.wsgi"

Run it like this: From inside the project directory

gunicorn -c config.py
Chaddha Ji
  • 74
  • 1
  • 3
-3

I don't quite understand what you are trying to do here. If you pass environment variables in the bash command line, they are already in os.environ: there is no need to get them from anywhere else. The environ dictionary is made up of elements passed from the request, not the shell.

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895