Introduction

How to configure nginx as a front end to apache and why it is needed – it has been written repeatedly, including on Habré. My case is a little different from the classic one. It all started as usual, a project on apache, an increase in the number of visitors and, associated with it, insufficient server resources. But the project used SSL to protect the exchange of data with clients. What I encountered and how I solved the problems I will tell under the cut.

Problems

Since the direct reception of client requests has passed on to nginx, then work with SSL should be transferred to it. Apache, which now hung but loopback 127.0.0.1:8080, did not need SSL support. The first problem was that the certificate was from Thawte, and they required the use of an intermediate certificate. Nginx to work with such certificates has no special directive. In apache config it was like this:

<VirtualHost 1.2.3.4:443>
  ...
  SSLEngine on

  SSLCertificateFile /usr/local/ssl/www.xyz.com/public.crt
  SSLCertificateKeyFile /usr/local/ssl/www.xyz.com/private.key
  SSLCACertificateFile /usr/local/ssl/www.xyz.com/intermediate.crt
  ...
</VirtualHost>

How to deal with SSLCACertificateFile in nginx? It turned out that you just need to “splice” two files by putting their contents into one (public certificate, followed by an intermediate one):

cd /usr/local/ssl/www.xyz.com
cp public.crt public_concat.crt
cat intermediate.crt >> public_concat.crt

Everything, now in nginx we just write:

    server {
        listen                  1.2.3.4:443;
        server_name             www.xyz.com;

        ssl                     on;
        ssl_certificate         /usr/local/ssl/www.xyz.com/public_concat.crt;
        ssl_certificate_key     /usr/local/ssl/www.xyz.com
/private.key;
        ...
    }

A redirect from an unprotected site to a protected one did not cause any difficulties in setting up:

    server {
        listen          1.2.3.4:80;
        server_name     www.xyz.com xyz.com;
        # rewrite ^(.*) https://www.xyz.comu$1 permanent;
        return 301 https://www.xyz.com$request_uri;
    }

Difficulties started with ajax. Asynchronous requests to the server were performed with the http: // prefix, which caused the ajax-destructive redirect 301. There was a need to transfer environment variables, in particular the protocol name, from nginx to apache, it was done this way: 
to nginx:

    server {
        ...
        location / {
            ...
            proxy_set_header            X-Forwarded-Proto $scheme;
            ...
        }
        ...
    }

The most important thing in apache is to specify in the definition of a virtual host:

<VirtualHost 127.0.0.1:8080>
  ServerName www.xyz.com
  ...
  SetEnvIf X-Forwarded-Proto https HTTPS=on
  ...
</VirtualHost>

Now all ajax requests go to https: // as required. For this trick, the apache setenvif_module module must be installed and enabled in the config file:

LoadModule setenvif_module libexec/apache22/mod_setenvif.so

It is also worth bearing in mind that some applications may themselves determine their path based on environment variables. For example, phpMyAdmin, which is needed by resource developers, if it doesn’t have the full path specified in the config, it will form it with the port specified. So I got something like this:

https://www.xyz.com:80/myadmin

This is the most: 80 badly spoiled everything, phpMyAdmin did not open with swearing that the SSL security error. It was cured, as stated above, by direct indication of the path in the phpMyAdmin config:

$cfg['PmaAbsoluteUri'] = 'https://www.xyz.com/myadmin';

Do not forget to transfer the real IP addresses of visitors to apache to save the existing logging scheme. This is painted repeatedly, dig in the direction of the apache rpaf_module module. 

PS: Everything was done under FreeBSD 8.2, Apache 2.2.22_5, nginx-1.0.14,1. I did not post the full texts of the configs so as not to inflate the note. For the same reason, I focused on the transfer of real IP clients and the rpaf_module module. If necessary – lay out.