23
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 1/23 @chrismeller awesome coder. unashamed php lover. dot net developer. mac user. nginx enthusiast. open data addict. frequent foia filer. @habari cabal member. system admin. nerd. Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) There have been several fellow members of the Habari community that have decided to switch to Nginx lately. Knowing that I run Nginx exclusively (and set up and maintain the instance that hosts the Habari website itself), they’ve asked questions from time to time. Unfortunately, it turns out some of the guides floating around (even some written and publicized by major hosting companies) are helping users configure things sub-optimally and in some cases outright wrong. The standard set of config adjustments I use have been assembled from dozens of places and lots of time, reading, and experimentation. So I’m going to try and take you through setting everything up, from scratch, the right way. I’ve used these same basic steps to install PHP-FPM and Nginx on a variety of versions of Ubuntu. The packages and default configs should remain very similar, regardless of your exact version (or even if you’re using Debian). Before you install anything new on your box you should always make sure you’ve updated the list of available packages and upgraded any that have updates available: sudo aptitude update sudo aptitude safe‐upgrade Supposedly about config, debian, guide, nginx, optimization, php, php-fpm, sysadmin, and ubuntu.

Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

Embed Size (px)

DESCRIPTION

Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) by Chris Meller

Citation preview

Page 1: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 1/23

@chrismellerawesome coder. unashamed php lover. dot net developer. mac user. nginx enthusiast. open dataaddict. frequent foia filer. @habari cabal member. system admin. nerd.

Configuring and Optimizing PHP-FPM andNginx on Ubuntu (or Debian!)

There have been several fellow members of the Habari community that have decided to switch toNginx lately. Knowing that I run Nginx exclusively (and set up and maintain the instance that hosts theHabari website itself), they’ve asked questions from time to time.

Unfortunately, it turns out some of the guides floating around (even some written and publicized bymajor hosting companies) are helping users configure things sub-optimally and in some casesoutright wrong. The standard set of config adjustments I use have been assembled from dozens ofplaces and lots of time, reading, and experimentation. So I’m going to try and take you throughsetting everything up, from scratch, the right way.

I’ve used these same basic steps to install PHP-FPM and Nginx on a variety of versions of Ubuntu. Thepackages and default configs should remain very similar, regardless of your exact version (or even ifyou’re using Debian).

Before you install anything new on your box you should always make sure you’ve updated the list ofavailable packages and upgraded any that have updates available:

sudo aptitude updatesudo aptitude safe‐upgrade

Supposedly about config, debian, guide, nginx, optimization, php, php-fpm, sysadmin, and ubuntu.

Page 2: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 2/23

PHP-FPMInstalling

Getting PHP installed is the first step. This is ridiculously simple, you’ll just need to install the php5‐

fpm package:

sudo aptitude install php5‐fpm

You’ll also want to install whichever other PHP packages you need for your specific setup. In mystandard production setups, I usually add php5‐cli php5‐curl php5‐mcrypt php5‐mysqlnd php5‐sqlite .

Accept any dependencies aptitude wants to install. Once it’s done churning, it’s time to configureyour PHP-FPM pool to handle requests.

Configuring Your Pool

This is the only place where we have to do a little math, and perform some guesswork. You see, youhave to tell PHP-FPM how many separate processes it should be allowed to spawn at any one time. Ifyou’ve ever configured Apache this will be very familiar (and possibly miserable).

If you set everything too low, you’ll have spare memory sitting on your system not being used andduring a spike in traffic clients could end up queueing up endlessly, waiting for their turn for PHP toprocess their request.

Of course if you set everything too high, you’ll run out of memory during a spike in traffic becausePHP-FPM is trying to process too many requests simultaneously and your box will jump over the cliffand kill itself.

How do you get the right mix, then? Well, that’s going to take more than a single config session tofigure out. Once you’re done and your box is serving normal levels of traffic you’ll have to keep an eyeon the amount of free memory you have available and how many processes php-fpm usually hashanging around and make adjustments. In the meantime, we’ll just go with some pretty safe (low)defaults, since it’s vastly better to have some free resources available than the alternative.

From simple observation, I’ve seen that my php-fpm processes tend to start off small and slowly growinto the 20-25mb range as they serve requests. On my system (with about 512mb of RAM), that means

Page 3: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 3/23

after everything else is running I can easily allow up to 5 php-fpm processes. We’ll go with thatfor now…

The main PHP-FPM configuration file is /etc/php5/fpm/php‐fpm.conf . For reference here is a copy of

the default version I’ve got. We won’t be changing anything in here, but note the last line. Any configfiles in the pool.d directory are included — that’s where we’ll stick all of our goodies.

By default there is also a pool pre-configured for you in pool.d/www.conf (again, here is a copy of the

default version I have). As much as I hate editing default files that could change in future versions ofthe packages they belong to, there’s really no way to avoid it here.

Choose Your Own Adventure

For some peculiar personal reason I like breaking things up into their own files, so I have severaldifferent ones in pool.d . We have to edit the default www.conf anyway, so feel free to make the

changes directly if you like. The only hard advantage I can see in having separate files is that if thedefault should be replaced by a future package update, you’ll throw errors because configurationvalues are duplicated across the files. Think of it as a rather harsh safety net of sorts…

All of the pool.d config files I use can be found in this single Gist, if you want a single page to

reference back against. We’ll be going through them individually, too.

First, let’s edit www.conf and simply comment out (add a ; at the beginning of the line) anything we’re

going to override:

Line 33: listen = 127.0.0.1:9000

Line 91: pm.max_children = 10

Line 96: pm.start_servers = 4

Line 101: pm.min_spare_servers = 2

Line 106: pm.max_spare_servers = 6

Now down to the nitty-gritty individual files.

You can have any number of “pools” you like. They will each maintain their own set of processes andlive in their own little sandbox. For most setups there’s no reason to have more than one (especially ifyou are the only one hosting sites on the server), so we’ll configure a single global pool called “www” — just like the default.

Page 4: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 4/23

view raw

Config files are simply INI files, so anywhere you see “[www]”, that means we’re defining any of thesettings that follow as belonging to the “www” pool.

ping.confIf you ever need to simply make sure that php-fpm is alive and handling requests, there is a special“ping” URL you can visit that will simply return “pong”. This defines what path php-fpm will look forping requests on, we’ll actually make it work (and limit it to any particular vhosts we like) later whenwe configure Nginx.

1

2

gistfile1.ini hosted with by GitHub

processes.confHere’s where we define exactly how many processes php-fpm is allowed to spawn. I’ve addedcomments above each line explaining what they do.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

[www]

ping.path = /ping

[www]

; at any time, there can be no more than 5 child processes

; if you know how much memory each process consumes regularly

; and how much free memory you have on your system, this is how

; you set a "hard limit" on the amount of memory php‐fpm will be able to consume

pm.max_children = 5

; when php‐fpm first starts, how many processes should

; it immediately generate to handle requests?

; when you restart php‐fpm, there may be an influx of requests.

; spawning a new process can take time (albeit very small), so we want

; to go ahead and have this many ready to go

pm.start_servers = 2

; if there are no requests currently, how many spare

; processes should we always make sure to keep around?

; again, there is a delay in spawning new processes,

; so having a few always ready to go is a good idea.

; the offset is that they will be taking up memory that your system

; might otherwise be able to use for other things

pm.min_spare_servers = 1

; the inverse of the former. if there's nothing going on,

; how many spare processes are we allowed to keep around?

; again, fewer means more memory on the system for other things,

Page 5: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 5/23

view raw

view raw

view raw

26

27

gistfile1.ini hosted with by GitHub

socket.confBy default php-fpm listens on a TCP port, just like your web server. This works great if you’ve got acluster of web servers handing requests back to separate servers which handle PHP requests, but ona single server there’s not much point and a Unix socket can be (minorly) faster.

1

2

gistfile1.ini hosted with by GitHub

status.confTo go along with our ping.conf endpoint, we’ll also enable one for some detailed statistics. This

might not be of much use to you unless you’ve got some external script scraping it for monitoring orperformance graphing, but it will tell you when php-fpm was last started, how many requests it hasserved, the current number of processes, clients in the queue, etc.

1

2

gistfile1.ini hosted with by GitHub

And that’s it. Restart PHP-FPM ( sudo /etc/init.d/php5‐fpm restart ) and everything should be good

to go.

Now it’s time to get Nginx installed and configured to actually process PHP requests!

NginxInstalling

The version of Nginx that comes with Ubuntu can be incredibly outdated. In the past I have alwaysused the Nginx PPA repository to get more recent versions, but this appears not to be as supported asit was in the past. Fortunately the Nginx team has an official repo you can add easily.

These instructions start on the Nginx wiki, but can use some more user-friendly details.

; but more means less of a delay if an influx of requests comes in

pm.max_spare_servers = 3

[www]

listen = /var/run/php5‐fpm.socket

[www]

pm.status_path = /status

Page 6: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 6/23

First off, Nginx signs their packages with their own PGP key. Before apt will allow this unknown key,

you need to import it: wget ‐O ‐ http://nginx.org/keys/nginx_signing.key | sudo apt‐key add ‐

Then you need to figure out which release codename you are using so you get the right version ofNginx for your system. This varies between distros, so…

Ubuntu

In Ubuntu run cat /etc/lsb‐release . Look for the DISTRIB_CODENAME value.

Debian

In Debian run cat /etc/os‐release . Look for the VERSION value and your “codename” is in

parenthesis after the numeric version.

Now we can finally add the new sources to apt: sudo vim /etc/apt/sources.list.d/nginx‐stable.list

The lines you add vary depending on whether you are using Debian or Ubuntu.

Ubuntu

For Ubuntu boxes, add the following two lines, substituting your codename where it says “precise”:

deb http://nginx.org/packages/ubuntu precise nginxdeb‐src http://nginx.org/packages/ubuntu precise nginx

Debian

If you’re running Debian, you’ll need these two lines instead, of course substituting your appropriatecodename for “squeeze”:

deb http://nginx.org/packages/debian/ squeeze nginxdeb‐src http://nginx.org/packages/debian/ squeeze nginx

If you had previously installed an old version of Nginx (such as your distro’s native version) you canget rid of it quickly using the command sudo aptitude purge nginx nginx‐light nginx‐full nginx‐

extras nginx‐common . Note that we’re using purge , which also makes sure all the related config files

Page 7: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 7/23

view raw

are gone, just in case.

Now we’re good to go. Note that in the official release package there is only one version, you don’thave an option between nginx-full or nginx-light. Just update your list of packages to pull in the newrepos and you’re good to go:

sudo aptitude updatesudo aptitude install nginx

Base Configuration

Nginx’s default config is much less annoying than PHP-FPM’s — there’s not a single thing we need tochange. Because new versions of Nginx may come with new default configurations, you shouldn’tedit the default /etc/nginx/nginx.conf file.

Instead, you can stick all of your custom modifications in the /etc/nginx/conf.d directory, much like

we did with the pool.d directory when we were configuring PHP.

Again I split everything out into its own distinct configuration file, just so it’s easier to keep track ofthings and find the bits you’re looking for if you need to change something down the line.

PHP-FPM

The entire goal of this process is to get PHP working with Nginx, right? Well, here we go…

1

2

3

4

5

6

gistfile1.nginxconf hosted with by GitHub

This makes sure that index.php is included first in the list of files we’ll consider a directory index.

More importantly, it sets up a named “upstream” server that we’ll use to hand all requests for PHPfiles to.

Using the named upstream is very important. You’ll have a bunch of vhosts setup, each of which have

upstream php

server unix:/var/run/php5‐fpm.socket;

# make sure index.php is first in all our vhosts

index index.php index.html index.htm;

Page 8: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 8/23

view raw

to include a location block telling Nginx to hand any requests for PHP files off to PHP-FPM forprocessing. If you should change your PHP-FPM config (for example, you need to expand and decideto put it on its own server) having the single named upstream server means you only have to updatethis in one place, rather than in each separate vhost.

Other Tweaks

Now that we’ve got PHP working, there are still a bunch of other knobs we should turn and settingswe should tweak. Let’s run through a bunch of those quickly.

charset.confBy default, Nginx does not alter the character encoding of anything it serves. Since we shoulddefinitely be serving everything we possibly can as UTF-8 these days and files tend to come from lotsof different places, the first thing we want to do is make sure any other screwy character setsare converted.

The charset directive will not only cause Nginx to re-encode anything that is not in the definedcharacter set, it will also add it to the Content‐Type HTTP header so browsers know.

1

gistfile1.nginxconf hosted with by GitHub

expires.confBy default Nginx does not modify any of the headers sent with your content. For static resources,though, one of the first optimizations you should make for any site is to set a far-futureExpires header.

The expires directive will do just that for you.

Most people will try to limit (based on file extension) which files the Expires header gets set on.Personally I’ve never liked this approach - you’re pretty much guaranteed to miss something. A badanalogy would be whitelisting (rather than blacklisting) email providers to avoid SPAM.

So I set the Expires header on… everything. Anything that should not be cached for a long period oftime should set its own headers to prevent that. PHP does this on any page in which a session existsautomatically (in other words, most pages where you have to log in and content would be dynamic),so most people probably don’t need to worry much.

charset utf‐8;

Page 9: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 9/23

view raw

You can, of course, look up any variety of examples on how to use regex in a location block to limitbased on file extension.

1

gistfile1.ini hosted with by GitHub

gzip.confThe Nginx Gzip module compresses content before transmission to save on bandwidth. On flakeymobile connections this can be especially important.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

expires max;

# most people include something like this. don't.

# check your default nginx.conf, it's already covered in a much better way.

#gzip_disable "MSIE [1‐6]\.(?!.*SV1)";

# compress proxied requests too.

# it doesn't actually matter if the request is proxied, we still want it compressed.

gzip_proxied any;

# a pretty comprehensive list of content mime types that we want to compress

# there's a lot of repetition here because different applications might use different

# (and possibly non‐standard) types. we don't really care, we still want them included

# don't include text/html ‐‐ it is always included anyway

gzip_types

text/css

text/plain

text/javascript

application/javascript

application/json

application/x‐javascript

application/xml

application/xml+rss

application/xhtml+xml

application/x‐font‐ttf

application/x‐font‐opentype

application/vnd.ms‐fontobject

image/svg+xml

image/x‐icon

application/rss+xml

application/atom_xml;

# increase the compression level, at the expense of additional CPU

# cpu cycles are cheap virtually everywhere now, bandwidth not nearly as much

gzip_comp_level 9;

Page 10: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 10/23

view raw

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

gistfile1.nginxconf hosted with by GitHub

ssl.confIf you’re going to use SSL, this is a very important one. The default SSL config for Nginx has a numberof potential weaknesses.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

# the default is to gzip only HTTP 1.1 requests

# we want to gzip http 1.0 requests, too, so lower the level required

gzip_http_version 1.0;

# set the Vary: Accept‐Encoding header to force proxies to store compressed and uncompressed versions

# per the nginx docs, a bug in IE 4 ‐ 6 will cause them to not cache anything with this on

# most people aren't going to care about ie 6 anymore, but keep that in mind

gzip_vary on;

# increase the size of the buffers which hold responses to make sure larger content can be compressed too

# this means there are 16 buffers and they can each hold 8k

# if you serve a lot of ridiculously large text (like combined CSS) you might consider upping this slightly

gzip_buffers 16 8k;

# up the minimum length a little to account for gzip overhead

# this means anything smaller than 50 bytes won't be compressed.

# the default is 20 bytes, which is sooo tiny it's a waste to compress

gzip_min_length 50;

# we want to enable ssl session resumption to avoid

# having to start the handshake from scratch each page load

# so first we enable a shared cache, named SSL (creative!) that is 10mb large

ssl_session_cache shared:SSL:10m;

# save things in the cache for 3 minutes

# if you're not making a request at least every 3 minutes, this isn't going

# to accomplish anything anyway

ssl_session_timeout 3m;

# now we're going to change a bunch related to SSL ciphers and protocol

# the primary goal here is to be more secure, and i've generally tried to

# go with things that comply with the Federal Information Processing Standard (FIPS)

# set by the US government for non‐military government use

# we don't want to support SSLv3, it's known to be insecure

# FIPS 140‐2 compliance, TLS1+ only

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

Page 11: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 11/23

view raw

view raw

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

gistfile1.nginxconf hosted with by GitHub

uploads.confMost people have probably had to adjust a couple of INI values for PHP to allow larger file uploads.Well, now you’ve got one more thing to adjust. The default Nginx client_max_body_size is 1mb.That’s too small for most everything these days, so I go ahead and up it to a more reasonable (yet stillmemory-conscious) limit.

Yes, this means that if someone tries to attack your site by constantly uploading multiplesimultaneous large files, your system could run out of memory. Let’s be realistic: there are probablydozens of better ways someone who’s set on being malicious could interfere with the normaloperation of your site.

1

gistfile1.nginxconf hosted with by GitHub

Vhost Config

# now we go through a couple different options for the SSL ciphers to support, mainly just to

# give you a bunch of options to pick from

# this is a very concise definition of ciphers that don't allow anonymous DH or MD5 ‐ the big weaknesses

# per: https://calomel.org/nginx.html

#ssl_ciphers HIGH:!ADH!MD5:@STRENGTH;

# this is a very (not so) short list of very secure ciphers that may be incompatible with older browsers

# per: https://calomel.org/nginx.html

#ssl_ciphers ECDHE‐RSA‐AES256‐GCM‐SHA384:ECDHE‐RSA‐AES256‐SHA384:ECDHE‐RSA‐AES256‐SHA:AES256‐GCM‐SHA384:AES256‐SHA256:AES256‐SHA:AES128‐SHA;

# this excludes insecure ciphers and sorts the others by strength

# it is BEAST‐resistant, prioritizing RC4

# per: http://groups.drupal.org/node/179344

#ssl_ciphers !aNULL:!LOW:!MD5:!EXP:RC4:CAMELLIA:AES128:3DES:SEED:AES256@STRENGTH;

# this is a combination of everything above and openssl docs ‐ very secure, FIPS‐compliant, ordered by strength

ssl_ciphers !aNULL:!eNULL:FIPS@STRENGTH;

# don't let the client decide what ciphers to use, we've told the server which to allow

ssl_prefer_server_ciphers on;

client_max_body_size 32m;

Page 12: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 12/23

Now that we’ve got all that stupid stuff out of the way, it’s time to get a vhost configured so you canactually start seeing your new site in action!

All vhosts go in /etc/nginx/sites‐available . It doesn’t technically matter what you name them, but

you should keep a rigid standard. I name all of mine exactly what they are, like blog.chrismeller.com .

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

server

# we want to listen on port 80 on all IPs on our system ‐ both IPv4 and IPv6

listen [::]:80;

# our primary server name is the first, aliases simply come after it. you can also include wildcards like *.example.com

server_name blog.chrismeller.com new.chrismeller.com;

# where are our site files stored?

root /media/www/public_html/blog.chrismeller.com/public;

# define our access and error logs for this vhost

access_log /media/www/public_html/blog.chrismeller.com/logs/access.log;

error_log /media/www/public_html/blog.chrismeller.com/logs/error.log;

# very important, php won't work without this ‐ it sets a bunch of the server

# values that it expects

include fastcgi_params;

# we are very simple ‐ any requests that don't match one of the later location blocks we

# define will be matched by this one

location /

# for habari, i want to redirect any requests for the admin or login pages

# to the ssl versions, to protect any potential sensitive input

rewrite ^/(admin|auth)(.*) https://$host$request_uri?;

# the magic. this is the equivalent of all those lines you use for mod_rewrite in Apache

# if the request is for "/foo", we'll first try it as a file. then as a directory. and finally

# we'll assume its some sort of "clean" url and hand it to index.php so our CMS can work with it

try_files $uri $uri/ /index.php$is_args$args;

# $is_args will be '?' if there is a GET string, or '' if there isn't

# $args is obviously then the GET string, or '' if there isn't one

# remember that PHP‐FPM status URL we setup? we want to support it for this

# vhost. so if the request is for /status, hand that back to

# PHP using our named upstream server

location /status

Page 13: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 13/23

view raw

39

40

41

42

43

44

45

46

47

48

49

50

51

52

gistfile1.nginxconf hosted with by GitHub

What about an SSL vhost? Well, it’s very similar, so I’ll only point out the differences.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

fastcgi_pass php;

# this is identical, but for the ping URL we setup

location /ping

fastcgi_pass php;

# and finally, the magic that makes PHP work. if the file being requested ends in ".php"

# it's something that PHP‐FPM should process, so hand it to our named upstream server

location ~ \.php$

fastcgi_pass php;

server

# the same as for non‐ssl, except we indicate that when listening on port

# 443, it should use ssl

listen [::]:443 ssl;

server_name blog.chrismeller.com new.chrismeller.com;

# specify the certificate (chain) and key file to be used for this vhost

ssl_certificate ssl/chrismeller.com.2012.pem;

ssl_certificate_key ssl/chrismeller.com.2012.key;

# i use a different directory as a mater of practice, and just

# create a symlink to the normal non‐ssl "public" directory when they are the same

root /media/www/public_html/blog.chrismeller.com/ssl;

# note the different logs for ssl and non‐ssl. no real reason, it's just convenient for me

access_log /media/www/public_html/blog.chrismeller.com/logs/ssl.access.log;

error_log /media/www/public_html/blog.chrismeller.com/logs/ssl.error.log;

include fastcgi_params;

location /

# the only other difference is that i'm not redirecting admin

# and login pages ‐ we're already on ssl

try_files $uri $uri/ /index.php$is_args$args;

Page 14: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 14/23

view raw

26

27

28

29

30

31

32

33

34

35

36

37

38

gistfile1.nginxconf hosted with by GitHub

And for the record, I name them very similarly to the non-SSL vhosts, but keep them in separate filesso they can be enabled and disabled individually and I can tell at a directory glance which onessupport SSL: blog.chrismeller.com‐ssl .

40 Comments Chris Meller Login1

Share⤤ Sort by Best

Join the discussion…

• Reply •

phillip • 2 years ago

Having an explanation for just about every single line made this post super­valuable to me.Thank you for this.

10

• Reply •

Jose Vega • a year ago> phillip

Me too. I´m setting up my vps and this post is gold.

miklb • 2 years ago

Just an fyi, seems someone on the php­fpm package must have read this post, as thedefaults for www.conf max_children, start servers, and min/max spare servers are thesame as your tutorial. It also defaults to listen = /var/run/php5­fpm.socket

Recommend 5

Share ›

Share ›

location /status

fastcgi_pass php;

location /ping

fastcgi_pass php;

location ~ \.php$

fastcgi_pass php;

Originally published 3 years ago and tweaked 9 months later.

Page 15: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 15/23

• Reply •

Thanks again for writing this up, was a handy reminder for setting up a new VPS. 2

• Reply •

miklb • 2 years ago> miklb

A couple of notes since I commented:

* I needed to add `fastcgi_param SCRIPT_FILENAME$document_root$fastcgi_script_name` to fastcgi_params. Otherwise, I was gettinga blank page on php pages with zero errors and 200 status on the access log. Tooka long time to track that one down.

* Also, it seems the listen should be /var/run/php5­fpm.sock, not socket anymore.Not sure if they are synonymous but I used it and everything is working now.

2

• Reply •

chrismeller • 2 years agoMod > miklb

Can you check what OS (and version) and version of Nginx you're usingthat you had to add SCRIPT_FILENAME? I haven't had to add that manuallyin quite a while.

The socket extension has no special meaning beyond letting you know it's asocket when you list directory contents. If the default has changed you canchange either it or your Nginx config, it's all good.

• Reply •

miklb • 2 years ago> chrismeller

My current version of Nginx is 1.4.4.1~wheezy. Php info showsystem Debian 3.2.41­2+deb7u2 i686.

• Reply •

jose heriberto perez magaña • 10 months ago> miklb

I had the same problem, I have ubuntu 14 with nginx version:nginx/1.6.2

I'm using in the socket.conf file:[www]listen = /var/run/php5­fpm.sockinstead of[www]listen = /var/run/php5­fpm.socket

and that did the job

btw thanks for this incredible tutorial

Share ›

Share ›

Share ›

Share ›

Share ›

Page 16: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 16/23

• Reply •

James Morris • 2 years ago

Thanks for a great explanation and all the comments. 1

• Reply •

PHP Guru • 2 years ago

Hey Chris, this guide was extremely helpful. I used the dotdeb repos with Debian Squeezeand now have LEMP up and running with nginx 1.4.1, php 5.4.16 php5­fpm & MySQL5.5.31. Took about an hour, and I've only worked with Apache before today. Nice work!

1

• Reply •

mrrssy • 6 months ago

thank you for this super explained documentation!

• Reply •

Thomas • 10 months ago

Hi Chris,

what do you think about the usage / configuration of deditacted sockets for eachsubdomain:

upstream php server unix:/var/run/php5­fpm­<subdomain1>.socket;

upstream php server unix:/var/run/php5­fpm­<subdomain2>.socket;

chrismeller • 10 months agoMod > Thomas

If you've got multiple FPM pools (say to protect the resources of one site fromanother) then you would logically have multiple listeners (either sockets or ports)that Nginx would need to relay traffic to. So in that case you'd definitely needmultiple upstreams.

One error I see in your example is that you've named both the upstreams "php".Remember that those need to be unique as well, so Nginx knows which upstreamyou're telling it to use.

Now the real question is... should you do this? I don't, but that's because I run avery small VPS that only hosts my own personal sites. If one of them getsclobbered it's probably going to take the entire server down anyway, so there's nopoint in adding the extra overhead to use multiple FPM pools (since each pool wouldhave its own set of processes listening and its own pm. min_spare_servers).

Share ›

Share ›

Share ›

Share ›

Page 17: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 17/23

• Reply •

I probably *would* recommend using multiple pools if you're hosting independentclient sites, though. Giving each one their own set of processes can definitely helpmake sure that they're less vulnerable to one site killing everything. Just rememberthat all that "how many processes can I run with the amount of RAM I have?" mathwill get a lot more complicated.

You would also obviously need multiple upstreams (though they'd be using ports,not sockets) if you had Nginx sitting in front of more than one backend server thatran FPM (rather than running FPM on the same box as Nginx), but that opens up awhole different can of worms we won't go into.

• Reply •

Locke • 2 years ago

this is a great how to , thanks , but I 'm getting :

[02­May­2014 18:20:11] ERROR: An another FPM instance seems to already listen on/var/run/php5­fpm.sock

[02­May­2014 18:20:11] ERROR: FPM initialization failed

do you know why this is happening????

• Reply •

chrismeller • 2 years agoMod > Locke

You've already got an instance of FPM running, then. Running `ps aux | grep ­i php`should show you. I wouldn't be able to tell you how another is running, but that'syour problem.

• Reply •

Locke • 2 years ago> chrismeller

Oh!!! , now I see, this is because I have a lot of domains in the server. lot ofsites­available that are running php­fpm maybe that is my main problem..

• Reply •

temuri • 2 years ago

Thanks for the write­up.

How do you handle redirects to SSL in your nginx config?

chrismeller • 2 years agoMod > temuri

I use a redirect to SSL in two different ways depending on the goal.

In one instance, I want all requests to end up on SSL. So forhttp://www.example.com everything should end up at https://www.example.com. In

Share ›

Share ›

Share ›

Share ›

Share ›

Page 18: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 18/23

• Reply •

http://www.example.com everything should end up at https://www.example.com. Inthat case, I simply set up a barebones vhost for the non­SSL version:https://gist.github.com/chrism...

If you're going to always redirect all requests to SSL, you should also look atincluding the Strict­Transport­Security header so modern browsers never try to hitthe plain text version anyway.

If there are only certain requests that I want to ensure are SSL­protected, like thelogin and admin pages of a CMS where passwords might be seen, you can redirectonly those requests: https://gist.github.com/chrism...

Here the vhost is otherwise the same as the example I gave in the guide, but if thepath starts with admin or auth we want to make sure those are SSL requests.

• Reply •

m4nuco • 2 years ago

Thanks Chris, Awesome article. I didn't get one thing tho where would you put the upstreamphp server thingy? In it's own file ?

• Reply •

chrismeller • 2 years agoMod > m4nuco

Short answer: I put it in conf.d/php.confLong answer: Anywhere that nginx will include it. In my examples all the config filesare in /etc/nginx/conf.d/ because those are the config files included by default. Itdoesn't actually matter what you name the file, just something that you will recognize(php seemed obvious to me).

1

• Reply •

m4nuco • 2 years ago> chrismeller

Ok thanks Chris that was helpful. Note tho i had same problem as miklb, needed to add fastcgi_paramSCRIPT_FILENAME $document_root$fastcgi_script_name in order to get itto work. ( Ubunutu 12.4, nginx 1.4.4 ). You probably should add a note aboutthat in your post

• Reply •

KJ • 2 years ago

Thanks for doing this...Cleared up a lot of questions (fears) I had before taking the leap intoself­managed VPS

cakuki • 2 years ago

As the article itself is a real masterpiece, my "just one thing" is about php­fpm poolconfiguration separation. As pool directory intended to contain more than default www pool

Share ›

Share ›

Share ›

Share ›

Share ›

Page 19: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 19/23

• Reply •

configuration separation. As pool directory intended to contain more than default www poolconfiguration.

I have changed the include value in /etc/php5/fpm/php­fpm.conf to:

include=/etc/php5/fpm/pool.d/*/*.conf

so I have my www configurations separated like pool.d/www/foo.conf.

This makes TCP and socket proxies available in different pool configurations withoutconfusion.

• Reply •

chrismeller • 2 years agoMod > cakuki

Thanks, cakuki! That's a nice logical separation, if you need both types of listeners!

• Reply •

tushar • 2 years ago

Great tutorial. After I upgraded nginx server from 1.1.19 to 1.4.4 and made the above changes, I'm nowgetting Error 503. What might be the cause?

• Reply •

chrismeller • 2 years agoMod > tushar

Blindly, off the top of my head, with 0 details? I have no clue. Like any time you'retroubleshooting, check your error log.

The main nginx log (as opposed to the vhost­specific ones you define in eachconfig) is usually /var/log/nginx/error.log, which may contain more details.

1

tushar • 2 years ago> chrismeller

2013/12/09 08:35:48 [crit] 14861#0: *7415 connect() to unix:/var/run/php5­fpm.sock failed (2: No such file or directory) while connecting to upstream,client: 127.0.0.1, server: 95.85.29.90, request: "GET / HTTP/1.1", upstream:"fastcgi://unix:/var/run/php5­fpm.sock:", host: "livingwithict.com"

2013/12/09 09:30:42 [emerg] 1927#0: bind() to 0.0.0.0:80 failed (98: Addressalready in use)2013/12/09 09:30:42 [emerg] 1927#0: bind() to 0.0.0.0:80 failed (98: Addressalready in use)2013/12/09 09:30:42 [emerg] 1927#0: bind() to 0.0.0.0:80 failed (98: Addressalready in use)2013/12/09 09:30:42 [emerg] 1927#0: bind() to 0.0.0.0:80 failed (98: Addressalready in use)

Share ›

Share ›

Share ›

Share ›

Page 20: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 20/23

• Reply •

already in use)2013/12/09 09:30:42 [emerg] 1927#0: bind() to 0.0.0.0:80 failed (98: Addressalready in use)2013/12/09 09:30:42 [emerg] 1927#0: still could not bind()

• Reply •

jose heriberto perez magaña • 10 months ago> tushar

I can confirm the error what I did to fix the error just replace thefollowing: [www]listen = /var/run/php5­fpm.socketfor[www]listen = /var/run/php5­fpm.sock

• Reply •

chrismeller • 2 years agoMod > tushar

The first error indicates that either Nginx or PHP­FPM is mis­configured. Check your Nginx php upstream to make sure the serverdirective is correct. More likely, you didn't set the listen directive inyour PHP­FPM pool configuration "socket.conf" in my guide.

The latter errors are most likely because the default vhostconfiguration includes an incompatible `listen` directive. Doublecheck all your vhosts and make sure they have the same `listen`directive.

If you can't find the problem, move into /etc/nginx and run `grep ­ri"listen" .`, which should show you every file that might include theproblem.

• Reply •

Josh • 2 years ago

I don't understand how to set the pm.max_children, pm.start_servers,pm.min_spare_servers and pm.max_spare_servers... I have an Intel(R) Core(TM) i7 CPU920 @ 2.67GHz with 8 cores and 48GB of RAM. I have set: pm.max_children = 1000,pm.start_servers = 245, pm.min_spare_servers = 45, pm.max_spare_servers = 350 (Iwant at least 1000 concurrents users). But I have some error saying me that i have toomane processes... What's wrong? Thank you very Much!

chrismeller • 2 years agoMod > Josh

Like I said, it all depends on exactly what you're running. You should start off low,run your application for a while (even if it's just you stepping through it like a normaluser for a while, possibly over a day or two), and then see how much memory each

Share ›

Share ›

Share ›

Share ›

Page 21: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 21/23

• Reply •

php­fpm process is occupying on your system (`ps aux | grep php` or similar).

After that, you need to divide out the amount of RAM you have left on your box(make sure to account for MySQL or any other background processes that you'llhave running) and figure out the number of processes you can reasonablyaccommodate.

Without the exact error, I can't help with the "too many processes" error either.

• Reply •

Daniel Searles • 2 years ago

I forgot to mention that this is a great post and that I appreciate you writing it up. Good job!

• Reply •

Daniel Searles • 2 years ago

`location ~ \.php$ ` is a security vulnerability since it allows any php file to be run includinguploaded files. See this article for a more in depth explanation:https://nealpoole.com/blog/201...

• Reply •

chrismeller • 2 years agoMod > Daniel Searles

In the example he provides, FPM actually understands that the request is forrandom.gif, even if Nginx attempts to pass the request to it based on the ending of.php.

If you check your error.log file you'll see a response from FPM along the lines of:Access to the script '/whatever/public/random.gif' has been denied (seesecurity.limit_extensions)

The security.limit_extensions pool option was added in PHP 5.3.9 and defaults toonly including the extension .php, preventing exactly this problem. Since 5.3.9 wasreleased almost two years ago (January, 2012) there's a pretty good bet most of usare fine (Ubuntu 12.04 LTS includes 5.3.10, but if you're still running 10.04 LTS youmight have an issue).

For some inexplicable reason this isn't included in the PHP documentation, but thetop comment on the page points it out: http://php.net/manual/en/insta...

Tecto • 2 years ago

About this bit:# check your default nginx.conf, it's already covered in a much better way.#gzip_disable "MSIE [1­6]\.(?!.*SV1)";

My default nginx config doesn't appear to have anything to cover this. Can you clarify?

Share ›

Share ›

Share ›

Share ›

Page 22: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 22/23

• Reply •

• Reply •

chrismeller • 2 years agoMod > Tecto

The Ubuntu and Debian defaults I've seen usually have a `gzip_disable msie` line,which is a faster version of the regex pattern most people stick in there:http://nginx.org/en/docs/http/...

If you don't have one you can simply add: gzip_disable msie; in your gzip.conf.

• Reply •

Vilhjálmur Magnússon • 2 years ago

Any ideas on how to fix the "File not found" issue when using userdir and vhosts for php?

• Reply •

Rieks Visser • 2 years ago

Very concise and well written, thank you! This helped me a lot in moving from Apache2 toNginx. I can also confirm that your guide works just as well on a Debian 7 (Wheezy) server.Two things I did encounter were:

1. Installing nginx from PPA didn't work out for me, perhaps I was a bit impatient. In the end,I went with a simple apt­get install nginx. On an updated Wheezy this ended up giving menginx/1.2.1. Not quite bleeding edge, but recent enough.

2. Rule 3 in the vhost config resulted in an 'address already in use' error. A fix was easilyfound: http://stackoverflow.com/quest.... In short: listening to port 80 for both ipv4 and ipv6in one rule conflicts with the nginx default config.

chrismeller • 2 years agoMod > Rieks Visser

I've actually just recently stopped using the PPA. It looks like it's not being updatedas regularly as it used to be... But the official Nginx Debian / Ubuntu repositoryworks fine. I'll update that soon.

As for the default config, you're probably correct. I may have accidentally skippedover removing that bit from the default config. That's what happens when you'rewriting a guide after the fact! I'm in the process of migrating some sites to a new boxnow (it's there, I just have to get around to configuring it!), so I'll be sure to giveeverything another run­through as I do and make any needed updates.

Thanks very much for the feedback!

Share ›

Share ›

Share ›

Share ›

L A S T P O S T G E T Y O U R G I T H U B I S S U E S A S A N R S S F E E D

N E X T P O S T C R E A T I N G A N D M A N A G I N G S S L C E R T I F I C A T E S W I T H N G I N X

Page 23: Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) _ Chris Meller

11/4/2015 Configuring and Optimizing PHP­FPM and Nginx on Ubuntu (or Debian!) | Chris Meller

http://blog.chrismeller.com/configuring­and­optimizing­php­fpm­and­nginx­on­ubuntu­or­debian 23/23