Python and Apache on the Raspberry Pi using the Flask Framework

From reading the Raspberry Pi forum, I see many are wanting to control their hardware projects from the web. Here I will show a method of integrating Python with the Apache web server, and allowing the Apache server access to the GPIO and UART ports without having to run it as root, if you have PHP already installed, both will run in the same environment. For this I am using am using Debian from here:, on a freshly installed SD card.

Part One: Installation, configuration and testing

As root, install the following packages:
# apt-get update
# apt-get upgrade
# apt-get install apache2 libapache2-mod-wsgi python-setuptools python-flask

edit your virtual host in /etc/apache2/sites-enabled, here I have added the wsgi components to the default host 000-default.

Parts easily missed are setting ExecCGI on the Options and adding to the DirectoryIndex. Note that I have set the wsgi to identify python by the extension .py, normally .wsgi is used, I think this is some kind of tradition, or old charter, or something.

Set permissions:
Apache on Debian runs as the user www-data, for access to the serial port and GPIO on the Raspberry Pi you will need to add that user to the relevant groups. Do not run apache as root, while this is not so important when on the Pi it is good practice to avoid.

Edit /etc/rc.local and add these two lines to the end of the file:
chgrp -R dialout /sys/class/gpio
chmod -R g+rw /sys/class/gpio
when you reboot the computer, group permissions will be set to dialout on the gpio

add www-data to the dialout group
# usermod -a -G dialout www-data

Update: the /etc/rc.local method does not work, instead I have found found a tool called GPIO Admin and they have also written a Python GPIO API for it. Currently it is under development, but once installed add apache to the gpio group:
# usermod -a -G gpio www-data
and the web server will have access to the gpio pins

enable the module (it may of been enabled when installed) and restart apache
# a2enmod wsgi
# /etc/init.d/apache2 restart

To test your wsgi installation place the following file into your apache root directory /var/www as and load it using your web browser, http://<pi’s ip address>/ .

Part 2: Using The Flask Framework
Here I have made a simple demonstration of how to use Flask, it consists of a wrapper,, the actual program and some html to process, demo.html. It does not show how to use the GPIO or UART. The wrapper is used to capture error messages and conveniently display them in the web browser. Again save these files into your apache root directory, /var/www and load it using your web browser, http://<pi’s ip address>/


Now all you have to do is open the port 80 forwarding on your router, and everyone in the world can make your little buzzer project make noises at two in the morning.

8 thoughts on “Python and Apache on the Raspberry Pi using the Flask Framework”

  1. I am recieving 403 “Forbidden

    You don’t have permission to access / on this server.”

    I am assuming this is permissions, i have tried chmod 755 / 777 but this does not work, any ideas?

    1. Are you placing the file in the proper directory? the default is /var/www? A more detailed error message will be recorded in the logs, have a look at /var/log/apache2/error.log

      The server only needs read permissions to the script, so chmod 644 should be OK.

  2. “Options ExecCGI is off in this directory: /var/www/” was in the error log.

    Where you have added:

    “WSGIScriptReloading On
    Addhandler wsgi-script .py”

    I had to add:

    “Options +ExecCGI”

    Into the

    Thank you for your help.

  3. I wondered if you could give any advice to a learner. I’ve got this working on my Pi, but I’m trying to figure out how to extract the value of the text into a string, and the value of the button.

    I can see ImmutableMultiDict([(‘text’, u”), (‘select’, u’a1′), (‘submitBtn’, u’submit’)]) but I want to be able to do something along the lines of:
    if ‘a1’ in data
    if ‘a2’ in data
    if ‘hello’ in data

    I think I can figure out the rest – I’m more familiar with several varieties of basic, so Python is a bit of a new step.

    1. Hello Ivan,
      Here you go, a quick change to the file to show how to get items from the submitted data:
      def index(self,request):
      ## reads an html file and does things with it
      ## there are better ways, but they are more complicated

      output = ""
      if request.form.get('submitBtn', None) == "submit":
      data = request.form
      if data['select'] == 'a1':
      output = "fred"
      elif data['select'] == 'a2':
      output = "harry"
      elif data['select'] == 'a3':
      output = "trevor"
      if data['text'].lower() == 'hello':
      output = "goodbye "+ output
      data = "

      no output recieved


      html = self.showDemoHTML(data)
      html += str(output)
      return html

      1. Thanks for getting back with this. I’ll test later and try to integrate with GPIO. Really excited about the possibilities!

        1. I got the webserver working and can do the conditional branching. Thanks for the help.
          Has anyone got this working with GPIO? – I’d love to see some examples of what this looks like with Python. I couldn’t past the Pin = … bit working following the blink example from the Quick2wire files, even though the blink example worked on its own.
          I wondered if another way would be to read and write to a shared file, with another Python program checking and controlling the real world.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.