A Dynamic Route Manager for Nginx

Dynamic routing is useful when web applications or services are launched in an ad-hoc manner. This can be simply accomplished by dynamically adding new routes to an nginx reverse proxy.

A Dynamic Route Manager for Nginx
Photo by Ed 259 / Unsplash

Application servers do not generally allow incoming connections from the internet for security reasons and it is for this reason that reverse-proxies such as nginx are used to proxy connections back to some running service.

In most cases, there is usually some web-server running on some known host with some known port that connections can be routed to and in general, it is easy to configure these connections in a static configuration file.

Dynamic routing is useful when web applications or services are launched in an ad-hoc manner. Take for example when running allowing users to run VSCode or running instances of Jupyter notebook and allowing a brower to communicate to that application. The application gets launched on some host with some ports that are then opened for connection. However, once the application is running, it then becomes necessary to find a way to route a connection to start interacting with the application.

The diagram below gives an idea of multiple applications being spun up on multiple machines. A route is needed so that a user on the internet is able to connect to a running service. It then becomes necessary to dynamically manage these routes.

Dynamically launched Applications associated to some host and port

A simple way of accomplishing would be adding new routes to an nginx reverse proxy. This is possible via the creation of a http endpoint that accepts json to define the parameters to configure a server and provide configuration for each route. A docker container with this capability has been published by us and is available on docker hub. In addition, the source code for this application is available on our respository at github.

This docker image can then be run using the following command docker run -p 8000:8000 -p 8080:80 spherexdev/nginx-route-manager:0.1 & which then exposes the running nginx port at 8080 and a management endpoint at port 8000.

The management port expoeses the folloing endpoints:

  • [POST] /start_nginx
  • [POST] /stop_nginx
  • [POST] /update_routes
  • [GET] /get_routes
  • [GET] /nginx_running

By default, the nginx server is running and a sample configuration is provided below that can be posted to the update_routes endpoint:

config = {
    "server": [
        ["listen", "80"],
        ["server_name", "_"],
    ],
    "routes": {
        "/r/server1": [
            ["proxy_pass", "http://localhost:8000/"],
        ],
        "/r/server2": [
            ["proxy_pass", "http://localhost:8001/"],
        ],
        "/r/server3": [
            ["proxy_pass", "http://localhost:8003/"],
            ["rewrite", "^/.well-known/host-meta.json /public.php?service=host-meta-json last"]
        ]
}

This results in the following nginx configuration to be generated and automatically loaded by the server:

server {
    listen 80;
    server_name _;

  location /r/server1 {
        proxy_pass http://localhost:8000/;
    }
  location /r/server2 {
        proxy_pass http://localhost:8001/;
    }
  location /r/server3 {
        proxy_pass http://localhost:8003/;
        rewrite ^/.well-known/host-meta.json /public.php?service=host-meta-json last;
    }
}

We see here that a server is running at port 80 with 3 different proxy pass routes defined. From here, it would be possible to define additional routes dynamically as new services come online to allow users to get access to them.