Using in production

Update: I wrote a post about how to call get_url from within a SimpleTemplate template. The same technique works to make any Python variable or function you want globally accessible by default from a SimpleTemplate template.

This is a quick guide to using in a (semi-)production environment with lighttpd. is a super-lightweight (one source file!) web framework for Python which I use for quick, single-purpose web scripts. For example, I have used for small web applications to:

  • Monitor CPU and HDD temps
  • Provide a quick and easy personal file drop location
  • Administer hg repositories

This guide will show some techniques to write a URL-agnostic app in and then deploy it, using FCGI and lighttpd. Requirements:

  • python>=2.7
  • flup tips


Use the get_url function to write a URL-agnostic app. With get_url, you can mount your app at any root URL on your server. For example, if your app handles the /viewpost and /listposts URLs, and you mount it at, the final URLs that you would access from your web browser would be and You can only use get_url with named routes:

import bottle
app = bottle.default_app()

@app.route('/viewposts', name='viewposts')
def handle_viewposts():
    return 'first post!'

# Calling get_url from handle_index
def handle_index():
    return '<a href="{}">View posts</a>'.format(app.get_url('viewposts'))

You can also use get_url for dynamic routes (routes with parameters):

@app.route('/get/<name:path>', name='getobj')
def handle_getobj(name):
    return bottle.static_file(name, root='/path/to/files')

# Call get_url like this
url = app.get_url('getobj', name='filename.txt')

Deploying with flup

Usually I deploy Python web apps with flup (there's also a Python 3 version). I use FastCGI on a Unix socket, running behind lighttpd. For these examples, assume that the app socket is called /run/lighttpd/myapp.sock.

Python configuration

For Python 2.7 and flup, use Bottle's builtin flup server, setting the bindAddress to the path to the socket:

if __name__ == "__main__":
    run(server='flup', options={'bindAddress': '/run/lighttpd/myapp.sock'})


Make sure mod_fastcgi is loaded in your config. To mount an FCGI Bottle app at some URL, say /myapp, add this to your lighttpd.conf:

fastcgi.server = (
    "/myapp" => (
        "myapp-fcgi" => (
            "socket" => "/run/lighttpd/myapp.sock",
            "check-local" => "disable",
            "docroot" => "/",

Disabling check-local allows your app to handle URL requests even if a file of the same name does not exist on the local filesystem. For more information on lighttpd and FastCGI, see the official documentation.


comments powered by Disqus