I know it has been asked several times but I can't find any way to solve it.
Recently I've setup an Ubuntu server serving two nodejs app.
Both apps resides on the same domain mydomain.com but on different ports.
One app is a keystonejs app
the second is a nextjs app
I'm trying to use Nginx to reverse proxy both application. I've been trough lot of tutorials but never find the right answer.
What I would like to achieve is to use nginx to reverse proxy in the following way:
(nextjs) example.com --> localhost:3001
(keystone) example.com/admin --> localhost 3000
The nextjs app works well while the keystonejs not. It returns a 404 page. My understanding is that when I add the location /admin it changes the path and the app is not able to load static files but I might be wrong.
here is my Nginx conf file.
server {
listen 8080;
listen [::]:8080;
server_name example.com;
return 301 https://example.com$request_uri;
}
server {
listen 443;
listen [::]:443 ssl;
ssl on;
ssl_certificate /mypath/example.com/fullchain.pem;
ssl_certificate_key /mypath/example.com/privkey.pem;
include /mypath/options-ssl-nginx.conf;
ssl_dhparam /mypath/ssl-dhparams.pem;
server_name example.com;
location / {
proxy_pass http://localhost:3001;
}
location /admin {
proxy_pass http://localhost:3000/;
}
}
both application runs inside a dedicated folder so the structure is
└── my-app
├── backend
│ ├── auth.ts
│ ├── keystone.ts
│ ├── package.json
│ ├── package-lock.json
│ ├── README.md
│ ├── Schema
│ │ ├── Blog
│ │ │ ├── linkSchema.ts
│ │ │ ├── postSchema.ts
│ │ │ └── tagSchema.ts
│ │ └── userSchema.ts
│ ├── schema.graphql
│ ├── schema.prisma
│ ├── schema.ts
│ └── tsconfig.json
└── client
├── next.config.js
├── package.json
├── package-lock.json
├── pages
│ ├── api
│ │ └── hello.js
│ ├── _app.js
│ └── index.js
├── public
│ ├── favicon.ico
│ └── vercel.svg
├── README.md
└── styles
├── globals.css
└── Home.module.css
Is there any possibility I should run both nodejs apps in this way? Thanks in advance for any help
1 Answer 1
Well, the sub_filter method I mentioned in comments is the last chance when you don't have any other choice. There is no guarantee and sometimes it can be impossible to get the desired result at all. The aforementioned answer gives a general example of substitutions set, mostly for HTML/CSS content. For your configuration it will look like
location /admin {
proxy_pass http://localhost:3000/;
sub_filter_types text/css application/javascript;
sub_filter_once off;
sub_filter 'href="/' 'href="/admin/';
sub_filter "href='/" "href='/admin/";
sub_filter 'src="/' 'src="/admin/';
sub_filter "src='/" "src='/admin/";
sub_filter 'url("/' 'url("/admin/';
sub_filter "url('/" "url('/admin/";
sub_filter "url(/" "url(/admin/";
}
Some of those substitutions may be not needed for your particular application, it depends on its HTML/CSS structure. On the other hand it can require some additional substitution rules, especially for javascript code that used fetch requests, etc. Consider the following JS code:
fetch('/data/dataset.json').then((response) => {
// do something
});
To correctly rewrite given code you'll need an additional substitution rule:
sub_filter "fetch('/" "fetch('/admin/";
It can be even worse when the fetch method takes URL as a variable composed somewhere else:
fetch(url).then((response) => { // "url" is some variable assigned elsewhere
// do something
});
Here you can use the following substitution rule (applicable to the previous example too):
sub_filter "fetch(" "fetch('/admin' +";
However it can be several ways to made asynchronous requests (using XMLHttpRequest, jQuery.ajax etc.) and every complex webapp require individual approach. I think you've got the idea.
/keystone). Many apps allow to do it via some settings. I you can't, you can check this answer.proxy_redirectnginx directive for that.