Adding a Django site breaks my virtual hosts on CentOS 7 - django

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.

Related

Rewrite Rule to redirect everything in a directory to root of site

I just set up my first VPS. I have a primary domain - "mysite.com". I am hosting other websites within the directory of the primary domain. So that they are organized, I have placed them in a folder called "sites".
The problem is that i am able to reach the secondary sites by going to "mysite.com/sites/othersite/index.php as well as by the secondary domain's url.
I know I need to use .htaccess to fix this. so far I have tried the following after some research:
RewriteRule ^/sites/(.*)$ http://www.othersite.com/$1 [R=301,L]
This DOES rewrite mysite.com/sites/ back to the root url, but mysite.com/sites/othersite/index.php still produces a copy of othersite.com
I am looking for a rewrite rule or set of rules that will redirect absolutely any request for anything (files, subfolders, etc) in the /sites/ directory to the root directory (mysite.com)
That's not the way to do it. You should set up virtual hosts and set the webroot to separate folders.
Create a virtual host file for each site. And write an include statement for the entire directory in your httpd config.
Example of a virtual host file:
<VirtualHost *:80>
ServerName domainname.com
DocumentRoot /var/www/vhosts/domainname.com
<Directory /var/www/vhosts/domainname.com>
Options Indexes FollowSymLinks MultiViews
AllowOverride All
</Directory>
CustomLog /var/log/httpd/domainname.com-access.log combined
ErrorLog /var/log/httpd/domainname.com-error.log
LogLevel warn
</VirtualHost>
This will separate your error logs by domain

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>

settings in apache for django app which need ssl for some pages

My django app (let me call it partlysecureapp)has an index page which is visible to all.All the other pages (reachable from links on index page) need the user to log in. I want to use the app with SSL in apache2.
I already have an app(say mysecureapp) deployed on apache with SSL, which has all pages needing login by the user. I have set the configurations for this as follows.
My apache2 is at /etc/apache2 which has the following directory structure.
/etc/apache2/
|--conf.d---*charset,security,localized-error-pages*
|---mods-available---...
|---mods-enabled---...
|---sites-available---default,default-ssl,ssl
|---sites-enabled---shortcut to ssl
|---apach2.conf
|---httpd.conf
|---ports.conf
|---magic
|---envvars
For the secureapp, I have set this in file sites-available/ssl
<VirtualHost *:443>
ServerAdmin webmaster#localhost
DocumentRoot /home/dev/python/django/mysecureapp
SSLEngine on
SSLOptions +StrictRequire
SSLCertificateFile /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
...
WSGIScriptAlias /mysecureapp /home/dev/python/django/mysecureapp/mysecureapp.wsgi
Alias /site_media/ /home/dev/python/django/mysecureapp/media/
</VirtualHost>
This works perfectly..
To deploy my partlysecureapp,
http://127.0.0.1:8080/partlysecureapp/ need to show index page which is accessible to all.
but
../partlysecureapp/link1/
../partlysecureapp/link2/
../partlysecureapp/link3/
require login and should be served through ssl .
I think, I need to add another WSGIScriptAlias for my partlysecureapp. Do I need to add another DocumentRoot for the partlysecureapp? How to tell apache to serve the index page from port 8080 and others through ssl port?
As of now the /etc/apache2/httpd.conf is blank. Only the sites-available/ssl file has a VirtualHost element.
First of all, let's separate the concerns here: one thing is to require login, other is to require SSL. The former is specific to Django, and should be handled in your views; and for the latter, IMHO you should consider the possibiilty of serving everything through SSL, that would simplify your setup a lot. Sure, there's some overhead, and it's up to you to decide whether it matters or not for your particular case.
That said, for your proposed scenario:
To serve anything from plain HTTP, you need to listen to the port 80 (or, in your case, 8080). So you need a separate VirtualHost bound to that port, with a separate WSGI application for itself.
To allow a single path (your index file) from this virtual host, but require everything else to be served by the SSL protected one, you can use mod_rewrite:
RewriteEngine On
RewriteRule ^/partlysecureapp$ - [L,NC]
RewriteRule (.*) https://127.0.0.1/partlysecureapp%{REQUEST_URI} [L,R=301]
The first rule tells Apache not to perform any redirect if the path is exactly like your root path; the second redirects everything else to https (which will be handled by your *:443 virtual host).
(Note: you might want to serve /site_media without SSL as well)
Then you can simply add your WSGI alias; even if Django sends the user to a different page, Apache will ensure that page is served through SSL.
You final code would be something like:
<VirtualHost *:8080>
ServerAdmin webmaster#localhost
DocumentRoot /home/dev/python/django/partlysecureapp
RewriteEngine On
RewriteRule ^/partlysecureapp$ - [L,NC]
RewriteRule ^/site_media - [L,NC]
RewriteRule (.*) https://127.0.0.1/partlysecureapp%{REQUEST_URI} [L,R=301]
...
WSGIScriptAlias /partlysecureapp /home/dev/python/django/partlysecureapp/partlysecureapp.wsgi
Alias /site_media/ /home/dev/python/django/partlysecureapp/media/
</VirtualHost>
And your code for the SSL protected virtual host would be identical to the mysecureapp one (using partlysecureapp instead, of course; note also that you can have both apps running side-by-side, just pay attention to your MEDIA and STATIC paths).

Apache config to hook SSL into Django

I have a django app that requires some user credentials. I want to send login/register data over HTTPS. I've self-generated a certificate to test out and have also requested an external certificate, though that's pending.
I want to make sure that I don't royally screw up my AWS instance. I've grabbed pieces from different tutorials. For instance, in one tutorial, the SSLCertificateKeyFile was a .pem file but another tutorial had it as a .key file. I could only find a .key file in my dirs, so I just used that. Also, I'm not sure if "IfDefine" conditional is necessary/applicable and I also don't know whether the last line of my SSL virtual host, which seems to be making a change based on sniffing IE, should be included.
My mod-WSGI config normally looks like this:
<VirtualHost *:80>
ServerName mysite.com
ServerAlias www.mysite.com
DocumentRoot /home/dir/
Alias /media/ /home/dir/public_html/media/
<Directory /home/dir/public_html/media>
Options -Indexes
Order deny,allow
Allow from all
</Directory>
Alias /admin_media/ /home/dir/project/admin/
<Directory /home/dir/project/admin >
Order deny,allow
Allow from all
</Directory>
WSGIScriptalias / /home/dir/project/apache/django.wsgi
WSGIScriptalias / /home/dir/project/apache/django.wsgi
<Directory /home/dir/project/apache >
Order deny,allow
Allow from all
</Directory>
ErrorLog /var/log/apache2/error.log
</VirtualHost>
I've added the following virtual host for https connections:
<IfDefine SSL>
<VirtualHost *:443>
ServerName mysite.com
ServerAlias www.mysite.com
DocumentRoot /home/dir/
SSLEngine on
SSLCertificateFile /usr/lib/ssl/www.mysite.com.crt
SSLCertificateKeyFile /usr/lib/ssl/www.mysite.com.key
#SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown
</VirtualHost>
</IfDefine>
Does this look about right? Is this sufficient to start requiring https for certain views via a custom decorator? I also want to require https for requests to admin. I've seen the following:
RewriteRule (.*) https://example.com/$1 [L,R=301]
...
I wasn't sure how to make that RewriteRule work without getting rid of Alias-ing. How should I handle that?
Thanks!

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.