Reputation: 15030
I have a Django app which runs on Gunicorn, and is managed by SupervisorD which is managed by Ansible.
I want Django to read the DJANGO_SECRET_KEY
variable from the environment, since I don't want to store my secret key in a config file or VCS. For that I read the key from the environment in my settings.py
:
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
Looking at Supervisor docs it says:
Note that the subprocess will inherit the environment variables of the shell used to start “supervisord” except for the ones overridden here. See Subprocess Environment.
Here's my supervisor.conf
:
[program:gunicorn]
command=/.../.virtualenvs/homepage/bin/gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid
directory=/.../http/homepage
When I set the variable and run Gunicorn command from the shell, it starts up just fine:
$ DJANGO_SECRET_KEY=XXX /.../.virtualenvs/homepage/bin/gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid
However when I set the variable in the shell and restart the Supervisor service my app fails to start with error about not found variable:
$ DJANGO_SECRET_KEY=XXX supervisorctl restart gunicorn
gunicorn: ERROR (not running)
gunicorn: ERROR (spawn error)
Looking at Supervisor error log:
File "/.../http/homepage/homepage/settings.py", line 21, in <module>
SECRET_KEY = os.environ['DJANGO_SECRET_KEY']
File "/.../.virtualenvs/homepage/lib/python2.7/UserDict.py", line 40, in __getitem__
raise KeyError(key)
KeyError: 'DJANGO_SECRET_KEY'
[2017-08-27 08:22:09 +0000] [19353] [INFO] Worker exiting (pid: 19353)
[2017-08-27 08:22:09 +0000] [19349] [INFO] Shutting down: Master
[2017-08-27 08:22:09 +0000] [19349] [INFO] Reason: Worker failed to boot.
I have also tried restarting the supervisor service, but same error occurs:
$ DJANGO_SECRET_KEY=XXX systemctl restart supervisor
...
INFO exited: gunicorn (exit status 3; not expected)
My question is how do I make Supervisor to "pass" environment variables to it's child processes?
Upvotes: 2
Views: 2193
Reputation: 15030
OK figured it out myself. Turns out ansible has feature called Vault, which is used for exactly this kind of jobs - encrypting keys.
Now I added the vaulted secret key to ansible's host_vars, see: Vault: single encrypted variable and Inventory: Splitting out host and group specific data.
I added a task to my ansible playbook to copy the key file from ansible vault to the server:
- name: copy django secret key to server
copy: content="{{ django_secret_key }}" dest=/.../http/homepage/deploy/django_secret_key.txt mode=0600
And made Django read the secret from that file:
with open(os.path.join(BASE_DIR, 'deploy', 'django_secret_key.txt')) as secret_key_file:
SECRET_KEY = secret_key_file.read().strip()
If anyone has a simpler/better solution, please post it and I will accept it as the answer.
Upvotes: 0
Reputation: 524
Create executable file similar to this and try to start it manually.
i.e create file and copy script below /home/user/start_django.sh
You need to fill in DJANGODIR
and make other adjustments according to your case. also, you may need to adjust permissions accordingly.
#!/bin/bash
DJANGODIR=/.../.../..
ENVBIN=/.../.virtualenvs/homepage/bin/bin
# Activate the virtual environment
cd $DJANGODIR
source $ENVBIN/activate
DJANGO_SECRET_KEY=XXX
#define other env variables if you need
# Start your Django
exec gunicorn homepage.wsgi -w 1 --bind localhost:8001 --pid /tmp/gunicorn.pid
If it starts manually then just use this file in your conf.
[program:django_project]
command = /home/user/start_django.sh
user = {your user}
stdout_logfile = /var/log/django.log
redirect_stderr = true
# you can also try to define enviroment variables in this conf
environment=LANG=en_US.UTF-8,LC_ALL=en_US.UTF-8,DJANGO_SECRET_KEY=XXX
Upvotes: 0