How to run Nginx on multiple ports - nginx

I am trying to configure nginx on two ports with the same instance, for example on port 80 and port 81, but no luck so far. Here is an example of what I am trying to do:
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name chat.local.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_buffering off;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 81;
server_name console.local.com;
location / {
proxy_pass http://127.0.0.1:8888;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_set_header Host $host;
proxy_buffering off;
}
}
}
When I try to run console.local.com, it shows the content from chat.local.com. Is there a way to make nginx run on two ports? Thanks in advance!

your config looks ok
I think the problem is this (correct me if I'm wrong):
you have console.local.com listening on port 81,
that means you need to access it as http://console.local.com:81/
when you access it as http://console.local.com/ (no explicit port so defaults to port 80)
nginx will check, notice that noting is listening on port 80 for that server_name, and consequently will pass the request to the default server-block. Since the defaut server-block is the first one (in the absence of configuration to change it) you end up in the chat.local.com handling.
In all likelyhood you want to change your console.local.com to listen on port 80 also since:
the server_name directive in both serverblocks is enough to differentiate the requests
that avoids you having to add the :81 to the domainname in the requests all the time

You can add listen statement 2 times simple; like below
listen 80;
listen 81;
This should work with nginx

Related

Deploying actix Application with nginx

I created actix web & websocket within single application, and it works fine in localhost.
Basically, after passing a login page, it opens a dashboard and a common Javascript's WebSocket.
new WebSocket(`ws://server:8181/client?token=${TokenString}`);
And it works fine.
I don't want to expose this 8181 port on my production server, so my plan is using a sub path /ws to map to 8181 port.
So my /etc/nginx/sites-enabled/default config is:
server {
server_name my_domain.com; # managed by Certbot
....
#WebSocket part is here, under /ws path and mapped to 8181 port
location /ws {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $host;
proxy_set_header X-NginX-Proxy false;
proxy_pass http://127.0.0.1:8181;
proxy_redirect off;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
#Here is my web app, / mapped to 8080 port
location / {
client_max_body_size 50m;
client_body_buffer_size 50m;
proxy_pass http://127.0.0.1:8080;
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;
proxy_cache_bypass $http_upgrade;
}
location ^~ /\. {
deny all;
}
#configs generated by Certbot
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl;
#...
}
#redirect http to https
server {
if ($host = my_domain.com) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80 ;
listen [::]:80 ;
server_name my_domain.com;
return 404; # managed by Certbot
}
My web page https://my_domain.com, works fine. But my mapped WebSocket connection doesn't.
new WebSocket(`wss://my_domain.com/ws/client?token=${TokenString}`);
With just WebSocket connection to ... failed: message, and /var/log/nginx/error.log shows nothing.
Is something wrong with my nginx config?
*Edit: it turns out showing 404 in /var/log/nginx/access.log 😪
It turns out, the /ws path should be URL rewritten since my websocket didn't map /ws to anything.
The idea was from here
So my configuration is:
location ~* ^/ws/ {
rewrite ^/ws/(.*) /$1 break;
....

Nginx only responding to 1 of multiple https servers

The problem I'm facing is that I have nginx configured for 2 HTTPS servers and 1 is responding and working correctly but the other one with a near identical server config is showing "connection refused".
System:
Description: Ubuntu 22.04 LTS
nginx version: nginx/1.18.0 (Ubuntu)
I am working with a default nginx.conf file and have unlinked the default sites-available entry and each server_name is a subdomain with its own SSL cert & key. When I check the access and error logs there are no entries describing why subdomain2 connection is refused, or even log entries showing a connection attempt was made. Both cert/key pairs were generated by the IT dept at a university and since 1 is working fine I have good reason to think both pairs are valid.
I'm no nginx expert but I've setup multiple subdomains like this on different systems with success and am not sure what's going on. I've double & triple checked the basic stuff like making sure a valid sym-link exists in sites-enabled, no errors show up on nginx restart or systemctl status, and obviously the machine itself is listening on 0.0.0.0:https per netstat output as well as subdomain1 working correctly. I've also verified that the proxy_pass destination works when I use subdomain1 to point to it (also verified with curl on the nginx host).
Let me know if there is any other information I can provide.
Any help is appreciated.
Thanks
/etc/nginx/sites-available/subdomain1:
server {
listen 443 ssl;
server_name subdomain1.base.edu;
ssl_certificate /path/server.crt;
ssl_certificate_key /path/server.key;
client_max_body_size 0;
add_header Strict-Transport-Security max-age=15768000;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
/etc/nginx/sites-available/subdomain2:
server {
listen 443 ssl;
server_name subdomain2.base.edu;
ssl_certificate /path/server.crt;
ssl_certificate_key /path/server.key;
location / {
proxy_pass http://127.0.0.1:10123;
}
}
UPDATE (nginx -T output)
user#host:/etc/nginx/sites-available$ sudo nginx -T
[sudo] password:
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
.....
# configuration file /etc/nginx/sites-enabled/subdomain1.base.edu:
# top-level http config for websocket headers
# If Upgrade is defined, Connection = upgrade
# If Upgrade is empty, Connection = close
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 80;
server_name subdomain1.base.edu;
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name subdomain1.base.edu;
ssl_certificate /path/.ssl/server.crt;
ssl_certificate_key /path/.ssl/server.key;
client_max_body_size 0;
add_header Strict-Transport-Security max-age=15768000;
include /etc/nginx/sites-available/shinyapps;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# websocket headers
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;
proxy_buffering off;
}
}
# configuration file /etc/nginx/sites-available/shinyapps:
location /5627 {
proxy_pass http://localhost:5627/;
proxy_redirect / $scheme://$http_host/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_read_timeout 20d;
proxy_buffering off;
}
# configuration file /etc/nginx/sites-enabled/subdomain2.base.edu:
#
# bustalab1 domain to proxy localhost shiny apps
server {
listen 80;
server_name subdomain2.base.edu;
# Tell all requests to port 80 to be 302 redirected to HTTPS
return 302 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name subdomain2.base.edu;
ssl_certificate /path/.ssl/subdomain2.crt;
ssl_certificate_key /path/.ssl/subdomain2.key;
error_log /var/log/nginx/subdomain2_err.log debug;
access_log /var/log/nginx/subdomain2_acc.log;
location / {
proxy_pass http://127.0.0.1:10123;
}
}

forward websocket to websocket

I'm using the nginx as reverse proxy for django and React with as config
worker_processes 1;
events {
worker_connections 1024;
}
http{
server{
include mime.types;
default_type application/octet-stream;
keepalive_timeout 240;
sendfile on;
listen 8001;
server_name 127.0.0.1;
location /{
proxy_pass http://localhost:3000;
}
location /backend {
proxy_pass http://127.0.0.1:8000;
}
}
}
its working fine but i want to forward websocket for react hot loading. i have still no solution after lot of googling. currently it have connection error as from chrome console
WebSocket connection to 'ws://127.0.0.1:8001/sockjs-node' failed: Error during WebSocket handshake: Unexpected response code: 404
because of http directive, i that thought it will not support forward WebSocket proxy but after more spending time on google. i known that http is upgrade to Websocket after initial handshake So finally the solution is here
its worked for me as forward proxy for Django as backend and react as frontend. so i can pass CORS problem due to server are at different IP and its unsecure so setting header not support much regard cookie sharing
worker_processes 1;
events {
worker_connections 1024;
}
http{
client_max_body_size 100M;
server{
include mime.types;
default_type application/octet-stream;
keepalive_timeout 240;
sendfile on;
listen 8001;
server_name 127.0.0.1;
location /{
proxy_pass http://localhost:3000;
}
location /backend {
proxy_pass http://127.0.0.1:8000;
}
location /sockjs-node {
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;
}
}
}

NGinx forward websocket from 80 to websocket port

I am using Nginx as a web host and proxy for a websocket running on the same device listening on port 8888. Trying to find a way to have nginx listen on 80 and forward the websocket requests to the internal port. Without exposing a new port to the outside. Is this even possible?
UPDATE:
This is my current configuration:
error_log /var/log/nginx/error_log.log warn;
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream websocket {
server localhost:8888;
}
server {
listen 80;
#listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html/EncoderAdmin;
# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
auth_basic "Restricted Content";
auth_basic_user_file /etc/nginx/.htpasswd;
}
location /ws {
proxy_pass http://localhost:8888;
proxy_http_version 1.1;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
When I try to connect to it with ws://[address]/ws I get:
WebSocket connection to 'ws://[address]/ws' failed: Error during WebSocket handshake: Unexpected response code: 400
Yes, it's possible assuming you can distinguish the normal HTTP requests and the socket ones.
The simplest solution is to match the socket uri with location, for example all the requests to /ws will be redirected to localhost:8888, any other url to localhost:8889. Here it is an example of configuration
server {
server_name _;
location /ws {
proxy_pass http://localhost:8888;
# this magic is needed for WebSocket
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
}
location / {
proxy_pass http://localhost:8889;
}
}
You should also remember to bind the websocket server to localhost:8888 and not to 0.0.0.0:8888. This step is not needed but with it the original port is not exposed!

RoR 5.0.0 ActionCable wss WebSocket handshake: Unexpected response code: 301

Hello I'm trying to serve a simple chat using ror 5.0.0 beta (with puma)
working on production mode (in localhost there are no problems).
This is my Nginx configuration:
upstream websocket {
server 127.0.0.1:28080;
}
server {
listen 443;
server_name mydomain;
ssl_certificate ***/server.crt;
ssl_certificate_key ***/server.key;
ssl on;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers
HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4;
ssl_prefer_server_ciphers on;
access_log /var/log/nginx/jenkins.access.log;
location / {
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;
proxy_pass http://localhost:3000;
proxy_read_timeout 90;
proxy_redirect http://localhost:3000 https://mydomain;
location /cable/{
proxy_pass http://websocket/;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $http_host;
break;
}
}
This is config/redis/cable.yml
production:
url: redis://localhost:6379/1
development:
url: redis://localhost:6379/2
test:
url: redis://localhost:6379/3
and config/environments/production.rb
# Action Cable endpoint configuration
config.action_cable.url = 'wss://mydomain/cable'
# config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ]
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = false
And this is the error i'm receiving:
application-[...].js:27 WebSocket connection to 'wss://mydomain/cable' failed: Error during WebSocket handshake: Unexpected response code: 301
Any tips? :) Thanks
I solved adding phusion passenger.
nginx config is now :
server{
listen 80;
passenger_enabled on;
passenger_app_env production;
passenger_ruby /../ruby-2.3.0/ruby;
root /path to application/public;
client_max_body_size 4G;
keepalive_timeout 10;
[...]
location /cable{
passenger_app_group_name websocket;
passenger_force_max_concurrent_requests_per_process 0;
}
}
You have to remove default folder config/redis/cable.yml and move that file to /config only.
For SSL just enable default ssl options and it will works .-)
Thanks everyone for the help
Your websocket URI is /cable/ and not /cable, so the latter will hit the location / block. Try:
location /cable {
rewrite ^/cable$ / break;
rewrite ^/cable(.*)$ $1 break;
proxy_pass http://websocket;
...
}
Also, not sure you need a break; in there. I presume the missing } between the two location blocks is just a typo in the question.
EDIT1: Added rewrite to restore correct upstream mapping.
EDIT2: Alternative solution is to explicitly rewrite /cable to /cable/ like this:
location = /cable { rewrite ^ /cable/ last; }
location /cable/ {
proxy_pass http://websocket/;
...
}
I spend almost 5 hours yesterday trying to solve this particular problem. I ended up using a separate domain for the websocket connection called ws.example.com as everything else resulted in a 301 redirect.
Here's is my nginx.conf file. I've removed the SSL parts, but you could just insert your own. Note that you need nginx 1.4+ as everything prior to this version doesn't support websocket proxying.
upstream socket {
server unix:/mysocket fail_timeout=0;
}
upstream websocket {
server 127.0.0.1:28080;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
server_name ws.example.com;
access_log off;
# SSL configs here
location / {
proxy_pass http://websocket/;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
server {
listen 443 ssl;
server_name example.com;
# SSL configs here
location #app {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://socket;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 4G;
keepalive_timeout 10;
}
I read somewhere that allowed_request_origins didn't work as expected so I went the safe way (until the bug is fixed) and turned the checker of completely using ActionCable.server.config.disable_request_forgery_protection = true.
Here's my cable.ru file for starting action cable.
require ::File.expand_path('../../config/environment', __FILE__)
Rails.application.eager_load!
require 'action_cable/process/logging'
Rails.logger.level = 0
ActionCable.server.config.disable_request_forgery_protection = true
run ActionCable.server
I'm also using the latest rails version from Github.
gem "rails", github: "rails/rails"

Resources