How to configure nginx for Amazon ec2 - nginx

I saw example configurations of nginx, most of them use example.com as a server_name and uwsgi_pass similar to unix:/var/www/run/blog.sock; or in combination with ip/port address. but what should I use in case of amazon ec2 instance, since it has long public name, ip is private and if I restart my instance it gets different public name and ip. I need shutdown instances sometime. I want to configure it for using uwsgi+django, but I am totally beginner in web area and servers.

The server_name directive is useful in cases where you want to host different sites on the same server, and handling them differently depending on the "Host" header field (ex: mysite1.com => a PHP website, mysite2.com => a django website,...)
It's actually a virtual server (see also [the server directive])1.
From this article :
[...] nginx tests only the request’s header field
“Host” [against the server_name directive] to determine which server the request should be routed to. If
its value does not match any server name, or the request does not
contain this header field at all, then nginx will route the request to
the default server for this port.
If I understood, you don't want that. So you can use the underscore character (in the Miscellaneous Names section).
When I don't need to handle specific domains, I generally use "localhost". To be honest I couldn't find any explanation on what it does. I just found examples with this value, and it seems to work exactly as the underscore character.
So I'd go with
server_name _;
or
server_name localhost;

Related

Subdomain is unexpectedly resolving despite Nginx not being set up to reverse proxy it

So I have been setting up my home network to host a few websites under a domain (and it's subdomains) using a combination of cloudflare to proxy and provide DDoS protection/HTTPS to the sites, and an Nginx reverse proxy running on my network to allow multiple sites to return from behind the same gateway that the DNS records in cloudflare are pointed at.
For the purposes of this explanation, I will replace my real domain name with [domainNameHere].
The first thing to explain is my DNS setup on cloudflare.
I have 4 CNAME records setup to do the following:
Note that I'm using CNAME records because I do not have a static home IP, therefore I'm using a Dynamic DNS address that resolves to the IP address of my gateway. This same Dynamic DNS address is used in place of an A record as I'm aiming to not need to update A records all the time, and instead just have it resolve via a automatically updating Dynamic DNS record.
[domainNameHere].net - Reverse proxy returns the root site when this domain is requested.
www.[domainNameHere].net - Behaves the same as the above, just there to handle any www requests, the reverse proxy returns the same root site for both wwww and the root domain name.
map.[domainNameHere].net - When this subdomain of [domainNameHere] is called, the reverse proxy instead returns a different site (a map, as you might have guessed).
test.[domainNameHere].net - This is a proxied DNS record setup in cloudflare for future purposes, I do not yet intend for it to actually return a site.
Now, the expected behaviour is that all of these DNS records should currently return a site, expect for test.[domainNameHere].net which shouldn't - I'd expect it to just return a standard ERR_NAME_NOT_RESOLVED like any other DNS record that doesn't actually go anywhere.
Instead though, when test.[domainNameHere].net is used, it returns the root site that [domainNameHere].net and www.[domainNameHere].net resolve to?
Using map, www or the root domain name all return the expected content.
I believe that I have configured something incorrectly in the Nginx settings, below are the two configuration files that are currently in my sites-enabled directory:
server {
listen 80;
listen [::]:80;
root /var/www/html;
index index.nginx-debian.html;
server_name [domainNameHere].net www.[domainNameHere].net;
location / {
try_files $uri $uri/ =404;
}
}
server {
listen 80;
listen [::]:80;
server_name test.[domainNameHere].net;
location / {
proxy_pass http://jake-server:8123;
}
}
Is there anything wrong with my Nginx setup? I thought the behaviour would be that if I haven't setup test.[domainNameHere].net within Nginx, then it wouldn't resolve on the reverse proxy and therefore wouldn't return anything, or would just return the Nginx 404/403 page?
Is it maybe something to do with how the first setup file is setup to point to local files on the proxy, rather than using proxy_pass like is usually done in a reverse proxy?
Or is this not an issue with Nginx, and is an issue with how I've set Cloudflare up?

How to use server_name in Nginx under HTTP/2?

I want to use 2 server blocks.
The first is:
server {
listen 443 ssl http2 fastopen=3 reuseport;
server_name a.example.xyz;
include server_safe.conf;
root /home/www/blog/;
}
The second is:
server {
listen 443 ssl http2;
server_name b.example.xyz;
include server_safe.conf;
}
What I want:
I want the server_name to be valid, that is , if I use a c.example.xyz to visit my website, both a.example.xyz,b.example.xyz,c.example.xyz is the same IP , the server should block the c.example.xyz request because it is not in the server_name.
However, if I enter https://c.example.xyz, the Nginx will still receive the request and reponse as a.example.xyz
I know HTTP/2 has no host in its header, it has a :authority instead.
My question is that : How can I reject any other request? I only want to accept the request under(with) the host(:authority) = a(b).example.xyz
The problem is the first Server block is used by default if no other name matches.
Therefore to achieve what you want, you need to create a default block, before the other two, and have it block or redirect, or show an error page.
The downsides of this are:
Unless you have HTTPS certificates that all the domain names (or use a wildcard cert that covers this), then they will get an error when going to https version of your site and use this default config. Though this would happen under your current set up anyway. There is no way AFAIK to send a block message before the HTTPS negotiation happens.
Older clients that don't support SNI (primarily Windows XP) will go to default config, whereas previously they would have gotten through for Server A as it was the default (though not for server B).
The alternative is to write a redirect rule based on the hostname provided. Not 100% sure how to do this on nginx to be honest but if not possible by default then is possible with ModSecurity. Again it will only take effect after the HTTPS negotiation has happened so still leaves you with a potential incorrect cert problem.

Domain name and port based proxy

I think I finally grasped how Docker works, so I am getting ready for the next step: cramming a whole bunch of unrelated applications into a single server with a single public IP. Say, for example, that I have a number of legacy Apache2-VHost-based web-sites, so the best I could figure was to run a LAMP container to replicate the current situation, and improve later. For argument sake, here is what I have a container at 172.17.0.2:80 that serves
http://www.foo.com
http://blog.foo.com
http://www.bar.com
Quite straightforward: publishing port 80 lets me correctly access all those sites. Next, I have two services that I need to run, so I built two containers
service-a -> 172.17.0.3:3000
service-b -> 172.17.0.4:5000
and all is good, I can privately access those services from my docker host. The trouble comes when I want to publicly restrict access to service-a through service-a.bar.com:80 only, and to service-b through www.foo.com:5000 only. A lot of reading after, it would seem that I have to create a dreadful artefact called a proxy, or reverse-proxy, to make things more confusing. I have no idea what I'm doing, so I dove nose-first into nginx -- which I had never used before -- because someone told me it's better than Apache at dealing with lots of small tasks and requests -- not that I would know how to turn Apache into a proxy, mind you. Anyway, nginx sounded perfect for a thing that has to take a request a pass it onto another server, so I started reading docs and I produced the following (in addition to the correctly working vhosts):
upstream service-a-bar-com-80 {
server 172.17.0.3:3000;
}
server {
server_name service-a.bar.com;
listen 80;
location / {
proxy_pass http://service-a-bar-com-80;
proxy_redirect off;
}
}
upstream www-foo-com-5000 {
server 172.17.0.4:5000;
}
server {
server_name www.foo.com;
listen 5000;
location / {
proxy_pass http://www-foo-com-5000;
proxy_redirect off;
}
}
Which somewhat works, until I access http://blog.bar.com:5000 which brings up service-b. So, my question is: what am I doing wrong?
nginx (like Apache) always has a default server for a given ip+port combination. You only have one server listening on port 5000, so it is your defacto default server for services on port 5000.
So blog.bar.com (which I presume resolves to the same IP address as www.foo.com) will use the default server for port 5000.
If you want to prevent that server block being the default server for port 5000, set up another server block using the same port, and mark it with the default_server keyword, as follows:
server {
listen 5000 default_server;
root /var/empty;
}
You can use a number of techniques to render the server inaccessible.
See this document for more.

How do I serve multiple domains on the same port with nginx

For development, I'd like to serve multiple projects on different local domains, all on port 80. In my hosts file I direct local.example.com to localhost, same for local.example2.com.
Now I'm trying to convince nginx to serve the example resources for the one url, and the example2 resources for the other.
I've read the nginx documentation and this blog post. But I think I must be missing something.
I've added to my nginx.conf:
include /Users/iwein/Sites/conf/*.conf;
Then in sites I add configuration like example.conf:
server {
listen 80;
server_name local.example.com;
…
and example2.conf:
server {
listen 80;
server_name local.example2.com;
…
Now the weird thing is that nginx seems to load the alphabetically first config, but on the second url, it serves the resources from the first server definition too. Nginx seems to totally ignore the server_name. How should I configure for this use case?
UPDATE:
It appears that if you use only one separator in the domain name (e.g. example1.local), it works just fine. I didn't further pursue this, because I have better things to do, but it's odd.
Apparently, nginx doesn't like the format of my server names. If I remove the 'local' subdomain it seems to work much better. I'm now working with example.dev and example2.dev and the problem is gone.

Stop NGINX from logging my IP address

I'd like to stop NGINX from logging my own IP addreess in my access.log Is this possible? I can easily do it in Apache but I haven't been able to find anything like this for NGINX.
This should really be on serverfault so I'll vote for a move.
But I can help a little here.
Short version, no you can't.
Long version. You can hack around it by using different backends for where you log one and don't log the other. Or by creating an extra server on a different port. But there isn't really a clean way of filtering an IP address from the logs.
You can however filter by url, perhaps that is an option for you?
You could create a virtual host that will log only your accesses, while the main log will log the rest. In this case you would access the new virtual host from your machine.
server {
listen 80;
server_name domain.com www.domain.com;
access_log logs/domain.access.log;
Then you create a second one
server {
listen 80;
server_name me.domain.com;
access_log logs/me.domain.access.log;
Or remove the last line.
This way your accesses won't mix with the external accesses.
You have to add me.domain.com in DNS or in your /etc/hosts, with the same IP as the main domain.

Resources