1

I run docker-compose with one frontend and two backend servers. The requests to the backends work like a charm, I can navigate in my app by using angulars router. The urls are changed in my browser but I assume this is done somehow internally by angular. My baseref is / I also tried it with ./.

Problem: As soon as I reload a page (or enter an uri manually) which is not index nginx tries to forward this page to @node where it is not found. I could then redirect with express to index but this does not sound like a ligid solution to me.

My nginx config:

#This is a minimalist nginx configuration file that might be an appropriate starting point for dev work
#This file was not developed with the intent of being used on a production environment.
#user nobody nogroup;

worker_processes 1;

pid        /var/log/nginx/nginx.pid;
error_log  /var/log/nginx/error.log error;

events {
    worker_connections 512;
}

http {
  include   /etc/nginx/mime.types;

  #send all requests which are not served by nginx to nodejs core
  upstream docker-node {
      server myapp_core:3000;
  }
  upstream docker-intergram {
      server myapp_intergram:5000;
  }

  #chatbot
  server {
    listen 8443 default_server ssl;
    ssl_certificate /etc/ssl/cert_chain.crt;
    ssl_certificate_key /etc/ssl/my-app.key;
    server_name my-app.com;

    location / {
        proxy_pass         http://docker-intergram;
        proxy_redirect     off;
        proxy_set_header   Host $host;
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Host $server_name;
    }
  }

  #redirect to ssl
  server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name _;
    return 301 https://$host$request_uri;
  }

  # nginx server instance
  server {
      access_log /var/log/nginx/access.log;
      listen 443 default_server ssl;
      ssl_certificate /etc/ssl/cert_chain.crt;
      ssl_certificate_key /etc/ssl/my-app.key;
      server_name my-app.com;

      client_header_buffer_size 256k;
      large_client_header_buffers 8 1024k;
      client_max_body_size 5M;

      location /assets {
          alias /usr/src/app/assets/;
      }

      location /node_modules {
          alias /usr/src/app/node_modules;
      }

      location / {
          index index.html index.htm;
          root /usr/src/app;
          # try_files $uri $uri/ @node;
          try_files $uri$args $uri$args/ $uri/ @node;
      }

      location @node {
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_set_header X-NginX-Proxy true;
          proxy_buffering on;

          proxy_pass http://docker-node;
          proxy_redirect off;

          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
      }

      location /socket.io/ {
          proxy_set_header X-Real-IP $remote_addr;
          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
          proxy_set_header Host $http_host;
          proxy_set_header X-NginX-Proxy true;
          proxy_buffering off;

          proxy_pass http://docker-node;
          proxy_redirect off;

          proxy_http_version 1.1;
          proxy_set_header Upgrade $http_upgrade;
          proxy_set_header Connection "upgrade";
     }
  }

}

Neither

try_files $uri $uri/ @node;

nor (from nginx-angular2-angular-routes)

try_files $uri$args $uri$args/ $uri/ @node; # solution from other stackoverflow question does not work

work.

In this solution seems to be to froward to index but I would like to keep my backend routes unprefixed.

Andi Giga
  • 3,744
  • 9
  • 38
  • 68

2 Answers2

1

I think route order matters in the nginx config. I recommend putting "location /" route as the last route. Otherwise it might overwrite routes that follow, could be happening with your /socket.io route?

Try changing your try_files line under location / to:

try_files $uri /index.html

I'm using it that way in my setup and it works. If you need the config under @node for your root location you can copy it to that location.

  • The order matters but if a location returns 404 it will try the subsequent locations. So socket.io will be still served.I will put this in the front but it's not solving the question because it's the routes not the websockets which are not served. Thx anyways for this advice. I cannot do this `try_files $uri /index.html` because it will require to have a diff location for the be routes. – Andi Giga Feb 28 '19 at 13:33
  • Didn't see you wanted backend routes unprefixed. Angular offers hash routing that would solve your problem without any nginx changes. https://angular.io/guide/router#appendix-locationstrategy-and-browser-url-styles – Finnur Eiríksson Feb 28 '19 at 14:35
1

As suggested, the location order is important. try something like this (in the following i use a prefix for all API)

upstream node_server {
  server localhost:3000;
}

server {
    listen 80;

     root /home/ec2-user/Elaisian/dist/;
     include /etc/nginx/default.d/*.conf;

    if ($http_x_forwarded_proto = 'http'){
       return 301 https://$host$request_uri;
    }

location /api/ {
   proxy_pass http://node_server/api/;
   proxy_http_version 1.1;
   proxy_set_header Host $host;
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   proxy_set_header X-Forwarded-Proto $scheme;
 }

 location / {
   try_files $uri $uri/ /index.html;
 }
Robdll
  • 5,865
  • 7
  • 31
  • 51
  • I wanted to avoid the prefix because I need to change it in a lot of external apps then. I was more looking for a redirect which redirects again after a 404. S.th. like `try_files $uri $uri/ @node /index.html;` but, unfortunately, this doesn't work so I had to go for the solution with two locations. – Andi Giga Feb 28 '19 at 14:29
  • you should consider [serving static files](https://expressjs.com/en/starter/static-files.html) from node then. ```app.use(express.static(path.join(__dirname, '../dist')));``` – Robdll Feb 28 '19 at 14:46