Hide Domain Folder via Nginx reverse proxy - nginx

I am trying to remove a part of my URL and make an app available on sub-domain level.
Users shall access mail.example.com. The mailing app is currently available at mail.example.com/mail. How can I proxy user, opening mail.example.com, while accessing mail.example.com/mail via NGINX?
Following config fails for CCS and other files:
server {
listen 443 ssl http2;
server_name mail.example.com;
location / {
proxy_pass https://1.2.3.4/mail$request_uri;
proxy_http_version 1.1;
proxy_redirect off;
}
}

Related

nginx config to create subdomain from domain proxy_pass

I am trying to setup a domain and subdomain for my domain name in nginx server for www.example.com/users to www.people.example.com
i am able to configure subdomain but when i typed url in browser of subdomain url it is redirecting to www.example.com/users
But i need it to be in subdomain
is there anything that i missed in nginx config? please provide me any suggestion nginx config for subdomain
server
{
server_name people.example.com www.people.example.com;
error_log /var/log/nginx/error.log;
location / {
proxy_pass http://example.com/users$request_uri;
proxy_set_header "Host" $host;
proxy_redirect http://$host/users http://$host;
}
And also suggest me config for www.example.com to block access via www.example.com/users but can be accessed via www.people.example.com
Try redirecting from a separate server stanza. Then remove the proxy_* commands from the people.example.com server.
server {
server_name example.com www.example.com;
location = /users {
return 301 http://people.exxmple.com;
}
}

Nginx - Redirect domain to localhost:port content

I installed Nginx on my server (my server uses WHM). And on this server has two accounts. Each account will run a server a NextJS site and each account has its own domain.
Site1 will run on port 3000
Site2 will run on port 3004
What I want to do is:
I want to access domain1 I see the content of my site1 in NextJS that runs on localhost:3000
And when I access domain2 I see the content of my site2 on NextJS running on localhost:3004
I tried to do a Nginx implementation for site1. But when I accessed it I saw a Cpanel screen, and the url was dominio1/cgi-sys/defaultwebpage.cgi
Here's the Nginx implementation I tried to do:
server {
listen 80;
server_name computadorsolidario.tec.br www.computadorsolidario.tec.br ;
location / {
proxy_pass http://localhost:3004;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
}
}
So how do I do this setting for nginx to have this behavior? And I'm changing the correct file?
Note: I created the configuration file in /etc/nginx/conf.d/users/domain1/domio1.conf And within /etc/nginx/conf.d/users have several configuration files with the name of the accounts you have on the server. (They are already implemented.)
Try
server {
listen 80;
server_name www.domain1.com;
proxy_pass http://127.0.0.1:3000;
}
server {
listen 80;
server_name www.domain2.com domain2.com;
proxy_pass http://127.0.0.1:3004;
}
Each domain listens on same port and reverse-proxies to local network on the ports you specify. To differentiate between hosts, specify the server_name field.
server {
listen 80;
server_name www.domain1.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
server {
listen 80;
server_name www.domain2.com domain2.com;
location / {
proxy_pass http://127.0.0.1:3004;
}
}

Routing meant for a subdomain is also being applied to the root domain

Consider two websites hosted on the same server: domain.com and foo.domain.com. I want to start up a monitoring panel for each site on port 5555. Each site has a separate monitoring panel so I need to use nginx to route domain.com:5555 and foo.domain.com:5555 to two different places.
Here is the configuration for foo.domain.com:
server {
listen 5555;
server_name foo.domain.com;
location / {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://localhost:5678;
}
}
While this works fine for foo.domain.com:5555, it is also routing domain.com:5555 to the monitoring panel. This is acting like I had defined server_name domain.com foo.domain.com, but clearly I only defined it for foo.domain.com.
The only other nginx configs on the server are for ports 80 and 443. Neither of those configs use any wildcards and explicitly use the full name.
nginx always has a default server - if you do not define a default server, it will use the first server block with a matching listen directive.
If you want to discourage this behaviour, you will need to define a catch-all server for port 5555.
For example:
server {
listen 5555 default_server;
return 444;
}
See this document for more.

Nginx/Pyramid custom SSL port

As a prefix, I have been using the following stack for some time with great success:
NGINX - web proxy
SSL - configured in nginx
Pyramid web application, served by gunicorn
The above combo works great, here is a working configuration.
server {
# listen on port 80
listen 80;
server_name portalapi.example.com;
# Forward all traffic to SSL
return 301 https://www.portalapi.example.com$request_uri;
}
server {
# listen on port 80
listen 80;
server_name www.portalapi.example.com;
# Forward all traffic to SSL
return 301 https://www.portalapi.example.com$request_uri;
}
#ssl server
server {
listen 443 ssl;
ssl on;
ssl_certificate /usr/local/etc/letsencrypt/live/portalapi.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/portalapi.example.com/privkey.pem;
server_name www.portalapi.example.com;
client_max_body_size 10M;
client_body_buffer_size 128k;
location ~ /.well-known/acme-challenge/ {
root /usr/local/www/nginx/portalapi;
allow all;
}
location / {
proxy_set_header Host $host;
proxy_pass http://10.1.1.16:8005;
#proxy_intercept_errors on;
allow all;
}
error_page 404 500 502 503 504 /index.html;
location = / {
root /home/luke/ecom2/dist;
}
}
Now, this is how I serve my public facing apps, it works very well. For all my internal applications, I used to simply direct users to an internal domain example: http://subdomain.company.domain , again this worked well for a long time.
Now in the wake of KRACK attack although we have some very thorough firewall rules to prevent a lot of attacks, I want to force all internal traffic through SSL, and I don't want to use a self signed certificate, I want to use lets encrypt so I can auto-renew certificates which makes administration much easier (and cheaper).
In order to use lets encrypt, I need to have a public facing DNS and server to perform the ACME challenge (for auto renewing). Now again this was a very easy thing to setup in nginx, and the below config works perfectly for serving static content:
What it does is if a user from the internet accesses intranet.example.com it simply shows a forbidden message. However, if a local user tries, they get forwarded to intranet.example.com:8002 and the port 8002 is only available locally, so there is no way external users can access a webpage on this site
geo $local_user {
192.168.155.0/24 0;
172.16.10.0/28 1;
172.16.155.0/24 1;
}
server {
listen 80;
server_name intranet.example.com;
client_max_body_size 4M;
client_body_buffer_size 128k;
# Space for lets encrypt to perform challenges
location ~ /\.well-known/ {
root /usr/local/www/nginx/intranet;
}
if ($local_user) {
# If user is local, redirect them to SSL proxy only available locally
return 301 https://intranet.example.com:8002$request_uri;
}
# Default block all non local users see
location / {
root /home/luke/forbidden_html;
index index.html;
}
# This server block is only available to local users inside geo $local_user
# this block listens on an internal port only, so it is never availble to
# external networks
server {
listen 8002 default ssl; # listen on a port only accessible locally
server_name intranet.example.com;
ssl_certificate /usr/local/etc/letsencrypt/live/intranet.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/intranet.example.com/privkey.pem;
client_max_body_size 4M;
client_body_buffer_size 128k;
location / {
allow 192.168.155.0/24;
allow 172.16.10.0/28; # also add in allow/deny rules in this block (extra security)
allow 172.16.155.0/24;
root /home/luke/ecom2/dist;
index index.html;
deny all;
}
}
Now, here comes the pyramid/nginx marrying problem, if I use the same above configuration, but have the below settings for my server on 8002:
server {
listen 8002 default ssl; # listen on a port only accessible locally
server_name intranet.example.com;
ssl_certificate /usr/local/etc/letsencrypt/live/intranet.example.com/fullchain.pem;
ssl_certificate_key /usr/local/etc/letsencrypt/live/intranet.example.com/privkey.pem;
client_max_body_size 4M;
client_body_buffer_size 128k;
location / {
allow 192.168.155.0/24;
allow 172.16.10.0/28; # also add in allow/deny rules in this block (extra security)
allow 172.16.155.0/24;
# Forward all requests to python application server
proxy_set_header Host $host;
proxy_pass http://10.1.1.16:6543;
proxy_intercept_errors on;
deny all;
}
}
I run into all sorts of problems, first off inside pyramid I was using the following code in my views/templates
request.route_url # get route url for desired function
Now using request.route_url with the above settings should cause https://intranet.example.com:8002/login to route tohttps://intranet.example.com:8002/welcome but in reality, this setup would forward a user to: http://intranet.example.com/welcome Again this is not correct.
And if I use route_url with the NGINX proxy setting:
proxy_set_header Host $http_host;
I get the error: NGINX to return a 400 error:
400: The plain HTTP request was sent to HTTPS port
And a request to: https://intranet.example.com:8002/ gets reverted to: http://intranet.example.com/login (omitting port and https)
Then I used the same nginx settings (header $htto), but thought I would change to using:
request.route_path
My theory was this should force everything to stay on the same url prefix, and just forward a user from https://intranet.example.com:8002/login to https://intranet.example.com:8002/welcome but in reality, this setup performed the same way as using route_url.
proxy_set_header Host $http_host;
I then get an error when navigating to https://intranet.example.com:8002
400: The plain HTTP request was sent to HTTPS port
And a request to: https://intranet.example.com:8002/ gets reverted to: http://intranet.example.com/login (omitting port and https)
Can anyone assist with the correct setup in order for me to serve my application on https://intranet.example.com:8002
EDIT:
Have also tried:
location / {
allow 192.168.155.0/24;
allow 172.16.10.0/28; # also add in allow/deny rules in this block (extra security)
allow 172.16.155.0/24;
# Forward all requests to python application server
proxy_set_header Host $host:$server_port;
proxy_pass http://10.1.1.16:8002;
proxy_intercept_errors on;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# root /home/luke/ecom2/dist;
# index index.html;
deny all;
}
Which gives the same result.
I’ve checked a similar configuration and your last example seems correct,
at least for a simplistic gunicorn/pyramid app combination.
Seems something is missing in your puzzle )
Here’s my code (I’m new to Pyramid so something might be done better)
helloworld.py
from pyramid.config import Configurator
from pyramid.renderers import render_to_response
def main(request):
return render_to_response('templates:test.pt', {}, request=request)
with Configurator() as config:
config.add_route('main', '/')
config.add_view(main, route_name='main')
config.include('pyramid_chameleon')
app = config.make_wsgi_app()
templates/test.pt
<html>
<body>
Route url: ${request.route_url('main')}
</body>
</html>
My nginx config
server {
listen 80;
server_name pyramid.lan;
location / {
return 301 https://$server_name:8002$request_uri;
}
}
server {
listen 8002;
server_name pyramid.lan;
ssl on;
ssl_certificate /usr/local/etc/nginx/cert/server.crt;
ssl_certificate_key /usr/local/etc/nginx/cert/server.key;
location / {
proxy_set_header Host $host:$server_port;
proxy_pass http://127.0.0.1:5678;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
This is how I run gunicorn:
gunicorn -w 1 -b 127.0.0.1:5678 helloworld:app
And yes, it works:
$ curl --insecure https://pyramid.lan:8002/
<html>
<body>
Route url: https://pyramid.lan:8002/
</body>
</html>
$ curl -D - http://pyramid.lan
HTTP/1.1 301 Moved Permanently
Server: nginx/1.12.2
Date: Thu, 02 Nov 2017 20:41:50 GMT
Content-Type: text/html
Content-Length: 185
Connection: keep-alive
Location: https://pyramid.lan:8002/
Lets figure out what might go wrong in your case
http 400 usually pops up when you go over httP instead of httpS to a server awaiting httpS requests. If there’s no typo in the post and it indeed occurs when you navigate to https://intranet.example.com:8002 it would be nice to see a curl request showing this and a tcpdump showing what’s happening. Actually you can easily reproduce it by simply typing http://intranet.example.com:8002
another idea is that you’re doing a redirect from your app and the link gets broken when the redirect occurs. I better description on how the user may navigate from https://intranet.example.com:8002/login to .../welcome would be helpful
one more idea is that your app is not that simple and you use some middlewares / customization that makes the default logic work differently and your X-Forwarded-Proto header gets ignored - in this case the behavior would be just as you described
The issue here is, obviously, the missing port within the Location directives that your backend produces.
Now, why is the port missing? Most certainly, because of the following code:
proxy_set_header Host $host;
Note that $host itself does not contain $server_port, unlike $http_host, so, your backend would have no way of knowing which port you meant if you just use $host all by itself.
Note that proxy_redirect default of default expects Location to correspond with the value from proxy_pass in order to do its magic (according to documentation), so, your explicit header setting likely interferes with such logic.
As such, from the nginx point of view, I see multiple possible independent solutions:
remove proxy_set_header Host, and let proxy_redirect do its magic;
set proxy_set_header Host appropriately, to include the port number, e.g., using $host:$server_port or $http_host as you see fit (if that doesn't work, then perhaps the deficiency is actually within your upstream app itself, but fear not -- read below);
provide a custom proxy_redirect setting, e.g., proxy_redirect https://pyramid.lan/ / (equivalent to proxy_redirect https://pyramid.lan/ https://pyramid.lan:8002/), which will ensure that all the Location responses will have the proper port; the only way this wouldn't work is if your upstream does non-HTTP redirects with the missing port.

NGINX Reverse Proxy for 2 jenkins servers. How?

I would like to run 2 jenkins server behind nginx reverse proxy, but I can not find the proper to configure it.
The config below is working fine
location /jenkins {
proxy_pass https://contoso.com/jenkins;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
If i try to change location to /jenkins_test, than it does not work anymore.
What do I wrong?
You will need two define each jenkins instance in its own server section.
Then depending on the url that you are calling on nginx, the right jenkins server will respond.
Your nginx config could have a structure like this:
http{
# application server for first jenkins instance
upstream app_servers_first_jenkins_instance {
# if jenkins is running on the same server this should be something like 127.0.0.1 ...
server https://contoso.com/jenkins;
}
# application server for secons jenkins instance
upstream app_servers_second_jenkins_instance {
server https://contoso.com/jenkins;
}
# JENKINS SERVER 1
server{
listen 80;
server_name jenkinsfirstinstance.yourdomain.com;
location / {
proxy_pass http://app_servers_first_jenkins_instance;
}
}
# JENKINS SERVER 2
server{
listen 80;
server_name jenkinssecondinstance.yourdomain.com;
location / {
proxy_pass http://app_servers_second_jenkins_instance;
}
}
} # END OF HTTP SECTION
In this example both urls will call the same jenknins endpoint (https://contoso.com/jenkins) if you want them to be different jenkins instances you will have modify this url in one of the upstream sections
If you want to run 2 servers behind the nginx proxy, that's mean you need 2 location contexts (also called "blocks").
In your configuration file which is probably located in /etc/nginx/sites-availables you should add the locations:
http{
listen 80;
location /jenkins1 {
proxy_pass http://jenkins1-local-ip-address:8000;
include /etc/nginx/proxy_params;
}
location /jenkins2 {
proxy_pass http://jenkins2-local-ip-address:8001;
include /etc/nginx/proxy_params;
}
}
One thing you schould note is that I consider that your jenkins server is in same LAN (Local Area Network) otherwise it will not make sense to habe a proxy in front because your sever is already accessible via internet.
If your jenkins servers are accessible via HTTPS you schould change http to https in a location context and edit the port number to listen 443 and some ssl certificates configurations.

Resources