I came under a weird situation with the default nginx server defined in nginx.conf deployed by aegir (see also #1975178: default nginx server is a 404, but doesn't make that clear in the config about that). The server was overriding vhosts created in `vhost.d/*`.

Here's the nginx.conf config snippet:

server {
  limit_conn   gulag 32; # like mod_evasive - this allows max 32 simultaneous connections from one IP address
  listen       127.0.0.1:80;
  server_name  _;
  location / {
     root   /var/www/nginx-default;
     index  index.html index.htm;
  }
}

Here's the vhost created for my hostmaster site:

server {
  include      /var/aegir/config/includes/fastcgi_params.conf;
  limit_conn   gulag 32; # like mod_evasive - this allows max 32 simultaneous connections from one IP address
  listen       *:80;
  server_name  aegir.angela.anarcat.ath.cx;
  root         /var/aegir/hostmaster-6.x-2.x;
  # Extra configuration from modules:
  include      /var/aegir/config/includes/nginx_advanced_include.conf;
}

Here's my hostname and hosts file:

root@angela:/var/aegir/config/server_master# hostname
angela
root@angela:/var/aegir/config/server_master# hostname -f
localhost
root@angela:/var/aegir/config/server_master# cat /etc/hosts
127.0.0.1 localhost angela.anarcat.ath.cx angela aegir.angela.anarcat.ath.cx testsite test.aegir.angela.anarcat.ath.cx

::1     localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

What is the weirdest thing is that this worked for a while, then suddenly failed, maybe after a server verify? I don't know.

This configuration used to work fine on Apache.

When the default server block is commented out in nginx.conf, the hostmaster vhost works again.

Comments

omega8cc’s picture

This is because for some unknown reason you have localhost IP instead of wildcard in the default server:

listen 127.0.0.1:80;

While it should be:

listen *:80;

This is normal Nginx behaviour, so all vhosts and also the default server should either listen on the public IP or on the wildcard (all IPs). Otherwise the default server takes precedence.

That said, I can't reproduce this and I have no idea how you have got that 127.0.0.1 there.

Here is the code in the server template, for reference:

$ip_address = !empty($ip_address) ? $ip_address : '*';
server {
  limit_conn   gulag 32; # like mod_evasive - this allows max 32 simultaneous connections from one IP address
<?php
if ($ip_address == '*') {
  print "  listen       {$ip_address}:{$http_port};\n";
}
else {
  foreach ($server->ip_addresses as $ip) {
    print "  listen       {$ip}:{$http_port};\n";
  }
}
anarcat’s picture

HUm... well, there *are* IP addresses allocated on this server. So

if ($ip_address == '*') {
  print "  listen       {$ip_address}:{$http_port};\n";
}
else {
  foreach ($server->ip_addresses as $ip) {
    print "  listen       {$ip}:{$http_port};\n";
  }
}

will *not* put * as an IP address, it will put the actual IP of the server.

IIRC, on Apache, we hardcode * if the site is not using SSL, maybe we should do the same thing here?

But the problem would remain, probably... for SSL sites...

omega8cc’s picture

Yeah, we didn't do that in Nginx to use wildcard by default, because it could break older installs on servers with more than one IP, in case the extra IPs were used for something else. Instead, we have only added a fallback to wildcard in case the $ip_address is empty (for whatever reason). That said, it should never use 127.0.0.1 here, because it is used for DB server and not web server, for obvious reasons. Why this happened here? No idea. Maybe all these fixes with SSL refactoring did some extra magic here?

anarcat’s picture

Well, i did put 127.0.0.1 as an IP in the server_master IP address list (and it did work, so that's something that is allowed right now). I didn't expect this to end up in the vhost, but it would have (even in Apache) if SSL was enabled on that vhost.

I think * should be hardcoded for non-SSL vhost. That's the way things have been working for a long time in Aegir, even in 1.x, and I don't see why this should be different in nginx.

omega8cc’s picture

Status: Active » Needs work

This was always different in Nginx, because the SSL vhost uses the IP both for port 443 and 80 and if non-SSL-enabled vhost would use wildcard, it would break things, because you can't use both wildcard and IP based vhost, as you have seen.

So we should hardcode wildcard for both standard, non-SSL vhosts and also hardcode wildcard in the server.tpl.php default vhost, so we will keep using IPs only in templates: server_ssl.tpl.php, vhost_ssl.tpl.php and vhost_ssl_disabled.tpl.php

anarcat’s picture

I am not sure I understand correctly: are you saying that Nginx cannot have wildcard and IP-based vhost *on the same port*? In Apache, there's the NameVirtualHost *:80 directive which indicates how the port should be managed (IP-based or name-based), isn't there a similar way of doing things in Nginx?

thanks for the feedback.

omega8cc’s picture

Yes, you can't use IP:port and *:port listen directives for the same port in vhosts on the same server, even if you use standard server_name directive for name based hosting, either with name wildcard _ or site name and aliases - this docs entry explains details.

omega8cc’s picture

When you have two vhosts, and one listens on IP:port and second on *:port, then the vhost on IP:port will act as a default server for the site with *:port directive, if both sites names point to the same IP address. This is easy to test with Drupal 6 sites where we create symlinks for aliases in the sites directory. Once you create a symlink for otherwise broken site listening on *:port pointing to the site with vhost listening on IP:port, you will discover that the site with IP:port serves the request.

anarcat’s picture

Aaah right, but this is about different ports! SSL is on port 443, and that one requires IP addresses. However, for non-SSL port, we explicitely decided to *not* specify the IP for port 80 to make management of this simpler.

It seems to me the same should be applied to the nginx config.

omega8cc’s picture

Status: Needs work » Fixed
anarcat’s picture

awesome!

omega8cc’s picture

One more commit was required to get it fixed: http://drupalcode.org/project/provision.git/commit/2233ee1

Deciphered’s picture

Status: Fixed » Needs review

This commit breaks listening on localhost, which is necessary for anyone running Aegir via Nginx on their local machine.

Simple fix is to add an additional listener for localhost:80.

http://drupalcode.org/sandbox/deciphered/2005700.git/shortlog/refs/heads...
Patch: http://drupalcode.org/sandbox/deciphered/2005700.git/patch/a54dbe0df2648...

realityloop’s picture

Status: Needs review » Reviewed & tested by the community

this patch is actually an improvement over previous behaviour as I can now access sites from within VM's as well as via my localhost without having to edit the vhost every time.

omega8cc’s picture

Status: Reviewed & tested by the community » Fixed

Not sure what you mean. This seems redundant, because the wildcard should work also for localhost IP. We shouldn't use localhost name here (for the listen directive), and wildcard works also for 127.0.0.1 (localhost). What is the problem are you trying to solve exactly? Please open separate issue to discuss this.

realityloop’s picture

It seems like the reason that both are required is to cover both IPv4 and IPv6

Deciphered’s picture

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

  • Commit 6d056ee on dev-drupal-8, 6.x-2.x, dev-ssl-ip-allocation-refactor, 7.x-3.x, dev-subdir-multiserver, 6.x-2.x-backports, dev-helmo-3.x by omega8cc:
    Issue #1975188 by anarcat - nginx default server overrides configured...
  • Commit 2233ee1 on dev-drupal-8, 6.x-2.x, dev-ssl-ip-allocation-refactor, 7.x-3.x, dev-subdir-multiserver, 6.x-2.x-backports, dev-helmo-3.x by omega8cc:
    Issue #1975188 by anarcat - nginx default server overrides configured...