Here is a recipe:
Write the environment variables in a file /home/ubuntu/prog/.env
.
export FLASK_APP=/home/ubuntu/prog/hello.py
export SECRET_KEY=ABCD
export DATABASE_PASSWORD=EFGH
Use dotenv
's load_dotenv
to load the environment variables.
from flask import Flask
from os.path import join, dirname
from os import environ
from dotenv import load_dotenv
app = Flask(__name__)
dotenv_path = join(dirname(__file__), '.env')
load_dotenv(dotenv_path)
@app.route('/')
def hello():
SECRET_KEY = environ.get("SECRET_KEY")
DATABASE_PASSWORD = environ.get("DATABASE_PASSWORD")
return SECRET_KEY + DATABASE_PASSWORD
Write a file /etc/supervisor/hello.conf
.
[program:hello]
command=/home/ubuntu/venv/bin/gunicorn -b localhost:8000 hello:app
directory=/home/ubuntu/prog
stdout_logfile=/home/ubuntu/prog/hello_out.log
stderr_logfile=/home/ubuntu/prog/hello_err.log
user=ubuntu
autostart=true
autorestart=true
stopasgroup=true
killasgroup=true
[supervisord]
logfile=/home/ubuntu/prog/hello_supervisord.log
pidfile=/tmp/supervisord.pid
Load the environment and point to the the app.
source /home/ubuntu/prog/.env
The environment variables are now loaded,
$ export | grep SECRET
declare -x SECRET_KEY="ABCD"
and they will be passed to the sub-process without messing with supervisord
's environment=
.
Launch supervisord
in the foreground to confirm all is well.
/usr/bin/supervisord -n -edebug -c /etc/supervisor/hello.conf
Confirm from another shell that all is well.
$ curl localhost:8000
ABCDEFGH
Kill supervisord
. Since it's in the foreground, it's enough to CTRL-c it.
Launch supervisord
as a daemon.
/usr/bin/supervisord -c /etc/supervisor/hello.conf
Keep an eye on the three log files prog/hello_out.log
, prog/hello_err.log
, and prog/hello_supervisord.log
.
Perhaps the most important point is to avoid using supervisord
's environment=
. SO chatter suggests that it handles commas, quotation marks, tabs, even newlines. Empirically, this doesn't hold (at least for supervisord
3.3.5), and the documentation does not settle it one way or the other. The two lines 942-943
seem to be where the parsing happens, if someone cares to investigate the insufficiency of the docs.