Continuing with our migration to Nginx (see previous posts here and here), the next set of servers to move were a load balanced group of PHP servers. Each server consists of an http server on port 80, an https server on port 443 and an upstream PHP server on port 8000.
- 1 to n upstream PHP servers can be configured, either local or remote
- configuration supports both http (80) and https (443)
- SSL is terminated before being passed to the upstream server
- PHP upstream server uses PHP5-FPM via a local socket
- static files are served directly via Nginx and are set to max expires
There are also some future optimizations I’m currently looking at:
- enable the proxy cache (http://people.adams.edu/~cdmiller/posts/nginx-reverse-proxy-cache/)
- serve static files directly from the proxy server, rather than via the upstream server
# round robin load balance pool | |
# servers can be local or remote | |
upstream lbpool { | |
ip_hash; | |
server 10.10.10.1:8000 max_fails=3 fail_timeout=120; | |
server 10.10.10.2:8000 max_fails=3 fail_timeout=120; | |
# additional servers | |
} | |
# http server | |
server { | |
listen 80; | |
server_name example.com; | |
access_log /var/log/nginx/example.com.80.access.log main; | |
error_log /var/log/nginx/example.com.80.error.log; | |
# proxy requests to the pool | |
# ensure ips are passed correctly | |
location / { | |
proxy_pass http://lbpool; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $remote_addr; | |
port_in_redirect off; | |
} | |
} | |
# https server | |
# terminates SSL before passing the request to the proxy | |
server { | |
listen 443 ssl; | |
server_name example.com; | |
access_log /var/log/nginx/example.com.443.access.log main; | |
error_log /var/log/nginx/example.com.443.error.log; | |
ssl_certificate /etc/nginx/ssl/example.com.crt; # or .pem | |
ssl_certificate_key /etc/nginx/ssl/example.com.key; | |
ssl_session_cache shared:SSL:1m; | |
ssl_session_timeout 5m; | |
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ | |
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS; | |
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; | |
ssl_prefer_server_ciphers on; | |
# proxy requests to the pool | |
# ensure ips are passed correctly | |
location / { | |
proxy_pass http://lbpool; | |
proxy_set_header Host $host; | |
proxy_set_header X-Real-IP $remote_addr; | |
proxy_set_header X-Forwarded-For $remote_addr; | |
port_in_redirect off; | |
} | |
} | |
# upstream php server | |
server { | |
listen 8000; | |
server_name example.com; | |
root /home/webapps/example.com; | |
access_log /var/log/nginx/example.com.8000.access.log main; | |
error_log /var/log/nginx/example.com.8000.error.log; | |
location / { | |
index index.php; | |
# pass php requests to the front controller (http://wiki.nginx.org/Pitfalls#Front_Controller_Pattern_based_packages) | |
# but don't proxy everything (http://wiki.nginx.org/Pitfalls#Proxy_Everything) | |
try_files $uri $uri/ /index.php; | |
} | |
location ~ \.php$ { | |
try_files $uri =404; | |
fastcgi_pass unix:/var/run/php5-fpm.sock; | |
fastcgi_index index.php; | |
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; | |
include fastcgi_params; | |
} | |
# deny access to .htaccess files, | |
# git & svn repositories, etc | |
location ~ /\.(?:ht|git|svn) { | |
deny all; | |
} | |
# redirect server error pages to the static page /50x.html | |
error_page 500 502 503 504 /50x.html; | |
location = /50x.html { | |
root /usr/share/nginx/html; | |
} | |
# caching | |
location ~* \.(pdf|css|js|png|gif|jpg|jpeg|ico|swf|mov|doc|pdf|xls|ppt|docx|pptx|xlsx)$ { | |
expires max; | |
log_not_found off; | |
access_log off; | |
} | |
} |