Run wsgi with apache and django in anaconda environment - python

I am trying to run a django application with wsgi_mod and apache2. But for some strange reason it cannot import django.
# /etc/apache2/apache2.conf
WSGIDaemonProcess django_apps python-home=/home/swacker/miniconda3/envs/django/
WSGIProcessGroup django_apps
WSGIScriptAlias /koala /var/www/production/Koala/Koala/wsgi.py process-group=django_apps
<Directory /var/www/production/Koala/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
The application sits in /var/www/production/Koala.
My conda enviromnent is installed in /home/user/miniconda3/envs/django.
I installed wsgi inside the conda environment.
I tried different things, but nothing worked. This is what I did to get wsgi running.
sudo apt-get install libapache2-mod-wsgi
pip install mod_wsgi
conda install -c https://conda.binstar.org/travis uwsgi
It looks like wsgi is just not working with conda environments and I have to use virtualenv?? Wsgi works, I can render a test file just fine.
Though, when I go to localhost/koala the /var/log/apache2/error.log shows:
from django.core.wsgi import get_wsgi_application
ImportError: No module named 'django'
I searched a lot, but could not find an answer that addresses this properly.

Related

Trouble hosting Django website in Ubuntu (Error)

I need to host a Django website in Ubuntu 18 (Desktop). I searched the web but couldn't find a well-written tutorial which demonstrates how to do this step by step. After doing some research I came across following procedure but I believe its incomplete.
Library installed
sudo apt-get install python3.6
pip3 install Django
sudo apt-get install apache2
sudo apt-get install libapache2-mod-wsgi
The project named mysite with an app polls and virtual environment mysite_env is located in /var/www with following directory structure
Configured wsgi.py at follows
import os
import sys
from django.core.wsgi import get_wsgi_application
sys.path.append('/var/www/mysite')
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings')
application = get_wsgi_application()
Added following lines in apache2.conf located in etc/apache2/apache2.conf
#ServerName mysite.com
WSGIScriptAlias / /var/www/mysite/mysite/wsgi.py
WSGIPythonHome /var/www/mysite/mysite_env
#WSGIPythonPath /path/to/mysite.com
<Directory /var/www/mysite/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
If everything setups perfectly then on opening localhost in the browser will let Apache server to open Django app but on the other hand, by doing it Django app doesn't loads.
I am missing lots of things I know, I need to host it and access it on the web. Can anybody tell me what steps I am missing, Any suggestions would be of great help.
References
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/modwsgi/y
I followed this simple step to step tutorial which I can recommend. It is for Ubuntu 16.04 but I believe you can simply transfer it to 18.04
https://simpleisbetterthancomplex.com/tutorial/2016/10/14/how-to-deploy-to-digital-ocean.html

Django ModuleNotFoundError: No module named 'myProject'

ModuleNotFoundError: No module named 'myProject' error, but I do not know the cause. I am glad if you tell me.
・ CentOS 7.2
・ Python 3.6
・ Django 2.0
・ apache 2.4
I set the virtual environment as follows
pip install virtualenv
mkdir xxx
cd xxx
python3 -m venv xxx
source xxx/bin/activate
pip install mod_wsgi
mod_wsgi-express module-config
LoadModule wsgi_module "/home/username/myProject/myProject/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so"
WSGIPythonHome "/home/username/myProject/myProject"
■ /etc/httpd/conf.d/django.conf
NameVirtualHost *:80
LoadModule wsgi_module /home/username/myProject/myProject/lib/python3.6/site-packages/mod_wsgi/server/mod_wsgi-py36.cpython-36m-x86_64-linux-gnu.so
WSGIPythonHome /home/username/myProject/myProject
WSGISocketPrefix /var/run/wsgi
<VirtualHost *:80>
ServerName xxx.com
DocumentRoot /home/username
WSGIApplicationGroup %{GLOBAL}
WSGIDaemonProcess xxx python-home=/home/username/myProject/myProject python-path=/home/username/myProject/myProject/lib/python3.6/site-packages
WSGIProcessGroup xxx
WSGIScriptAlias / /home/username/myProject/myProject/wsgi.py
<Directory /home/username/myProject/myProject/static>
Require all granted
</Directory>
<Directory /home/username/myProject/myProject>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
■ wsgi.py
import os,sys
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xxx.settings")
application = get_wsgi_application()
Read:
http://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html
The WSGIPythonHome directive or python-home option should point at the root directory for the Python virtual environment. This should be the same value as sys.prefix has when Python is run for that virtual environment.
The WSGIPythonPath directive or python-path option would then be set to your project code directory in which modules/packages exist, likely /home/username/myProject in your case.
Do not use these later options to point at the site-packages directory, use the first options for specifying the location of the virtual environment.
I would suggest since you are using daemon mode to add:
WSGIRestrictEmbedded On
after the LoadModule line. Then remove the WSGIPythonHome and WSGIPythonPath and rely on python-home and python-path options on WSGIDaemonProcess instead.
BTW, DJANGO_SETTINGS_MODULE wouldn't be xxx.settings. You likely mean myProject.settings.
Also, it appears that you have your virtual environment being your project code directory. If that is the case, is not really recommended. Create the virtual environment as a distinct sub directory somewhere of its own. Don't intermingle it with your code as then it becomes really hard to remove the virtual environment and re-create it.

Can't run Apache2 with virtualenv

I'm making a website based on Django, on the server was installed a Python 3.5, but my project requires a Python 3.6. I decided to use virtualenv. I successfuly installed needed version of Python but I can't make it works with Apatche2 using virtualenv.
Website is able to run only on Python 2.7, otherwise nothing happens, page is loading for a long time without any error.
Here is my VirtualHost config with my try to run on Python 3.6.
<VirtualHost *:443>
ServerName <site_adress>:443
ServerAdmin admin#<site_adress>
DocumentRoot /var/www/html/MMServer
ErrorLog /var/www/logs/error.log
CustomLog /var/www/logs/custom.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/mm.cert
SSLCertificateKeyFile /etc/apache2/ssl/mm.key
Alias /static/ /var/www/html/MMServer/static/
<Directory /var/www/html/MMServer/static>
Require all granted
</Directory>
WSGIDaemonProcess MMServer python-path=/var/www/html/MMServer python-home=/var/www/html/venv
WSGIProcessGroup MMServer
WSGIScriptAlias / /var/www/html/MMServer/mm_server/wsgi.py
<Directory /var/www/html/MMServer/mm_server>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
Below is my wsgi.py file:
import os
import sys
def application(environ, start_response):
start_response('200 OK',[('Content-type','text/html')])
return [sys.version]
Only one thing what I can get this way (while WSGIDaemonProcess and WSGIProcessGroup is deleted) is:
2.7.13 (default, Nov 24 2017, 17:33:09) [GCC 6.3.0 20170516]
Edit 1:
There is a posiblity I have missing packages, bacause I made reinstalation of python 3.5, what are required packages to work?
Solution:
I did two things, I'm not sure what exacly help me but first of all I disabled a mod (a2dismod wsgi) and deleted a package libapache2-mod-wsgi.
Option 1:
apt-get install libapache2-mod-wsgi-py3
Option 2:
I installed a mod-wsgi from the source:
wget https://github.com/GrahamDumpleton/mod_wsgi/archive/4.6.3.tar.gz
tar -xf 4.6.3.tar.gz
./configure --with-python=/usr/local/bin/python3.6
make
make install
Now everything works perfectly.
Thanks #Graham Dumpleton, your answer was helpful.
The mod_wsgi module is C code which links to the Python library. Thus the version of Python it is compiled for is embedded in the module. It doesn't just execute python program. This means it has to be compiled for the version of Python you want to use. You cannot force it via a virtual environment to use a different Python version. This is stated in the documentation on using mod_wsgi with virtual environments.
http://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html
In short, you need to uninstall the mod_wsgi module (likely the operating system packaged one), and install mod_wsgi yourself from source code, compiling it against the Python version you want to use. Easiest way of doing that is to use pip install method.
https://pypi.python.org/pypi/mod_wsgi

apache mod_wsgi error with django in virtualenv

I can't seem to find a good answer to this. Who needs to own the virtualenv when running it as a WSGIDaemon? I assume on my OS (Ubuntu 16) www-data, but I want to be sure. Trying some new things to get this thing working based off of the answer from this post...
django apache configuration with WSGIDaemonProcess not working
Does the django project, the virtualenv folder, or both need to be owned by the apache group? What ownerships need to be in place to serve a django project without specifying a port? Why do I get the following?
The root problem:
Call to 'site.addsitedir()' failed for '(null)'
When I start apache, I get this error. I've followed several different guides, including:
http://modwsgi.readthedocs.io/en/develop/user-guides/virtual-environments.html
and
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/modwsgi/
but have had zero success.
My virtual environment path is /usr/local/virtualenvs/servicesite
My django project path is /home/addohm/projects/rtservice/servicesite
this is where manage.py resides,
which leaves /home/addohm/projects/rtservice/servicesite/servicesite as the location of my wsgi.py.
wsgi.py:
SERVICESITE = ['/usr/local/virtualenvs/servicesite/lib/python3.5/site-packages']
import os
import sys
import site
prev_sys_path = list(sys.path)
for directory in SERVICESITE
site.addsitedir(directory)
new_sys_path = []
for item in list(sys.path):
if item not in prev_sys_path:
new_sys_path.append(item)
sys.path.remove(item)
sys.path[:0] = new_sys_path
""" **Doesn't seem to work, throwing error in apache logs**
site.addsitedir('/usr/local/virtualenvs/servicesite/lib/python3.5/site-packages')
"""
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "servicesite.settings")
application = get_wsgi_application()
DJANGO_PATH = os.path.join(os.path.abspath(os.path.dirname(__file__)), '..')
sys.path.append(DJANGO_PATH)
apache2.conf
[...]
WSGIDaemonProcess servicesite python-path=/home/addohm/projects/rtservice/servicesite:/usr/local/virtualenvs/servicesite/lib/python3.5/site-packages
WSGIProcessGroup servicesite
WSGIScriptAlias / /home/addohm/projects/rtservice/servicesite/servicesite/wsgi.py
Alias /static/ /home/addohm/projects/rtservice/servicesite/static/
<Directory /home/addohm/projects/rtservice/servicesite/static/>
Require all granted
</Directory>
<Directory /home/addohm/projects/rtservice/servicesite/servicesite>
<Files wsgy.py>
Require all granted
</Files>
</Directory>
[...]
You should not have need to change anything in the original wsgi.py generated by Django for you. It is generally sufficient to have:
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "servicesite.settings")
application = get_wsgi_application()
Your Apache configuration should then preferably be:
WSGIDaemonProcess service site python-home=/usr/local/virtualenvs/servicesite \
python-path=/home/addohm/projects/rtservice/servicesite
WSGIProcessGroup servicesite
WSGIScriptAlias / /home/addohm/projects/rtservice/servicesite/servicesite/wsgi.py
Alias /static/ /home/addohm/projects/rtservice/servicesite/static/
<Directory /home/addohm/projects/rtservice/servicesite/static/>
Require all granted
</Directory>
<Directory /home/addohm/projects/rtservice/servicesite/servicesite>
<Files wsgy.py>
Require all granted
</Files>
</Directory>
That is, use python-home for the location of the directory specified by sys.prefix for the virtual environment. Avoid using python-path and referring to the site-packages directory. Using python-home has been preferred way for a very long time and using it ensures that things fail in a more obvious way when you don't do things the correct way.
A few very important things.
The first is that mod_wsgi must be compiled for the specific Python major/minor version you want to use.
Second, the Python virtual environment must be created from the same Python installation as mod_wsgi was compiled for. You can't have mod_wsgi compiled against a system Python installation, but have your virtual environment based off a separate Python installation for same major/minor version in /usr/local.
Third, the user that Apache runs your code as must have read access to any directories/files for the main Python installation, the virtual environment and your application code. When you stick stuff under a home directory, it will not generally have access as the home directory prohibits others from reading anything in the home directory.
Fourth, if the mod_wsgi daemon process group is set to run as a different user than the Apache user, the Apache user still must at least have ability to read the wsgi.py file and all the directories down to that point.
Further reading on virtual environments which is more up to date:
http://blog.dscpl.com.au/2014/09/using-python-virtual-environments-with.html

Run mod_wsgi with virtualenv or Python with version different that system default

I am trying to make my Flask application work on CentOS server. Basically the issue is that I have Python 2.6 installed in /usr/bin which is system default and Python 3.4 installed in /usr/local/bin. I would like to use Python 3.4 virtualenv or at least Python 3.4 interpreter for mod_wsgi to run my application.
I have created virtualenv in ~/virtualenvs/flask.
I have this WSGI script:
import os
import sys
from logging import Formatter, FileHandler
APP_HOME = r"/home/fenikso/Album"
activate_this = os.path.join("/home/fenikso/virtualenvs/flask/bin/activate_this.py")
execfile(activate_this, dict(__file__=activate_this))
sys.path.insert(0, APP_HOME)
os.chdir(APP_HOME)
from app import app
handler = FileHandler("app.log")
handler.setFormatter(Formatter("[%(asctime)s | %(levelname)s] %(message)s"))
app.logger.addHandler(handler)
application = app
And following config in Apache:
<VirtualHost *:80>
ServerName album2.site.cz
Alias /static "/home/fenikso/Album/static"
Alias /photos "/home/fenikso/Album/photos"
Alias /thumbs "/home/fenikso/Album/thumbs"
WSGIScriptAlias / "/home/fenikso/Album/wsgi.py"
<Directory "/home/fenikso/Album">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/static">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/photos">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/thumbs">
AllowOverride None
Allow from all
</Directory>
</VirtualHost>
However, when trying to run the application, I get an error:
Apache/2.2.15 (Unix) DAV/2 mod_wsgi/3.2 Python/2.6.6 mod_fcgid/2.3.7 PHP/5.3.3 mod_ssl/2.2.15 OpenSSL/1.0.1e-fips SVN/1.6.11 mod_perl/2.0.4 Perl/v5.10.1 configured -- resuming normal operations
mod_wsgi (pid=14627): Target WSGI script '/home/fenikso/Album/wsgi.py' cannot be loaded as Python module.
mod_wsgi (pid=14627): Exception occurred processing WSGI script '/home/fenikso/Album/wsgi.py'.
Traceback (most recent call last):
File "/home/fenikso/Album/wsgi.py", line 15, in <module>
from app import app
File "/home/fenikso/Album/app.py", line 1, in <module>
from flask import Flask
ImportError: No module named flask
I have noticed that either Python 2.6 is being ran and my virtualenv is not activated. What would be the proper way to get this working and still have the Python 2.6 as a system default?
You have to add the following line in your apache.conf in order to give the right executable and the path to the virtualenv.
WSGIPythonHome /usr/local/bin
WSGIPythonPath /home/fenikso/virtualenv/lib/python3.4/site-packages
You will find all the options of these two command in the mod_wsgi documentation
Be aware that you must have the version of mod_wsgi compatible with the python executable. In your case, you probably have to install mod_wsgi3.4 and configure apache to use it instead of the standart mod_wsgi module.
The whole configuration file should be :
WSGIPythonHome "/usr/local/bin"
WSGIPythonPath "/home/fenikso/virtualenv/lib/python3.4/site-packages"
<VirtualHost *:80>
ServerName album2.site.cz
Alias /static "/home/fenikso/Album/static"
Alias /photos "/home/fenikso/Album/photos"
Alias /thumbs "/home/fenikso/Album/thumbs"
WSGIScriptAlias / "/home/fenikso/Album/wsgi.py"
<Directory "/home/fenikso/Album">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/static">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/photos">
AllowOverride None
Allow from all
</Directory>
<Directory "/home/fenikso/Album/thumbs">
AllowOverride None
Allow from all
</Directory>
</VirtualHost>
Look into the WSGIPythonHome and WSGIPythonPath directives. It's also possible that you have a python2.6 mod_wsgi installed, mod_wsgi must be compiled for the intended python version and does not support multiple python versions. So check that your mod_wsgi is py3.4 compatible and set the directives above.
Alternatively, you could run the flask app with a python server like gunicorn and proxypass from apache to gunicorn.
Another option, which I believe is much cleaner, logical, and flexible, is to simply reference the python interpreter from your venv at the beginning of your wsgi file. This way, it is easy to change (no fiddling with system config files) and opens the possibility for multiple apps running with different python environments, like so:
#!/path/to/your/venv/bin/python
If the python version installed on the system is different from the python version used in the virtual environment, then mod_wsgi will not work because mod_wsgi is always compiled for a specific python version.
In this situation, you need to install mod_wsgi in a virtual environment
pip install mod_wsgi-standalone
Then such a module should be loaded instead of the default one installed in the system.
For Ubuntu for example, modify the path to the module in /etc/apache2/mods-available/wsgi.load
LoadModule wsgi_module /home/user/etc/.venv/lib/python3.9/site-packages/mod_wsgi/server/mod_wsgi-py39.cpython-39-x86_64-linux-gnu.so
Then in order to avoid the error "no such file or directory: mod_wsgi (pid=XXXX): Couldn't bind unix domain socket '/usr/local/opt/httpd/logs/wsgi.xxxxx.11.1.sock" should be added to the httpd.conf file:
WSGISocketPrefix /var/run/wsgi
After restarting apache everything should work

Categories

Resources