I have a vue-ssr project, not using nuxt.js. And the server is express.
Project ran at port 3000.
When not using nginx, visited ip:3000, the page worked well.
When using nginx, visited my domain, I still could get HTML strings, but the strings were not rendered, like that:
(I don't have enought reputation to post images.)
html strings.png
And the request and response headers like that:
request and response headers.png
Here is my nginx config:
server {
server_name mydomain;
root /my/path;
location / {
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_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_pass http://localhost:3000;
proxy_redirect off;
}
}
I've tried the config introduced in nuxt.js documents, but didn't worked either.
If removing the nosniff header fixes the problem, that would be an indication that for some reason express is not sending the right mime types with your responses.
You could check that by hitting express directly and examining the headers it is returning, e.g.:
curl -D - -o /dev/null http://localhost:3000
If it's NOT returning text/html, it could be a sign you're accidentally breaking the default mime type somewhere in your application code.
Related
i want to host two small websites, both made with strapi backend and react frontend, on my server which is a digital ocean droplet.
I already configured nginx in order to work for one of the websites and everything is working correctly. I can access strapi from site1.com/dashboard and my queries point to site1.com/api/graphql. I followed some tutorials for that.
Here are the nginx files i added:
/etc/nginx/sites-available/site1.com:
server {
listen 80;
listen [::]:80;
root /var/www/site1.com/react;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name site1.com www.site1.com;
location /api/ {
rewrite ^/api/(.*)$ /$1 break;
proxy_pass http://strapi;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
location /dashboard {
proxy_pass http://strapi/dashboard;
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $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;
proxy_set_header Host $http_host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass_request_headers on;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ /index.html;
}
}
file /etc/nginx/conf.d/upstream.conf:
upstream strapi {
server 127.0.0.1:1337;
}
What i now want to do is to deploy another website to the same server and configure nginx to serve it as well (on another domain, for example site2.com).
So i added the nginx virtual server file for the second website, copying the first one and changing the domain name and root directory.
The site 2 frontend is now working correctly and accessible on its domain.
However when i start the site 2 strapi instance it says the port 1337 is already in use (obviously, it is used by site 1 strapi instance that is running with pm2). So i changed the port in strapi config to be 1338 (is it ok?) but now i don't know what do to in nginx in order to serve the two different strapi instances on different domains.
The hostname you are using for the proxy_pass directive is the upstream name you defined in the separate config file. This is basically an indirection to one or more real backends. In your case that's the application running on port 1337 on the same machine. It could also be a list of external domains where nginx takes care to distribute the load to.
Your approach with additional virtual hosts already looks good. The frontend that already "works" under site2 is probably the old instance served under the new domain if your proxy_pass directive still points to http://strapi for site2 (which probably still resolves to `localhost:1337).
As you already mentioned, a second instance of the backend needs to run on a different port. The port number you use is not really important as you will control this with your upstream configuration. Just make sure to not use a port number below 1024 (which requires root permissions), don't conflict with other processes on the system (you will notice) and as best practice, don't use port numbers that are default for some other protocols (maybe check this list).
To fix your setup, just define a second upstream like the first one but pointing to the new url e.g. localhost:1338 and then reference this new name in the proxy_pass directive of site2.
Technically, with just one backend per upstream, you could also skip the upstream part completely and reference the URL directly in the proxy_pass directives, but using a shorthand name can also support readability of your configuration.
I would like to have a more stable deployment of a sails 1 app on an AWS ubuntu server using nginx as reverse proxy.
Goal:
To have a non-version-dependent deployment of our app.
In particular:
We have an app on an AWS server.
App details include:
mobile focused
websockets enabled
reverse proxy with nginx
app persisting with pm2
Deployment details include
AWS ubuntu 18.04 LTS
mysql 8.x database
sails 1.2.4
nginx 1.14.0
node 8.4.0
The issue:
I was only able to get the reverse proxy working with the above versions of sails, nginx, and node. Any other combination resulted in a 403 error from the app server. Postman GET requests to the server when the app is served directly return a "sails.sid" cookie. However, when the app is served through any other reverse proxy software combination, no "sails.sid" cookie comes back in the GET header. I got the same no cookie GET request with apache2 reverse proxy.
When I hit the app directly (not through the reverse proxy) the cookies returned fine.
What I have tried
different versions of node, sails1, nginx, apache2
node versions > 10.22.0 cause the error
there is a known deprecation in node > 10.22.0 of the command
link to node deprecation
The http module OutgoingMessage.prototype._headers and OutgoingMessage.prototype._headerNames properties are deprecated.
This seems to break the nginx reverse proxy handling of headers from the sails app.
I have not seen a fix in nginx, and in particular nginx version 1.16.0 will break the headers.
other things I have tried
ownership and permissions (chmod, chown) are ok
apache2 reverse proxy: same problem as with nginx 1.16.0: no headers. I.E. the reverse proxy works, but the app returns a 403 code through the apache2 reverse proxy.
various permutations of versioning: sails, nginx, node
things I might try
Somewehere in the node-modules of sails, there may lurk header code depending on this old syntax. This could possibly be patched with a replace new-for-old on the appropriate statements. Just a thought.
What I would like:
Show me how to get this app working, i.e. get all the headers back from a vanilla Postman GET request, in a way that does not depend on these specific versions of sails, nginx, and node.
If I am missing something glaringly obvious, even better.
I am using a similar setup with node 11.15.0 and it works.
What is your nginx configuration?
Here is the server block code I tried to put in the comments. Remeber that you have to symlink it to the /etc/nginx/sites-enabled folder as well. This works for straight HTTP requests. Note that your app will only see the client "127.0.0.1". If you want to get the IP addresses from your clients out in the wild, you need to get them from the nginx reverse proxy server itself.
server {
listen 80;
server_name yourDomain.com ;
location / {
proxy_pass "http://127.0.0.1:1337";
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header Port $server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass_request_headers on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /socket.io/ {
proxy_pass "http://127.0.0.1:1337/socket.io/";
proxy_http_version 1.1;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header Port $server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_pass_request_headers on;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
We have a nodejs app that currently uses socket.io ( with namespaces ). This app is used as a dashboard for a specific financial market. Each instance of app subscribe to a specific market data and provides a dashboard. Initially we were running 3 separate instances of this app configured for 3 separate markets on the server, all binding to separate ports for serving requests.
Since we plan to add more markets it makes sense to have a reverse proxy server where a single port (along with separate URI for each market) can be used. However, setting up nginx has been a nightmare for various reasons.
(a) each instance of app for a market can be in different development stage and hence can have different static files. Managing all static file via nginx seems painful ? What can be done to leave handling of the static files with the app itself.
(b) socket.io communication is a failure. We tried to look into network communication and it seems it keeps on getting 404 page not found error when trying to connect to socket.io server. Not sure why it is connecting via http::/localhost/server.io/ instead of ws://localhost/server.io/ ? Can somebody point us to a similar example ? Anything that needs to be taken care of ?
IN our case we have been trying the following inside nginx sites-available/default
location /app/ {
proxy_pass http://localhost:3000/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# kill cache
add_header Last-Modified $date_gmt;
add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
Using nginx as a reversed proxy should not give you a hard time. The great thing about nginx is that you can have multiple projects on the same server with different domains.
Here is an example of nginx with multiple projects:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://localhost:3000;
#Rember to set the header like this otherwise the socket might not work.
proxy_set_header X-Real-Ip $remote_addr;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
}
server {
listen 80;
server_name subdomain.yourdomain.com;
location / {
proxy_pass http://localhost:3001;
}
}
I'm not sure why your socket should fail. Perhaps the mistake is that you try to define the route on the client site. Try having the javascript like this:
var socket = io();
or if your socket runs on one of your other applications:
var socket = io('http://yourdomain.com');
And remember that your changes should be added to sites-enabled instead of sites-avaible
I have a NodeJS + ExpressJS app running on port 3000 which has a route:
router.get('/getHello', function(req, res) {
res.send('Hello, world!');
});
and a HTML page which does a GET on this route
<a href="/getHello">
<input type="button" value="Visit Helo World page" />
</a>
This standalone app works as intended. It displays Hello, world! when the button is pressed.
Now, here's the problem:
I have setup a reverse proxy on this app using nginx. Here's the config file from sites-available (linked with sites-enabled)
server {
listen 80;
server_name localhost;
location /routetest/ {
proxy_pass http://127.0.0.1:3000/;
proxy_http_version 1.1;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header X-Forwarded-Proto $scheme;
proxy_redirect off;
proxy_cache_bypass $http_upgrade;
}
}
The app opens fine when I visit http://localhost/routetest but when I click on the button, it opens http://localhost/getHello whereas I wanted it to open http://localhost/routetest/getHello. Since http://localhost/getHello is not defined, I end up with a 404. (On the other hand, http://localhost/routetest/getHello correctly returns the Hello, world message)
Now, my question is:
My frontend is written with / as the base path (to make all GET and POST requests), for example <a href="/getHello"> and I feel manually appending /routetest/ before all URLs in my HTML not a good practice (since I may want to change this base path later and then I'll have to update it everywhere). So, is there a way for NGINX or some express middleware to add /routetest/ for URLs that are written with / as the base path, without having to change it in my HTML manually?
By a long way the easiest solution is to use relative paths without the leading / if that's an option that's available to you.
Rewriting URLs in the response is somewhere between tricky and impossible in the general case. If you think you can successfully identify the relevant URLs in your content you might be able to use nginx's catchily titled ngx_http_sub_module:
http://nginx.org/en/docs/http/ngx_http_sub_module.html
There are various Express middleware implementations that do a similar thing but I couldn't find one that looked reliable enough to recommend. The basic approach would be similar to the compression middleware if you fancy giving it a go yourself. Again it's quite difficult in general but depending on the specifics of how you serve up your HTML it might not be too bad.
I am trying to setup nginx as a reverse rpoxy server in front off several IIS web servers who are authenticating using Basic authentication.
(note - this is not the same as nginx providing the auth using a password file - it should just be marshelling everythnig between the browser/server)
Its working kind off - but getting repeatedly prompted for auth by every single resource (image/css etc) on a page.
upstream my_iis_server {
server 192.168.1.10;
}
server {
listen 1.1.1.1:80;
server_name www.example.com;
## send request back to my iis server ##
location / {
proxy_pass http://my_iis_server;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass_header Authorization;
proxy_redirect off;
proxy_buffering 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;
}
}
This exact situation took me forever to figure out, but OSS is like that I guess. This post is a year old so maybe the original poster figured it out, or gave up?
Anyway, the problem for me at least was caused by a few things:
IIS expects the realm string to be the same as what it sent to Nginx, but if your Nginx server_name is listening on a different address than the upstream then the server side WWW-Authenticate is not going to be what IIS was expecting and ignore it.
The builtin header module doesn't clear the other WWW-Authenticate headers, particularly the problematic WWW-Authenticate: Negotiate. Using the headers-more module clears the old headers, and adds whatever you tell it to.
After this, I was able to finally push Sharepoint 2010 through Nginx.
Thanks stackoverflow.
server {
listen 80;
server_name your.site.com;
location / {
proxy_http_version 1.1;
proxy_pass_request_headers on;
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_pass_header Authorization; //This didnt work for me
more_set_input_headers 'Authorization: $http_authorization';
proxy_set_header Accept-Encoding "";
proxy_pass https://sharepoint/;
proxy_redirect default;
#This is what worked for me, but you need the headers-more mod
more_set_headers -s 401 'WWW-Authenticate: Basic realm="intranet.example.com"';
}
}
I had these same symptoms with nginx/1.10.3. I have a service secured under basic authentication, and nginx as a reverse proxy between the clients and the server. The requirement was that nginx would passthrough the authorization.
First request to the server did pass through the Authorization header. Second request simply blocked this header, which meant the client was only able to make one request per session.
This was somehow related to cookies. If I cleared the browser cookies, then the cycle repeated. The client was able to authenticate but just for the first request. Closing the browser had the same effect.
The solution for me was to change the upstream server from https to http, using:
proxy_pass http://$upstream;
instead of:
proxy_pass https://$upstream;