Koen.pt

Using Nginx as SSL proxy for name based VirtualHosts in Apache

At the company where I work we develop all kinds of Facebook applications. And for them to properly work on Facebook, they need to be available over HTTPS.

And because registering and installing a new certificate for each and every new app we create is a real pain in the ass, we registered a wildcard certificate and are hosting all the apps on subdomains.

That worked well, but we still had to request a new IP address for every app, because the lack of SNI in all versions of Internet Explorer on Windows XP.

Now it happens to be that I just recently started to use Nginx as primary HTTP software on most of the servers I maintain. And using the great proxy functionality of Nginx I managed to setup a server with Nginx as frontend and Apache as backend, where Nginx handles the SSL requests (listening on port 443) for the wildcard domain, and proxies the requests with the correct –requested– hostname to Apache (listening on port 80) so it can use SNI to determine which content to show.

Now the problem arose that links generated by frameworks running under Apache do not know they are requested over SSL, so they would still begin with http:// instead of https://, because Apache doesn't tell them to.

There mod_rpaf (reverse proxy add forward) comes into place. This module can set Apache's REMOTE_ADDR, HTTPS and HTTP_PORT –which are generally used to determine if a site is running over SSL– to the values provided by Nginx.

See my configuration below.

Nginx server block:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
server { listen 443 ssl; server_name ~^(www\.)?(?<domain>.+)$; # It's possible to configure Nginx to serve static files directly, # and bypassing Apache but I won't describe that here. root /var/apps/$domain/current/public; ssl_certificate /etc/ssl/certs/cmpgns/STAR_cmpgns_nl.crt; ssl_certificate_key /etc/ssl/private/STAR_cmpgns_nl.key; location / { # Apache is listening here proxy_pass http://127.0.0.1:80; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # Set HTTPS flag for mod_rpaf proxy_set_header X-Forwarded-HTTPS on; } }

Apache VirtualHost:

1
2
3
4
5
6
7
8
9
<VirtualHost 127.0.0.1:80> ServerName some-subdomain.cmpgns.nl DocumentRoot "/var/apps/some-subdomain.cmpgns.nl/current/public" RewriteEngine on <Directory "/var/apps/some-subdomain.cmpgns.nl/current/public"> Allow from all </Directory> </VirtualHost>

Apache RPAF configuration:

1
2
3
4
5
6
RPAF_Enable On RPAF_ProxyIPs 127.0.0.1 RPAF_Header X-Real-IP RPAF_SetHostName On RPAF_SetHTTPS On RPAF_SetPort On