apache mod_wsgi basic authentication for django app - django

I've finished a first website based on django and I'm ready to deploy on a liveserver. However, I don't want this site to be visible to the public for now while tweaking and testing.
On PHP sites I always used basic http authentication via .htaccess to make last changes. This is a two liner which denies access for the whole site.
Ideally I want to run a environment like this:
static.mydomain.com (served by apache2 for static files)
mydomain.com (served by apache2 with mod_wsgi latest stable release -> available for public)
dev.mydomain.com (served by apache2 with mod_wsgi dev/testing -> not available for public (basic authentication))
Can this be done with django/apache2/mod_wsgi?

You could setup basic auth for your virtual host dev.mydomain.com. Look at http://httpd.apache.org/docs/2.2/mod/mod_auth_basic.html and http://httpd.apache.org/docs/2.2/vhosts/name-based.html for more details
EDIT: Your virtual host config will look somthing like:
<VirtualHost *:80>
ServerName mydomain.com
DocumentRoot /srv/www/wsgi
<Directory /srv/www/wsgi>
Order allow,deny
Allow from all
</Directory>
WSGIScriptAlias / /srv/www/wsgi/app.wsgi
</VirtualHost>
<VirtualHost *:80>
ServerName dev.mydomain.com
DocumentRoot /srv/www/wsgi-dev
<Directory /srv/www/wsgi-dev>
Order allow,deny
Allow from all
</Directory>
WSGIScriptAlias / /srv/www/wsgi-dev/app.wsgi
<Location />
AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require valid-user
</Location>
</VirtualHost>

mod_wsgi doesn't care if you use HTTP auth over it. The only provision would be that if you want it to be visible to the WSGI application then you'd need to use WSGIPassAuthorization, but this is not a concern in this case since Django has its own authentication scheme independent of HTTP auth.

Related

How to deploy multiple django apps on apache in Windows?

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>

Using Apache to proxy requests based on URL parameter

I have a back-end application (Django) that requires its static content (assets like images, scripts, stylesheets, etc.) to be served by a web server.
At current, I have my Django application serving on localhost:5000. I have this sitting behind an Apache2 server virtual host that is using mod_proxy to send requests to the Django app in the back.
I need to configure my VHost so that all of the URI requests for domain.com/static/asset will serve the asset from /path/to/asset statically, while everything else gets proxied to the back-end app localhost:5000.
My VHost config looks like this at the moment, the commented bits don't work properly.
<VirtualHost *:80>
ServerName www.domain.com
ServerAlias domain.com
ServerAdmin info#domain.com
ErrorLog ${APACHE_LOG_DIR}/domain_error.log
CustomLog ${APACHE_LOG_DIR}/domain_access.log combined
ProxyRequests Off
ProxyVia Off
<Proxy *>
Require all granted
</Proxy>
# DocumentRoot /path/to/static
# <Directory /path/to/static/>
# Require all granted
# </Directory>
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
</VirtualHost>

Reconfiguring Apache to serve website root from new php source and specific sub-urls from old django site

How do I make a django website (in a apache/mod_wsgi/django setup) which is configured to serve from the root url, serve only for specific sub-url but not the root url? The root url shall be served from a new source (php). All this with a minimum of reconfiguration.
Currently the condensed virtualhost config looks like this
<VirtualHost *:80>
ServerAdmin admin#mysite.com
ServerName mysite.com
# mappings to django
WSGIScriptAlias / /opt/mysite/mysite.wsgi
<Directory /opt/mysite>
Order allow,deny
Allow from all
</Directory>
# mappings to wordpress
Alias /wp/ /var/www/mysiteWP/
<Location "/var/www/mysiteWP/">
Options -Indexes
</Location>
Alias /show/ /var/www/mysiteWP/
Alias /collection/ /var/www/mysiteWP/
</VirtualHost>
As you can see django and php(wordpress) are running side by side. Wordpress just serving mysite.com/show/ and mysite.com/collection/. Django is serving the rest, including the root url mysite.com. This configuration works.
What I want to do now, is, I want to make wordpress serve everything except some specific urls which should be served by django. E.g. django should just serve mysite.com/shop/ and mysite.com/news/ but nothing else, also excluding mysite.com.
How would I do this with a minimum of reconfiguration?
Thanks for your answers and hints.
Props to Graham Dumpleton. He answered another question of the exact same kind in this Q&A: Django (wsgi) and Wordpress coexisting in Apache virtualhost.
In short, after configuring Apache so the root url is served from php, the solution to route specific sub urls to django, but making it think its mount point is still the root, is WSGIScriptAliasMatch.
To this (example)problem the simple addition to the apache virtual host config was this:
WSGIScriptAliasMatch ^(/(shop|news)) /opt/mysite/mysite.wsgi$1
The whole virtual host config for this example is:
<VirtualHost *:80>
ServerAdmin admin#mysite.com
ServerName mysite.com
# mappings to django
WSGIScriptAliasMatch ^(/(shop|news)) /opt/mysite/mysite.wsgi$1
<Directory /opt/mysite>
Order allow,deny
Allow from all
</Directory>
# mappings to wordpress
DocumentRoot /var/www/mysiteWP/
<Location "/var/www/mysiteWP/">
Options -Indexes
</Location>
</VirtualHost>

Two Django Sites on the same Apache Server - basic auth between the two giving 403 Forbidden

I'm running two Django sites from Apache. One is a demo page for an API so makes some API calls to the other authenticated by HTTP basic auth. I also tried doing the same thing from the same site but I had the same problem.
When a request is made, Apache is giving a 403 error message/page.
The following is the necessary parts virtual host for the API server:
<VirtualHost 12.34.567.890:80>
ServerAdmin admin#example.com
ServerName dev.example.com
ServerAlias dev.example.com
ErrorLog /var/log/apache2/lab-error.log
WSGIScriptAlias / /webapps/lab/lab-wsgi.py
WSGIPassAuthorization On
<Directory /webapps/lab>
<Files lab-wsgi.py>
Order deny,allow
Allow from all
</Files>
</Directory>
</VirtualHost>
And this is the demo site virtual host:
<VirtualHost 12.34.567.890:80>
ServerAdmin admin#example.com
ServerName dvdemo.example.com
ServerAlias dvdemo.example.com
ErrorLog /var/log/apache2/demo-error.log
WSGIScriptAlias / /webapps/lab/demo/Demo/wsgi.py
WSGIPassAuthorization On
<Directory /webapps/lab/demo/Demo>
<Files wsgi.py>
Order allow,deny
Allow from all
</Files>
</Directory>
</VirtualHost>
It seems that, although I have WSGIPassAuthorization On, the basic auth is still being handled by Apache (Apache 403 page as opposed to JSON error from Django if the authentication failed).
If I make an identical request from my local machine to the API server, it works.
Any suggestions on what could be wrong, or what I should investigate further? Thanks
Edit for clarification:
The API server has an OAuth2 API that I am attempting to create a demo page/site for. Requests to the API are successful if I make them via cURL or a different server, and only have issues when the request originates from the same server (different or same virtual host) as the API.
You can't have subdirectories in Files directive. Use:
<Directory /webapps/lab/demo/Demo>
<Files wsgi.py>
Order allow,deny
Allow from all
</Files>
</Directory>
The WSGIPassAuthorization is for passing credentials through needed for HTTP Basic authentication. It is generally highly unlikely that would be required for Django as it uses form based authentication. Are you definitely using something in Django for doing HTTP Basic authentication. Clarify what you are doing where to handle the HTTP Basic authentication.

Django (wsgi) and Wordpress coexisting in Apache virtualhost

I have a Django project that I need mounted at two different subdirectories of my url, and I need Wordpress running at /. So:
*.example.com - WordPress
*.example.com/studio - django
*.example.com/accounts - django
Here's the httpd.conf that I have so far:
<VirtualHost *:80>
ServerName wildcard.localhost
ServerAlias *.localhost
AddType application/x-httpd-php .php
DocumentRoot /var/empty
Alias /site_media/ /home/zach/projects/python/myproject/static/
Alias /media/ /home/zach/projects/python/myproject/env/lib/python2.6/site-packages/django/contrib/admin/media/
Alias / /home/zach/projects/python/myproject/wordpress/
WSGIScriptAlias /accounts /home/zach/projects/python/myproject/app/privio.wsgi
WSGIScriptAlias /studio /home/zach/projects/python/myproject/app/privio.wsgi
<Directory /home/zach/projects/python/myproject/app>
Order allow,deny
Allow from all
</Directory>
<Directory /home/zach/projects/python/myproject/wordpress>
Order allow,deny
Allow from all
</Directory>
Before I added the config for WordPress, the Django app was working fine. But with this new setup I am able to see the WordPress install at /, but the Django app isn't getting served. I'm sort of a noob at Apache config - what am I missing?
Replace:
DocumentRoot /var/empty
with:
DocumentRoot /home/zach/projects/python/myproject/wordpress
Remove:
Alias / /home/zach/projects/python/myproject/wordpress/
Replace:
WSGIScriptAlias /accounts /home/zach/projects/python/myproject/app/privio.wsgi
WSGIScriptAlias /studio /home/zach/projects/python/myproject/app/privio.wsgi
with:
WSGIScriptAliasMatch ^(/(accounts|studio)) /home/zach/projects/python/myproject/app/privio.wsgi$1
In other words, use DocumentRoot to refer to wordpress that needs to be at root of site and not Alias directive.
The WSGIScriptAliasMatch is so Django itself thinks it is still mounted at root site even though only nominated sub URLs of it are actually passed through. This simplifies things for urls.py.
Note that the $1 at end of WSGI script path is important, so don't leave it off.
Paging Graham Dumpleton :)
I'd venture a guess that the line
Alias / /home/zach/projects/python/myproject/wordpress/
overrides everything below it. Therefore any requests to /accounts will be processed by the wordpress application rather than by the Django application.
From the documentation:
Mounting At Root Of Site
If instead you want to mount a WSGI application at the root of a site, simply list '/' as the mount point when configuring the WSGIScriptAlias directive.
WSGIScriptAlias / /usr/local/www/wsgi-scripts/myapp.wsgi
Do note however that doing so will mean that any static files contained in the DocumentRoot will be hidden and requests against URLs pertaining to the static files will instead be processed by the WSGI application.