Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serve Django static files through HTTPS?

I'm getting 404 errors when accessing static files served through HTTPS but static files work fine through HTTP.

To be clear, I can access a particular page both ways e.g. http://domain.com/page and https://domain.com/page but in the HTTPS case, the images will fail to load.

Furthermore, accessing an image directly http://domain.com/static/image.png works but https://domain.com/static/image.png returns 404.

I am running Ubuntu 10.04 with Django 1.3 using mod_wsgi on apache2.

Here are the relevant files (wsgi and prod.conf and secure_prod.conf and settings.py):

django.wsgi

import os
import sys
import site

sys.stdout = sys.stderr # Allows use of print statements

PROJECT_ROOT = '/home/code/domain/src/domain-project/'
site_packages = '/home/code/domain/lib/python2.6/site-packages'

site.addsitedir(os.path.abspath(site_packages))
sys.path.insert(0, PROJECT_ROOT)
sys.path.insert(1, os.path.join(PROJECT_ROOT, "domain"))
sys.path.insert(2, site_packages)
os.environ['DJANGO_SETTINGS_MODULE'] = 'domain.settings'
os.environ['PYTHON_EGG_CACHE'] = '/home/administrator/.python-eggs'
os.environ["CELERY_LOADER"] = "django"

import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

# Load a monitor to automatically reload apache when files change
import domain.monitor
domain.monitor.start(interval=1.0)

production.conf

<VirtualHost *:80>

  # Admin email, Server Name (domain name) and any aliases
  ServerAdmin [email protected]
  ServerName domain.com
    ServerAlias *.domain.com

  DocumentRoot /home/code/domain/src/domain-project/domain
  LogLevel warn
  WSGIDaemonProcess domain-production processes=5 maximum-requests=500 threads=100
  WSGIProcessGroup domain-production
  WSGIScriptAlias / /home/code/domain/src/domain-project/apache/production.wsgi

  SetEnv PYTHON_EGG_CACHE /home/apache/.python_eggs

    Alias /admin/media /home/code/domain/lib/python2.6/site-packages/django/contrib/admin/media
    Alias /site_media /home/code/domain/src/domain-project/static
    Alias /static /home/code/domain/src/domain-project/static
    Alias /robots.txt /home/code/domain/src/domain-project/static/robots.txt
    Alias /favicon.ico /home/code/domain/src/domain-project/static/favicon.ico

  <Location /admin/media>
    SetHandler None
    Order allow,deny
    Allow from all
  </Location>

  <Location /site_media>
    SetHandler None
    Order allow,deny
    Allow from all
  </Location>

  <LocationMatch "\.(jpg|gif|png|mp4)$">
    SetHandler None
  </LocationMatch>

  <LocationMatch "^/(robots\.txt|favicon\.ico|crossdomain\.xml)$">
    SetHandler none
  </LocationMatch>

  ErrorLog /var/log/apache2/domain/production_error.log
  LogLevel info
  CustomLog /var/log/apache2/domain/production_access.log combined

</VirtualHost>

secure_production.conf

<VirtualHost *:443>

    ServerAdmin [email protected]
    ServerName domain.com
    ServerAlias *.domain.com

    DocumentRoot /home/code/domain/src/domain-project/domain 
    LogLevel warn
    WSGIDaemonProcess domain-production processes=5 maximum-requests=500 threads=100
    WSGIProcessGroup domain_production_secure
    WSGIScriptAlias / /home/code/domain/src/domain-project/apache/production.wsgi

    SSLEngine on
    SSLOptions +StrictRequire

    <Directory />
        SSLRequireSSL
    </Directory>

    SSLProtocol -all +TLSv1 +SSLv3
    SSLCipherSuite HIGH:MEDIUM:!aNULL:+SHA1:+MD5:+HIGH:+MEDIUM

    SSLCertificateFile /home/code/domain/src/domain-project/apache/key/domain.COM.crt
    SSLCertificateKeyFile /home/code/domain/src/domain-project/apache/key/domain.com.key
    SSLCertificateChainFile /home/code/domain/src/domain-project/apache/key/Apache_Plesk_Install.txt
    SSLVerifyClient none
    SSLProxyEngine off

    <IfModule mime.c>
        AddType application/x-x509-ca-cert      .crt
        AddType application/x-pkcs7-crl         .crl
    </IfModule>


    SetEnv PYTHON_EGG_CACHE /home/apache/.python_eggs


    Alias /admin/media /home/code/domain/lib/python2.6/site-packages/django/contrib/admin/media
    Alias /site_media /home/code/domain/src/domain-project/static
    Alias /static /home/code/domain/src/domain-project/static
    Alias /robots.txt /home/code/domain/src/domain-project/static/robots.txt
    Alias /favicon.ico /home/code/domain/src/domain-project/static/favicon.ico


    <Location /admin/media>
      SetHandler None
      Order allow,deny
      Allow from all
    </Location>

    <Location /site_media>
      SetHandler None
      Order allow,deny
      Allow from all
    </Location>

    <LocationMatch "\.(jpg|gif|png|mp4)$">
      SetHandler None
    </LocationMatch>

    <LocationMatch "^/(robots\.txt|favicon\.ico|crossdomain\.xml)$">
      SetHandler none
    </LocationMatch>

    ErrorLog /var/log/apache2/domain/production_secure_error.log
    LogLevel info
    CustomLog /var/log/apache2/domain/production_secure_access.log combined

</VirtualHost>

settings.py

# Django settings for domain project.
import os

DEBUG = False
TEMPLATE_DEBUG = DEBUG 

# create a relative path to anything on the project from the PROJECT PATH
SETTINGS_PATH = os.path.dirname(os.path.abspath(__file__))
PROJECT_PATH = os.path.join(*os.path.split(SETTINGS_PATH)[:-1])
rel = lambda * args: os.path.join(PROJECT_PATH, *args)

# Absolute path to the directory static files should be collected to.
# Don't put anything in this directory yourself; store your static files
# in apps' "static/" subdirectories and in STATICFILES_DIRS.
# Example: "/home/media/media.lawrence.com/static/"
STATIC_ROOT = rel('..', 'static')

# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/static/'

# Additional locations of static files
STATICFILES_DIRS = (
    # Put strings here, like "/home/html/static" or "C:/www/django/static".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
)

# List of finder classes that know how to find static files in
# various locations.
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
#    'django.contrib.staticfiles.finders.DefaultStorageFinder',
)

# List of callables that know how to import templates from various sources.
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
#     'django.template.loaders.eggs.Loader',
)

TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.request',
    'django.core.context_processors.static',
)


MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
)

ROOT_URLCONF = 'domain.urls'

TEMPLATE_DIRS = (
    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    # Always use forward slashes, even on Windows.
    # Don't forget to use absolute paths, not relative paths.
    rel('..', 'templates'),
)

DJANGO_APPS= [
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.admin',
]

THIRDPARTY_APPS = [
    'djcelery',
    'djkombu',
    #'sentry',
    #'sentry.client',
    #'south',
]

domain_APPS= []

INSTALLED_APPS = DJANGO_APPS + THIRDPARTY_APPS + domain_APPS
like image 552
Jordan Avatar asked Aug 05 '11 02:08

Jordan


People also ask

How do I serve static files in Django?

Serving the site and your static files from the same serverPush your code up to the deployment server. On the server, run collectstatic to copy all the static files into STATIC_ROOT . Configure your web server to serve the files in STATIC_ROOT under the URL STATIC_URL .

Where should I put static files in Django?

Make sure that django.contrib.staticfiles is included in your INSTALLED_APPS . In your templates, use the static template tag to build the URL for the given relative path using the configured STATICFILES_STORAGE . Store your static files in a folder called static in your app.

How do you serve a static file?

To serve static files such as images, CSS files, and JavaScript files, use the express.static built-in middleware function in Express. The root argument specifies the root directory from which to serve static assets. For more information on the options argument, see express.static.


2 Answers

You need to alias all your static media and admin files as well.

At the moment you seem to be serving django on port 80 and 443, but the site-media just on port 80. Just copy the alias rules and the location sections into secure_production.conf

like image 81
timc3 Avatar answered Nov 04 '22 22:11

timc3


Your 443 virtual host can't be getting used because if it was mod_wsgi would complain for a couple of reasons. The first reason is that 'domain-production' is used multiple times for WSGIDaemonProcess which mod_wsgi will not allow as name has to be unique across whole Apache instance. Second, the WSGIProcessGroup in 443 references 'domain_production_secure' for which there is no WSGIDaemonProcess group directive.

You need to verify which files are actually being read. You can do this by introducing a syntax error into the files and see if Apache complains when you start it up or do a configtest.

If you are modifying what you are posting, please try not to do that, as any changes you make which change the meaning make it harder to debug.

BTW, your config has inherited certain things which are not needed for mod_wsgi and only needed for mod_python. You should go back and revise mod_wsgi documentation and clean these things up. In particular SetEnv for Python egg cache doesn't work for mod_wsgi and SetHandler None is not needed with mod_wsgi. It is also bad practice to use Location directives around Apache access control directives. Apply them to physical directories using Directory directive instead.

like image 21
Graham Dumpleton Avatar answered Nov 04 '22 21:11

Graham Dumpleton