Django - Can't pass Environment Variable to Apache/Passenger on the WSGI Interface

3.2k views Asked by At

I'm looking for a solution, I can't pass to apache a variable define in /etc/profile.

Here is what I am trying to set:

I have a django application that I deploy through Apache/Passenger (modrails) through the WGSI interface.

In my settings.py I am using this python command : ENVIRONMENT = os.getenv('ENV', 'PROD') so if the ENVIRONMENT variable is not define it goes to the production settings by default.

That is helping me to manage which DB I connect to and activate debugging tools.

It is working in production because it is the default values, it's when I am on the DEV server that I can't get the environment variable from /etc/profile.

It is on an Ubuntu 10.04 Server

So here is some test I did:

1) put into /etc/profile -> ENV='DEV' export ENV

2) under /etc/profile.d/environment.sh -> #!/bin/sh ENV='DEV' export ENV

3) in my virtual host config file -> PassEnv ENV

4) still in my virtual host config file -> SetEnv ENV DEV

5) passenger require a passenger_wgsi.py to register your application if I force in this file viron['ENV'] = 'DEV' this gone a work but I am not able to do this

ENVIRONMENT = os.getenv('ENV', 'PROD')
os.environ['ENV'] = ENVIRONMENT

Any idea why or how can I fix this? thank you!





@Josh

Thanks for the reply. But I still have some questions.

With Passenger, the only things I had to set in the virtual host file was the location of the public folder inside my python/django app. So my virtual host file would look like this.

DocumentRoot path_to_my_public_folder # /home/user/workspace/myapp/public

Then inside the myapp folder there is the passenger_wsgi.py

which define very little like you said :

import sys, os
sys.path.append(os.getcwd())

os.environ['DJANGO_SETTINGS_MODULE'] = "myapp.settings"

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

and after these settings that was it, the application was running. So where I'm maybe missing your indication is when you are saying that we have to specify which wsgi file we used. I though it would directly locate passenger_wsgi.py and load it by default what it seems to be doing at the moment.

Another things you should know is that our project is residing in an SVN repository and I want to setup this file for many users so we don't have different settings.

But what I will test tomorow is the idea of having one base wsgi file with the common information and base on the hostname of the computer I will import the others settings from like dev_wsgi.py or prod_wsgi.py

I should be able to retrieve this name with python and base on the name I will set the variables I need to use.

Thank you for the idea, it is well appreciate.

2

There are 2 answers

2
Josh Smeaton On

I'm going to suggest an alternative solution since I have no idea how to fix your specific problem.

Create multiple WSGI files. production.wsgi, dev1.wsgi, dev2.wsgi, test.wsgi etc. Each webserver has to be configured with the /path/to/.wsgi anyway. There is only a minimal amount of code in a wsgi file anyway, so replicating this isn't very expensive. Also, you could have a _base.wsgi to supply all the common values, and require the derived wsgis to call application = wsgi.WSGIHandler().

Each developer on our project has their own setting files and wsgi files to enable tampering with settings without ever being able to break production with a rogue value.

0
DoRivard On

I finally got it to work and I will provide the way I figured it out after @Josh suggestion.

Here is what looks like my WSGI file now:

import sys, os

sys.path.append(os.getcwd())
# this allows us to run the project under Passenger on our workstation
# it is simply a list of all the developers machine hostname it can be expended as we want
LIST_OF_DEV_HOSTNAME = ['PC1', 'PC2','PC3',]
# Return the current machine hostname
HOSTNAME = os.uname()[1]

# Import Django app module
if HOSTNAME in LIST_OF_DEV_HOSTNAME:
    # here if it is not detected you can append to your python path the root folder of your django app
    sys.path.append('/home/user/workspace/django-app')
    # As previously mentioned I use an Environment Variable in the settings.py to switch DB and debug settings
    # so here I set the ENV variable I use in the settings.py to reflect the Development environment
    os.environ['ENV'] = 'DEV'
else:
    # we could append any other needed path in here too
    sys.path.append('/any/other/folder')
    # As previously mentioned I use an Environment Variable in the settings.py to switch DB and debug settings
    # so here I set the ENV variable I use in the settings.py to reflect the Development environment
    os.environ['ENV'] = 'PROD'

# Shared between the two environments    
sys.path.append('/usr/lib/python2.4/site-packages/')

# Import the django app settings and Environment variable
os.environ['DJANGO_SETTINGS_MODULE'] = 'myapp.settings'

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

So this is the way I got it to workout.

I could also achieved it in creating a file like /opt/environments and did the check like this: # check if the file exists if os.path.isfile('/opt/environments'): os.environ['ENV'] = 'DEV' else: os.environ['ENV'] = 'PROD'

it would have allowed me to perform the same check, but I would have to tell everyone to create the file. It depends on what you want to do create a file or add your hostname to the list, since our project is under SVN a simple commit of our WSGI file is for me more simple than the creation of the file.

Thank you.