Sanic app on NGINX subpath

Is there a variable/header I need to set to bind a Sanic application to a sub-path? During development my app runs at root, but when I deploy all of my endpoints are prefixed with, e.g. /api/v1, as I’m stitching together multiple apps with docker-compose. In flask, for reference, I would do this:

location /api/v1/ {
    proxy_set_header  SCRIPT_NAME         /api/v1/;
    proxy_set_header  Host                $host;
    proxy_set_header  X-Forwarded-Proto   $scheme;
    proxy_set_header  X-Forwarded-Port    $server_port;
    proxy_set_header  X-Forwarded-Host    $server_name;
    proxy_set_header  X-Original-URI      $request_uri;
    proxy_set_header  X-Real-IP           $remote_addr;
    proxy_set_header  X-Forwarded-For     $proxy_add_x_forwarded_for;
    proxy_set_header  Upgrade             $http_upgrade;
    proxy_set_header  Connection          "Upgrade";

    proxy_pass http://api:8080;

and Flask would get the url right. with the same setup and Sanic I get a 404.

Seems like this is (in theory) available in asgi mode, using root_path, but the available ASGI servers I looked at (e.g. uvicorn), only take root_path from their initial configuration, not from anything on the request path

To get this working right now, you would have to use nginx or something else in front of Sanic. With that said, there has been interest in this and I would like to see a PR on it soon.

I use something like this in front of my app:

server {
    server_name myserver.local;
    listen 80;

    #### HTTP Services ####

    # Authentication service
    location /api/auth/ {
        proxy_pass http://mxl-auth/;

    # Client information service
    location /api/client/ {
        proxy_pass http://mxl-client/;

    # Computed data service
    location /api/data/ {
        proxy_pass http://mxl-data/;

Each of those is an instance of Sanic.

Right, and I use NGINX for that, but sanic is giving a 404 because it’s looking for /api/v1/whatever when the paths I have registered are at /whatever. Maybe it’s to do with the other proxy variables I was passing from before?

I am not 100% clear I understand. Can you post a snippet of your nginx config?

Above is my snippet - looking more carefully at your snippet I may be falling victim to the vagaries of NGINX path management with the trailing slash; I’ll check and post back here.

Posted configuration was how we got url_for to work properly in flask where /api/v1/login would work with a path registered by a flask blueprint at /login

I’ve spent more time on this than I’d like to admit :dizzy_face: