Nginx load balance on server with multiple domains - apache

I haven't seen anything related to this topic on Google and since I'm a newbie on Nginx I'd like to ask a question about load balancing: I have a dedicated server currently running Apache with multiple accounts and domains. I'd like to switch to Nginx and set up a load balance only for one of these domains (mydomain1.com) to load balance traffic between this dedicated server and another 3 ones. I have the following Nginx config (/etc/nginx/conf.d/default.conf) on my dedicated server:
upstream mywebsite1 {
ip_hash;
server xxx.xxx.xxx.196 weight=1 max_fails=3 fail_timeout=15s;
server xxx.xxx.xxx.67 weight=1 max_fails=3 fail_timeout=15s;
server xxx.xxx.xxx.201 weight=1 max_fails=3 fail_timeout=15s;
}
server {
listen 80;
server_name mywebsite1.com;
access_log /var/log/nginx/proxy.log;
location / {
proxy_pass http://mywebsite1;
}
#error_page 404 /404.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}
}
But this is not working and when I read the proxy.log is also balancing traffic not just from mywebsite1.com, but also from my other domains: mywebsite2.com, mywebsite3.com, etc. Any help is really appreciated since as you see I'm not an expert! Thanks :)

I know it is years old question, but it still might help someone.
To make it work like you want, you must define at least two virtualhosts (server blocks).
1st is so called "default" - that is it serves everything that is not defined in any other virtualhost. Default in nginx context means defining:
server_name _;
You can add index.html to that virtualhost to tell visitors to go to right place. Display some sort of error message. Or redirect visitors to right place without any message - what ever suits your purposes.
But some sort of default is required if you want your other virtualhost block(s) to serve only specific domain(s) and nothing else.
2nd is "mywebsite1.com" - that only serves that particular domain. Your configuration for that domain is correct. And you can add more virtualhost blocks for different domains.
If you only have one virtualhost (even if it is not "default" type) then every single http request will go to that virtualhost, regardless if domain name matches or not.
You need to keep in mind that you should define different root path for every virtualhost, unless you want them all so serve same content.
root /some/path;
Which domain is served by which virtualhost is defined through server_name directive.
"_" means default and serves anything that does not match some other virtualhost.
You can define more than one domain if you want virtualhost block to serve more than one (do not forget to add both with and without www if you want both to work):
server_name www.example.com example.com some.other.domain.com;
You can also use wildcards:
server_name *.example.com;
So correct config file would be something like this:
# default virtualhost to serve everything that does not match other virtualhosts
server {
listen 80;
server_name _;
root /some/path/default_site;
# add other rules for default site
}
# virtualhost to server only (www.)mywebsite1.com
server {
listen 80;
# please note that you need to add both with and without "www." if you want both to work.
server_name mywebsite1.com www.mywebsite1.com;
root /some/path/mywebsite1.com;
# add other rules for mywebsite1.com
}
# virtualhost for example.com (without www)
server {
listen 80;
server_name example.com;
root /some/path/example.com;
# add other rules for example.com
}

If you send all of your traffic to your Nginx server, it has to do something with it. Since you only have one server block, regardless of what the server name is configured to be it will take the traffic for all host names.
If you don't want Nginx to handle traffic for all of your domains, simply don't point all of your domains at it (with DNS).

Related

NGINX Reverse Proxy redirecting instead of proxying

i have a NGINX server running as a reverse proxy. Proxy works for windows hosts however i have a owncloud server and the proxy will instead re wright the url to the internal host name or IP address. ex(I type cloud.example.com and my url bar will change to 10.1.1.19 which is unresolvable over wan
i have checked DNS records and made sure NGINX can resolve host name. also tried just forwarding http traffic to cloud server to make sure using domain name was not the issue.
server {
listen 80;
listen [::]:80;
server_name example.com;
location / {
proxy_pass http://10.1.1.16:80/;
}
}
server {
listen 80;
listen [::]:80;
server_name cloud.example.com;
location / {
proxy_pass http://10.1.1.19:80/;
}
}
server {
listen 80;
listen [::]:80;
server_name remote.example.com;
location / {
proxy_pass http://10.1.1.17:80/;
}
}
i just need NGINX to run as a proxy for "cloud.example.com" instead of rewriting URL
I found a partial answer to this -- Why is my Nginx reverse proxy doing a 301 redirect instead of proxying?.
For me, it kept nginx from changing the hostname (i.e. from good-domain.com to 10.1.5.5:8080), but there doesn't appear to be a way to stop nginx from appending the port to the client's request URL.
So, in using the answer referenced above, I was able to go from http://10.1.5.5:8080 to http://good-domain:8080. It's still not where I want to be, but it definitely gets me closer.

Nginx redirection conflicts with other ports

My situations is as follows:
app 1 running at: server.domain.com (192.168.1.3)
app 2 running at: server.domain.com:8080 (192.168.1.2)
My router is set up to route requests on port 80 to app 1 and port 8080 to app 2.
So far so good, this scenario has been working for ages.
Recently I tried switching to nginx and I decided to redirect http traffic to https traffic for app 1.
I set up a container with nginx and am using the following config:
server {
listen 80 default_server;
server_name _;
return 301 https://$host$request_uri;
}
# main server block
server {
listen 443 ssl default_server;
root /config/www;
index index.html index.htm index.php;
server_name _;
ssl_certificate /path to cert;
ssl_certificate_key /path to cert;
ssl_dhparam /path to cert;
ssl_ciphers '';
ssl_prefer_server_ciphers on;
client_max_body_size 0;
location / {
try_files $uri $uri/ /index.html /index.php?$args =404;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
# With php7-cgi alone:
fastcgi_pass 127.0.0.1:9000;
# With php7-fpm:
#fastcgi_pass unix:/var/run/php7-fpm.sock;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
}
}
This successfully redirects http to https and app 1 works as expected.
However when trying to visit app 2 I will also be redirected to https (which it shouldn't, app 2 doesn't support it)
Now I already figured out why this happens.
Google Chrome has a cache so when I visit the non-https url it gets a 301 redirect to the https version. It saves this in it's cache and now thinks I always want https regardless of the port.
The workaround I've found is going to chrome://net-internals and clearing the cache there. Opening app 2 then succeeds but after visiting app 1 I end up in the same loop all over again.
I've tried several default fixes found all over the net but none of them have worked thus far.
Anyone know what I have to put in my config to fix this?
ps: cert paths, domain names and ports are fake representations of the real situation
First off it would be helpful if in the nginx config you label which server definition corresponds to App 1 and App 2, because it appears there may be a mix up in the configuration. You are also missing some configuration, such as listening to port 8080. So first I'll clarify the requirements you clearly stated for both apps:
App 1:
Listens on port 80
Uses SSL
App 2:
Listens on port 8080
Does not use SSL / doesn't support it.
So I'd recommend config closer to:
# Corresponds better to app 2 given your requirements
server {
listen 8080 default_server;
server_name _;
# NOTE: You may want to listen for certain routes, without redirect EG
# location /foo/* { . . . }
return 301 $scheme://$host$request_uri;
}
# main server block - app 1
server {
listen 443 ssl default_server;
. . . # The rest of your definition here is fine for an SSL server
}
My main point here is that the server block on port 80 as you've defined it above is just a redirect machine to https, hardcoded. This block as you've defined it contradicts the requirements that you "route requests on port 80 to app 1" and you "use SSL for app 1" since your SSL configuration is actually in the second server definition. What you've set up in the first server definition is actually a pattern used to force ssl redirects leaving you in a position where you'll never serve non-ssl HTTP traffic. This might clear up the issue somewhat; perhaps I can help more once the server blocks more closely match the stated requirements.
Finally noting that it is possible to listen to multiple ports and route to http and https traffic within one server definition block:
server {
listen 80;
listen 443 ssl;
# can force some routes to be ssl or non ssl accordingly
}
Configuration like this may be more ideal if both app servers are hosted on the same machine using the same nginx service.

Only listen to ONE Subdomain and ONE Port

I need to find out how to listen to only one port-hostname combination and to return 404 on every other request.
My example:
I have set up a subdomain for owncloud that uses SSL and listens to port 12345 instead of 443. Let's assume this subdomain is oc.example.com. So I want nginx to only listen to https://oc.example.com:12345 but not to
http://oc.example.com:12345
https://oc.example.com:X where X != 12345
https://BLABLA.example.com:12345
http://IP.IP.IP.IP:12345
https://IP.IP.IP.IP:12345
and so on
If one requests any resource that does not exactly match https://oc.example.com:12345 an error (e.g. 404 not found) should be returned or the server simply should not respond.
My config so far looks like:
server {
# I think there's something wrong here?
listen 12345;
server_name oc.example.com;
ssl on;
ssl_certificate /etc/ssl/nginx/owncloud/owncloud.crt;
ssl_certificate_key /etc/ssl/nginx/owncloud/owncloud.key;
add_header Strict-Transport-Security max-age=31536000;
add_header X-Frame-Options DENY;
# Path to the root of your installation
root /var/some/path/to/my/owncloud/;
client_max_body_size 10G; # set max upload size
fastcgi_buffers 64 4K;
rewrite ^/caldav(.*)$ /remote.php/caldav$1 redirect;
rewrite ^/carddav(.*)$ /remote.php/carddav$1 redirect;
rewrite ^/webdav(.*)$ /remote.php/webdav$1 redirect;
index index.php;
error_page 403 = /core/templates/403.php;
error_page 404 = /core/templates/404.php;
... here are the definitions of my locations
}
I read the documentation and found that nginx first looks for the correct server definition by the port number. If there are multiple matches the server_name is used to find the correct definition. But I only have one definition!
Does somebody know how to solve the problem?
nginx checks for the host header and chooses the appropriate virtual host.. in order to have it drop everything else, just add a 'catch-all' using the default_server directive:
server {
listen 80 default_server;
return 404;
}
all requests to oc.example.com:X, besides 12345, will be dropped by default since you didn't define other vhosts listening on other ports.

nginx would not react to wildcard subdomains (*.domain)

i have have trouble with nginx wildcard sub-domains.
I've bought a domain from godaddy. then create host zone in amazone and then created a record set for A(A-IPv4) - for both www.domain.com / domain.com
and in nginx.conf i have the very basic configuration and 1 server file that look like this:
server {
listen 80 default_server;
listen [::]:80 default_server ipv6only=on;
access_log /var/log/nginx/domain.com.access.log;
error_log /var/log/nginx/domain.com.error.log;
# i tried the following for server name: domain.com *.domain.com/*.domain.com/.domain.com
server_name .domain.com;
root /usr/share/nginx/html/test;
index index.html;
}
when i visit subdomain.domain.com i get Firefox can't find the server at subdomain.domain.com
looking at the access log files nothing got logged it's completely empty.
Thanks
You have to add A-record for subdomains too. And before visiting site in Firefox, try ping - you will see if domain name can be resolved at all.

Nginx serving static content and proxy to apache

Is there a configuration I can use with nginx that would serve all static content for all wbsites on port 80 and all dynamic content would be forwarded to apache on port 8080? Preferably I would like to not have to change anything in apache vhosts other than port
Where can I find such working configuration?
Here's a good example; http://wiki.nginx.org/FullExample
Special emphasis on this part;
server { # simple reverse-proxy
listen 80;
server_name domain2.com www.domain2.com;
access_log logs/domain2.access.log main;
# serve static files
location ~ ^/(images|javascript|js|css|flash|media|static)/ {
root /var/www/virtual/big.server.com/htdocs;
expires 30d;
}
# pass requests for dynamic content to rails/turbogears/zope, et al
location / {
proxy_pass http://127.0.0.1:8080;
}
}