Running Python Flask on an Apache server

This week on the Linux server course our task is to set up Python Flask on an Apache server and run some basic stuff on it. I'll be setting this up on a server that I set up earlier and I will set it so that a subdomain of my main domain will direct there while it is still running.

Testing name based virtual host on local machine

The first task was to simulate a dns with the hosts file on Linux. I decided to make a site that would be available on on localhost. I added a new host to /etc/hosts and created a new site configuration in Apache's sites-available folder. I added a new folder named public_sites in my home directory where I put a folder named juusotesti. Inside I put a basic index.html that has some plain-text.

hosts       localhost       TpadJ

<VirtualHost *:80>
        DocumentRoot /home/juuso/public_sites/juusotesti
        <Directory /home/juuso/public_sites/juusotesti>
                Require all granted


sudoedit /etc/hosts
sudoedit /etc/apache2/sites-available/
mkdir -p public_sites/juusotesti
echo " toimii!" > public_sites/juusotesti/index.html
curl -H 'Host:' localhost toimii!

Setting up the subdomain

I already have an Apache server running on a DigitalOcean droplet and I have a domain name registered so I can just set it up with a few clicks. The site is now available on




Apache WSGI and Hello FLask!

First I will set up WSGI on Apache so that it can serve my upcoming Flask site. I'm following Tero Karvinen's post on Flask deployment to get this done. I'll start by setting up a user that will be used to manage the Flask app and installing all the required packages.

sudo adduser tempwsgi #Creating the user
sudo usermod --lock tempwsgi #Locking it because it will be not used on its own
sudo adduser $(whoami) tempwsgi #Adding myself to the group

sudo apt-get update
sudo apt-get -y install python3 python3-flask libapache2-mod-wsgi-py3

Then I'll set up a new config in Apache's sites available folder that so that the Python app can be served when it's ready.

sudoedit /etc/apache2/sites-available/tempwsgi.conf #Creating the conf file
sudo a2ensite tempwsgi #Enabling the site
sudo a2dissite 000-default #Disabling the default site
sudo systemctl restart apache2 #Restarting Apache

The config I used is the following

<VirtualHost *:80>

        WSGIDaemonProcess tempwsgi user=tempwsgi group=tempwsgi threads=5
        WSGIScriptAlias / /home/tempwsgi/public_wsgi/temp.wsgi

        <Directory /home/tempwsgi/public_wsgi/>
                WSGIScriptReloading On
                WSGIProcessGroup tempwsgi
                WSGIApplicationGroup %{GLOBAL}
                Require all granted

Now that Apache's config is set up, the next step is to create the required file structure in tempwsgi user's directory.

sudo mkdir /home/tempwsgi/public_wsgi
sudo chown tempwsgi:tempwsgi /home/tempwsgi/public_wsgi/#change ownership of folder because it was created with sudo
sudo chmod g=rwxs /home/tempwsgi/public_wsgi/#change folder rights so that everyone in the group can acces all new file inside
nano /home/tempwsgi/public_wsgi/temp.wsgi #creating the conf
nano /home/tempwsgi/public_wsgi/ #creating the hello Flask app


import sys
assert sys.version_info.major >= 3, "Python version too old in temp.wsgi!"

sys.path.insert(0, '/home/tempwsgi/public_wsgi/')
from hello import app as application

from flask import Flask
app = Flask(__name__)

def hello():
        return "Hello Flask!"

Testing that the app is running


Then the task was to test that the site was modifiable without using sudo and without restarting the Apache server. I created a new python file that was almost the same as, I just changed the return string. Then I modified the last line of temp.wsgi to from modified import app as application.


Adding templates to Flask

To use templates with Flask I created a folder for the templates and added a simple base html-template that I would try to use. I created a base.html file with the following code, added a new path to and changed temp.wsgi back to using The {{ message }} is replaced with the value assigned in the templated function in This was done based on this Tero Karvinen's post.


<!doctype html>
                <title>Flask Template</title>
                <meta charset="utf-8">
                <h1>{{ message }}</h1>

from flask import Flask, render_template
app = Flask(__name__)

def hello():
        return "Hello Flask!"

def templated():
        return render_template("base.html", message="Templates are working!")


Using Flask request

Next I created a page that read information about the visitor with Flask's request import. I added a new path to the app in and touched the temp.wsgi file to get the new setup running. The page tells the visitor their ip and user agent.

Addition to

def requestParams():
        addr = request.remote_addr
        agent = request.user_agent.string
        return "Hello: " + addr + " -- " + agent