mod_wsgi loading python script from wrong Pyramid app directory - python

I have two apps with nearly identical code base (same functionality, just different branding) that I am trying to do virtual hosting with using mod_wsgi and apache.
the virtual host settings for both apps (in two separate files) are identical (with the exception of paths of course)
WSGIPythonHome /home/ubuntu/BASELINE
<VirtualHost *:80>
ServerName appA.com
ServerAlias www.appA.com
ServerAdmin admin#appA.com
DocumentRoot /home/ubuntu/appA_virtualenv/appA-server/appA
ErrorLog /home/ubuntu/appA_virtualenv/appA-server/error.log
CustomLog /home/ubuntu/appA_virtualenv/appA-server/access.log combined
Alias /static/ /home/ubuntu/appA_virtualenv/appA-server/appA/appA/static/
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIDaemonProcess appA user=www-data group=www-data \
python-path=/home/ubuntu/appA_virtualenv/lib/python2.7/site-packages/ \
home=/home/ubuntu/appA_virtualenv/appA-server/appA/
WSGIProcessGroup appA
WSGIScriptAlias / /home/ubuntu/appA_virtualenv/appA-server/appA.wsgi
<Directory /home/ubuntu/appA_virtualenv/appA-server>
WSGIProcessGroup appA
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
.
<VirtualHost *:80>
ServerName appB.com
ServerAlias www.appB.com
ServerAdmin admin#appB.com
DocumentRoot /home/ubuntu/appB_virtualenv/server/appB
ErrorLog /home/ubuntu/appB_virtualenv/server/error.log
CustomLog /home/ubuntu/appB_virtualenv/server/access.log combined
Alias /static/ /home/ubuntu/appB_virtualenv/server/appB/appB/static/
WSGIApplicationGroup %{GLOBAL}
WSGIPassAuthorization On
WSGIDaemonProcess appB user=www-data group=www-data \
python-path=/home/ubuntu/appB_virtualenv/lib/python2.7/site-packages/ \
home=/home/ubuntu/appB_virtualenv/server/appB/
WSGIProcessGroup appB
WSGIScriptAlias / /home/ubuntu/appB_virtualenv/server/appB.wsgi
<Directory /home/ubuntu/appB_virtualenv/server>
WSGIProcessGroup appB
Order allow,deny
Allow from all
</Directory>
</VirtualHost>
Contents of appA.wsgi
import os
os.environ['PYTHON_EGG_CACHE'] = '/home/ubuntu/appA_virtualenv/appA-server/python-eggs'
from pyramid.paster import get_app, setup_logging
ini_path = '/home/ubuntu/appA_virtualenv/appA-server/appA/development.ini'
setup_logging(ini_path)
application = get_app(ini_path, 'main')
Contents of appB.wsgi
import os
os.environ['PYTHON_EGG_CACHE'] = '/home/ubuntu/appB_virtualenv/server/python-eggs'
from pyramid.paster import get_app, setup_logging
ini_path = '/home/ubuntu/appB_virtualenv/server/appB/development.ini'
setup_logging(ini_path)
application = get_app(ini_path, 'main')
I enabled both sites in apache and realize that when accessing appA, the python scripts in appB's directory is loaded instead. I confirmed this by adding a print statement in the __init__.py of both apps and the text for appB is printed even when I try to access appA.
I then disabled appB by $ sudo a2dissite appB. appB.com fails to load, but appA.com is still loading appB's codes...
I added the following to appB __init__.py (Note: NOT appA)
print sys.path[0]
print os.getcwd()
the outputs are
/home/ubuntu/appA_virtualenv/lib/python2.7/site-packages/pip-1.2.1-py2.7.egg
/home/ubuntu/appA_virtualenv/appA-server/appA
which is beyond my comprehension because the output point correctly to appA's directory, yet the print are added to appB's __init__.py which is located in /home/ubuntu/appB_virtualenv/server/appB/appB/__init__.py
Also, I have already disabled appB and the apache settings no longer refer to appB's directory anywhere anymore, so why is appA still loading appB's scripts?!
what am I doing wrong? What settings do I need to change to get appA to load the scripts in its own directory? Thanks
Additional checks as suggested by Graham
Embedded or Daemon Mode
Daemon mode: mod_wsgi.process_group = 'appA'
Sub Interpreter Being Used
Main Interpreter: mod_wsgi.application_group = ''
Request Environment
PATH_TRANSLATED: '/home/ubuntu/appA_virtualenv/appA-server/appA.wsgi/'
SERVER_NAME: 'appA.com'
SCRIPT_FILENAME: '/home/ubuntu/appA_virtualenv/appA-server/appA.wsgi'
mod_wsgi.application_group: ''
mod_wsgi.process_group: 'appA'
mod_wsgi.version: (3, 4)

Nothing looks an issue on first glance.
Use:
http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Embedded_Or_Daemon_Mode
http://code.google.com/p/modwsgi/wiki/CheckingYourInstallation#Sub_Interpreter_Being_Used
to confirm what process and application group they are each executing in.
Use:
http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Displaying_Request_Environment
to see what SERVER_NAME is set to for each in requests.
Edit your question with the results.
UPDATE 1
Where there are two VirtualHost's in the Apache configuration, one cause of requests always ending up at the first VirtualHost and never reaching the second is because NameVirtualHost directive isn't being specified for the port the VirtualHost's are listening on. Normally on Linux this isn't a problem though for port 80 as it would be on by default.
The other reason it can occur is because the host name used in the URL doesn't actually match either the ServerName or ServerAlias in the desired VirtualHost. When this happens Apache will fallback to directing the URL to the first VirtualHost it found when the Apache configuration file was read. To catch when this is occurring, it is generally a good idea to declare a default VirtualHost which is read first and which denies all access. At least this way a request will not end up at the wrong VirtualHost and will be blocked.
For details of this issue with it falling back to the first read VirtualHost, see discussion in:
http://blog.dscpl.com.au/2012/10/requests-running-in-wrong-django.html
Try defining the default VirtualHost and see whether this issue of it falling back to the first VirtualHost is the issue. Then you can workout what is the issue with the Apache configuration which is causing that to occur.

Related

Problems with deploying Flask application on Apache 2.4

I'm trying to deplay my Flask application on a RHEL7 Apache 2.4 server.
File structure is the following inside /var/www/html
/app
app.wsgi
/app
app.py
/templates
/static
In my /etc/httpd/conf/httpd.conf I have the following code to set up my project:
<VirtualHost *>
ServerName 10.65.112.75:443
WSGIDaemonProcess app user=apache group=apache threads=5 home=/var/www/html/app/app
WSGIScriptAlias / /var/html/app/app.wsgi
<Directory /var/www/html/app/app/>
WSGIProcessGroup app
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Order deny,allow
Require all granted
</Directory>
Alias /static /var/www/html/app/app/static/
<Directory /var/www/html/app/app/static/>
Order deny,allow
Require all granted
</Directory>
And my app.wsgi contains the following:
#!/usr/bin/python
import sys
sys.path.insert(0, "/var/www/html/app/app/")
from app import app as application
The code for the project itself can be found in my github repository here.
I do not get any errors when trying to browse the server. It just doesnt do anything. Running my script from the terminal works, though.
Thanks for the help.
There are various things which aren't right.
You have:
WSGIScriptAlias / /var/html/app/app.wsgi
whereas it appears it should be:
WSGIScriptAlias / /var/www/html/app/app.wsgi
And:
<Directory /var/www/html/app/app/>
appears it should be:
<Directory /var/www/html/app>
Your VirtualHost definition also looks wrong. You have:
<VirtualHost *>
ServerName 10.65.112.75:443
If you really want this to be for HTTPS connections, you are missing all the SSL directives to add a SSL certificate.
ServerName would also usually be a fully qualified domain name and not an IP:PORT. The port number would usually be in the VirtualHost directive. For example, for HTTP, use:
<VirtualHost *:80>
ServerName my.host.name
where my.host.name is the full public host name for your machine which you use in the URL, not an IP address.

Using Django w/ mod_wsgi and Apache

I've been trying to work out how I'll go about setting up a Django application on production, when it's ready for deployment. I'm using Django v1.11, and my EC2 is running Ubuntu 14.04. I have been attempting to refer to this guide as reference, however it is not specific to Ubuntu, so I've been experiencing a bit of difficulty in this regard. I've referred to several other resources, but much of what is out there seems to be outdated.
I have a host rule set up on my local machine, pointing www.example.com to my EC2 instance's public IP address.
I have a virtualenv set up which lives in /home/django/example.com/ENV. My Django project lives in /home/django/example.com directly. The project name is mysite, and was generated using django-admin startproject mysite, thus it has the default wsgi.py file inside the /home/django/example.com/mysite directory. The contents of wsgi.py look like:
"""
WSGI config for mysite project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
application = get_wsgi_application()
I've tried adding VirtualHost rules such as the following:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
WSGIScriptAlias / /home/django/example.com/mysite/wsgi.py
<Directory "/home/django/example.com/mysite">
<Files wsgi.py>
Require all granted
</Files>
</Directory>
</VirtualHost>
Similarly, I've tried adding:
Include /etc/apache2/httpd.conf
to /etc/apache/apache2.conf and chucking the following:
WSGIScriptAlias / /home/django/example.com/mysite/wsgi.py
WSGIPythonHome /home/django/example.com/ENV
WSGIPythonPath /home/django/example.com
<Directory /home/django/example.com/mysite>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
into httpd.conf.
In either case, I've restarted the Apache server directly afterwards.
I'm not getting any further than hitting "500 Internal Server Error" or hitting an "ERR_EMPTY_RESPONSE".
Anyone able to shed some light around a) where I'm going wrong, b) where I can refer to for up-to-date instructions, or c) how I can troubleshoot this?
After a lot of troubleshooting, and consulting with the resource mentioned in Graham's comment, here's what I established was required in my VirtualHost:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Alias /static /home/django/example.com/static
<Directory /home/django/example.com/static>
Require all granted
</Directory>
WSGIDaemonProcess mysite python-path=/home/django/example.com:/home/django/ENV/lib/python3.4/site-packages
WSGIProcessGroup mysite
WSGIApplicationGroup %{GLOBAL}
WSGIScriptAlias / /home/django/example.com/mysite/wsgi.py
<Directory /home/django/example.com/mysite>
Require all granted
</Directory>
</VirtualHost>
and here are the contents of wsgi.py that I settled on:
"""
WSGI config for mysite project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/
"""
import os, sys
from django.core.wsgi import get_wsgi_application
path = '/home/django/example.com'
if path not in sys.path:
sys.path.append(path)
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
And it is also worth noting (simply because it wasn't immediately obvious to me) that it is necessary to specify:
STATIC_ROOT = '/home/django/example.com/static'
in settings.py, and to run python manage.py collectstatic to collect static files from all applications into said STATIC_ROOT.
I hope this helps somebody else, in future!

Django app hangs when attempting to connect to database via Apache

I am having difficulty troubleshooting this issue. I have a Django app running on an Ubuntu 14.04 server (with Apache 2.4 and mod_wsgi for Python 3.4). It connects to SQL Server via pymssql.
In development, the app works fine. I query the database, and the database returns the expected results.
In production (under the Apache user), however, the script hangs at the exact point that a database query is made. My browser (Chrome or Firefox) shows a spinning wheel that continues to spin as long as the browser window is open.
I have the following in my apache2.conf file:
ServerName localhost
# WSGIDaemonProcess application
WSGIPythonPath /home/production_code/python3env/lib/python3.4/site-packages:/home/production_code/school
# WSGIProcessGroup application
WSGIScriptAlias / /home/production_code/school/school/wsgi.py
# Python virtualenv home
WSGIPythonHome /home/production_code/python3env
# Include the virtual host configurations:
IncludeOptional sites-enabled/*.conf
And the following in my sites-enabled/000-default.conf file:
<VirtualHost *:80>
ServerAdmin *****#school.edu
ServerName localhost
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
Alias /static/ /home/production_code/school/static/
<Directory /home/production_code/school/>
Require all granted
</Directory>
<Directory /home/production_code/school/>
<Files wsgi.py>
Require all granted
</Files>
</Directory>
<Directory /home/production_code/school/static>
Require all granted
</Directory>
</VirtualHost>
Does anyone have any idea what might be causing this or how I might troubleshoot this? The Apache error logs and access logs are not particularly helpful in this situation, since a response to the request is never rendered. Similarly, Django debugging is also not useful here.
Instead of:
# WSGIDaemonProcess application
WSGIPythonPath /home/production_code/python3env/lib/python3.4/site-packages:/home/production_code/school
# WSGIProcessGroup application
use:
WSGIDaemonProcess application python-path=/home/production_code/python3env/lib/python3.4/site-packages:/home/production_code/school
WSGIProcessGroup application
WSGIApplicationGroup %{GLOBAL}
A key part of this is the WSGIApplicationGroup directive, with it being set to %{GLOBAL}.
This is to get around faulty third party extension modules for Python that don't work in sub interpreters and which can fail with a dead lock or crash.
See:
https://code.google.com/p/modwsgi/wiki/ApplicationIssues#Python_Simplified_GIL_State_API
It is also recommend you go back to using daemon mode. It is generally not a good idea to use embedded mode.
http://blog.dscpl.com.au/2012/10/why-are-you-using-embedded-mode-of.html

How to disable directory browsing for a flask application hosted using apache mod_wsgi for CNAME access from a different domain

Something weird is happening with my flask application that I have hosted using apache mod_wsgi on Ubuntu. I have a virtualhost setup with my flask app imported to it. My virtualhost is present is /etc/apache2/sites-available/ and has been enabled. The file is this:
<VirtualHost *:80>
ServerName domain1.com
WSGIDaemonProcess app user=flask group=www-data threads=5 home=/var/www/app
WSGIScriptAlias / /var/www/app/app.wsgi
<Directory /var/www/app>
WSGIProcessGroup app
WSGIApplicationGroup %{GLOBAL}
WSGIScriptReloading On
Order deny,allow
Allow from all
</Directory>
</VirtualHost>
My application works perfectly fine when I access it using domain1.com. However, if I have a domain2.com with a CNAME record pointing to domain1.com, I can view the directories and files when domain2.com is accessed. Similarly, when I change the ServerName to domain2.com, the directory listing is visible from domain1.com.
I've been advised to edit the httpd.conf file and remove the Indexes entry or change it to -Indexes to turn off the directory browsing but the file is empty. I would like the app to work only from the domain specified in the ServerName and not from any other domain name pointing to it. Please advise.
The advice given is correct but I believe on Ubuntu the default virtual host is in /etc/apache2/apache2.conf or /etc/apache2/sites-available/default. what's happening is that because both domains resolve to the same ip, domain2 picks up the default Apache configuration because it doesn't have its own virtual host.
You could also prevent this by moving the document root of domain1 to a different location but its a good idea to turn off the indexes in any case.
For the second domain name, because Apache cannot find a matching VirtualHost, it will fall back to using the very first VirtualHost definition it found when parsing the configuration.
For an explanation of this in a slightly different context see:
http://blog.dscpl.com.au/2012/10/requests-running-in-wrong-django.html
Read the section 'Fallback to default VirtualHost definition'.
If you want all other domain names blocked, then change the default VirtualHost to:
<VirtualHost _default_:*>
Deny from all
</VirtualHost>

Multiple Django Apps on one Server

How is it possible to serve out multiple Django apps on multiple domains?
For example I have
djangoapp1.com and djangoapp2.com
I then have two separate apps in two separate locations
/srv/www/djangoapp1
/srv/www/djangoapp2
I am running Apache2 with mod_wsgi and I currently have the following in its httpd.conf
WSGIScriptAlias / /srv/www/app1/app1/wsgi.py
WSGIPythonPath /srv/www/app1
<Directory /srv/www/app1/system>
<Files wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
I also then obviously have the virtual host and I get the django default install page, but now I want to serve up my second app, can anybody point me in the right way to do this?
Django V: 1.4.1
There are many approaches you can take here, and no simple answer - it depends on your requirements and constraints.
The Simplest Thing That Could Possibly Work is very likely the approach suggested by #Hedde - to define the WSGI configuration per-site inside a virtualhost.
A second and possibly more flexible approach would be to run each Django application inside it's own containing application server e.g. gunicorn (hopefully in a virtualenv to isolate application specific dependencies) on different ports and then use Apache or even Nginx as a proxy for application traffic.
This involves a more complicated server environment to manage, but gives you the advantage of being able to manage your applications individually.
You can reconfigure your available workers, upgrade application versions, make changes to settings.py etc for one application at a time rather than having to restart a single monolithic process.
In addition, although it is, of course possible, monitoring virtualhosts within the same Apache process is more complex than monitoring individual application server instances separately.
YMMV
You can use Apache's VirtualHosts
There's plenty examples for Django, e.g. here
One of the ways to run multiple django apps on a single server is to run one app on one port each.
How to run two apps on two different ports?
As recommended by Django, I am using wsgi to interface between apache and Django code. Tricky thing here is that you cannot use wsgi in "embedded" mode. In embedded some os resources are shared and hence leads to race conditions. Solution is to use wsgi in daemon mode. In daemon mode, as the name suggests, wsgi runs as separate processes and hence no shared resources. Your two django apps will be unaware of each other.
This is how my configuration looks. I am running apps on port 8082 and 8083. Notice the lines with WSGIDaemonProcess and WSGIProcessGroup and process-group=pas
Listen 8082
<VirtualHost *:8082>
WSGIDaemonProcess djangoapp1 processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup djangoapp1
WSGIScriptAlias /apis /home/apis/djangoapp1/xyz/config.wsgi process-group=djangoapp1
WSGIApplicationGroup %{GLOBAL}
<Directory /home/apis/djangoapp1>
Options +ExecCGI
<Files config.wsgi>
Require all granted
</Files>
</Directory>
</VirtualHost>
Listen 8083
<VirtualHost *:8083>
WSGIDaemonProcess djangoapp2 processes=2 threads=15 display-name=%{GROUP}
WSGIProcessGroup djangoapp2
WSGIScriptAlias /apis /home/apis/discovery_api/nykaa/config.wsgi process-group=djangoapp2
WSGIApplicationGroup %{GLOBAL}
<Directory /home/apis/djangoapp2>
Options +ExecCGI
<Files config.wsgi>
Require all granted
</Files>
</Directory>
</VirtualHost>
How to serve both the apps on port 80 ?
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName example.com
ServerAlias localhost
ProxyPassMatch "^/(apis/v1/hello$.*)" "http://127.0.0.1:8082/$1"
ProxyPassMatch "^/(apis/v1/hi$.*)" "http://127.0.0.1:8082/$1"
ProxyPassMatch "^/(apis/v1/wassup$.*)" "http://127.0.0.1:8083/$1"
ProxyPassMatch "^/(apis/v1/howdy$.*)" "http://127.0.0.1:8083/$1"
</VirtualHost>
Two ways to access wassup and hello API:
http://example.com:8083/apis/v2/wassup?q=howsitgoing
http://example.com/apis/v2/wassup?q=howsitgoing
http://example.com:8082/apis/v2/hello?q=how are you
http://example.com/apis/v2/hello?q=howareyou
Django Code
As recommended on Django website I have replaced
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")
to
os.environ["DJANGO_SETTINGS_MODULE"] = "{{ project_name }}.settings"
Please see if this is helpful
in apache2.conf or htppd.conf
# Virtual hosts setup
NameVirtualHost *
<VirtualHost *>
ServerName example1.com
............
WSGIScriptAlias / /..../path/to/wsgi1.py
</VirtualHost>
<VirtualHost *>
ServerName example2.com
............
WSGIScriptAlias / /..../path/to/wsgi2.py
</VirtualHost>
in wsgi1.py
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings1' # or projectnaame.settings1
in wsgi2.py
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings2' # or projectname.settings2
In settings1.py & settings2.py you can make necessary databases and other configurations

Categories

Resources