1

I'm hoping someone can help me.

I am trying to re-deploy a set of flask apps on to a ubuntu 20 machine, from a Ubuntu 18 machine, but they are behaving differently to earlier deployments.

They have successfully been deployed on Ubuntu 14,16 and 18, including the conversion from python 2 to 3 at Ubuntu 18 deployment but the latest deployment on Ubuntu 20 has me totally stumped.

They are running with the config described below (successfully on Ubuntu 18). When deploying on a new Ubuntu 20 machine, flask is seeing the route as the script root (as well as the script root) which is resulting in a 404.

The setup currently working on U18 is as follows (nginx simplified for testing on non TLS connection)

The app running on :9999 is not on it's own location, and is working fine.

NGINX:

server {
 underscores_in_headers on;
 listen 80 default_server;
 server_name _;

 location /.well-known {
  root /var/www/html/;
 }

 location / {
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:9999;
 }
 
 location /a {
  uwsgi_param SCRIPT_NAME /a;
  uwsgi_modifier1 30;
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:10017;
 }
}

UWSGI:

    [uwsgi]
    socket = :10017
    plugin = python3
    wsgi-file = /home/webmaster/app/run
    callable = app
    master = true
    enable-threads = true
    processes = 1
    chdir= /home/webmaster/app
    uid =  www-data
    gid = www-data

I set the 404 handler to return some URL information and instead of getting the app's landing page, I get the 404 with the following (i.e. nginx is passing to uwsgi, and the app is running)

URL:

http://192.168.0.250/a

Output:

url root http://192.168.0.250/a/
script root /a
request url http://192.168.0.250/a/a
request path /a
request full_path /a?

So url_root and script_root are as you'e expect, and what we want to see, but request_url (http://192.168.0.250/a/a) and request_path (/a) are not. For everything to have it's own location, request_path should be "/".

What I've tried

I referred to previous questions, particularly this one: Q: Serving flask app on subdirectory nginx + uwsgi and this one: A: How to host multiple flask apps under a single domain hosted on nginx?

I've tried the suggestions in those posts, including the following nginx configurations:

super simple, with uwsgi being asked to do more:

location /c {
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:10017;
 }

with UWSGI:

[uwsgi]
socket = :10017
plugin = python3
wsgi-file = /home/webmaster/app/run
callable = app
master = true
enable-threads = true
processes = 1
chdir= /home/webmaster/app
uid =  www-data
gid = www-data
mount = /a=run
manage-script-name = true

This did not solve the problem

I next tried a re-write to (try) and trick uwsgi into thinking that it is running without the script root

 location /b {
  rewrite  ^/b/(.*) /$1 break;
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:10017;
 }

This too was unsuccessful

I have also been through the suggestion in the above questions discussion sections, and whilst most work on modifying the script root, none have remove the script root from the path enabling a flask route of "/start" to serve the root of the app identified by www.app.com/a/start

I am also aware that uwsgi_modifier1 30; is depreciated, although this is the first deployment of these flask apps where that has been an issue.

I have also tried to use the parameter script_name=None on the flask side as per this question: How can I avoid uwsgi_modifier1 30 and keep WSGI my application location-independent

but nothing thus far has worked, and I'm totally stumped. It's probably something simple, but I don't know where to look from here.

Last thing, these apps run in emperor mode, and running uwsgi from command line, both as individual .ini files, or the emperor file makes no difference.

uwsgi is running as a service installed via apt, not pip (but appearing to running fine with plugin=python3) in case anyone has had experience with this being problematic.

I'd like to stick with the apt installation if at all possible.

Thanks heaps in advance to anyone that can help.

[on edit]

This is my wsgi file where I tried to let flask handle the static route. Should have included it earlier, but it was an oversight.

Thanks

#!/usr/bin/python3
from application import app
app.config['SECRET_KEY'] = 'XXXXXXXXXX'
app.config["SESSION_COOKIE_SECURE"] = True
app.config["REMEMBER_COOKIE_SECURE"] = True
app.config["SESSION_COOKIE_HTTPONLY"] = True
app.config["REMEMBER_COOKIE_HTTPONLY"] = True
app.config['APPLICATION_ROOT'] = '/a'
app.static_url_path = '/a'
if __name__ == "__main__":
    app.run(debug = True, host= '0.0.0.0', port= 5000)

1 Answers1

0

For others who stumble across this:

use re-write as per other questions advice, just watch the expression you use for correctness.

This will fail:

 location /foo {
  rewrite  ^/foo/(.*) /$1 break;
  uwsgi_param SCRIPT_NAME /foo;
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:10017;
 }

as it will only work for script name "foo", route "/bar" at URL "/foo/bar". The root of /foo will fail.

This will work: rewrite ^/foo(.*) /$1 break;

e.g.

location /foo {
  rewrite  ^/foo(.*) /$1 break;
  uwsgi_param SCRIPT_NAME /foo;
  include uwsgi_params;
  uwsgi_pass 127.0.0.1:10017;
 }

it will pass the script name, and take it out of the request path which makes it work.

the problem is the extra "/" in the rewrite.

It was a simple mistake that took me a lot of finding as I couldn't see the forest for the trees... so I hope this can assist someone else.