Wednesday, January 21, 2015

Adding Apache Behind Nginx

I saw this article by Karl Blessing (kbezzie.com) about letting Nginx do what it's good at, but passing back to Apache everything PHP, mod_rewrite, and htaccess, since that's something it's good at. I ran across this article when I was trying to configure Nginx to run a PHP interpreter and perform mod_rewrite-like tasks for a content management system, not WordPress. The concept makes sense to me.

  1. Install both Nginx and Apache
  2. Go to /etc/apache2/sites-available/000_default.conf and open in Nano.
  3. Change default file to point to port 8000, or some other port than 80.
  4. Go to /etc/nginx/sites-available/default and open in Nano.
  5. Change the server block
server {
        listen 80 default_server;
        listen [::]:80 default_server ipv6only=on;

        root /var/www;
        index index.html index.php index.htm;

        # Make site accessible from http://localhost/
        server_name localhost;

        location / {
                try_files $uri $uri/ @backend;
        }

        location ~ \.php {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forward-For $remote_addr;
                proxy_set_header Host $host;
                proxy_pass http://127.0.0.1:8080;
        }

        location @backend {
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forward-For $remote_addr;
                proxy_set_header Host $host;
                proxy_pass http://127.0.0.1:8080;
        }

   }

A Server Block defines a server_name and listen directives to bind to TCP sockets. In this case, the server_name is localhost. The listen directive is told to bind to port 80.

The root is the root of your web server. Both Nginx and Apache will share the web server root /var/www. This is important. I tried getting both Nginx and Apache to serve files from Nginx's default root, /usr/share/nginx/html, but that did not work. I'm not entirely sure it wasn't just a typo that made me fall back to /var/www, but when I did, the system started working. It may have been a permissions issue too.

The Location directive reads the requests coming from a browser, just the URI portion of the request--everything before the ?. The first one directs requests to use URI to find a file or a directory; otherwise, go to the proxy @backend. The location directive @backend, sends the requests via proxy_pass to localhost (127.0.0.1 port 8080), which is the Apache server. The location directive above @backend is case sensitive and uses a Regular Expression to filter the URI request string. Only those requests ending in .php are sent via proxy_pass to the Apache server.

proxy_set_header let's you to redefine or append the header that is passed to the proxy server. $remote_addr is $_SERVER['remote_addr'], a server variable containing the client address.

X-Forwarded-For is usually used by proxies to carry original Client IP through intermediary hops. I guess the same could be said for X-Real-IP. It's just used by proxies to carry original Client IP.



~ case-sensitive matching
~* case-insensitive matching


Friday, January 2, 2015

Setting Up Multiple Domains on Nginx

I moved two domains off my shared hosting server to my Digital Ocean account.

It's a three-step process:

  • Point the domains to new name servers
  • Add domains to DNS
  • Writing Nginx configuation files

Use the domain registrar's control panel to change the domain name server addresses. I pointed both domains to the Digital Ocean name servers.

Before creating new configuration files for Nginx, create directories and index.html files for each of the domains. The server needs something to serve and Nginx needs a path to the root of each server defined in a server block.

On Digital Ocean, there's a control panel for my Droplet that let's me associate a domain name with a server IP address. I add both of my domain names and point them at the IP address for my Droplet.

This is a server block:

server {
        listen 80 default_server;
        listen [::]:80 default_server;

        root /usr/share/nginx/html/myDomainName.com/public_html/;
        index index.html index.htm;

        server_name myDomainName.com www.myDomainName.com;

        location / {
                # First attempt to serve request as file, then
                # as directory, then fall back to displaying a 404.
                try_files $uri $uri/ =404;
        }
}

The first two lines tell Nginx which port to listen for request. The first is for IPv4 and the second is for IPv6.

Next, tell Nginx where to find the root of the web server. The path that follows points to the index.html file. the next line, index index.html index.htm, tells Nginx what file name to look for.

server_name is a parameter that accompanies a server request. Only if the server name matches myDomainName.com or www.myDomainName.com, Nginx looks in the root for an index.html file and returns it.

The location block inside the server block contains a try_files directive. This tells Nginx how to handle the situation if there's no index.html file at the root location. In this case, it tells Nginx to return a 404 error.

Notice that default_server is red and in bold. It's trying to say that only one server block can have the string default_server in the listen statement. I could configure twenty domains on my DO Droplet, but only one can have default_server in the listen statement.


Sources:
Nginx Documentation - Server Names
Multiple Nginx Server Blocks
Set up a Host Name on Digital Ocean Droplet