I have question about nginx configuration - I want to pass error handling into nodejs application (frontend app), so for eg. 404 error (and others) will be handled by nodejs app.
The "problem" is, that the app is running directly via nginx (it doesn't use it's internal mini-web server as many nodejs apps).
nginx configuration is as simply as possible:
server {
listen 80;
server_name *.somedomain.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name *.somedomain.com;
ssl_certificate /etc/letsencrypt/live/somedomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/somedomain.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/somedomain.com/chain.pem;
root /usr/share/nginx/html;
}
Want to configure error handling via nodejs application, instead nginx.
Related
I have NGINX configured with SSL and angular website is hosted in it, whereas the Login API is running without SSL.
When I try logging on UI, I get below error,
Mixed Content: The page at 'https://example.com/login' was loaded over HTTPS, but requested an insecure XMLHttpRequest endpoint 'http://example.com:3333/auth/login'. This request has been blocked; the content must be served over HTTPS.
Note : UI calls internally 'http://example.com:3333/auth/login'.
Obvously, UI in SSL and node API without SSL.
But in nginx.conf I used "proxy_pass to route traffic through port 80 (to call http://example.com:3333/auth/login the way it was called without SSL certificate) to redirect to 80 port as below,
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
location / {
}
server {
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
server_name example.com;
location / {
proxy_pass http://example.com:80;
}
But no luck, If I remove SSL from NGINX, all works fine. Any suggestion on how to call non-SSL api from SSL based web call?
I have a server (VPS Amazon) with Ubuntu. In this server is running my backend node and my frontend React.
My ReactApp is running over nginx and my backend over pm2.
In my react app I defined REACT_APP_BASE_URL: http://[my_ip_server]:4000.
So everything was working OK but after I configured SSL in nginx, I can access my frontend login page but when I send the request, I catch the following errors:
a) If I set https in my REACT_APP_BASE_URL (https://[my_ip_server]:4000), I get this error: ERR_SSL_PROTOCOL_ERROR.
b) If I let with http, I get Mixed Content error
Someone know How I do this work?
Thanks a lot!
My nginx.conf. At moment I'm using just port 80 until I solve my problem.
server {
#listen [::]:443 ssl ipv6only=on; # managed by Certbot
#listen 443 ssl; # managed by Certbot
#ssl_certificate /etc/letsencrypt/live/mysite.com.br/fullchain.pem; # managed by Certbot
#ssl_certificate_key /etc/letsencrypt/live/mysite.com.br/privkey.pem; # managed by Certbot
#include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
#ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
#if ($host = surveys.alcancenet.com.br) {
# return 301 https://$host$request_uri;
#} # managed by Certbot
listen 80 default_server;
listen [::]:80 default_server;
server_name mysite.com.br;
#return 404; # managed by Certbot
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri /index.html;
}
}
With help from #Markido. I managed to solve that.
I added in my backend the default route "/api" and after that I put in my nginx config the following
location /api {
proxy_pass http://localhost:4000;
}
Tks!!!
First off, there is a difference between running the applications (which is what i assume you are using PS2 for), and exposing them through an nginx proxy.
It would be most helpful to show us your nginx config file, and also tell us which port your backend runs on (assuming the frontend runs on port 4000).
Edit;
Thanks for the config and backend port.
I don't think you need to set the create react app base url to https, just set the port and run it on the VPS using PS2.
I can't see how you have any proxy at all pointing to 4000 in your config - do you not expose the backend?
The only exposed part is static html files. The relevant code is;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri /index.html;
}
If you want to call the backend using https, or generate your site using some tool with a process which entails HTTPS calls, you need to do so correctly in the frontend. IE something doesn't add up here.
The usual approach is;
Expose the backend and the frontend on port 443 SSL only, using different sub-domains (eg. api.mydomain.com), and then use the proxy in nginx to redirect 443 traffic for each domain to the corresponding local ports (4000, and the frontend port or static files directory more likely).
Instead of:
location / {
try_files $uri $uri /index.html;
}
Use something like:
location / {
proxy_pass http://localhost:4000;
}
I've got an NGINX reverse proxy on my server handling requests for http://apcompdoc.com. It listens on port 80, and can successfully return the Vue Dist, however, I have a backend node API running on port 8081 and another node process running on port 8082. The user never directly requests anything on 8082, but rather the process on 8081 sometimes requests the process on 8082, so I'm assuming I never have to even expose that to Nginx at all, but I'm not too sure. However, the main problem is that the API is never reached I believe. I have it so that when you hit the endpoint http://apcompdoc.com/api/* it should proxy over to the node process. I am using PM2 to keep the process alive and monitor it, and am assured it's running. This is my NGINX apcompdoc.com config file:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name: apcompdoc.com www.apcompdoc.com;
charset utf-8;
root /var/www/apcompdoc/dist;
index index.html index.htm;
# Always serve index.html for any request;
location / {
root /var/www/apcompdoc/dist;
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://localhost:8081;
}
error_log /var/log/nginx/vue-app-error.log;
access_log /var/log/nginx/vue-app-access.log;
}
I am trying to get all requests to my API at /api/* to get redirected to the API at localhost:8081 and then returned to the user. I saw something about redirecting the proxy back, do I have to do that? I also don't know if I have to do /api/* in the NGINX config file.
I'm really new to NGINX but I just want the requests to http://apcompdoc.com/api/* to be redirected to the node process on port 8081.
Bad or good practice, I'm not sure, but I always defining my backend as upstream.
For example, your file will look like this:
upstream nodeprocess {
server localhost:8081;
}
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
server_name: apcompdoc.com www.apcompdoc.com;
charset utf-8;
root /var/www/apcompdoc/dist;
index index.html index.htm;
# Always serve index.html for any request;
location / {
root /var/www/apcompdoc/dist;
try_files $uri /index.html;
}
location ^~ /api {
proxy_pass http://nodeprocess;
}
error_log /var/log/nginx/vue-app-error.log;
access_log /var/log/nginx/vue-app-access.log;
}
Please note I added ^~ in the location of the api and removed the trailing /
I have two files in sites-available, one for each website running on the machine. Both have identical code with only the domain name and port for the website replaced. Both sites are also symlinked to sites-enabled.
reesmorris.co.uk (which works fine):
# Remove WWW from HTTP
server {
listen 80;
server_name www.reesmorris.co.uk reesmorris.co.uk;
return 301 https://reesmorris.co.uk$request_uri;
}
# Remove WWW from HTTPS
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/reesmorris.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/reesmorris.co.uk/privkey.pem;
server_name www.reesmorris.co.uk;
return 301 https://reesmorris.co.uk$request_uri;
}
# HTTPS request
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name reesmorris.co.uk;
ssl_certificate /etc/letsencrypt/live/reesmorris.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/reesmorris.co.uk/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3000;
include /etc/nginx/proxy_params;
}
}
francescoiacono.co.uk (has a redirection loop):
# Remove WWW from HTTP
server {
listen 80;
server_name www.francescoiacono.co.uk francescoiacono.co.uk;
return 301 https://francescoiacono.co.uk$request_uri;
}
# Remove WWW from HTTPS
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/francescoiacono.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/francescoiacono.co.uk/privkey.pem;
server_name www.francescoiacono.co.uk;
return 301 https://francescoiacono.co.uk$request_uri;
}
# HTTPS request
server {
# Enable HTTP/2
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name francescoiacono.co.uk;
ssl_certificate /etc/letsencrypt/live/francescoiacono.co.uk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/francescoiacono.co.uk/privkey.pem;
location / {
proxy_pass http://127.0.0.1:4000;
include /etc/nginx/proxy_params;
}
}
To experiment, I replaced the return value in the first server block of the broken website to be a 403, which seems to be shown even if the site is using HTTPS. Additionally, removing the first server block on the broken website altogether will cause the website to completely redirect to the already-working website.
Both websites use CloudFlare for the DNS routing. CloudFlare is 'paused' on both websites which means that it only handles the routing, in which both websites have identical routing to the server with AAAA and A records being the same.
I'm not too familiar with server blocks, so if anybody has any ideas as to what is happening then it would be greatly appreciated.
It appears as though this issue was resolved by making both websites 'paused' in the CloudFlare DNS. This was done originally, though may have not had enough time to propagate.
I had not modified the code since this post was created, though I had ensured that both sites were 'paused' on CloudFlare (reesmorris.co.uk was, however francescoiacono.co.uk was not) - and so it seems to have been a misconfiguration issue with CloudFlare.
Here's the situation -
node express app1 (backend app - REST API server) - running on port 8888 -
bunch of POST routes (auth, api, download, upload..) - communicating with mysql server - maintained by developer #1
node (webpack, react) app2 (front end app) running on port 80 - maintained by developer #2
This week we set up nginx and HTTPS (via Let's encrypt), which means that when a user comes to the www.oursite.com - it is redirected to the https site with nice green lock and secure site. So far so good. However, when the user enter her email, the app2 is supposed to call app1 and email with registration token should be sent. This worked well before we try to set up nginx - and use http on both apps. Now this call is not happening. This is our nginx setting:
server {
listen 80;
listen [::]:80;
root /var/www/oursite.com/html;
index index.html index.htm index.nginx-debian.html;
server_name oursite.com www.oursite.com;
location / {
try_files $uri $uri/ =404;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/oursite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/oursite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
if ($scheme != "https") {
return 301 https://$host$request_uri;
} # managed by Certbot
# Redirect non-https traffic to https
# if ($scheme != "https") {
# return 301 https://$host$request_uri;
# } # managed by Certbot
}
My question (developer #1) - should I replace all routes in my app (backend app - app1 - backend) to be https instead of http? Apparently Chrome is not calling http request from https site (as is our case)
and how should I setup the nginx then - I belive I should add another location part in nginx setting.
If there are other suggestions please let us know.
Each port must get its own server{ } block, so port 80 gets one and port 443 get another each with a listen directive to the respective port ... in above you have both ports in the same server{ } block
If the app is exposed to the internet they should be using https and if not their incoming traffic using http which is port 80 block must get redirected to send traffic to 443 ... so your nginx config file will look similar to
server {
listen 80 ;
listen [::]:80 ;
server_name example.com, www.example.com;
# Redirect all HTTP requests to HTTPS
rewrite ^/(.*) https://example.com/$1 permanent;
}
server {
listen 443 ssl ;
listen [::]:443 ssl ;
server_name example.com;
ssl_certificate /etc/letsencrypt/live/oursite.com/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/oursite.com/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
location / {
# direct traffic to my server on its host IP and port
proxy_pass http://172.19.0.5:3000/; # notice http not https
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
}
}
In your case looks like app1 is not exposed to the internet and so does not appear in your nginx config ... it only receives http traffic downstream from app2 ... all of above config is only for your app2 ... incoming internet traffic using secure https port 443 (or port 80 which gets redirected to 443) receives what is called TLS termination ... apps shielded from the internet by the nginx TLS termination receive http traffic not https which is fine since the app ports are not visable from the internet ... and so your app2 gets http traffic not https
We got this to work by setting the app1 (backend up) as https as well. However, this works in all major browser, except for firefox. SO I guess I shiuld post a new question now. The site is not letting through the form on firefox - but only if the address does not have www. That means https://testsite.com -> not working, https://www.testsite.com working ok. But is working ok on all other browsers.