Seting Up Multiple Flask Apps

Question: How do I set up an Apache server so that it supports multiple Python apps that use Flask, but also uses other languages, like PHP and node.js?

Short answer: Have a look here for a very good overview of how to set up multiple Flask apps with Apache and mod_wsgi – and google the rest.

Long answer (in the form of a series of annotated links with a brief introductory story):

When I started working on my personal website, I took over my wife’s Bluehost account. She was working on a 90s nostalgia site; I actually came up with a great name for it: the90scalled.com (the project died and the domain has been expired for a while, so visit the URL at your own risk).

Anyway.

My first few projects were mainly done with front end technologies, with occasional PHP code. Well, some of my mini-projects relied on PHP more than others, so eventually I ended up with enough legacy PHP code.

I decided to try Python (with the Flask framework) and Bluehost suddenly didn’t give me enough freedom for that. I wanted to give DigitalOcean a try as it seemed perfect – a VPS (so that I could install and run pretty much anything) and very cheap (I’m currently using their cheapest, $5/month “droplet” for all my sites – stefanbohacek.com, spaceandquotes.com and simplesharingbuttons.com – the last of which can get up to 10,000 views a month, so it seems this is a pretty good setup as I haven’t run into any problems with uptime, bandwidth or anything else.

Originally I followed the “official” way of managing large Flask apps (my actual website being one large app). This worked really well until my code base started to grow and I also started using custom domains for some of the “apps” – things spiraled out of control pretty quickly.

A much better solution, as I learned, is to set up each Flask app to run independently and let the server manage the low-level stuff, like most of the routing.

So what you’ll want to do is to create a configuration file mywebsite.conf inside /etc/apache2/sites-available. Then you can enable your mywebsite site with:

a2ensite mywebsite

Note: I am assuming here that you already have a basic understanding of how Apache works and can look up some of the details yourself; if you need an overview, you can read this tutorial on how to set up Apache virtual hosts – or use Google.

Here is a very simplified example of what your mywebsite.conf file could look like. It assumes you want to have your main Flask app handle your root directory and your projects handled separately in sub-folders.

  <VirtualHost *:80>
    ServerName www.stefanbohacek.com
    ServerAlias stefanbohacek.com
    ServerAdmin stefan@stefanbohacek.com
    DocumentRoot /var/www

    WSGIScriptAlias /sitesummary /var/www/sitesummary/sitesummary.wsgi

    <Directory /var/www/sitesummary>
      WSGIProcessGroup fourtonfish
      WSGIApplicationGroup %{GLOBAL}
      Order deny,allow
      Allow from all
      AllowOverride all
    </Directory>

    # The script handling your root folder has to come last
    WSGIScriptAlias / /var/www/fourtonfish/fourtonfish.wsgi

    Alias /simplesharingbuttons "/var/www/simplesharingbuttons"

    <Directory /var/www/simplesharingbuttons>
      Order deny,allow
      Allow from all
      AllowOverride all
    </Directory>

    Alias /hellosalut "/var/www/hellosalut"

    <Directory /var/www/hellosalut>
      Order deny,allow
      Allow from all
      AllowOverride all
    </Directory>
  </VirtualHost>

And if you want to give one of your Flask apps its own domain, you can simply create a new configuration file called anothersite.conf and write something like this:

  <VirtualHost *:80>
    ServerName www.spaceandquotes.com

    ServerAdmin stefan@spaceandquotes.com
    WSGIDaemonProcess spaceandquotes user=www-data group=www-data threads=5
    WSGIScriptAlias / /var/www/spaceandquotes/spaceandquotes.wsgi

    <Directory /var/www/spaceandquotes>
      WSGIProcessGroup spaceandquotes
      WSGIApplicationGroup %{GLOBAL}
      Order deny,allow
      Allow from all
      AllowOverride all
    </Directory>
  </VirtualHost>

Again, this is pretty simplified with just the most important directives, you might want to add logging, configure mod_expires and other stuff. You can find more examples on the page I mentioned in the beginning.

More tutorials

A tinted, zoomed in screenshot of a JSON object showing server information about a Mastodon instance.
A tinted screenshot of two charts, one showing the popularity of various fediverse platforms (with Mastodon far ahead of the rest), and the other chart showing distribution of domain creation dates, mostly clustered around 2023.
A tinted screenshot showing the @mtaupdates Mastodon profile and a few example posts with subway status alerts.

💻 Browse all