0

I'm working on an nginx s3 reverse proxy container image to proxy frontend files (Angular apps) from s3 behind an Application Load Balancer. The frontend files are located in the specific folder of the given app name in the s3 bucket. These are angular apps which are built using standard angular commands. The dist contents are uploaded to s3 and then the ALB route paths, along with the nginx locations map to those app folders in s3. For example, here is my nginx conf file:

server {
    listen 80;
    listen  443 ssl;
    ssl_certificate     /etc/ssl/nginx-server.crt;
    ssl_certificate_key   /etc/ssl/nginx-server.key;

    server_name timemachine.com;
    sendfile on;
    default_type application/octet-stream;
    resolver        8.8.8.8;
    server_tokens   off;

    location ~ ^/app1/(.*) {
        proxy_http_version     1.1;
        proxy_buffering        off;
        proxy_ignore_headers   "Set-Cookie";
        proxy_hide_header      x-amz-id-2;
        proxy_hide_header      x-amz-request-id;
        proxy_hide_header      x-amz-meta-s3cmd-attrs;
        proxy_hide_header      Set-Cookie;
        proxy_set_header       Authorization "";
        proxy_intercept_errors on;
        rewrite ^/app1/?$ /app1/index.html;  
        proxy_pass https://<s3 bucket name here>;
        break;
    }
}

So there is a corresponding bucket folder /app1 in s3 which has the dist contents and is serving up the index.html. And on the ALB, there are two route paths. The first is /app1 which redirects to https:{port}//app1/ and then the second route path /app1/* which just forwards to the nginx reverse proxy container deployed via ECS Fargate.

This is not using cloudfront. The bucket is proxied internally on https and specific permissions are set on the bucket to be accessible w/in the given VPC.

The angular apps have specific modules, but the issue is since Im not saving any of this content in the container, I can't just do a try_files, or set an index to make this work, since all of this is proxied from s3 and the content is accessed differently.

I can access the app at with the given proxy configuration above, but for other paths, say when I navigate to the part of the apps where its /app1/account and then do a refresh, the page throws an access denied on the bucket and I just get the standard xml page in the browser.

How do I get this to work with all of those other relative paths without having to add each of those paths to nginx or the ALB routes? In other words, I dont want to have to add

location /app1/account {

}

and so on, or something like that. Yes, Im sort of new to nginx, so im still figuring things out.

I was expecting the above proxy to work with all paths on /app1 but im unsure what other route paths need to be added to the ALB or if the regex is off, or what else needs to be added to the nginx conf file.

All that to say, when I enter this

https://timemachine.com/app1

or this,

https://timemachine.com/app1/

both work and just rewrite to the index.html which is good.

After this, when I click on another icon in the UI that directs to another path on /app1/, I get directed to the page correctly at...

 https://timemachine.com/app1/news

but then on a refresh on this path, instead of hitting url https://timemachine.com/app1/news, with all the data shown when I accessed this through UI, the url stays at https://timemachine.com/app1/news but the page defaults to s3 bucket access denied on that route(.xml).

The goal is just to be able to reload on the pages I can already access without the UI blowing up and defaulting to the access denied message. So I would like to be able to just enter https://timemachine.com/app1/news, which will display the content, then do a refresh and see the content again.

The are various modules within the angular apps and so these are relative paths, which may be part of the problem.

NOTE: All files, aside from assets folder, are in the base app1 bucket folder. So https://<s3_bucket_name>/app1 (with app1 being the folder).

  • I was genuinely assuming you were saying to ask in a different post. Postmodern world; different interpretations. My bad. Whichever post, any insight into the issue at hand? – stonewalker747 Feb 17 '23 at 20:22
  • Just modified the post question a bit more. Maybe that’s closer to what u were saying idk. – stonewalker747 Feb 17 '23 at 20:53
  • @AD7six just updated the question with the specifics you mentioned above about route paths. Also submitted request for nginx slack channel. – stonewalker747 Feb 19 '23 at 17:21
  • Im still getting my feet wet with some of this b/c the requirement is to serve the frontend files from s3, and those files are stored and accessed differently than just building an nginx container and copying in dist content within the container to be further used in nginx configurations. I've already deployed the apps using that method, and it worked fine. This is a different requirement. There is no "news" folder or file in s3, just typical html, js, and css files. This is part of my concern as well. How can a folder or file be accessed that's a relative path or angular module? – stonewalker747 Feb 19 '23 at 17:40
  • I see part of the misunderstanding here so I’ll try asking the same thing, again, a different way - what file on s3 are you expecting that to load and what file is it actually requesting? – AD7six Feb 19 '23 at 17:46
  • Great question. I think this would just be one of the many .js files which is packaged on the dist build. I think this b/c I know when building the container and initially copying the dist contents within nginx that this worked. Nothing changed w/ those files, just where they're located and being served from. There's no news file w/in the dist folder, though just a bunch of .js files. – stonewalker747 Feb 19 '23 at 17:57
  • What you say sounds exactly correct to me, that is, “how to rewrite none-asset requests to /app1/index.htm”” – stonewalker747 Feb 19 '23 at 20:19
  • `rewrite ^/app1?.*$ /app1/index.html` should be rewriting all requests to /app1/index.html. However, when I do this im getting the mime type error "Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec." I've got include mime types added, etc. and its still throwing that error. – stonewalker747 Feb 20 '23 at 00:47
  • @AD7six question updated w/ more specifics about the folder – stonewalker747 Feb 20 '23 at 13:50

1 Answers1

0

Angular's docs indicate to use the Frontend Controller pattern for static files like so:

Use try_files, as described in Front Controller Pattern Web Apps, modified to serve index.html:

try_files $uri $uri/ /index.html;

Obviously, that won't work here (since the files aren't local to nginx) so my understanding is we're looking for equivalent logic to that for when the files are hosted elsewhere.

Route not-assets to index.html

All assets are in the /assets/ folder - so the simplest solution is to look for anything starting with not-that and proxy those requests to the html file for the response:

server {
    location ~ /app1/ {
        rewrite ^/app1/(?!assets/) /index.html;
        proxy_pass https://domain/bucket/app1/;
    }
}

That regex means that:

  • /app1/assets/some.css gets proxied to https://domain/bucket/app1/assets/some.css
  • /app1/ gets proxied to https://domain/bucket/app1/index.html
  • /app1/something/else gets proxied to https://domain/bucket/app1/index.html
  • etc.

Do note that this is going to make your app respond HTTP 200 OK with html to almost any url - which may be confusing.

If there are any problems setting this up, enable the nginx debug log to see to what url requests are being proxied, and determine the difference from what's desired.

AD7six
  • 63,116
  • 12
  • 91
  • 123
  • Tested this and Im just seeing the nginx homepage, with no content. Do I need to do, `rewrite ^/app1/(?!assets/) /app1/index.html;` , since app1 is, in this case, the base path? – stonewalker747 Feb 20 '23 at 16:04
  • Is it possible to just capture the 401 from the proxy target for any url and then do a redirect? And if I add the /portal/index.html it just goes back to that js error "Failed to load module script: Expected a JavaScript module script but the server responded with a MIME type of "text/html". – stonewalker747 Feb 20 '23 at 16:10
  • `If there are any problems setting this up, enable the nginx debug log` <--- please do this. – AD7six Feb 20 '23 at 16:23