Reverse Proxy with multiple subdir

I have been playing around with Nixos as a reverse proxy with the end goal of trying to use it to proxy multiple site on different port numbers to one domain with multiple subdir, e.g:

I have been doing most of my playing around, trying to proxy transmission, as it is easy to set up. I have reached a point where I don’t seem smart enough to figure things out on my own, and Googling has failed me.

I have mostly been using Nginx - NixOS Wiki as a starting point and using the" TLS reverse proxy" method I have gotten this far:

{config, pkgs, ...}:
{

 ...

 services.nginx.virtualHosts."example.com" = {
   enableACME = true;
   forceSSL = true;
   basicAuth = { user= "password"; };
   root = "/var/www/default";

 locations."/transmission/" = {
   proxyPass = "http://127.0.0.1:9091/transmission/";
   proxyWebsockets = true;
     extraConfig =
       # required when the target is also TLS server with multiple hosts
       "proxy_ssl_server_name on;" +
       # required when the server wants to use HTTP Authentication
       "proxy_pass_header Authorization;"
       ;
   };
 };
}

This however give me the following error which I can’t seem to resolve, and suggestions?

409: Conflict
Your request had an invalid session-id header.

To fix this, follow these steps:

When reading a response, get its X-Transmission-Session-Id header and remember it
Add the updated header to your outgoing requests
When you get this 409 error message, resend your request with the updated header
This requirement has been added to help prevent CSRF attacks.

X-Transmission-Session-Id: xLyWEsK5zEDsqyU6eb5S2ixeLUbslZzxecGJFeCjUXVkg5i2

The Nginx - NixOS Wiki also give the “Hardened setup with TLS and HSTS preloading” method, from which I got this:

{config, pkgs, ...}:
{
  
...

  services.nginx =  {
    virtualHosts = let
      base = locations: {
        inherit locations;

        forceSSL = true;
        enableACME = true;
        basicAuth = { test = "password"; };
      };
      proxy = port: base {
        "/".proxyPass = "http://127.0.0.1:" + toString(port) + "/";
      };
    in {
       "exmaple.com" = proxy 9091 // { default = true; };
    };

  };
}

This seems to work perfectly as far as I can tell. However, my attempts to rework it so that it also maps subdir have not been successfully. Any ideas or suggestions on how to do that?

Also, of the two suggestions is one preferred over the other or is there a better way. I really hope this not a loaded question.

Thank you

Firstly, that error is apparently a very common problem when people try to reverse proxy transmission: Slashes fixes by uprt · Pull Request #857 · transmission/transmission · GitHub

Guess it’s due to the confusing endpoint. You need to ensure that your reverse proxy keeps the /transmission/ bit of the URL in tact.

Since you specify /transmission/ on both, it should probably work, but for the record, if you omit the URI component like so:

proxyPass = "http://127.0.0.1:9091";

nginx won’t rewrite the URI at all, and the /transmission/ from the location will persist exactly as transmission intends. I’ve seen at least a few people fix their problems with that.

That said, I don’t think this should actually change the URI. This is probably a better question for the transmission forums.


As for the second question, you cannot assign the same domain to multiple virtualHosts, to my knowledge.

You can, however, use different subdomains:

"transmission.exmaple.com" = proxy 9091;
"blog.exmaple.com" = proxy 9092 // {
  serverAliases = [ "exmaple.com" "www.exmaple.com" ];
  default = true;
};

This will for example make your transmission server available under https://transmission.exmaple.com/transmission/, and your blog under https://blog.exmaple.com. As a bonus, it will make your blog available under https://exmaple.com as well, and if someone visits your server by IP adress the blog will show up, too.

I find this nicer, because it makes paths refer to paths, not different sites. It’s also often easier to set up. But I appreciate this isn’t your original design.

The uses of different subdomains is a nicer solution. However, I seem to be too cheap to buy a domain or to suck in my ways and just uses https://freedns.afraid.org/ which does not give the option of a subdomain.

I have been playing around with this and think I have a solution and seem to work.

{config, pkgs, ...}:
{
  services.nginx.virtualHosts."example.com" = {
    enableACME = true;
    forceSSL = true;
    basicAuth = { test = "password"; };
    root = "/var/www/default";

    locations."/transmission" = {
      proxyPass = "http://127.0.0.1:9091/transmission";
      proxyWebsockets = true;

    };
  };
}

Thank you

1 Like