Linux & Bash: Reverse proxying a webapp

In this blog post we will be setting up nginx to reverse proxy your webapp. You'll need nginx set up, and your webapp running and listening on a known port.

Let's edit the default site. Here's the default configuration, with less comments:

sudo nano /etc/nginx/sites-enabled/default  
server {

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

    server_name _;
    include hhvm.conf;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ /index.php?$args;
    }

}

Reverse proxying in Nginx is using the directive (configuration option) proxy_pass. The documentation describes the syntax as:

Syntax: proxy_pass URL;
Context: location, if in location, limit_except

The context is the blocks that the directive can be used in. The location block specifies location-specific directives. An example would be:

location /meow/ {  
    return 400; 
}

This example returns the status code 400 when the URL /meow/ is accessed, and any other subdirectories under /meow/.

Let's have the webapp run on the path /app/:

location /app/ {  
    proxy_pass http://localhost:8081;
}

That would make our configuration:

server {

    root /var/www/html;

    # Add index.php to the list if you are using PHP
    index index.php index.html index.htm index.nginx-debian.html;

    server_name _;
    include hhvm.conf;

    location / {
        # First attempt to serve request as file, then
        # as directory, then fall back to displaying a 404.
        try_files $uri $uri/ /index.php?$args;
    }

    location /app/ {
        proxy_pass http://localhost:8081/;
    }

}

Whoops. When you mounted the app on /app/, the JavaScript and CSS still think the app is mounted on /. The quick and dirty way to do this is to replace all occurrences of "/ with "/app/:

location /app/ {  
    proxy_pass http://localhost:8081/;
    sub_filter '"/' '"/app/'; # Replace root paths
    sub_filter_once off; # Replace all occurrences
}

There, we're done! Now just reload nginx.

sudo systemctl reload nginx