Search code examples
nginxflaskuwsgi

How to host multiple flask apps under a single domain hosted on nginx?


What I am trying to achieve:

I have an nginx web server hosting mydomain.com. When someone types my domain.com into their client I would like my server to serve index.html from /var/www/mydomain/ When they type mydomain.com/flaskapp1 they should see flaskapp1. When they type mydomain.com/flaskapp2 they should see flaskapp2.

I have managed to get one or the other flask apps served using the tutorial here http://www.markjberger.com/flask-with-virtualenv-uwsgi-nginx/ but when trying to implement serving two separate flask apps I run into difficulty. Instead of seeing the flask app I get a 404 message when I try to access either of the flask apps with mydomain.co.uk/flaskapp or mydomain.co.uk/flaskapp2 in a browser.

This is what I have so far:

cat /etc/nginx/sites-available/mydomain.co.uk

server {
       listen 80;

        server_name www.mydomain.co.uk mydomain.co.uk;

        location / {
               root /var/www/html/;
               index index.html index.htm;
        }

        location /flaskapp {
                include uwsgi_params;
                uwsgi_pass unix:/tmp/flaskapp.sock;
        }

         location /flaskapp2 {
              include uwsgi_params;
              uwsgi_pass unix:/tmp/flaskapp2.sock;
         }
 }

The above conf file has been sim linked into /etc/nginx/sites-enabled.

cat /etc/uwsgi/apps-available/flaskapp.ini

[uwsgi]
vhost = true
socket = /tmp/flaskapp.sock
venv = /var/www/flaskapp/venv
chdir = /var/www/flaskapp
module = flaskapp
callable = app

cat /etc/uwsgi/apps-available/flaskapp2.ini

[uwsgi]
vhost = true
socket = /tmp/flaskapp2.sock
venv = /var/www/flaskapp2/venv
chdir = /var/www/flaskapp2
module = flaskapp2
callable = app

Both .ini files have been symlinked into /etc/uwsgi/apps-enabled. UWSGI restarts fine without any issues and is up and running. Both flaskapp.sock and flaskapp2.sock are owned by www-data

cat /var/www/flaskapp/flaskapp.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World from flaskapp1!'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

cat /var/www/flaskapp2/flaskapp2.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World from flaskapp2!'

if __name__ == '__main__':
    app.run(host='0.0.0.0')

cat /var/www/mydomain.co.uk/index.html

<!DOCTYPE html>
<html>
<body>

<h1>mydomain.co.uk</h1>

<p>This is the index page of my domain.co.uk</p>

</body>
</html>

Both virtual environments have flask installed and will run the flask apps using the development server.

I hope it's something simple that I've missed.


Solution

  • Looking at the uwsgi documentation for NGINX here.

    Specifically:

    Unfortunately nginx is not able to rewrite PATH_INFO accordingly to SCRIPT_NAME. For such reason you need to instruct uWSGI to map specific apps in the so called “mountpoint” and rewrite SCRIPT_NAME and PATH_INFO automatically:

    Changing my flaskapp.ini and flaskapp2.ini files to contain the mount points for the apps and turning on the manage-script-name variable has worked.

    cat /etc/uwsgi/apps-available/flaskapp.ini

    [uwsgi]
    vhost = true
    socket = /tmp/flaskapp.sock
    venv = /var/www/flaskapp/venv
    chdir = /var/www/flaskapp
    module = flaskapp
    callable = app
    mount = /flaskapp=flaskapp.py
    manage-script-name = true
    

    cat /etc/uwsgi/apps-available/flaskapp2.ini

    [uwsgi]
    vhost = true
    socket = /tmp/flaskapp2.sock
    venv = /var/www/flaskapp2/venv
    chdir = /var/www/flaskapp2
    module = flaskapp2
    callable = app
    mount = /flaskapp2=flaskapp2.py
    manage-script-name = true
    

    And now both flask apps are running via uwsgi through nginx as required.