How to setup StaticGenerator with Apache + mod_wsgi

29comments

3rd May 2010 in Coding Tags: apache, django, mod_wsgi, performance, staticgenerator

StaticGenerator is an excellent Python class for Django that can help to boost drastically the performance of certain types of web-sites.

It works by generating static html files for the chosen pages, this way the server will avoid all the work of generating a page at every request. As you might know, static html pages are much faster to load than any other script processed by the server.

I noticed StaticGenerator while I was looking for some cache invalidation solution and I understood that would have been just perfect for my web-site, because the pages of blog and a portfolio don't change that often. The result, as you can see, it's brilliant but it took me some time to make it work properly with Apache because the StaticGenerator instructions show only how to configure it with Nginx.

Using Apache instead of Nginx

I've found some suggestions around the net that show how to make this trick with mod_python, but unfortunately I use the more recent mod_wsgi, following the suggestion wrote in the Django Documentation.

So here it is the code to use:

<VirtualHost *>
    # ...
    # ...
    # your virtual host setup
    
    # change this with your correct path
    <Directory "/yourpathto/yoursitefolder/public">
        # ...
        # your directory setup here

        # You might need this in case your server is not configured to open index.html as default index
        DirectoryIndex index.html
    </Directory>

    # make sure mod_rewrite is loaded
    RewriteEngine On

    # this tells apache to serve any file that match the request
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
    # this tells apache to serve the index.html produced by StaticGenerator
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.html !-f
    # this tells Apache to forward all the other requests to
    RewriteRule ^/(.*)$ /yourscript.wsgi/$1 [QSA,L,PT]

    # the WSGIScriptAlias directive, you should already know this if you're using mod_wsgi
    WSGIScriptAlias /yourscript.wsgi /yourpathto/yoursitefolder/django/django.wsgi

</VirtualHost>

You will have to put this code in your main apache configuration file, that is located in "/etc/apache2/sites-available/default" or "/etc/apache2/apache2.conf" on debian,

If you are not sure, use "locate" in the terminal:

$ locate apache
$ locate httpd

This trick can work also if you use FastCGI, just replace the WSGI  with the FastCGI directive and it should work.

Retweet

Comments

  1. 1.

    Angelo said:

    ( on 3rd of May 2010 at 17:34 )

    wow! nice guide! I love your constancy to do your best! ^^

    cya friend ;-)

  2. 2.

    Federico Capoano said:

    ( on 3rd of May 2010 at 17:36 )

    Thank you bro! ;-)

  3. 3.

    Vikash said:

    ( on 20th of May 2010 at 13:05 )

    Nice article !! But I am not getting the way to implement it,
    What are the configuration I need to made to achieve this.
    I am using apache + mod_wsgi.
    Please guide me as step by step process so that I can implement it for my site.
    Thank you

  4. 4.

    Federico Capoano said:

    ( on 20th of May 2010 at 14:45 )

    You need to install StaticGenerator and configure it properly in your django settings file, then you need to edit your apache configuration file in the virtualhost section to what suggested in this article or similar.

    If you give me more information I can be more helpful.

  5. 5.

    vikash said:

    ( on 20th of May 2010 at 14:55 )

    Thanks for your response,
    I need apache settings for mod_wsgi instead of mod_python.
    I installed static generator and made other configurations in settings.py but I am not getting apache configuration(using mod_wsgi)
    If you want any other information please let me know.
    Thanks again for your fast response.

  6. 6.

    Vikash said:

    ( on 20th of May 2010 at 15:02 )

    I made the settings what is shown here but still not getting the result.

  7. 7.

    Federico Capoano said:

    ( on 20th of May 2010 at 15:09 )

    Did you restart apache?
    /etc/init.d/apache2 restart
    what do you get?
    what linux distribution does your server use?

  8. 8.

    Vikash said:

    ( on 20th of May 2010 at 15:42 )

    Ya i did !
    this is my virtualhost
    <VirtualHost *:80>
    ServerName example.com
    Alias /admin_media /usr/lib/python2.4/site-packages/django/contrib/admin/media
    WSGIScriptAlias / /home/djuser/demo/Explocity.wsgi
    WSGIDaemonProcess demo user=djuser group=djuser processes=1 threads=10
    WSGIProcessGroup demo
    <Directory /home/djuser/demo>
    Options +ExecCGI
    Allow from all
    </Directory>
    </Virtualhost>

    in settings.py
    WEB_ROOT = '/home/djuser/demo/StaticGenerator'
    MIDDLEWARE_CLASSES = (
    'staticgenerator.middleware.StaticGeneratorMiddleware',
    )

    what am i missing??

  9. 9.

    Federico Capoano said:

    ( on 22nd of May 2010 at 13:00 )

    Lots of stuff missing dude.

    Read carefully the staticgenerator docs.

    In particular you're missing:

    - STATIC_GENERATOR_URLS directive
    - WEB_ROOT has to coincide with the public directory, usually "public_html" or "www" or "httpdocs" or whatever you configure on your server, but has to coincide with the one that is available to reach from the web.
    - all the code I wrote in this article is missing, the rewrite rules and directory index. Please pay more attention and read carefully otherwise you'll never be able to do it properly.

  10. 10.

    vikash said:

    ( on 26th of May 2010 at 11:41 )

    Thanks for the response.
    I made the correction what you suggested.
    Can u tell me please how to check that it is working properly.
    In brief How to test if staticgenerator is working properly ?

    Thanks again for your valuable suggestion .

  11. 11.

    Federico Capoano said:

    ( on 27th of May 2010 at 12:41 )

    Login as root user into your server and modify one of the html file produced by staticgenerator by writing for example "Test" somewhere in it and save.
    Reload the page and if you see the word Test correctly where you placed it, it means is working correctly.
    I tested it by writing "Test" in the <title> tag of the homepage.

  12. 12.

    Christian Louboutin Shoes said:

    ( on 9th of June 2010 at 13:06 )

    Oh..wonderfull post and great information - will have a try all the tips..thanks

  13. 13.

    Chin said:

    ( on 18th of June 2010 at 08:44 )

    Great description !!
    I solved all my issues regarding configuration, Staticgenerator is creating the folder and index.html in it but it's not serving through this.
    It is not passing the test as u explain above.
    Where I m lacking ??

  14. 14.

    Federico Capoano said:

    ( on 18th of June 2010 at 10:45 )

    You have to be sure your virtualhost is configured properly.

    In particular:

    * mod_rewrite has to be enabled in your apache conf and RewriteEngine directive must be ON
    * be sure DirectoryIndex is index.html
    * be sure the last 4 lines explained in this post are set properly and they match each other.

    Also, are you sure you are really saving the HTML files generated by staticgenerator? When I open one of the file and try to save it I cannot save it unless I open it as ROOT or with the SUDO command.

    Hope it helps.

  15. 15.

    Vishnu said:

    ( on 21st of June 2010 at 09:15 )

    Hi,
    I got the staticgenerator working, its creating folders and caching the index.html files.
    The site is also functioning properly.
    But when i edit one file and write 'Test', that is not shown when i refresh my page.
    Seems it is getting overwritten.
    What could be wrong?

  16. 16.

    Federico Capoano said:

    ( on 22nd of June 2010 at 02:57 )

    Same as # 14, have to be sure everything is set properly.

    Also, be sure you are actually saving the html files, because in my case I cannot edit the files created by staticgenerator unless i'm logged as root or using the sudo command via ssh.
    Through a normal FTP user access I can't do it cos the permission doesn't let me.

  17. 17.

    Vishnu said:

    ( on 22nd of June 2010 at 08:05 )

    @Federico
    the files are getting saved, i did recheck them.
    But when i refresh the page, the edit is no longer there.

    Also,
    -ya, i checked the 4 lines.
    -mod_rewrite is enabled
    -DirectoryIndex is index.html

    and, FYI, am using mod_wsgi for django delivery, so the files are being created as myuser cause WSGI is running as myuser.

  18. 18.

    Federico Capoano said:

    ( on 22nd of June 2010 at 17:18 )

    If the edit is no longer there it means Django re-generates the html files. This happens because apache passes the request to mod_wsgi instead of the static html files.

    Did you set up staticgenerator to output files in the public folder?

  19. 19.

    Vishnu said:

    ( on 23rd of June 2010 at 07:54 )

    Hi Frederico,
    Its working !! :)
    I had put the parent directory of public folder as DocumentRoot in Apache VirtualHost.
    I changed the DocumentRoot to the public folder.
    Thanks, you made look at my Apache Virtualhost. ;)

  20. 20.

    Federico Capoano said:

    ( on 23rd of June 2010 at 22:29 )

    Very good, glad you succeeded. Come back here once every now and then ;-)

  21. 21.

    karthi said:

    ( on 29th of June 2010 at 12:55 )

    Hi

    Gr8 work !!

    I got static generator working and it is serving from automatic generated folder but after making change in original file ( or in database ) it's not reflecting changes. May be I have to use signal for this.

    How to use signals ? I have some doubt about it :

    1. Where should I write signal code ?

    2. Which models should I include for dispatching signals ?

    3. Should I include all the model that are being used in template ?

    Thanks

  22. 22.

    Federico Capoano said:

    ( on 30th of June 2010 at 14:53 )

    I put the signal directives in the model, but I think you can put it even in the urlconf or in the __init__.py of your application if you prefer.

    The key function to clean the generated html files is "quick_delete".
    I wrote a wrapper function around this that does more stuff, here's how I did it:

    # static generator
    from django.db.models import signals
    from staticgenerator import quick_delete
    from settings import WEB_ROOT
    import shutil

    def delete_post(sender, instance, **kwargs):
    quick_delete('/')
    quick_delete('/blog/')
    quick_delete('/blog/feed/')
    try:
    shutil.rmtree('%s/blog/page/' % WEB_ROOT)
    except OSError:
    pass
    quick_delete('blog/%s/' % (instance.category.slug))
    quick_delete('blog/%s/%s/' % (instance.category.slug, instance.slug))
    try:
    shutil.rmtree('%s/blog/%s/page/' % (WEB_ROOT, instance.category.slug))
    except OSError:
    pass
    try:
    shutil.rmtree('%s/blog/tags/' % WEB_ROOT)
    except OSError:
    pass

    # signal on Post
    signals.post_save.connect(delete_post, sender=Post)
    signals.post_delete.connect(delete_post, sender=Post)

  23. 23.

    karthi said:

    ( on 2nd of July 2010 at 09:01 )

    I had put this signal code in __init__.py but getting no result.

    I changed a text in my original index.html and expected the change will be reflect on site but still it is serving template from auto generaed (public) folder and no change is displaying.

    My code in a glance :


    from django.db.models import signals
    from staticgenerator import quick_delete
    from settings import WEB_ROOT
    from models import *
    import shutil


    def delete_post(sender, instance, **kwargs):
    quick_delete('/')
    quick_delete('/home/')
    quick_delete('/login/')
    try:
    shutil.rmtree('%s/login/' % WEB_ROOT)
    except OSError:
    pass
    quick_delete('login/%s/' % (instance.event.title))

    # signal on Post
    signals.post_save.connect(delete_post, sender=event)
    signals.post_delete.connect(delete_post, sender=event)


    What is wrong with this ??

  24. 24.

    karthi said:

    ( on 6th of July 2010 at 12:55 )

    Thanks Federico

    I made it working properly !!

  25. 25.

    Federico Capoano said:

    ( on 7th of July 2010 at 20:25 )

    Hey Karthi, sorry for not answering, I just moved into a new house and I don't yet have the internet line working.
    Btw I'm glad you succeded!

  26. 26.

    Vishnu said:

    ( on 9th of July 2010 at 16:50 )

    Hi Federico,
    Am Back Again.
    I have a issue.
    -----------
    Alias /static-media/ /home/django/mysite/static-media/
    RewriteEngine On
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f
    RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME}/index.html !-f
    RewriteRule ^/(.*)$ /my.wsgi/$1 [QSA,L,PT]
    WSGIScriptAlias /my.wsgi /home/django/mysite/my.wsgi
    ----------
    A setting like this does not load my css which i have kept in a folder 'static-media' in /home/django/mysite/static-media
    mysite is my django site
    my is my django app

    What could be the issue?

  27. 27.

    Federico Capoano said:

    ( on 13th of July 2010 at 12:38 )

    @Vishnu

    So I guess the HTML page is trying to load an address that gives a 404.
    Instead of using Alias, that might be bypassed by the rewrite rule, link (symbolic link) the static-media folder into the public folder.

    Example:

    Create a link called "site-media" in your site's document root that point to "/home/django/mysite/static-media/" and this should do the trick.

    Let me know

  28. 28.

    Andrew said:

    ( on 18th of April 2011 at 10:12 )

    Hi, i have one problem, many content in my site, the staticgenerator have a directory based structure, but in unix systems we have max filders limit its 32k so, if u have cache more then 32k files, staticgenerator does not work...

  29. 29.

    Federico Capoano said:

    ( on 20th of April 2011 at 15:16 )

    @Andrew:
    Hi andrew, I quite don't get your problem, I also have a unix based server (linux) but I never encountered the problem you described. Could you explain a bit more what is this 32 bit folder limit? I didn't know about it.

Comments are closed.

Comments have been closed for this post.

Categories

Let's be social

Popular posts

Latest Comments

  1. I got very good results with this, thanks for sharing.

    By Yasir Atabani in How to speed up tests with Django and PostgreSQL

  2. Hi Amad, for any question regarding OpenWISP, use one of the support channels: http://openwisp.org/support.html

    By Federico Capoano in How to install OpenWISP

  3. Sir please guid , i have install the ansible-openwisp2 , now how to add the access points . What is the next procedure . Please help.

    By Ahmad in How to install OpenWISP

  4. Hi Ronak, for any question regarding OpenWISP, use one of the support channels: http://openwisp.org/support.html

    By Federico Capoano in netjsonconfig: convert NetJSON to OpenWRT UCI

  5. Hi, I have installed openwisp controller using ansible playbook. Now, i am adding the configurations automatically using OPENWRT devices in openwisp file by specifying shared_key so can you suggest me if I want to set limit to add configuration how can i do it?

    By Ronak in netjsonconfig: convert NetJSON to OpenWRT UCI

Popular Tags

battlemesh censorship creativity criptography django event fosdem google-summer-of-code ibiza inspiration javascript jquery linux nemesisdesign netjson ninux nodeshot open-source openwisp openwrt performance photo programming python security staticgenerator talk upload wifi wireless-community