Does Aegir works with Nginx?

We encourage users to post events happening in the community to the community events group on https://www.drupal.org.
wong.101@osu.edu's picture

Hello all,
I'm new here. But it seems like everywhere I looked, Aegir has documentations mostly with apache server. Does Aegir work with Nginx?

Thanks,

Comments

It depends on your setup

omega8cc's picture

We are using Aegir with Nginx (no need to restart/reload Apache) and it works with Nginx wildcard configuration for hosted domains as long as you will not try to upgrade any site to newer platform (Drupal version) within Aegir, because the path to the site will change. I'm testing now how it could work without modifying anything in Aegir and will post results here.

HTH,
Grace

Quick and simple hack to get it done

omega8cc's picture

In your nginx configuration use:

catch-all server_name:

server_name  _;

and for wildcard doc-root use:
root /path/to/nginx/vroot/$host/;

In provision module add 6 lines to file:
/home/aegir/.drush/provision/web_server/provision_apache.drush.inc

so it will look like below:

function _provision_apache_create_config($file, $data, $template) {
  drush_log(dt("Generating apache host configuration file %file.", array('%file' => $file)));
  $writable = provision_path("writable", drush_get_option('vhost_path'), TRUE , NULL,
      dt("Virtual host configuration path @path is not writable."),
      'PROVISION_VHOST_PATH_NOT_WRITABLE');

  if ($writable) {
    $file = fopen(drush_get_option('vhost_path') .'/'. $file, "w");
    $text = provision_render_config($template, $data);
    fwrite($file, $text);
    fclose($file);
    // Add below 6 lines to create symlink for nginx wildcard virtual domains
    $nginx_publish_path = drush_get_option('publish_path');
    $nginx_wildcard = '/path/to/nginx/vroot/';
    $nginx_site_url = drush_get_option('site_url');
    $nginx_site_url = $nginx_wildcard . $nginx_site_url;
    if(is_link($nginx_site_url)) { unlink($nginx_site_url); }
    symlink($nginx_publish_path,$nginx_site_url);
  }
}

Done.
Tested and works.

HTH,
Grace

Thanks Grace!

wong.101@osu.edu's picture

Thanks Grace! I'll give it a try.

Just curious, how did you configure your nginx? I configured my nginx according to this site: http://www.guvnr.com/web/web-dev/install-nginx-not-apache/

How important is it to create an aegir account? Is it a must?

THE_GUV recipe is nice, but...

omega8cc's picture

...it requires creating one pair of file/symlink per (sub)domain to include in main Nginx config file. This is useful when you need different configurations per domain, but this is not the case with Drupal powered by Aegir hosting system, where you need just one working Nginx configuration for all sites (I believe you need VPS or similar cloud based VPS to host Aegir).

You need aegir separate user to follow separation of Drush jobs (and web server user), used behind the scene by Aegir. It is explained in detail while you install Hostmaster profile - read carefully everything in every installation step/screen and you will learn how important it is and why.

To follow THE_GUV recipe you should create full working copy of Apache submodule available in Provision module. I believe it is easy to avoid if you manage to add just 6 lines of code there (for Nginx) and you will create just one-for-all configuration in Nginx itself.

My Nginx configuration looks like below (it would be much simpler, but I use also Boost and it requires more details there). In this example Nginx works as a backend server behind Pound proxy. PHP as a separate FastCGI daemon thanks to http://php-fpm.org patch.

#######################################################
###  nginx.conf  BEGIN
#######################################################
#
pid                   /var/run/nginx-s.pid;
user                  www www;
worker_processes      4;
worker_rlimit_nofile  8192;

events {
    worker_connections  2048;
    use epoll;
}

http {
## MIME types
  include            /usr/local/etc/fastcgi.conf;
  include            /usr/local/etc/mime.types;
  default_type       application/octet-stream;

## Size Limits
  client_body_buffer_size   1k;
  client_header_buffer_size 1k;
  client_max_body_size      10m;
  large_client_header_buffers 3 3k;
  connection_pool_size      256;
  request_pool_size           4k;
  server_names_hash_bucket_size  128;

## Timeouts
  client_body_timeout   30;
  client_header_timeout 30;
  keepalive_timeout     75 20;
  send_timeout          30;

## General Options
  ignore_invalid_headers on;
  limit_zone gulag $binary_remote_addr 1m;
  recursive_error_pages  on;
  sendfile               on;
  set_real_ip_from      92.243.0.0/16;
  real_ip_header        X-Forwarded-For;

## TCP options 
  tcp_nodelay on;
  tcp_nopush  on;

## Compression
  gzip              on;
  gzip_buffers      16 8k;
  gzip_comp_level   9;
  gzip_http_version 1.1;
  gzip_min_length   10;
  gzip_types        text/plain text/css image/png image/gif image/jpeg application/x-javascript text/xml application/xml application/xml+rss text/javascript;
  gzip_vary         on;
  gzip_static       on;
  gzip_proxied      any;
  gzip_disable      "MSIE [1-6]\.";

## Log Format
  log_format        main '"$http_x_forwarded_for" $host [$time_local] '
                         '"$request" $status $body_bytes_sent '
                         '$request_length $bytes_sent "$http_referer" '
                         '"$http_user_agent" $request_time "$gzip_ratio"';

  client_body_temp_path /my/cache/nginx_s/client_body_temp 1 2;
  access_log  /my/log/nginx_s_access.log main;
  error_log   /my/log/nginx_s_error.log crit;


#######################################################
###  nginx.conf catch-all
#######################################################

  server {
        limit_conn   gulag 5;
        listen       92.243.4.111:88;
        server_name  _;
        root         /var/aegir/data/u/$host/;

     ## Only requests to our Host are allowed
      if ($host ~ ^(92.243.)) {
         return 444;
      }
     ## Deny some crawlers
      if ($http_user_agent ~* (HTTrack|HTMLParser|libwww) ) {
         return 444;
      }
     ## Deny certain Referers (case insensitive)
      if ($http_referer ~* (poker|sex|girl) ) {
        return 444;
      }
     ## Deny certain URI (for all)
      location ~* (gclid|_vti_bin|MSOffice) {
        return 444;
      }
     ## Serve static files directly
      location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico)$ {
          access_log        off;
          expires           30d;
          root /var/aegir/data/u/$host/;
      }
      location = /node {
          rewrite ^/node$  http://$host/  permanent;
      }
    
   location = / {
      root /var/aegir/data/u/$host/;
      index index.php index.html;
      if ($query_string ~ ".+") {
         break;
      }
      if ($http_cookie ~ "DRUPAL_UID" ) {
         break;
      }
      if ($request_method !~ ^(GET|HEAD)$ ) {
         break;
      }
      if (-f $document_root/cache/$host/0/index.html) {
         add_header  X-Header "Boost Red 2.2";
         add_header  Expires "Tue, 24 Jan 1984 08:00:00 GMT";
         add_header  Cache-Control "store, no-cache, post-check=0, pre-check=0";
         charset     utf-8;
         rewrite     ^/(.*)$ /cache/$host/0/index.html break;
      }
      error_page 404 = @dynamic_request;
   }

   location ~ \.html$ {
      root /var/aegir/data/u/$host/;
      index index.php index.html;
      if ($query_string ~ ".+") {
         break;
      }
      if ($http_cookie ~ "DRUPAL_UID" ) {
         break;
      }
      if ($request_method !~ ^(GET|HEAD)$ ) {
         break;
      }
      if (-f $document_root/cache/$host/0$request_uri.html) {
         add_header  X-Header "Boost Yellow 2.2";
         add_header  Expires "Tue, 24 Jan 1984 08:00:00 GMT";
         add_header  Cache-Control "store, no-cache, post-check=0, pre-check=0";
         charset     utf-8;
         rewrite     ^/(.+)$ /cache/$host/0/$1.html break;
      }
      if (-f $document_root/cache/$host/0$request_uri/index.html) {
         add_header  X-Header "Boost Green 2.2";
         add_header  Expires "Tue, 24 Jan 1984 08:00:00 GMT";
         add_header  Cache-Control "store, no-cache, post-check=0, pre-check=0";
         charset     utf-8;
         rewrite     ^/(.+)$ /cache/$host/0/$1/index.html break;
      }
      error_page 404 = @dynamic_request;
   }

   location / {
      root /var/aegir/data/u/$host/;
      index index.php index.html;
            if (!-e $request_filename) {         
                rewrite ^/\?q=([^.]+)$                    /index.php?q=$1 last;
                rewrite ^/(.*)\?token=([^.]+)$            /index.php?q=$1&token=$2 last;
                rewrite ^/([^.]+)\?t=([^.]+)$             /index.php?q=$1&t=$2 last;
                rewrite ^/([^.]+)\?string=([^.]+)$        /index.php?q=$1&string=$2 last;
                rewrite ^/([^.]+)\?destination=([^.]+)$   /index.php?q=$1&destination=$2 last;
                rewrite ^/([^.]+)\?page=([^.]+)$          /index.php?q=$1&page=$2 last;
                rewrite ^/([^.]+)\?filter0=([^\/]+)$      /index.php?q=$1&filter0=$2 last;
                rewrite ^/([^.]+)\?sort([^.]+)$           /index.php?q=$1&sort$2 last;
                rewrite ^/([^.]+)\?slide=([^.]+)$         /index.php?q=$1&slide=$2 last;
                rewrite ^/([^.]+)\?quote([^.]+)$          /index.php?q=$1&quote$2 last;
                rewrite ^/([^.]+)$                        /index.php?q=$1 last;
                rewrite ^/(.+)$                           /index.php?q=$1 last;
                break;
            }
            error_page 404 = /404.htm;
   }
            
        # redirect server error pages to the static page /50x.html
        #
        error_page 400 401 402 403 405 406 407 408 409 410 411 412 413 414 415 416 417
                   500 501 502 503 504 505 /50x.html;
        location = /50x.html {
            root   /my/nginx-errors;
        }
        location = /404.htm {
            root   /my/nginx-errors;
        }
        location ~ \.php$ {
          if ( $uri !~ "^/files/") {
            fastcgi_pass   92.243.4.111:9009;
          }
        }

     ## dynamic
   location @dynamic_request {
          # only internal requests can reach this point
          # internal;
          # dispatch to our app_server cluster / instance
             rewrite ^/\?q=([^.]+)$                    /index.php?q=$1 last;
             rewrite ^/(.*)\?token=([^.]+)$            /index.php?q=$1&token=$2 last;
             rewrite ^/([^.]+)\?t=([^.]+)$             /index.php?q=$1&t=$2 last;
             rewrite ^/([^.]+)\?string=([^.]+)$        /index.php?q=$1&string=$2 last;
             rewrite ^/([^.]+)\?destination=([^.]+)$   /index.php?q=$1&destination=$2 last;
             rewrite ^/([^.]+)\?page=([^.]+)$          /index.php?q=$1&page=$2 last;
             rewrite ^/([^.]+)\?filter0=([^\/]+)$      /index.php?q=$1&filter0=$2 last;
             rewrite ^/([^.]+)\?sort([^.]+)$           /index.php?q=$1&sort$2 last;
             rewrite ^/([^.]+)\?slide=([^.]+)$         /index.php?q=$1&slide=$2 last;
             rewrite ^/([^.]+)\?quote([^.]+)$          /index.php?q=$1&quote$2 last;
             rewrite ^/([^.]+)$                        /index.php?q=$1 last;
             rewrite ^/(.+)$                           /index.php?q=$1 last;
             fastcgi_pass 92.243.4.111:9009;
   } 
  } # end of server


#######################################################
###  nginx.conf catch-all
#######################################################
}

HTH,
Grace

BTW: above example works with Boost 5.x only. 6.x example will be posted soon. But if you don't use Boost, it will work with both 5.x and 6.x Drupal platforms on Aegir.

Awesome!

wong.101@osu.edu's picture

Thanks Grace! I'll give this a try.

my understanding is that

anarcat's picture

my understanding is that nginx is a reverse proxy server that doesn't support PHP in itself, so properly speaking, it will not support Aegir in itself: it needs an Apache backend.

Now, if nginx needs a special configuration for vhosts (which seems to be the case, according to the discussion I saw above), this could be performed in a separate module (like provision_apache, but provision_nginx). Config files could even be created per vhost, it's simple enough...

@theanarcat

omega8cc's picture

We use Pound for proxy/balance traffic etc. Nginx is a full featured web server and can replace Apache completely. There is no need to have PHP module in Nginx since PHP works here as a standalone FastCGI daemon working with Nginx. In my example there is no need to create any kind of separate provision_nginx sub-module. Also vhosts are much easier to manage here, since you don't need new configuration files for every (sub)domain and you don't need to restart/reload Nginx. I prefer shortcuts whenever possible, but understand others prefers to use perfect solutions. Why bother with new module when you have it done with 6 (or less) lines of simple code?

Best,
Grace

@theanarcat

omega8cc's picture

Years ago we had advanced Apache rewrites setup for mass virtual hosting, and I remember we didn't tried to get it all done the way it is here, in Provision module, with creating new included config file for every vhost. It looks over-engineered for me. As far as I remember, we used maps - one for domain/doc-root-path and second for domain/user (to run PHP with vhost owner's rights). When we needed to add new vhost, the script had to modify only those 2 files/maps, without touching Apache configuration. Why we need here separate files included, when in real world I suppose all of them will always share the same setup? I believe there is something like wildcard setup? Nginx allows to forget about configuration after initial setup. No need to create/include new files, no need to restart/reload. Everything you need is just proper symlink to vhost/site root (changing when upgrading between platforms in Aegir).

HTH,
Grace

Drupal multisite under nginx

mshaver's picture

You seem to know a lot about Nginx and Drupal and I wondered if you ever came across a problem I'm having with my nginx and drupal setup?

The problem is with the password reset function in Drupal. Everything works as expected, until you get to the point where you are selecting the "login" button that is supposed to redirect you to your account edit page where you change your password. In my case it instead does not redirect and gives you an error for trying to use the reset url again. I read someplace that running PHP in CGI mode sometimes has issues with sessions after a redirect in the URL?

Does this sound familiar at all?

@Michael

omega8cc's picture

It sounds like a problem with sessions, but I would need to check your Nginx & PHP (is it php-fpm?) configuration.

There must be something wrong there, since I never experienced something like that. Running PHP in CGI mode (I mean FastCGI) shouldn't make any difference.

I did tried many default installs on Aegir for testing how it will work with Open Atrium and Ubercart/Acquia when using Pressflow as a core etc. and never seen any problems, when running on Nginx and FastCGI based on php-fpm.

If you wish, send us your config files (I mean your nginx.conf, php-fpm.conf and php.ini files) at admin@omega8.cc and I hope to find the reason there and help you (and others maybe).

BTW. it is also possible there is something messed up in your settings.php for Drupal, so you can attach it also (without database details of course).

~Grace

-- Turnkey Drupal Hosting on Steroids -- http://omega8.cc

Thanks! I'm not the Nginx

mshaver's picture

Thanks! I'm not the Nginx expert in our group, so I'll forward on to the person who can send you the config files. There isn't any problem with another Nginx and Drupal install, but it isn't running multisite. Maybe the base URL needs to be set in settings.php?

Thanks for your help!

nginx with multiple domains and aegir

anthonysomerset's picture

hi there

i am testing aegir on a vps.net node currently with apache2, and it works brilliantly including with extra domains (not subdomains)

because i am on a vps.net node i want to reduce memory load as much as possible and nginx with php-fpm is my idea, my question is regarding setup of sites with aegir that are not subdomains, will nginx need to have vhosts reconfigured each time.

i will manage dns elsewhere (but looking forward to when aegir can manage it as well!), can nginx be configured on the fly much like apache is now by aegir?

and what happens when it comes around to needing to upgrade platforms? i am assuming at this moment in time we would have to manually edit/create nginx vhost conf files?

@anthonysomerset

omega8cc's picture

You can use wildcard/catch-all setup in Nginx/Aegir so not only you don't need to (re)configure vhosts, only create sites in Aegir and point domains to your server IP address, but you also don't need to reload/restart Nginx.

Example: http://omega8.cc/blog/53-aegir-hosting-system-on-nginx-full-configuration

We have also Nginx g.d.o: http://groups.drupal.org/nginx

~Grace

thanks

anthonysomerset's picture

thanks i was aware of this feature of nginx, my other question is how are upgrades handled? i know the best way is to setup a new platform and migrate sites to the new platform and test, but with the catch-all thats not possible anymore, i guess that you would have to migrate all sites, manually edit the config file and restart nginx for the update to work.

guess what i am looking/waiting for is for aegir to work directly with nginx's config files and restart it much in the way it works with apache currently, i guess it isnt too difficult to do, but i bet there are the UI things that have to be worked through - i guess either some form of server detection/web server type selection

looking to try and do nginx + php-fpm but had issues so far, getting annoyed at having to reset my vps each time (glad am only testing at the moment)

@anthonysomerset

omega8cc's picture

There is no need to modify Nginx catch-all config for upgrades/migrations between platforms. There is a six-line patch for provisions and it is enough to make it working without Nginx restart and without changing anything in configuration.

If you are interested, there is even free Aegir on Nginx VPS install available: http://omega8.cc/vpsnet - I think it's a good start to learn more how it works, if you are experiencing problems.

~Grace

Appreciate this is

jvc26's picture

Appreciate this is re-enlivening an old dead thread, however wondered whether you could give me some help in setting up the above (i.e. Aegir on nginx).

I have a working setup for catchall sites for nginx (which are all hosted under /mnt/sites/~host). However, I am not sure where I install the hostmaster install to?

I would assume that I want it under:

aegir.domain.com

Which would suggest running the hostmaster-install command of drush to put the files under /mnt/sites/aegir.domain.com with the appropriate user/group etc. set.

What I wondered was how do I pass such variables to hostmaster-install, and indeed, is this the correct process to install aegir into the multi-site layout you have described above?

Thanks,

J

barracuda

attiks's picture

for an easy install have a look at barracuda, see http://groups.drupal.org/node/89594. i should leave your existing setup untouched, but better be safe than sorry ;p

Aegir hosting system

Group organizers

Group categories

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: