Can I use Nginx as server and proxy as the same time? - nginx

I want to use nginx as reverse proxy and load balancer, but i don't want Apache as server. It's possible to have two or more nginx as the same time? One as proxy and other serving content?
upstream backend_hosts {
server nginx1;
server nginx2;
}
server {
listen 80;
server_name example.com;
location /proxy-me {
proxy_pass http://backend_hosts;
}
}

Nginx is very capable of hosting a site with one server/location block and being a reverse proxy in another server/location block.

Related

How to set nginx reverse proxy in remote server

I have one server Server-1 where my app server is running.
In Server-2 I want to set up my Nginx to act as a reverse proxy for my app server.
how do I set up Nginx(in Server-2) which forwards traffic to Server-1
how do I check that everything is working fine, Nginx(Server-2) is acting as a reverse proxy for my app server(Server-1)
Traffic--->Server-2(with Nginx reverse proxy)--->Server-1(with server)
1) You should add location that will be redirecting all traffic from Server-2 to Server-1, e.g.:
server {
listen 80;
server_name Server-2.com;
location / {
proxy_pass http://Server-1.com/;
}
}
2) Try load http://Server-2.com page and if everything fine, you will get response from your app on Server-1.com

Configure Nginx to reverse proxy requests to backend server based on port number

I have have four web applications running in one ec2-instance with hostname "ip-10-176-225-83.us-west-2.compute.internal" on the ports 8888, 8088, 8042 and 8890. All those web application are on HTTP.
Our security team doesn't allow to open http port from onpremise to AWS. The suggest to setup a reverse proxy in same VPC subent which takes HTTPS requests and forward the same to back end webservers using HTTP.
I have created a new instance in same subnet with hostname "ip-10-176-225-84.us-west-2.compute.internal" and installed Niginx Server.
How can i configure Nginx so that it does as below
https://ip-10-176-225-84.us-west-2.compute.internal:8080 call http://ip-10-176-225-83.us-west-2.compute.internal:8080 and responds back
same for other ports
TL;DR: There are several methods of accomplishing what you're looking for here.
Adhering to the principle of reducing attack surface where possible, it's usually best to not expose ports to the public internet unless absolutely necessary. A reverse proxy is an excellent way to accomplish this. Generally, you'd want all of the backend web apps to be reverse proxied over HTTPS on port 443, and you would access each service either:
with different host names, such as app1.example.com and app2.example.com, or
with different subdirectories, such as example.com/app1 and example.com/app2
Depending on the method you choose, the configuration may vary significantly, either with multiple server blocks for the former scenario, or location blocks for the latter. In either case, we'll be making use of the upstream and proxy_pass directives. I'll give an example of both scenarios.
Multiple Hosts
If you're using multiple hostnames (or multiple ports) for the frontend, you'll need to create multiple server blocks for them:
# Nginx reverse-proxy configuration
upstream app1 {
server 10.176.225.83:8888;
}
upstream app2 {
server 10.176.225.83:8088;
}
upstream app3 {
server 10.176.225.83:8042;
}
upstream app4 {
server 10.176.225.83:8890;
}
server {
listen 443 ssl;
server_name app1.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app1;
}
}
server {
listen 443 ssl;
server_name app2.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app2;
}
}
server {
listen 443 ssl;
server_name app3.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app3;
}
}
server {
listen 443 ssl;
server_name app4.example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location / {
proxy_pass http://app4;
}
}
Several things to note here:
All of the backends have been defined at the top, using the upstream directive, and can now be referenced by name.
If you don't want to do it this way, you can omit the upstream blocks, and the proxy_pass lines would look like this: proxy_pass http://10.176.225.83:8888;
Because each app is being served on a different hostname, each gets its own server block. This would also be the case if they were each being served on different ports.
The ssl_certificate and ssl_certificate_key in each server block can point to different certificates, or even the same certificate, if you defined multiple SANs in the certificate.
Each app will be available from its own hostname, which all point to the frontend server:
App 1: https://app1.example.com
App 2: https://app2.example.com
App 3: https://app3.example.com
App 4: https://app4.example.com
Multiple Directories
For a configuration using a single host and port, serving the backend apps from subdirectories, you'll be using a single server block with multiple location blocks:
# Nginx reverse-proxy configuration
upstream app1 {
server 10.176.225.83:8888;
}
upstream app2 {
server 10.176.225.83:8088;
}
upstream app3 {
server 10.176.225.83:8042;
}
upstream app4 {
server 10.176.225.83:8890;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate_key /path/to/your/ssl-key.pem;
ssl_certificate /path/to/your/ssl-cert.pem;
location /app1 {
proxy_pass http://app1;
}
location /app2 {
proxy_pass http://app2;
}
location /app3 {
proxy_pass http://app3;
}
location /app4 {
proxy_pass http://app4;
}
}
A few more things to note with this one:
We still define all four upstream services, as before. And you can still omit them if you prefer the direct route. This directive is more useful in complex configurations.
Because all the apps are being served from the same hostname, they share a server block, but have separate location blocks for their respective subdirectories.
Since they all share the same hostname, multiple SANs aren't necessary for the server certificate in this case.
Each backend app will be available from a subdirectory on the frontend server:
App 1: https://example.com/app1
App 2: https://example.com/app2
App 3: https://example.com/app3
App 4: https://example.com/app4
TLS Configuration
In either scenario, you'll need to configure SSL certificates, either signed by a public CA, or your internal PKI, if applicable. If your apps are to be public facing, you will need to use public certificates. Then you'd add their location to the above Nginx config.
Further Reading
For a real world example, you can check out the Nginx configuration I'm using for a Genieacs TR-069 server, which implements SSL and reverse proxies several other services, albeit on their original ports, not to 443. This may be useful if you wanted to keep them on their original ports.
The Nginx site also has a decent primer on reverse proxy basic configuration.

Nginx Reverse Proxy upstream not working

I'm having trouble figuring out load balancing on Nginx. I'm using:
- Ubuntu 16.04 and
- Nginx 1.10.0.
In short, when I pass my ip address directly into "proxy_pass", the proxy works:
server {
location / {
proxy_pass http://01.02.03.04;
}
}
When I visit my proxy computer, I can see the content from the proxy ip...
but when I use an upstream directive, it doesn't:
upstream backend {
server 01.02.03.04;
}
server {
location / {
proxy_pass http://backend;
}
}
When I visit my proxy computer, I am greeted with the default Nginx server page and not the content from the upstream ip address.
Any further assistance would be appreciated. I've done a ton of research but can't figure out why "upstream" is not working. I don't get any errors. It just doesn't proxy.
Okay, looks like I found the answer...
two things about the backend servers, at least for the above scenario when using IP addressses:
a port must be specified
the port cannot be :80 (according to #karliwsn the port can be 80 it's just that the upstream servers cannot listen to the same port as the reverse proxy. I haven't tested it yet but it's good to note).
backend server block(s) should be configured as following:
server {
# for your reverse_proxy, *do not* listen to port 80
listen 8080;
listen [::]:8080;
server_name 01.02.03.04;
# your other statements below
...
}
and your reverse proxy server block should be configured like below:
upstream backend {
server 01.02.03.04:8080;
}
server {
location / {
proxy_pass http://backend;
}
}
It looks as if a backend server is listening to :80, the reverse proxy server doesn't render it's content. I guess that makes sense, since the server is in fact using default port 80 for the general public.
Thanks #karliwson for nudging me to reconsider the port.
The following example works:
Only thing to mention is that, if the server IP is used as the "server_name", then the IP should be used to access the site, means in the browser you need to type the URL as http://yyy.yyy.yyy.yyy or (http://yyy.yyy.yyy.yyy:80), if you use the domain name as the "server_name", then access the proxy server using the domain name (e.g. http://www.yourdomain.com)
upstream backend {
server xxx.xxx.xxx.xxx:8080;
}
server {
listen 80;
server_name yyy.yyy.yyy.yyy;
location / {
proxy_pass http://backend;
}
}

Ngixn load balancer keep changing original URL to load balanced URL

I have met an annoying issue for Nginx Load Balancer, please see following configuration:
http {
server {
listen 3333;
server_name localhost;
location / {
proxy_pass http://node;
proxy_redirect off;
}
}
server {
listen 7777;
server_name localhost;
location / {
proxy_pass http://auth;
proxy_redirect off;
}
}
upstream node {
server localhost:3000;
server localhost:3001;
}
upstream auth {
server localhost:8079;
server localhost:8080;
}
}
So what I want is to provide two load balancers, one is to send port 3333 to internal port 3000,3001, and second one is to send request to 7777 to internal 8079 and 8000.
when I test this setting, I noticed all the request to http://localhost:3333 is working great, and URL in the address bar is always this one, but when I visit http://localhsot:7777, I noticed all the requests are redirected to internal urls, http://localhost:8080 or http://localhost:8079.
I don't know why there are two different effects for load balancing, I just want to have all the visitors to see only http://localhost:3333 or http://localhost:7777, they should never see internal port 8080 or 8079.
But why node server for port 3000 and 3001 are working fine, while java server for port 8080 and 8079 is not doing url rewrite, but only doing redirect?
If you see the configuration, they are exactly the same.
Thanks.

What does upstream mean in nginx?

upstream app_front_static {
server 192.168.206.105:80;
}
Never seen it before, anyone knows, what it means?
It's used for proxying requests to other servers.
An example from http://wiki.nginx.org/LoadBalanceExample is:
http {
upstream myproject {
server 127.0.0.1:8000 weight=3;
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
}
server {
listen 80;
server_name www.domain.com;
location / {
proxy_pass http://myproject;
}
}
}
This means all requests for / go to the any of the servers listed under upstream XXX, with a preference for port 8000.
upstream defines a cluster that you can proxy requests to. It's commonly used for defining either a web server cluster for load balancing, or an app server cluster for routing / load balancing.
If we have a single server we can directly include it in the proxy_pass directive. For example:
server {
...
location / {
proxy_pass http://192.168.206.105:80;
...
}
}
But in case if we have many servers we use upstream to maintain the servers. Nginx will load-balance based on the incoming traffic, as shown in this answer.

Resources