Environment variables are not available with systemd - python

I am deploying a flask app that is running inside virtual env
I have the systemd file as follow:
[Unit]
Description=Gunicorn instance to serve my-page
After=network.target
[Service]
User=jb
Group=www-data
WorkingDirectory=/home/jb/webjosue/my-page
Environment="PATH=/home/jb/webjosue/FlaskENV/bin"
ExecStart=/home/jb/webjosue/FlaskENV/bin/gunicorn --workers 3 --bind unix:my-page.sock -m 007 wsgi:app
[Install]
WantedBy=multi-user.target
In my main.py I have
settings = os.environ['APP_SETTINGS']
and I get this error
raise KeyError(key)
Sep 24 00:10:13 ubuntu-512mb-nyc3-01 gunicorn[23439]: KeyError: 'settings'
I am guessing since I have my environment pointing to the virtualenv (FlaskENV) the other environment variables that are in my .profile are not being recognized.
Any ideas?

As #Joe Doherty said here, you can use Environment directive in Service section to add environment variables, more information. For instance:
[Service]
Environment="PATH=/xx/yy/zz/venv/bin"
Environment="FLASK_ENV=development"
Environment="APP_SETTINGS=config.DevelopmentConfig"
I was using virtualenv so /xx/yy/zz/venv/bin is the path of virtualenv folder.

Somehow Environment="FLASK_ENV=development" with quotes wasn't working
Environment=FLASK_ENV=development
with no quotes was working just fine

Related

Django Virtual Environment - No module named 'gunicorn'

I've followed this guide (https://www.digitalocean.com/community/tutorials/how-to-set-up-django-with-postgres-nginx-and-gunicorn-on-ubuntu-16-04), but I'm presently seeing the following when trying to run gunicorn via the gunicorn service file (/etc/systemd/system/gunicorn.service):
Oct 04 11:30:22 ukgcdeploy01 gunicorn[8095]: File "/opt/envs/automation-console-env/bin/gunicorn", line 5, in <module>
Oct 04 11:30:22 ukgcdeploy01 gunicorn[8095]: from gunicorn.app.wsgiapp import run
Oct 04 11:30:22 ukgcdeploy01 gunicorn[8095]: ModuleNotFoundError: No module named 'gunicorn'
The gunicorn.service file contains the following:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/opt/envs/automation-console-env
ExecStart=/opt/envs/automation-console-env/bin/gunicorn --timeout 600 --log-level debug --error-log /var/log/automation-console-env_error.log --access-logfile /var/log/automation-console-env_access.log --workers 3 --bind unix:/opt/envs/automation-console-env/automation-console-env.sock django_forms.wsgi:application
[Install]
WantedBy=multi-user.target
Running gunicorn manually works fine:
gunicorn --bind 0.0.0.0:8000 myproject.wsgi
This was previously working before I had to upgrade my Python version from 3.5.2 to 3.9, and due to some issues I ended up having to recreate the virtual environment, so I don't think it's necessarily an issue with the service file, but rather my Python/Gunicorn installation.
If anyone could offer some advice, it would be greatly appreciated :)
Does the automation-console-env environment exist? If so, is gunicorn installed there? In either case, since it is working as gunicorn ... on the command line, you should be able to use this installation.
which gunicorn
Then change your systemd unit file to point to this executable.
It seems that you either are defining the wrong path or you might be facing a permission issue in gunicorn.service.
First try to enable the service by using systemctl enable gunicorn.service. If it didn't work, then try the following:
Edit gunicorn.service as follows:
from: --bind unix:/opt/envs/automation-console-env/automation-console-env.sock django_forms.wsgi:application
to: --bind unix:/opt/envs/automation-console-env/automation-console-env.sock django_forms.wsgi

uWSGI runs Django project from command line but not from Emperor uwsgi.service file

I am running a virtualenv with Python3.6 on Ubuntu 16.04 for my Django project using uwsgi and NGINX.
I have uWSGI installed globally and also in the virtualenv.
I can run my project from the command line using uWSGI within the env with
/home/user/Env/myproject/bin/uwsgi --http :8080 --home /home/user/Env/myproject --chdir /home/user/myproject/src/myproject -w myproject.wsgi
and go to my domain and it loads fine.
However I am obviously running uWSGI in "Emperor mode" and when I set the service file up (along with NGINX) the domain displays internal server error.
The uWSGI logs trace to --- no python application found ---
I was having this problem when running
uwsgi --http :8080 --home /home/user/Env/myproject --chdir /home/user/myproject/src/myproject -w myproject.wsgi
because it was using the global install uwsgi instead of the virtualenv one.
I changed my StartExec to the virtualenv uwsgi path but no luck.
I can't figure out what I'm doing wrong, path error? Syntax error?
my /etc/systemd/system/uwsgi.service file
[Unit]
Description=uWSGI Emperor service
[Service]
ExecStartPre=/bin/bash -c 'mkdir -p /run/uwsgi; chown user:www-data /run/uwsgi'
ExecStart=/home/user/Env/myproject/bin/uwsgi --emperor /etc/uwsgi/sites
Restart=always
KillSignal=SIGQUIT
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.target
Okay bit silly but it seems I ran sudo systemctl stop uwsgi and then sudo systemctl start uwsgi and it works now.

How to use Systemd for Django-q daemon

I use Django-Q for task queue and scheduler. I need to keep running the command: python manage.py qcluster.
How can I do it with Systemd?
I've found this code for .service file but I don't know how to use my Virtualenv for python path:
[Unit]
Description=Async tasks runner
After=network.target remote-fs.target
[Service]
ExecStart=/usr/bin/django-admin qcluster --pythonpath /path/to/project --settings settings
User=apache
Restart=always
[Install]
WantedBy=multi-user.target
Use the django-admin binary installed in your virtualenv's bin directory, or the python binary there to run manage.py within your project's working directory:
ExecStart=/path/to/my-venv/bin/django-admin qcluster --pythonpath /path/to/project --settings settings
or
ExecStart=/path/to/my-venv/bin/python manage.py qcluster --pythonpath /path/to/project --settings settings
RootDirectory=/path/to/project
For those who still have problem with this, Just follow these steps:
create a service, example:
sudo nano /etc/systemd/system/qcluster.service
Edit service as follows:
[Unit]
Description=qcluster runner
After=network.target
[Service]
User=user
WorkingDirectory=/home/user/path_to_project
ExecStart=/home/user/path_to_project_env/bin/python manage.py qcluster
[Install]
WantedBy=multi-user.target
Enable the service:
sudo systemctl enable qcluster.service
Start the service:
sudo systemctl start qcluster.service

Gunicorn not using right settings file Django?

In my wsgi.py I am conditionally setting DJANGO_SETTINGS_MODULE to two different files(local and production).
On the server I have set "PROD" variable in /etc/profile
if "PROD" in os.environ:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")
else:
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings_dev")
But, still I am getting an error because right settings file is not being set. So maybe if condition isn't working. See below pic.
My gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=root
Group=www-data
WorkingDirectory=/home/myproject/myproject
ExecStart=/usr/local/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myproject/myproject/myproject.sock myproject.wsgi:application
[Install]
WantedBy=multi-user.target
You should set PROD environment variable in your Gunicorn configuration this way:
[Service]
environment=PROD=True
User=root
Group=www-data
WorkingDirectory=/home/myproject/myproject
ExecStart=/usr/local/bin/gunicorn --access-logfile - --workers 3 --bind unix:/home/myproject/myproject/myproject.sock myproject.wsgi:application
// EDIT: I overlooked that you set ENV var in /etc/profile... You can try my solution, otherwise I will delete my answer.
You can set the environment variable in Gunicorn.service file. From there it can be accessed by Gunicorn.
[Service]
...
ExecStart=/virtuall_env_path/bin/gunicorn --workers 3 --bind
unix:/path_to_myproject.sock
myproject.wsgi:application -e my_var=value -e my_var2=value2
...

Gunicorn Service Environment File Format?

I'm deploying a Django project on an ubuntu machine using gunicorn and nginx, following this tutorial to do it.
I have a gunicorn service that looks like this, similar to the one in the tutorial:
[Unit]
Description=gunicorn daemon
After=network.target
[Service]
User=ubuntu
Group=www-data
WorkingDirectory=/home/ubuntu/project/mysite
EnvironmentFile=/home/ubuntu/.virtualenvs/projectenv/bin/postactivate
ExecStart=/home/ubuntu/.virtualenvs/projectenv/bin/gunicorn --access-logfile - --workers 10 --bind unix:/home/ubuntu/project/mysite.sock mysite.wsgi:application
[Install]
WantedBy=multi-user.target
Since, as I understand, the gunicorn service is run in a completely new environment instead of my project's virtual environment I need to find another way to pass it environment variables. I found this page which says I can add an EnvironmentFile to my service file, which I did above.
I directed the environment file to my virtualenv's postactivate script, which looks something like this:
#!/bin/bash
# This hook is sourced after this virtualenv is activated.
export DJANGO_DEBUG=False
...
Which doesn't work, unsurprisingly.
What is the correct format for this EnvironmentFile to be in?
You just need to pass something like:
DJANGO_DEBUG=False
PYTHON_PATH=:bla
documentation here

Categories

Resources