Configuring Nginx as a proxy for a Vapor API - macos

'm pretty stuck after a few days of trying to get this working and I could use some help.
I have a vapor API that works fine. I created a route and can access it from http://localhost:8080/backend/returnA in a browser on the server. It returns some JSON.
Where I'm stuck is in trying to configure Nginx to server as a proxy. Can anyone help me understand how the http://localhost:8080/backend/returnA URL translates into a working URL accessible from the LAN?
I'm pretty confused as the Nginx.conf asks for a root URL but I don't know what to put in. If I leave it blank it defaults to /usr/local/Cellar/nginx/1.15.6/html/backend/returnA/index.html which obviously won't work. If I set it to the public folder in the Vapor app directory this also doesn't work. In both instances I get a "No such file or directory".
I've gone through countless Nginx conf settings found online, tried adding a proxy location, nothing works. Trying http://172.16.1.25/backend/returnA/ always returns a 404 from the Nginx server.
How do I point Nginx to my Vapor route when it's not serving a static file like index.html, and instead retuning JSON?
Any help is much appreciated.
Here's the config, edited to include Thanh's code, old location commented out:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
#pid logs/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#access_log logs/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
#gzip on;
server {
server_name 172.16.1.25;
listen 80 default_server;
root /Users/localadmin/Developer/server/MedicapAPI/Public/;
# location #proxy {
# proxy_pass http://127.0.0.1:8080;
# proxy_pass_header Server;
# 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 Server;
# proxy_connect_timeout 3s;
# proxy_read_timeout 10s;
# }
location / {
proxy_ignore_client_abort on;
proxy_pass http://localhost:8080/;
proxy_redirect off;
}
}
include servers/*;
}

Using this :
listen 80 default_server;
server_name 172.16.1.25; #ip address of server
it will catch all server blokck and:
location / {
proxy_ignore_client_abort on;
proxy_pass http://localhost:8080/;
proxy_redirect off;
}
It will be proxy_pass to application which is running in port 8080

server {
#server_name mysite.com;
listen 80;
error_log /var/log/mysite.com_error.log warn;
access_log /var/log/mysite.com.ru_access.log;
large_client_header_buffers 8 32k;
client_max_body_size 10M;
location / {
# redirect all traffic to localhost:8080;
proxy_set_header Host $http_host;
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 X-Forwarded-Proto $scheme;
proxy_pass http://127.0.0.1:8080/;
proxy_redirect off;
proxy_read_timeout 86400;
# enables WS support
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# prevents 502 bad gateway error
proxy_buffers 8 32k;
proxy_buffer_size 64k;
reset_timedout_connection on;
tcp_nodelay on;
}
# Give direct access to Public files of your app instead of using FileMiddleware
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|xml|html|mp4|pdf)$ {
access_log off;
expires 30d;
root /path/to/your/app/Public;
}
}
This is my working example.
For production I suggest you to use SSL certificate e.g. from LetsEncrypt, replace listen port to 443 and add the following configuration lines after listen line:
ssl on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /etc/letsencrypt/live/mysite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mysite.com/privkey.pem;
ssl_ciphers 'HIGH:!aNULL:!MD5:!kEDH';
add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;";
ssl_stapling on;
ssl_stapling_verify on;
That's it, now you're ready for production!

Related

nginx keycloak spring boot reverse proxy redirect loop

I have dockerized spring boot application and keycloak for authorization. So, i tried to use nginx as reverse proxy(nginx not dockerized). When i use nginx without ssl it works perfectly. But when i try enable ssl with https to http redirect, keycloak fall into redirect loop after enter credentials.
My nginx config
# For more information on configuration, see:
# * Official English Documentation: http://nginx.org/en/docs/
# * Official Russian Documentation: http://nginx.org/ru/docs/
user docker-user;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 5m;
ssl_prefer_server_ciphers on;
ssl_stapling on;
resolver 8.8.8.8;
include /etc/nginx/mime.types;
default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf;
server {
server_name myhost.com;
listen 443 ssl;
ssl_certificate /etc/nginx/ssl/certs/bundle.crt;
ssl_certificate_key /etc/nginx/ssl/certs/cert.key;
ssl_dhparam /etc/nginx/ssl/certs/dhparam.pem;
ssl_session_cache shared:le_nginx_SSL:10m;
ssl_session_timeout 1440m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384";
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
client_max_body_size 500M;
proxy_read_timeout 3600;
location /auth {
proxy_http_version 1.1;
proxy_set_header Host $http_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 X-Forwarded-Host $server_name;
proxy_pass http://myhost.com:8080;
proxy_redirect off;
}
location / {
proxy_http_version 1.1;
proxy_set_header Host $http_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 X-Forwarded-Host $server_name;
proxy_pass http://myhost.com:9010;
proxy_redirect off;
}
error_page 404 /404.html;
location = /usr/share/nginx/html/50x.html/40x.html {
}
error_page 500 502 503 504 /50x.html;
location = /usr/share/nginx/html/50x.html {
}
}
server {
if ($host = myhost.com) {
return 301 https://$host$request_uri;
}
server_name myhost.com;
listen 80;
return 404;
}
}
spring boot log on redirect loop
2021-05-13 10:45:25.756 ERROR 1 --- [qtp276869158-20] o.k.adapters.OAuthRequestAuthenticator : failed to turn code into token
2021-05-13 10:45:25.757 ERROR 1 --- [qtp276869158-20] o.k.adapters.OAuthRequestAuthenticator : status from server: 301
2021-05-13 10:45:25.757 ERROR 1 --- [qtp276869158-20] o.k.adapters.OAuthRequestAuthenticator : <html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx/1.14.1</center>
</body>
</html>
I solved my problem.
In keycloak docker compose file need to add reverse proxy location in KEYCLOAK_FRONTEND_URL
Like KEYCLOAK_FRONTEND_URL: "https://myhost.com/auth"

use Nginx as proxy, ajax request get 405 every other request

I'm using nginx to separate the static and dynamic content,
this is my nginx config:
#user nobody;
worker_processes 1;
#error_log logs/error.log;
error_log /usr/local/var/logs/nginx/error.log notice;
#error_log logs/error.log info;
pid /usr/local/var/logs/nginx/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr:$remote_port - [$request_method] [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'rt=$request_time uct="$upstream_connect_time" uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /usr/local/var/logs/nginx/access.log main;
sendfile on;
#tcp_nopush on;
#keepalive_timeout 0;
keepalive_timeout 65;
upstream tomcat_backend {
server localhost:8090;
}
server {
listen 9797;
server_name localhost;
server_name_in_redirect off;
access_log /usr/local/var/logs/nginx/test.access.log main;
error_log /usr/local/var/logs/nginx/test-error.access.log debug;
location ~ \.(jpg|png|js|ico|html|gif|css|map)$ {
root /path/to/static;
}
location ^~ /api/ {
access_log /usr/local/var/logs/nginx/nginx-location.access.log main;
error_log /usr/local/var/logs/nginx/nginx-location-error.access.log debug;
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 X-Request-Time $msec;
proxy_redirect off;
proxy_set_header Host $host;
proxy_pass http://tomcat_backend;
#proxy_set_header X-Request-Id $request_id;
}
location / {
root /path/to/static;
index index.html;
if (!-e $request_filename) {
rewrite ^/(.*) /index.html last;
}
}
}
include servers/*;
}
sometimes tomcat can get the request and response it correctly, sometimes nginx just return 405 directly, not event forward to tomcat
this is the console of chrome, it always follow that pattern, 405, 401, 405, 401..., it shows 401 is because I input wrong password in purpose, that mean the request has been forward to tomcat:
I found that if I use node.js as backend(just a proxy server), everything is ok, no 405 anymore.
OK, finally I found the reason.
there is another process is monitoring the same port.
but it's wired that two process are using the same port

Share same session with multiple domain using nginx & tomcat

We've a running a grails application on a tomcat server behind nginx for multiple subdomain:
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$tempRequest" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" \n';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
gzip on;
gzip_http_version 1.1;
gzip_min_length 1000;
gzip_buffers 16 8k;
gzip_disable "MSIE [1-6] \.";
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript text/x-js;
gzip_vary on;
upstream main {
server localhost:8081;
}
include /etc/nginx/conf.d/*.conf;
# First server config to listen top level domain request (https/http) & redirect to mnop.com
server {
listen 80;
listen 443 ssl;
server_name xyz.com www.xyz.com;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
return 301 https://mnop.com;
}
# Second server config to redirect all non https requests to https request.
server {
listen 80;
# Remember wildcard domain with "*" doesn't listen top level domain.
# Hence no conflict with first server config.
server_name *.xyz.com;
rewrite ^ https://$host$request_uri? permanent;
}
# Third server config to listen https request & serves all html with nginx.
server {
listen 443 ssl;
server_name *.xyz.com;
ssl on;
ssl_certificate /etc/nginx/server.crt;
ssl_certificate_key /etc/nginx/server.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_session_cache shared:SSL:10m;
location / {
set $tempRequest $request;
if ($tempRequest ~ (.*)j_password=[^&]*(.*)) {
# Mask spring authentication password param.
set $tempRequest $1j_password=****$2;
}
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://main;
proxy_redirect http://$host https://$host;
}
location /ng/app {
root /usr/share/apache-tomcat-7.0.54/webapps/ROOT;
}
}
}
A tomcat app is running on port 8081 and any subdomain like: a.xyz.com or b.xyz.com, working fine and sharing same session.
But We need to use the same session and app using a different domain like: abc.com, how can I achieve that? I tried setting virtual hosts and proxy_cookie_domain but nothing worked?

nginx redirect only fails with firefox

I am using the following config file for nginx and it works fine with Chrome but not with Firefox. With Firefox, I get the following error:
"Firefox has detected that the server is redirecting the request for
this address in a way that will never complete."
Clearing the cookies and cache if Firefox does not help.
upstream dev_server {
server 127.0.0.1:8100 fail_timeout=0;
}
server {
listen 80;
server_name subdomain.pro.domain.com;
location /blog {
proxy_pass http://dev_server;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Accept-Encoding "";
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_set_header X-Forwarded-Proto $scheme;
add_header Front-End-Https on;
proxy_redirect off;
}
location / {
rewrite ^(.*)$ https://subdomain.pro.domain.com$1;
}
}
server {
listen 443;
ssl on;
server_name subdomain.pro.domain.com;
ssl_certificate /etc/nginx/star.pro.domain.com.crt;
ssl_certificate_key /etc/nginx/star.pro.domain.com.key;
### SSL settings here ###
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
keepalive_timeout 60;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security max-age=500;
location /blog {
rewrite ^(.*)$ http://subdomain.pro.domain.com$1;
}
location / {
proxy_pass http://dev_server;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_set_header Accept-Encoding "";
proxy_set_header Host $http_host;
proxy_set_header X-M-Secure "true";
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;
add_header Front-End-Https on;
proxy_max_temp_file_size 0;
proxy_redirect off;
}
}
Found the issue.
Because the /blog redirected to HTTP and all other paths redirected to HTTPS, the problem was with the following configuration line:
add_header Strict-Transport-Security max-age=500;
When I commented out that line, the issue went away.

How to redirect address.com/foo/bar to address.com:port/bar with nginx?

I have running nginx on my server ansel.ms and a node.js app on ansel.ms:46156.
I want to setup nginx so it redirects everything from
ansel.ms/rhythm
to
ansel.ms:46156.
ansel.ms/rhythm/sub/path
should become
ansel.ms:46156/sub/path
This is my file in sites-available:
upstream rhythm {
server ansel.ms:46156;
}
server {
listen 80;
server_name ansel.ms www.ansel.ms;
access_log /srv/www/ansel.ms/logs/access.log;
error_log /srv/www/ansel.ms/logs/error.log;
location / {
root /srv/www/ansel.ms/public_html;
index index.html index.htm;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /srv/www/ansel.ms/public_html$fastcgi_script_name;
}
location /rhythm{
proxy_set_header X-Real-IP $remote_addr;
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_pass http://rhythm;
proxy_redirect off;
}
}
I do not really understand deeply what this does (the proxy_set_header stuff), I only copied & pasted it from several sources.
It doesn't work.
Can you give me a hint what to change so it does what I described above?
Thank you!
I cannot spot the error in your configuration file; I'm an nginx-newbie as well.
But here is my full nginx.conf config file which redirects http://myhost/cabaret/foo/bar to http://myhost:8085/foo/bar:
user www-data;
worker_processes 1;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
access_log /var/log/nginx/access.log;
sendfile on;
keepalive_timeout 65;
tcp_nodelay on;
server {
listen *:80; ## listen for ipv4
access_log /var/log/nginx/localhost.access.log;
location /cabaret {
rewrite /cabaret(.*) $1 break;
proxy_pass http://127.0.0.1:8085;
proxy_redirect 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;
}
}
}
It is not perfect, because it will not work with http://myhost/cabaret, only if a slash follows carabet like in http://myhost/cabaret/ or http://myhost/cabaret/foo/bar.

Resources