NGINX - Proxy making me crazy


Yes I like Abyss but I could not get it to work either. It had the same symptom of a mis-formatted “Gone Off Line” message so I assumed that how Abyss handled things was different. That is why I started looking at NGINX.

Now I am thinking that maybe the server itself is the issue.

But … I am at a loss on how to debug at this point because I have tried everything I can think of.


Good progress but different server. ONE PROBLEM REMAINS

I managed to get NGINX working on a different Windows server 2008 R2. This server is very similar to the other one but works with Tim’s config. (I will return to the other server later.)

The only problem I now have is there are two domains (actually sub-domains) and they run different Stand Alone Xojo apps on different ports. NGINX is handling the certs up front and they are proxied to different ports like this : It works fine if I go directly to the HTTPS URL.

I wanted to have NGINX do an HTTP 301 and force HTTP to HTTPS.

Here is the NGINX to redirect to the HTTPS site from HTTP:

#This forces http to https server { listen 80; server_name <sub-domain-1> <sub-domain-2>; return 301 https://$server_name$request_uri; }
This redirect does work but it always ends up at the same sub-domain no matter which sub-domain is used in the URL in the browser.

I would have thought that the RETURN 301 line with the parameters would do the correct redirect.

It seems to be possibly browser cache related. If I clear the cache then it always goes to the first sub-domain I use after clearing no matter which one I specify in the URL.

I have these in the NGINX config (in the location section) but it does not help:

proxy_buffering off; proxy_cache off;

My temporary work around is simply deny HTTP (no S).

Any thoughts on an HTTP 301 redirect would be appreciated.



I created TWO of these blocks and hard coded the redirect:

[code] #This forces http to https

#Xojo App 1
server {
listen 80;
return 301

#Xojo App 2
server {
listen 80;
return 301

Hard coding the server name without a URI was OK because I don’t have any URI’s in either of these apps.

The browser cache did require clearing but after that each sub-domain HTTP did the correct redirection to HTTPS.

SO … the browser cache does play a part some how. Can the NGINX server force the browser to NOT follow the cache? Not sure.

I am posting the details of what I have learned to maybe help others. It appears that 301 redirects are sometimes cached by different browsers.

Here is an article on which browsers cache 301 redirects:

Here is a Wikipedia page on all of the different codes. Note that there are many 30x versions.

One more update then I am done.

I went back to my original server that was giving problems. I made sure the config was similar to the working Windows server. I cleared the cache in my browser … AND SUCCESS.

Apparently the cache in ALL of my browsers were pointing somehow to the site that returned an immediate “This Application Has Gone Off Line”. I suppose as I was testing I tried the same “broken” NGINX config with three different browsers and it was cached on all three.

Ahhhhh … how software tries to “silently help” and ends up doing the wrong thing.

SO … The net result:

  1. NGINX for Windows CAN be a front end for Xojo Stand Alone Apps using the proxy_pass parameter.

  2. NGINX can easily handle SSL certificates then connect to a NON-SSL HTTP Stand Alone App on a non-standard port of your choice while behind the Windows firewall on that server that does not have the non-standard port open to the public. Essentially you manage the backend Stand alone apps on IP<various_ports>.
    The certs are VERY easy. Two config lines: One for the cert bundle and one for the private key

  3. NGINX can redirect a PUBLIC HTTP request to a PUBLIC HTTPS request to always force SSL.

  4. NGINX can load balance between several Xojo Stand Alone Apps. Although not throughly tested this appears to work.

  5. NGINX appears to be able to handle multiple domain names on the SAME IP and proxy them to the correct Stand Alone app (also not throughly tested).

All of this seems to make NGINX a viable alternative to work as a “front end” to multiple Stand Alone Xojo apps to avoid the problems of CGI when performance is an issue. It also works in Windows and gives an alternative to HAProxy that is only available in Linux.

I hope this helps somebody.

Hey Mark,

Could you post your NGINX config file that works for Windows? I’m not likely to run Web Apps on Windows, but it’d rock to have that option.

In my config file that I posted in this thread for Linux, it includes what you mentioned for your items 1 - 4, although I’m using a Let’s Encrypt cert that should automatically renew itself. I’ll find out when it gets closer to the expiration date. I also haven’t tested pointing to multiple app instances on the same box or different boxes yet…

Here is based on my working config. I added lots of comments and made it sort of generic. Hopefully I did not introduce any typos.


#This works in Windows Server.  Not tested in other OS's.

#Note that forward slashes are used in file paths even in Windows.

#Also this has been edited for this post so it is possible some syntax error might exist.

#NOTE the <> characters in the domains and ports below should not be included in the config.
#     Added for clarity.

#Not used in Windows
#user  nobody;

worker_processes  1;

#error_log  logs/error.log;
#error_log  logs/error.log  notice;
#error_log  logs/error.log  info;

#pid        logs/;

events {
    worker_connections  1024;

http {
    include       mime.types;
    default_type  application/octet-stream;

    server_names_hash_bucket_size 64;

    #You can change the log format if you want with something like this
    #log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
    #                  '$status $body_bytes_sent "$http_referer" '
    #                  '"$http_user_agent" "$http_x_forwarded_for"';

    #access_log  logs/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    #keepalive_timeout  0;
    keepalive_timeout  65;

    gzip  on;

    #This is for load balancing.  See below for different proxy_pass directive.
    #If you wanted to load balance multiple different apps you would need more upstream
    #  directives with different names pointing to different ports for that group of apps.
    #This essentially gives a logical name to a group of server directives and attempts
    #  to distribute the load among the group.
    #Disabled for now.
    #upstream YourLogicalAppName {
    #    ip_hash;  #Needed for session persistence.
    #      My limited testing for ip_hash shows this may not result in evenly
    #        distributing the load among the different instances but Xojo must
    #        have session persistence.
    #    server<XojoAppONEport1>;  #Instance One
    #    server<XojoAppONEport2>;  #Instance Two
    #} #End Upstream

    #Normally you would do this return directive to force HTTP to HTTPS using variables ... but ...
    #  return 301 https://$server_name$request_uri;
    #I had trouble with this format when I had multiple domains resolving to the same IP.
    #My solution was to just "Hard Code" the return URL but other formats may work.
    #This forces http to https for domain 1
    #Browser cache can cause problems with 301 redirects.
    #Read here for more:
    server {
        listen 80;
        server_name <YourDomainNameONE>;
        return 301 https://<YourDomainNameONE>;
    } #End Server

    #This forces http to https for domain 2 (if you need a second domain)
    server {
        listen 80;
        server_name <YourDomainNameTWO>;
        return 301 https://<YourDomainNameTWO>;
    } #End Server

    server {
        server_name <YourDomainNameONE>;
        listen 443 ssl;
        #You can put your certs anywhere you want.
        #Note that in the bundle your site specific cert should be
        #  ADDED IN FRONT of the other intermediate certs if needed.
        #The server key should not have a password if you intend to run
        #  NGINX as a Windows service with NSSM.
        #  With a password you will be prompted when NGINX launches.
        #The password can be removed with OPENSSL.  Be careful not to expose the key file.
        ssl_certificate      C:/mycertdirectory/SBS_Bundle.crt;
        ssl_certificate_key  C:/mycertdirectory/server.key;

        location / {
                    proxy_buffering off;
                    proxy_cache off;
                    #If you enable load balancing (upstream) above use this instead
                    #proxy_pass http:YourLogicalAppName;  #For load balancing
                   } # End Location

    } #End Server

    server {
        server_name <YourDomainNameTWO>;
        listen 443 ssl;
        ssl_certificate      C:/nginx-1.11.10/certs/SBS_Bundle.crt;
        ssl_certificate_key  C:/nginx-1.11.10/certs/server.key;

        location / {
                    proxy_buffering off;
                    proxy_cache off;
                   } #End Location

    }# End Server

} #end http

I have discovered a few more settings are needed when you proxy to a stand alone app. Without these settings it appears the source of all sessions is Adding these proxy_set_header parameters fixes that issue.

location / { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto https; proxy_set_header X-Forwarded-For $remote_addr; proxy_set_header X-Forwarded-Host $remote_addr; proxy_pass<your-port>; }

Apologies for resurrecting a potentially dead thread, but has anyone gotten a definitive answer as to why this is an issue? I have absolutely no issue proxying other apps/frameworks, but Xojo is none too happy with the idea. I had it working earlier when I was directing the entire primary domain to the Xojo box. Currently I’m routing a subdomain as in the previous example:

subdomain1.domain.tld -> (WILL WORK)

…however, instead of, I’m routing to a private box on “10.x.x.x”. As I mentioned, it worked before, but attempting to use a subdomain or an endpoint with a rewrite, it presents the “off line” error. Can anyone provide any further detail as to why Xojo specifically doesn’t like this?

@Michael Williams - it is definitely doable, I have apps running behind proxies without any issue on subdomains. It is difficult to say exactly what the problem is from the info above, there are several unknown variables:

If it worked before at but not does NOT work at 10.x.x.x then I would first of all check that the box with nginx on it has access to the server at 10.x.x.x:80/443 on the http or https port you are trying to reach - just to double check that firewalling or network routing is not the issue.

If you can confirm that you can reach the standalone app without issue from the nginx box, then does your setup include any load balancing between standalone instances running on different ports? If so, not routing to the same instance consistently can cause the “offline” message and is fixed with sticky sessions (there are multiple ways to implement this) on the proxy.

If it is not either of those things, are you routing requests from the root or a directory? (https://subdomain1.domain.tld/ or https://subdomain1.domain.tld/myapp/) The second option is more tricky to get working. I would advise against it unless absolutely necessary.

Those are the first things that come to mind. LMK thx.

@John Joyce – The actual Xojo web instance is running on IIS on a Windows Server 2016. Nginx proxy is running on Ubuntu 18.04 box on the same internal network with a public facing IP. Yes, the Linux box has access to the Windows box over “10.x.x.x” – we actually have other applications proxied and communicating on different ports just fine.

Apologies for the vaguery, on the initial state. Previously, I’d redirected the primary domain “domain.tld” via “location /” and it worked. However, when reconfiguring the nginx instance, creating the same settings, but under “subdomain.domain.tld”, I get the “This application has gone offline” error. Besides fiddling with the proxy header settings (even completely removing them) the only line of code I have is “proxy_pass http://10.x.x.x:9000” (same as before).

Per Dev Tools, it can’t retrieve the CSS or “framework/framework.js”. I’ve tried adding new “location /framework” nonsense, as well as lines for static resources, but that just ends up going down a rabbit hole. At this point it’s not completely obvious why it can’t retrieve the resources.

Any further insight you could provide would certainly be appreciated.

NOTE: I’d already gone down the “/xojoendpoint” rabbit hole. Rewrites were required just to get to the normal failure of “location /”, so it was no better.

Would you mind sharing the public IP if it is open to the internet? You can DM me if you prefer.

Actually the actual public hostname would be better

I’ve run into something similar before, but I can’t remember exactly what the issue was. I’m pretty sure there was already a discussion of it on these forums and a couple of feedback reports filed.

I suspect that this issue will be resolved in the new framework, but it’s just a guess.

You might try searching feedback for web proxy and see what turns up.

Turns out that placing the following before the initial location / of the config file was sufficient:

location ~ / {
    proxy_pass 10.x.x.x:port

I have no idea why a “case sensitive” flag would make any difference whatsoever, but everything loads now. Obviously more research will be necessary on my part as this makes zero sense, but it works. shrug