Setting up several Django apps on one server - django

I've been trying to configure two separate Django apps on one server such that they can be accessed at different URL's...using the below config, I can access the first app, but I'm at a loss at how to include the setup for the second app. The admin media is also not being loaded at all
NameVirtualHost *:8032
ServerName localhost
ServerAdmin webmaster#example.com
DocumentRoot "/usr/local/www/djcode/test"
<Directory "/usr/local/www/djcode/test">
Options +ExecCGI
Order allow,deny
Allow from all
</Directory>
Alias /site_media "/usr/local/www/djcode/test/site_media/"
Alias /media "/usr/local/www/djcode/test/site_media/media/"
WSGIDaemonProcess test user=www group=www processes=2 threads=5
WSGIProcessGroup test
AddHandler wsgi-script .wsgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /test.wsgi/$1 [QSA,L]
ServerName localhost
ServerAlias localhost
DocumentRoot "/usr/local/www/apache22/data"

Make two configuration files in /etc/apache2/sites-available folder. Give them proper logical names according to your sites (e.g. example1.com , example12.com etc). Use a2ensite command to enable both of them and restart your apache server.
Each of your config file should look something like this:
<Virtualhost *:8032>
ServerName localhost
ServerAdmin webmaster#example.com
DocumentRoot "/usr/local/www/djcode/test"
<Directory "/usr/local/www/djcode/test">
Options +ExecCGI
Order allow,deny
Allow from all
</Directory>
Alias /site_media "/usr/local/www/djcode/test/site_media/"
Alias /media "/usr/local/www/djcode/test/site_media/media/"
WSGIDaemonProcess test user=www group=www processes=2 threads=5
WSGIProcessGroup test
AddHandler wsgi-script .wsgi
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ /test.wsgi/$1 [QSA,L]
</Virtualhost *:8032>
You'll also need to add up some directives to serve static content. Serving static content from apache has overhead so it'll be a better idea if you server it using some lightweight webserver such as Lighttpd or Nginx and connect to apache using reverse proxy to serve the django based content. Here's a tutorial on using NginX
Since you are using mod_wsgi, you can run each site as different user as well so that two of them may not access each other's data. This is useful if the two sites belong to different stakeholders.

It is not clear whether you want them to both be hosted under the same VirtualHost or not. Others have gone off and told you to use separate VirtualHost's but that isn't necessary and it can be done under the same VirtualHost. Some have provided a configuration using mod_python when you were actually using mod_wsgi. You also technically didn't need the Alias directives for the static media, although where you stored them may need to change depending on URL you expected to be able to use to access them.
That all said, for your current configuration, because you have used AddHandler to map .wsgi files you can already host multiple applications, you would just need to create multiple .wsgi files in the document directory and use the appropriate URL to access them. Further configuration could be added to avoid needing to specify the '.wsgi' extensions in the URL.
I can give a proper answer if you do the following:
Say whether they need to be under the same VirtualHost.
Say what URL within the VirtualHost each distinct application should be accessible as.
Say what media URL should be used for each distinct application.
Say whether each should run in a separate process, or whether them running in different sub interpreters of the same process is adequate. Running in separate processes would allow each to be restarted independently when making code changes.

You can create multiple Virtual Hosts in Apache, and modify the following for each app:
<VirtualHost *:80>
DocumentRoot /var/www
ServerName www.site.com
<location "/<name>">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE <app name>.settings
PythonPath "['/path/to/app'] + sys.path"
</location>
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/site2
ServerName www.site2.com
<location "/<name2>">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE <app2 name>.settings
PythonPath "['/path/to/app2'] + sys.path"
</location>
</VirtualHost>
edit: also add the following to each Virtual Host
<location "/media">
SetHandler None
</location>
<location "/admin_media">
SetHandler None
</location>
<locationmatch ".(jpg|gif|png)$">
SetHandler None
</locationmatch>

I've encountered something like this. Here's some related questions, albeit not precisely on point:
How does one set up multiple accounts with separate databases for Django on one server?
Multiple installs of Django - How to configure transparent multiplex through the webserver (Lighttpd)?
Hope it helps, though.

For the admin media you can put the same alias in both virtual hosts, or if they need to be different setup a copy of them and have 2 different aliases.

Related

Adding a Django site breaks my virtual hosts on CentOS 7

I have a CentOS 7 server with about 20 domains all managed automatically with a vhosts file in /etc/httpd/conf.d.
I am trying to learn Django and wanted to set up a single domain using it, so I added a specific virtualhost to the .conf file.
The result is that the Django domain works fine but all the other sites are broken (try to use Django but cause errors).
The Django domain has two folders: djangodomain.com for static files and djangodomain.app for the Python files.
How can I integrate a single Django domain into my existing many-domain virtual host setup?
Existing vhosts.conf:
<VirtualHost *:80>
serveradmin username#domain.com
serveradmin username#domain.com
usecanonicalname off
# www.site.com ยป site.com
rewriteengine on
rewritecond %{HTTP_HOST} ^www\.(.*)$ [nc]
rewriterule ^(.*)$ http://%1 [r=301,l]
# file locations
virtualdocumentroot "/home/username/%0"
<directory "/home/username/*">
allowoverride all
require all granted
options indexes followsymlinks
options +execcgi
options +includes
</directory>
</VirtualHost>
What I added that broke all but the Django site:
<VirtualHost djangodomain.com:80>
ServerName djangodomain.com
ServerAlias www.djangodomain.com
ServerAdmin user#domain.com
DocumentRoot /home/username/djangodomain.com
WSGIScriptAlias / /home/username/djangodomain.app/django.wsgi
<Directory /home/username/djangodomain.app>
Order allow,deny
Allow from all
</Directory>
Alias /robots.txt /home/username/djangodomain.com/robots.txt
Alias /favicon.ico /home/username/djangodomain.com/favicon.ico
Alias /images /home/username/djangodomain.com/images
Alias /static /home/username/djangodomain.com/static
ErrorLog /home/username/djangodomain.logs/error.log
CustomLog /home/username/djangodomain.logs/access.log combined
</VirtualHost>
Crossposted to unix.stackexchange.com
When Apache gets an HTTP request, it needs to know what virtual host is supposed to process this request. Now, the way it works is. Apache picks up the IP address that the client request came into (the server IP, not the client) and it goes through the list of virtual host definitions to find any virtual hosts defined for that IP. If there is more than one, it will look at the Host header and try to match it to a particular ServerName or ServerAlias directive. If it still cannot find one, it will look for a default virtual host.
You have two virtual host definitions. One if the default vhost on port 80 <VirtualHost *:80>. It is the default because it has * for IP. The other is specific for the IP address <VirtualHost djangodomain.com:80>. The IP it uses is whatever djangodomain.com resolves to.
So any request that comes to that IP will be handled by the IP specific config before it might be allowed to drop into default.
To fix this, you need to replace your django virtual host directive with <VirtualHost *:80>, same as your other vhosts. This should put them all at the same parsing priority and it will just use the Host header to figure out the rest.
The said, if you are running a web server with 20+ vhosts, you really need to have better understanding on how it works. Read up on HTTP and web hosting when you have the time.

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>

Pointing subdomain to specific url in Django

I have a Django site, working on mod_wsgi and Apache. (eg, example.com) I made a subdomain (eg, info.example.com) and want to point it to app in the existing project. Is it possible, that I have one urls.py file, and example.com/info and info.example.com point to the same view in Django project (without duplicating the whole project in different directory)?
If so, how can I do it? Currently the example.com virtalhost config for the existing project looks like this:
<VirtualHost 12.34.56.78:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /srv/www/Example/Pub_html
WSGIScriptAlias / /srv/www/Example/example.wsgi
<Directory /srv/www/Example/Example>
Order allow,deny
Allow from all
</Directory>
Alias /robots.txt /srv/www/Example/robots.txt
Alias /favicon.ico /srv/www/Example/favicon.ico
....
</VirtualHost>
Thanks in advance!
UPDATE: I did a quick fix here by creating another Django project which shares database tables and template folder with the existing one. It works, but it's not really DRY :)
I'd do this with a reverse proxy, I reckon. If you have mod_proxy and mod_proxy_html available, try something like this:
<VirtualHost 12.34.56.78:80>
ServerName info.example.com
ProxyPass / http://example.com/info
SetOutputFilter proxy-html
<Location />
ProxyPassReverse /info/
ProxyHTMLURLMap /info/ /
</Location>
ProxyHTMLURLMap http://example.com/info /
</VirtualHost>
the details may not be quite right, so let me know if you can't get it to work.

Django + apache: How can I create a server alias which invisibly redirects to my django app on the server?

I am trying to figure out a how to forward a specific alias of a server to a specific django web app, and at the same time, keep the URL address bar in the user's browser to only show the server alias.
To be more specific:
This is for an intranet project at my company. We have a big linux server which does a lot of computational work, and it is also running apache to serve a variety of web pages and apps. My current django app is running at:
http://deptserver.example.com/mydjangoapps/myapp
But, I would love it if my users could use this instead:
http://myapp.example.com/
(I already have the IT folks forwarding myapp.example.com to deptserver.example.com via a CNAME in the DNS)
I can't break anything on the apache server, since it is serving critical stuff, but I do have the ability to add in things like a VirtualHost or some url rewriting rules, etc.
This is my django setup in the apache httpd.conf file:
<Location "/mydjangoapps">
SetHandler python-program
PythonHandler django.core.handlers.modpython
SetEnv DJANGO_SETTINGS_MODULE mydjangopath.settings
PythonOption django.root /mydjangoapps
PythonPath "['/home/me/mydjangopath'] + sys.path"
PythonDebug On
</Location>
And, this is in the sites-enabled default file (i.e. I can't break this part of the server):
<VirtualHost *:80>
ServerAdmin webmaster#example.com
DocumentRoot /var/www
<Directory />
Options FollowSymLinks
AllowOverride None
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
allow from all
</Directory>
ScriptAlias /cgi-bin/ /usr/lib/cgi-bin/
<Directory "/usr/lib/cgi-bin">
AllowOverride None
Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
LogLevel warn
</VirtualHost>
In that above VirtualHost I've tried something like this using mod_rerwite:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^myapp\.example\.com
RewriteRule ^(.*) mydjangoapps/myapp$1
Which doesn't work because it thinks that mydjangoapps/myapp is a file path and not a URL path, so it gives me a 400 error. I wish that it would forward to a URL path instead.
I have also tried this:
RewriteEngine On
RewriteCond %{HTTP_HOST} ^myapp\.example\.com
RewriteRule ^(.*) http://deptserver.example.com/mydjangoapps/myapp$1
Which just forwards the user to that long URL.
These are the things I have thought about but haven't tried too much:
virtualhost
mod_rewrite
alias
proxy (?)
port (putting my own apache server on a different port of the main server)
What's the best way (or only way) to do this?
Thanks!
Ask your IT folks to add another IP address (let's say a.b.c.d) to that box's network interface, and then route myapp.example.com to that new ip address.
That way, you can set up a completely separate VirtualHost:
<VirtualHost a.b.c.d:80>
# Your configuration here
</VirtualHost>
<VirtualHost *:80>
# The existing configuration here, unchanged
</VirtualHost>
Then you just have to change <Location "/mydjangoapps"> to <Location "/"> and you'll be able to access your website from a browser at http://myapp.example.com/.
As AndrewF noted, VirtualHosts are the way to go here. If you don't want to use the IP address, you can just set it up with name-based virtual hosting:
NameVirtualHost *:80
<VirtualHost *:80>
ServerName myapp.example.com
(...etc...)
Then that bit of the configuration will only respond to requests on myapp.example.com, leaving the standard configuration to pick up everything else.
Edit after comment If you're on a Debian-based system, which you seem to be as you mention sites-enabled, you shouldn't really be putting anything in httpd.conf - all the site-specific stuff should be in a separate file. This file should go in sites-available, and then run sudo a2ensite my_site_file to symlink it to the sites-enabled directory.

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.