Nginx reverse proxy arbitrary directory to subdomain

dynamic-dnsnginxreverse-proxy

We currently use Nginx as a reverse proxy in front of several IOT devices to access them from outside our internal network. Up until now, I've statically mapped a location to each device's interal IP address.

We're adding several devices that use dynamic DNS in for form of http://DeviceName.ServiceName.com but we want them to appear in the form of https://OurDomain.com/DeviceName/ in our current directory structure along side the other devices. There are going to be lots of these new devices, and I'd rather make a dynamic rule that will take the DeviceName from the URL and send the request to the correct device.

How do I set a variable from the URL and re-write it in my proxy_pass so I don't end sending the request to http://DeviceName.ServiceName.com/DeviceName/

I'm trying to follow the format at https://chrismarslender.com/2014/07/21/url-based-variables-nginx/ and I've tried:

server {
listen 80;
    server_name OurDomain.com./(?P<DeviceName>)$;
    root /var/www/html/

    location / {
    proxy_pass http://$DeviceName.ServiceName.com;
}

I've left the HTTPS stuff out of the code I posted, but haven't had trouble proxying our internal HTTP devices on our existing HTTPS site through Nginx.

Best Answer

This one should work:

server {
    listen 80;
    server_name example.com;
    root /var/www/html/;

    location ~ ^/(?:[^/]+)/(?P<path>.+)$ {
        proxy_pass http://$DeviceName.example.net/$path;
    }
}

I replaced ourdomain.com with example.com and ServiceName.com with example.net.

I changed the server_name from your version, since you have only one domain in use for the proxy virtual server.

In the location block, the regular expression picks up the first part of the normalized URI and then picks up the rest of the URI and stores it into the $path variable. That is then used in the proxy_pass destination.

You might need to tweak the location regular expression, if you have URLs like http://example.com/device, that is without the last slash character.

Related Topic