Serve multiple Angular apps from the same server with Nginx
Solution 1
It is generally a bad security practice to have multiple independent apps on a single domain.
However, I believe what you're facing here is the peculiarity of the way that try_files
works -- according to http://nginx.org/r/try_files,
If none of the files were found, an internal redirect to the uri specified in the last parameter is made.
Effectively, this means that if there would have been an extra parameter after your /index.html
specification (i.e., basically, anything at all), then your code would have worked as you expected; however, due to the lack of any such final parameter, what happens in each case is that everything gets redirected back to the /
location
, as if a GET /index.html HTTP/1.1
request was to have been made (except it's all done internally within nginx).
So, as a solution, you can either fix the path for the internal redirect to remain within the same location
(e.g., /projectX/index.html
), or leave the paths alone, but make the last parameter return an error code (e.g., =404
, which should never be triggered as long as your file always exists).
E.g,
try_files $uri /projectX/index.html;
,Or,
try_files $uri /index.html =404;
.
As in:
location /projectX/ {
alias /home/projectX/dist/;
try_files $uri /projectX/index.html; # last param is internal redirect
}
Or:
location /projectX/ {
alias /home/projectX/dist/;
try_files $uri /index.html =404;
}
In summary, note well that /projectX/index.html
would only work as the last parameter, and /index.html
would only work as a non-final one.
Solution 2
Hope this helps someone
Step 1 - Build all your projects
ng build --prod --base-href /project1/
ng build --prod --base-href /project2/
ng build --prod --base-href /project3/
Step 2 - Configure your nginx, note the change added in try_files
section
server {
listen 80;
server_name website.com;
# project1
location / {
alias /home/hakim/project1/dist/;
try_files $uri/ /project1/index.html;
}
# project2
location /project2/ {
alias /home/hakim/project2/dist/;
try_files $uri/ /project2/index.html;
}
# project3
location /project3/ {
alias /home/hakim/project3/dist/;
try_files $uri/ /project3/index.html;
}
}
Step 3 - Reload nginx configuration
sudo service nginx reload
Solution 3
Try the solution for multilingual Angular application AOT builds that are basically different apps - OK its the same app multiple times, build with different languages in different bundles in different directories.
Related videos on Youtube
Comments
-
Hakim almost 2 years
I'm serving multiple
angular
apps from the sameserver
block inNginx
. So in order to let the user browse directly to certain customAngular
routes I've declared without having to go through the home page (and avoid the 404 page), I'm forwarding these routes from nginx to each angular app'sindex.html
, I've added atry_files
to eachlocation
:server { listen 80; server_name website.com; # project1 location / { alias /home/hakim/project1/dist/; try_files $uri /index.html; } # project2 location /project2/ { alias /home/hakim/project2/dist/; try_files $uri /index.html; } # project3 location /project3/ { alias /home/hakim/project3/dist/; try_files $uri /index.html; } }
This solution avoids the 404 error when going to an Angular route, but the problem is that when I browse to
/project2/
or/project3/
it redirects to the/project1/
. That's obviously not what is expected, since I want to have each location to forward to the/project-i/index.html
of the adequate project.-
Hakim over 6 yearsExactly, but even if I browse directly to
website/project2
, it goes toproject1
. -
David over 6 yearsYou need to use base href maybe
-
-
Hakim over 6 yearsI've changed
href="/"
tohref="/project2"
in project2/dist/index.html, but it doesn't seem to fix it. -
hayden over 6 yearsDid anything change when you added that?
-
Hakim over 6 yearsThe behaviour is exactly the same (redirect to /project1).
-
Hakim over 6 yearsYou answer was the closest to how I've solved it. I've actually left the
location
forproject1
as it was, while in the try_files inproject2
andproject3
I had to add in theirtry_files
's index.html, the prefixproject-i
. So it became as the following forproject2
andproject3
:try_files $uri /project[2-3]/index.html
-
cnst over 6 years@h4k1m, great that it works! Regarding "the closest", TBH, I don't see how your solution is any different from what I wrote above. :-p (The other answers are obviously totally wrong -- I never suggested (nor meant to imply) doing any changes for project1.)
-
Hakim over 6 yearsCould you please just mention that the modifications done on location /projectX/, should only be carried out on project2 and project3 (that's what I meant by closest, because when I read it I thought I had to change even the location of the first project).
-
cnst over 6 years@h4k1m, that would only be the case if you just look at the code snippets, and skip the explanation on how it works. :-)
-
Nobody over 5 yearsCurious to know the security issue involved with multiple files in the same domain. Can you kindly explain?
-
cnst over 5 years@Nobody it has to do with Cookies, JavaScript and XSS (Cross-Site Scripting) attacks. If you use a single domain, the browser treats all apps as the same app, so, vulnerability in one app, makes all the rest of them vulnerable just as much.
-
Arokia Lijas over 3 yearscan you share a link on this?