Maybe some needed context:
I installed python3.9 into a directory /opt/python39/. I compiled mod_wsgi with this version of python (as per this post) and was able to conduct a test to make sure that it was working correctly. I am not using a virtual environment.
I am trying to move my django project to production, so naturally, I am following the django docs. When I use the default file configurations at the very beginning, i.e.:
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
WSGIPythonHome /opt/python39/bin/python3.9
WSGIPythonPath /path/to/mysite.com
<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
It works (for the most part - there are resources missing on the page, but thats for another SO post) like a charm.
So I continue through the docs (which is now telling me that I should move it to "Daemon mode"):
“Daemon mode” is the recommended mode for running mod_wsgi (on non-Windows platforms). To create the required daemon process group and delegate the Django instance to run in it, you will need to add appropriate WSGIDaemonProcess and WSGIProcessGroup directives. A further change required to the above configuration if you use daemon mode is that you can’t use WSGIPythonPath; instead you should use the python-path option to WSGIDaemonProcess, for example:
So I change my file to look like:
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py
#WSGIPythonHome /opt/python39/bin/python3.9
#WSGIPythonPath /path/to/mysite.com
WSGIDaemonProcess mysite.com python-home=/opt/python39/bin/python3.9 python-path=/path/to/mysite.com
WSGIProcessGroup mysite.com
<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
then run sudo apachectl restart, go back to my browser, refresh, shows 500 internal server error, check my logs, and "what do you know?" - ImportError: "No module named 'django'".
I've come across this SO article that seems to be describing my problem, but for virtual environments, and offers a solution, but I give it a go anyway:
WSGIProcessGroup mysite.com
WSGIDaemonProcess mysite.com python-home=/opt/python39 python-path=/path/to/mysite.com
WSGIScriptAlias / /path/to/mysite.com/mysite/wsgi.py process-group=iengravethat.com application-group=%{GLOBAL}
<Directory /path/to/mysite.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
I rerun sudo apachectl restart, check my browser - same error, check the logs - same error.
I have tried a multitude of other configurations, but they all boil down to this error. Does anyone have any idea as to how to remedy this problem?
---UPDATE---
SUTerliakov and I opened up a channel for discussion, the end conclusion was thus:
Regarding recompilation - I was absolutely happy with the following installation (from Dockerfile, but it doesn't really matter):
pip install -U --no-cache-dir mod-wsgi
mod_wsgi-express install-module | tee /etc/apache2/mods-available/wsgi_express.load /etc/apache2/mods-available/wsgi_express.conf
And it can be done from venv too.
I really don't understand why did your paths stop working after
switching to daemon mode. I just suggest to try virtualenv instead,
because this method is recommended by maintainer.
You can just drop "tee" part and use standalone mod_wsgi-express install-module. It will print two lines of config, you can add them to your config file manually. It will print WSGIPythonHome, take this value and use for python-home option of WSGIDaemonProcess.
(may require root, AFAIR)
So, basically just create a venv and link it in your .conf file.
Create a virtual environment with the python interpreter you want to use and activate it.
pip install the packages you were using for django.
pip install mod-wsgi.
Grab the version of mod_wsgi you want.
untar it and enter the directory.
./configure --with-python=python3 (This python3 is the same version as the python3 I wanted - not python 3.6 which comes pre-installed on centos7).
make LDFLAGS='-L/path/to/venv/lib -Wl,-rpath,/path/to/venv/lib'.
sudo make install.
run mod_wsgi-express module-config and copy and paste it at the top of your .conf file.
deactivate your environment.
restart apache - sudo apachectl restart
I have the following config:
ServerName ${SERVER_NAME}
ServerAdmin ${SERVER_ADMIN}
<IfModule unixd_module>
User ${APP_USER}
Group ${APP_USER}
</IfModule>
WSGIRestrictEmbedded On
WSGIPassAuthorization On
IncludeOptional /etc/apache2/conf.d/*.conf
Timeout 60
<VirtualHost *:80>
Redirect permanent / https://${SERVER_NAME}/
</VirtualHost>
<VirtualHost *:443>
Alias /media <media folder>
<Directory <media_folder> >
Options -Indexes
Require all granted
</Directory>
Alias /static <static_folder>
<Directory <static_folder> >
Options -Indexes
Require all granted
</Directory>
WSGIDaemonProcess <name> processes=1 threads=5 display-name=%{GROUP} home=<top_folder>
WSGIScriptAlias / <wsgi.py path> process-group=<name> application-group=%{GLOBAL}
... SSL config here ...
</VirtualHost>
It is not a full config: logging, SSL and WebSocket proxies are thrown away.
<name> is any alias
<top_folder> is folder with manage.py file
<wsgi.py path> is <top_folder>/something/wsgi.py
<media_folder> and <static_folder> are paths of MEDIA_ROOT and STATIC_ROOT settings.
It is deployed with docker (system-level package installation as root, no virtual environment).
Final attempt
Probably something gets messed up when using system python that is not the default interpreter. You can set up virtual environment and make httpd use it. To avoid manual recompilation, mod_wsgi pip package can be used:
# With venv activated
pip install mod_wsgi
sudo mod_wsgi-express install-module
This will install mod_wsgi for venv python and print two lines of config: LoadModule ... and WSGIPythonHome <path>. You can add LoadModule to configuration file and use the following daemon config:
WSGIDaemonProcess mysite.com home=/path/to/mysite.com python-home=<venv_root>
Note
You don't need to recompile mod_wsgi manually with this package, it is the most amazing aspect of such installation! Two commands above are sufficient to install mod_wsgi. It will copy module files to required folders for you (see end of this readme), so your steps 4-8 can be omitted.
Related
I want to deploy multiple django apps on apache on Windows but only know how to deploy one.
Overriding the localhost of the Wamp Server I can deploy the app without problem but I need to deploy more and don't know how. I've sehen virtual hosts and think are good but don't know how to configurate them. Anyone know how can I do this? Thanks in advance.
hosting severel django apps with Apache is possible using virtual hosts (vhosts)
important to care about:
during config of Apache I recommend to start apache from command line as "httpd.exe" as in XAMPP or WAMP you will not see some of the initial start-up error messages in error.log files.
you can only use 1 python version even in different virt.env for each vhost as apache module mod_wsgi compilation needs to fit to it and is loaded once at startup of apache
something like this in httpd.conf (you should have this already in place because of your running single app config):
LoadFile "c:/.../python/python38/python38.dll"
LoadModule wsgi_module "c:/..../mod_wsgi.cp38-win_amd64.pyd"
for those starting from scratch:
activate virt.env.
> pip install mod_wsgi
> mod_wsgi-express module-config
will give above output (LoadFile ....) that you need to copy to httpd.conf
how to set path to virt.env and app folders:
with 1 host you would point to your virt.env by setting WSGIPythonHome and WSGIPythonPath to point to your app folders in httpd.conf:
WSGIPythonHome "d:/..../django_project/env_folder"
WSGIPythonPath "d:/..../django_project/app_name"
but: you can not place WSGIPythonHome/WSGIPythonPath inside the VirtualHost declaration in httpd-vhosts.conf .... it will cause an error message
Solution: set paths in wsgi.py dynamically and remove WSGIPythonHome/WSGIPythonPath from apache *.conf:
wsgi.py:
# replacement for WSGIPythonHome "d:/..../django_project/env_folder"
# choose one:
sys.path.append('d:/.../env_folder/lib/site-packages') # add individual virt.environment packages at the end of sys.path; global env packages have prio
sys.path.insert(0,'d:/.../env_folder/lib/site-packages') # add individual virt.environment packages at the beginning of sys.path; indiv. virt.env packages have prio over global env
# replacement WSGIPythonPath "d:/..../django_project/app_name"
sys.path.append('d:/.../django_project/app_name') # add indiv. app folder to search path
here is example for apache conf:
(why the dummy host: there is a (strange or buggy) behavior of apache ... if none of the virtual host names match the request, then automatically apache will dispatch the request to the first vhost in the config - no matter which server name is defined ther. This can lead to confusion because the total wrong app is called and an error messages will most certainly pop-up from inside django, not indicating that the error is on the Apache conf level. A dummy host with a simple index.html and an error message can make this tranparent)
httpd-vhost.conf:
<VirtualHost *:80>
ServerName Dumme_Host
DocumentRoot "d:/WEBSPACES/Dummy_Host"
<Directory d:/WEBSPACES/Dummy_Host>
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName xxxx1
WSGIScriptAlias / "d:/.... /wsgi.py" application-group=app_name1
Alias /media/ d:/.../media/
Alias /static/ d:/.../static/
<Directory d:/.../app_name1>
Require all granted
</Directory>
<Directory d:/.../media>
Require all granted
</Directory>
<Directory d:/.../static>
Require all granted
</Directory>
</VirtualHost>
<VirtualHost *:80>
ServerName xxxx2
WSGIScriptAlias / "d:/.... /wsgi.py" application-group=app_name2
Alias /media/ d:/.../media/
Alias /static/ d:/.../static/
<Directory d:/.../app_name2>
Require all granted
</Directory>
.....
</VirtualHost>
I've tried every other thread and their suggested solutions but without success so far.
I have a Django app with a virtualenv and Apache 2.4 and mod_wsgi, which i developed on other server. Now, I'm migrating (rebuilding from scratch) everything on another server.
While everything else works, when i tried to install pandas, the app served through Apache throws me an ImportError for Numpy.
Original error was: /optilab/env/lib64/python3.6/site-packages/numpy/core/_multiarray_umath.cpython-36m-x86_64-linux-gnu.so:
failed to map segment from shared object
Thing is, this doesn't happen while using runserver with manage.py . Everything is the same: Python Version (3.6.8), Python Executable (/optilab/env/bin/python) except the Python Path order.
For the testing runserver, this is the Python Path list:
['/optilab',
'/optilab/env/lib64/python3.6/site-packages',
'/usr/lib64/python36.zip',
'/usr/lib64/python3.6',
'/usr/lib64/python3.6/lib-dynload',
'/optilab/env/lib64/python3.6/site-packages',
'/optilab/env/lib/python3.6/site-packages',
'/home/appuser/.local/lib/python3.6/site-packages',
'/usr/local/lib64/python3.6/site-packages',
'/usr/local/lib/python3.6/site-packages',
'/usr/lib64/python3.6/site-packages',
'/usr/lib/python3.6/site-packages',
'/env/lib64/python3.6/site-packages']
But, for the app served through Apache, the Python Path is:
['/optilab',
'/optilab/core',
'/usr/lib64/python36.zip',
'/usr/lib64/python3.6',
'/usr/lib64/python3.6/lib-dynload',
'/optilab/env/lib64/python3.6/site-packages',
'/optilab/env/lib/python3.6/site-packages',
'/usr/local/lib64/python3.6/site-packages',
'/usr/local/lib/python3.6/site-packages',
'/usr/lib64/python3.6/site-packages',
'/usr/lib/python3.6/site-packages']
I suspect that the list order is the culprit for this problem, but it seems i'm not able to change it.
My file structure is the following:
/optilab
/core <-- startproject directory
/env <-- virtualenv files
/static
/media
... other apps
This is the first part of my apache config (BTW, I tried with python-path in WSGIDaemonProcess but didn't help):
WSGIPythonPath /optilab/env/lib64/python3.6/site-packages:/optilab/env/lib/python3.6/site-packages:/optilab:/optilab/core
<VirtualHost *:80>
ServerName optilab
WSGIDaemonProcess optilab python-home=/optilab/env
WSGIProcessGroup optilab
WSGIApplicationGroup %{GLOBAL}
WSGIScriptAlias / /optilab/core/wsgi.py
<Directory /optilab>
Require all granted
</Directory>
<Directory /optilab/core>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
....
I tried everything but nothing worked.
I have a django web application which I need to serve from an apache server on CentOS 6.8. In order to get this, I´m using mod_wsgi.
I have my project located in /path/to/myproject.
Right there I have the following directories and files:
- app1/
- db.sqlite3
- myproject/
- myprojectenv/
- manage.py
- static/
I have added to my setting.py this directive: STATIC_ROOT = os.path.join(BASE_DIR, "static/") and I´ve tried to run the django server and I can see my app view correctly.
So, after that I´ve tried to configure apache server in order to send a petition from my browser to my app, but apache rises a 403 Forbidden error.
The steps that I followed are:
- Add to httpd.conf the following information:
<VirtualHost *:80>
Alias /static /path/to/myproject/static
Alias /app1 /path/to/myproject/app1
<Directory /path/to/myproject/static>
Order allow,deny
Allow from all
</Directory>
<Directory /path/to/myproject/app1>
Order allow,deny
Allow from all
</Directory>
<Directory /path/to/myproject/myproject>
<Files wsgi.py>
Order allow,deny
Allow from all
</Files>
</Directory>
WSGIDaemonProcess myproject user=myuser group=mygroup python-path=/path/to/myproject:/path/to/myproject/myprojectenv/lib/python2.7/site-packages
WSGIProcessGroup myproject
WSGIScriptAlias / /path/to/myproject/myproject/wsgi.py
</VirtualHost>
Then, I gave rights to apache user, in order to allow apache to have access to my django project:
- sudo usermod -a -G myuser apache
- chmod 710 /home/myuser
- chmod 664 ~/myproject/db.sqlite3
- sudo chown :apache ~/myproject/db.sqlite3
- sudo chown :apache ~/myproject
Finally, I restarted the htttpd service and tried to send a petition to my app, but I got a "403 Forbidden error".
After that, I tried to copy my django project to the apache directory /var/www/ and doing this, I finnaly could see my django files but just like files, apache couldn´t run my app and show my view correctly.
I think that the problem could be about the permissions of apache user but I don´t know what else I can do.
What am I doing wrong?
What is the actual error in the Apache error log, not the 403 error in the browser?
Most likely the problem is due to your home directory being 710. This means an other user such as the Apache user cannot see into your home directory. It needs to be able to do that as the Apache user to map the URL to the WSGI application.
Either move your whole project outside of your home directory, or create a separate WSGI script file called myproject.wsgi under /var/www/myproject or similar, which has in it:
from myproject.wsgi import application
Also change:
WSGIScriptAlias / /path/to/myproject/myproject/wsgi.py
<Directory /path/to/myproject/myproject>
<Files wsgi.py>
Order allow,deny
Allow from all
</Files>
</Directory>
to:
WSGIScriptAlias / /var/www/myproject/myproject.wsgi
<Directory /var/www/myproject>
<Files myproject.wsgi>
Order allow,deny
Allow from all
</Files>
</Directory>
The Apache user only needs to be able to see the WSGI script file when doing URL mapping. The application code will actually run in your case under daemon mode with user myuser which presumably can read stuff from your home directory.
You didn't need to change ownership of your directory/files to Apache user, again because the code will run as myuser.
Although I have found a bunch of tech support to deploy Django over Apache using WSGI but infact they all have confused me unfortunately, and I couldn't get the Django running. I hope this to be real easy job but being a new comer I am facing difficulties.
I have two Django projects namely website1 and website2 inside my /home/zia/Documents/Codes/Django/website1 and ..../website2 dir, respectively. The folder containing settings.py file is root/ inside the /website1 and /website2 dir.
Apache, mod_wsgi everything is installed as required. How to edit apache2.conf and wsgi.py file to keep these two projects running over port 8080 and 8081?
I am struggling with this issue for past few days and have tried all the following websites.
link1,link2,link3,link4
UPDATE1:
I have followed the following approach right from the beginning to make things going well but found myself in some new issues. Kindly guide me where I am wrong.
Installing mod-wsgi and apache2:
sudo apt-get install libapache2-mod-wsgi && sudo apt-get update && sudo apt-get install apache2
Edit the apache2 port to 8083, instead of 80 by altering file "/etc/apache2/ports.conf": Listen 8083
Add the following line into "/etc/hosts" file: 160.75.133.175 160.75.133.175
Edit the following code in the "/etc/apache2/apache2.conf" file:
<Directory />
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Create a file inside "/etc/apache2/sites-available/" dir with name "sql_api.conf":
<VirtualHost *:8083>
ServerAdmin zia#gmail.com
ServerName 160.75.133.175
ServerAlias http://160.75.133.175
<Directory /home/zia/Documents/Codes/Django/sql_api/ >
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /home/zia/Documents/Codes/Django/sql_api/root/wsgi.py
WSGIDaemonProcess 160.75.133.175 user=www-data group=www-data threads=25 python-path=/home/zia/Documents/Codes/Django/sql_api/root/:/usr
WSGIProcessGroup 160.75.133.175
ErrorLog /home/zia/Documents/Codes/Django/sql_api/root/error.log
</VirtualHost>
Run the following commands being in "/etc/apache2/sites-available" dir: sudo a2enmod wsgi && sudo a2ensite sql_api.conf && sudo service apache2 restart
Open http://160.75.133.175:8083/ but getting the following error:
Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.
Please contact the server administrator at zia#gmail.com to inform them of the time this error occurred, and the actions you performed just before this error.
More information about this error may be available in the server error log.
Apache/2.4.7 (Ubuntu) Server at 160.75.133.175 Port 8082
NOTE: When I am making a Django project in /var/www/ dir and then doing the same approach then working just fine! I think because I am trying to access /home/zia/.... dir, there is this issue. Anyways, this is just a guess. I would appreciate your help.
Thanks to everyone. Finally found a working procedure. Follow the following steps in order:
Installing mod-wsgi and apache2:
sudo apt-get install libapache2-mod-wsgi && sudo apt-get update && sudo apt-get install apache2
Edit the apache2 port to 8083, instead of 80 by altering file "/etc/apache2/ports.conf": Listen 8083
Add the following line into "/etc/hosts" file: 160.75.133.175 160.75.133.175
Edit the following code in the "/etc/apache2/apache2.conf" file:
<Directory />
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
</Directory>
Create a file inside "/etc/apache2/sites-available/" dir with name "sql_api.conf" (make as many .conf files you want with different names, each serving different website):
<VirtualHost *:8083>
ServerAdmin zia#gmail.com
ServerName 160.75.133.175
ServerAlias http://160.75.133.175
<Directory /home/zia/Documents/Codes/Django/sql_api/ >
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /home/zia/Documents/Codes/Django/sql_api/root/wsgi.py
WSGIDaemonProcess 160.75.133.175 user=www-data group=www-data threads=25 python-path=/home/zia/Documents/Codes/Django/sql_api/root/:/usr
WSGIProcessGroup 160.75.133.175
ErrorLog /home/zia/Documents/Codes/Django/sql_api/root/error.log
</VirtualHost>
Add the following lines in the wsgi.py file inside "/home/zia/Documents/Codes/Django/sql_api/root/": sys.path.append('/home/zia/Documents/Codes/Django/sql_api/root')
sys.path.append('/home/zia/Documents/Codes/Django/sql_api')
Run the following commands being in "/etc/apache2/sites-available" dir: sudo a2enmod wsgi && sudo a2ensite sql_api.conf && sudo service apache2 restart
Open http://160.75.133.175:8083/
you should probably just start over if you made a bunch of changes to your Apache config. I'm most familiar with setups under Ubuntu.
What you need to look to do is setup both sites under apache as a virtual host. After installing apache there is a folder called sites-available and sites-enabled they should contain the virtual host files with the names of your website projects. Each virtual host will point to whereever your .wsgi file is located. these virtual hosts typically listen under the same port number (as Daniel mentioned above) but serve whichever app is requested based on the domain name. noobmovies.com google.com ect...
how to setup a virtual host with apache is pretty well explained here. this assumes you're using ubuntu though.
https://www.digitalocean.com/community/tutorials/how-to-set-up-apache-virtual-hosts-on-ubuntu-14-04-lts
your virtual host (the file should be named after your domain exp... noobmovies.com) and will look something like this...
**<VirtualHost *:8080>
ServerAdmin your_admin_email#gmail.com
ServerName www.yourdomain.com
ServerAlias yourdomain.com
<Directory /home/path/your/project/ >
Order deny,allow
Allow from all
</Directory>
WSGIScriptAlias / /home/path/your/project/app/wsgi.py
WSGIDaemonProcess yourdomain.com user=www-data group=www-data threads=25 python-path=/path/to/your/project/app/:/path/to/python/virtual/host/site-packages
WSGIProcessGroup yourdomain.com
ErrorLog /path/to/your/app/error.log
</VirtualHost>**
keep in mind the WSGIDaemonProcess is only if you're running your app using virtualenv (which you should). this tells apache where python is that should be used to read the wsgi app/run django app.
So if you're using ubuntu or linux you may just want to uninstall apache and reinstall then just follow the digital ocean instructions to get setup.
I've successfully setup one Django application using virtualenv on Ubuntu and Apache 2, using the WSGIPythonHome directive pointing to my virtualenv location. Now I am in need to create a separate Django application, that is going to run on Apache on a different port on the same Ubuntu server. I am wondering if there's a way to have Apache run multiple WSGIPythonHome instances? Currently with WSGIPythonHome being set to one virtualenv root, there's a problem with imports on the second Django app…
The best way to do this, I've discovered about a year ago, is to use WSGI as a daemon and set the python path in the daemon directive. Example is below
<VirtualHost *:80>
ServerName yourhost.com
<Directory />
Order deny,allow
#Require all granted
</Directory>
#Alias /static /opt/yourhost/static
WSGIScriptAlias / /opt/yourhost/wsgi.py
WSGIApplicationGroup %{GLOBAL}
WSGIDaemonProcess yourhost.com python-path=/opt/yourhost:/opt/yourhost/venv/lib/python2.7/site-packages processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup yourhost.com
</VirtualHost>
WSGISocketPrefix /var/run/wsgi
You should do this with separate virtual hosts in Apache. Each one can listen to a particular port, and can have its own separate WSGI directives.