You are on page 1of 23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

@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!)
Supposedly about config, debian, guide, nginx, optimization, php, php-fpm, sysadmin, and ubuntu.

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), theyve asked questions from time totime.
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 Im going to try and take you through
setting everything up, from scratch, the rightway.
Ive 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
youre usingDebian).
Before you install anything new on your box you should always make sure youve updated the list of
available packages and upgraded any that have updatesavailable:
sudoaptitudeupdate
sudoaptitudesafeupgrade

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

1/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

PHP-FPM
Installing
Getting PHP installed is the first step. This is ridiculously simple, youll just need to install the
fpm

php5

package:

sudoaptitudeinstallphp5fpm

Youll also want to install whichever other PHP packages you need for your specific setup. In my
standard production setups, I usually add php5cliphp5curlphp5mcryptphp5mysqlndphp5sqlite .
Accept any dependencies aptitude wants to install. Once its done churning, its time to configure
your PHP-FPM pool to handlerequests.

Configuring Your Pool


This is the only place where we have to do a little math, and perform some guesswork. You see, you
have to tell PHP-FPM how many separate processes it should be allowed to spawn at any one time. If
youve ever configured Apache this will be very familiar (and possiblymiserable).
If you set everything too low, youll have spare memory sitting on your system not being used and
during a spike in traffic clients could end up queueing up endlessly, waiting for their turn for PHP to
process theirrequest.
Of course if you set everything too high, youll run out of memory during a spike in traffic because
PHP-FPM is trying to process too many requests simultaneously and your box will jump over the cliff
and killitself.
How do you get the right mix, then? Well, thats going to take more than a single config session to
figure out. Once youre done and your box is serving normal levels of traffic youll have to keep an eye
on the amount of free memory you have available and how many processes php-fpm usually has
hanging around and make adjustments. In the meantime, well just go with some pretty safe (low)
defaults, since its vastly better to have some free resources available than thealternative.
From simple observation, Ive seen that my php-fpm processes tend to start off small and slowly grow
into the 20-25mb range as they serve requests. On my system (with about 512mb of RAM), that means
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

2/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

after everything else is running I can easily allow up to 5 php-fpm processes. Well go with that
fornow
The main PHP-FPM configuration file is

/etc/php5/fpm/phpfpm.conf

. For reference here is a copy of

the default version Ive got. We wont be changing anything in here, but note the last line. Any config
files in the

pool.d

directory are includedthats where well stick all of ourgoodies.

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 of
the packages they belong to, theres really no way to avoid ithere.

Choose Your Own Adventure


For some peculiar personal reason I like breaking things up into their own files, so I have several
different 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 the
default should be replaced by a future package update, youll throw errors because configuration
values are duplicated across the files. Think of it as a rather harsh safety net ofsorts
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. Well be going through them individually,too.


First, lets edit

www.conf

and simply comment out (add a ; at the beginning of the line) anything were

going tooverride:
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 individualfiles.


You can have any number of pools you like. They will each maintain their own set of processes and
live in their own little sandbox. For most setups theres no reason to have more than one (especially if
you are the only one hosting sites on the server), so well configure a single global pool called www
just like thedefault.
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

3/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

Config files are simply INI files, so anywhere you see [www], that means were defining any of the
settings that follow as belonging to the wwwpool.
ping.conf
If 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 for
ping requests on, well actually make it work (and limit it to any particular vhosts we like) later when
we configureNginx.
1

[www]

ping.path=/ping

gistfile1.inihostedwithbyGitHub

viewraw

processes.conf
Heres where we define exactly how many processes php-fpm is allowed to spawn. Ive added
comments above each line explaining what theydo.
1

[www]

;atanytime,therecanbenomorethan5childprocesses

;ifyouknowhowmuchmemoryeachprocessconsumesregularly

;andhowmuchfreememoryyouhaveonyoursystem,thisishow

;youseta"hardlimit"ontheamountofmemoryphpfpmwillbeabletoconsume

pm.max_children=5

7
8

;whenphpfpmfirststarts,howmanyprocessesshould

;itimmediatelygeneratetohandlerequests?

10

;whenyourestartphpfpm,theremaybeaninfluxofrequests.

11

;spawninganewprocesscantaketime(albeitverysmall),sowewant

12

;togoaheadandhavethismanyreadytogo

13

pm.start_servers=2

14
15

;iftherearenorequestscurrently,howmanyspare

16

;processesshouldwealwaysmakesuretokeeparound?

17

;again,thereisadelayinspawningnewprocesses,

18

;sohavingafewalwaysreadytogoisagoodidea.

19

;theoffsetisthattheywillbetakingupmemorythatyoursystem

20

;mightotherwisebeabletouseforotherthings

21

pm.min_spare_servers=1

22
23

;theinverseoftheformer.ifthere'snothinggoingon,

24

;howmanyspareprocessesareweallowedtokeeparound?

25

;again,fewermeansmorememoryonthesystemforotherthings,

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

4/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

26

;butmoremeanslessofadelayifaninfluxofrequestscomesin

27

pm.max_spare_servers=3
viewraw

gistfile1.inihostedwithbyGitHub

socket.conf
By default php-fpm listens on a TCP port, just like your web server. This works great if youve got a
cluster of web servers handing requests back to separate servers which handle PHP requests, but on
a single server theres not much point and a Unix socket can be (minorly)faster.
1

[www]

listen=/var/run/php5fpm.socket
viewraw

gistfile1.inihostedwithbyGitHub

status.conf
To go along with our

ping.conf

endpoint, well also enable one for some detailed statistics. This

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

[www]

pm.status_path=/status
viewraw

gistfile1.inihostedwithbyGitHub

And thats it. Restart PHP-FPM (

sudo/etc/init.d/php5fpmrestart

) and everything should be good

togo.
Now its time to get Nginx installed and configured to actually process PHPrequests!

Nginx
Installing
The version of Nginx that comes with Ubuntu can be incredibly outdated. In the past I have always
used the Nginx PPA repository to get more recent versions, but this appears not to be as supported as
it was in the past. Fortunately the Nginx team has an official repo you can addeasily.
These instructions start on the Nginx wiki, but can use some more user-friendlydetails.
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

5/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

First off, Nginx signs their packages with their own PGP key. Before
you need to import it:

apt

will allow this unknown key,

wgetOhttp://nginx.org/keys/nginx_signing.key|sudoaptkeyadd

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

Ubuntu
In Ubuntu run

cat/etc/lsbrelease

. Look for the

DISTRIB_CODENAME

value.

Debian
In Debian run

cat/etc/osrelease

. Look for the

VERSION

value and your codename is in

parenthesis after the numericversion.


Now we can finally add the new sources to apt:

sudovim/etc/apt/sources.list.d/nginxstable.list

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

Ubuntu
For Ubuntu boxes, add the following two lines, substituting your codename where it saysprecise:
debhttp://nginx.org/packages/ubuntuprecisenginx
debsrchttp://nginx.org/packages/ubuntuprecisenginx

Debian
If youre running Debian, youll need these two lines instead, of course substituting your appropriate
codename forsqueeze:
debhttp://nginx.org/packages/debian/squeezenginx
debsrchttp://nginx.org/packages/debian/squeezenginx

If you had previously installed an old version of Nginx (such as your distros native version) you can
get rid of it quickly using the command sudoaptitudepurgenginxnginxlightnginxfullnginx
extrasnginxcommon

. Note that were using

purge

, which also makes sure all the related config files

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

6/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

are gone, just incase.


Now were good to go. Note that in the official release package there is only one version, you dont
have an option between nginx-full or nginx-light. Just update your list of packages to pull in the new
repos and youre good togo:
sudoaptitudeupdate
sudoaptitudeinstallnginx

Base Configuration
Nginxs default config is much less annoying than PHP-FPMstheres not a single thing we need to
change. Because new versions of Nginx may come with new default configurations, you shouldnt
edit the default /etc/nginx/nginx.conf file.
Instead, you can stick all of your custom modifications in the
we did with the

pool.d

/etc/nginx/conf.d

directory, much like

directory when we were configuringPHP.

Again I split everything out into its own distinct configuration file, just so its easier to keep track of
things and find the bits youre looking for if you need to change something down theline.

PHP-FPM
The entire goal of this process is to get PHP working with Nginx, right? Well, here wego
1

upstreamphp{

serverunix:/var/run/php5fpm.socket;

4
5

#makesureindex.phpisfirstinallourvhosts

indexindex.phpindex.htmlindex.htm;

gistfile1.nginxconfhostedwithbyGitHub

This makes sure that

index.php

viewraw

is included first in the list of files well consider a directory index.

More importantly, it sets up a named upstream server that well use to hand all requests for PHP
filesto.
Using the named upstream is very important. Youll have a bunch of vhosts setup, each of which have
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

7/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

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

Other Tweaks
Now that weve got PHP working, there are still a bunch of other knobs we should turn and settings
we should tweak. Lets run through a bunch of thosequickly.
charset.conf
By default, Nginx does not alter the character encoding of anything it serves. Since we should
definitely be serving everything we possibly can as UTF-8 these days and files tend to come from lots
of different places, the first thing we want to do is make sure any other screwy character sets
areconverted.
The charset directive will not only cause Nginx to re-encode anything that is not in the defined
character set, it will also add it to the ContentType HTTP header so browsersknow.
1

charsetutf8;

gistfile1.nginxconfhostedwithbyGitHub

viewraw

expires.conf
By 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-future
Expiresheader.
The expires directive will do just that foryou.
Most people will try to limit (based on file extension) which files the Expires header gets set on.
Personally Ive never liked this approach - youre pretty much guaranteed to miss something. A bad
analogy would be whitelisting (rather than blacklisting) email providers to avoidSPAM.
So I set the Expires header on everything. Anything that should not be cached for a long period of
time should set its own headers to prevent that. PHP does this on any page in which a session exists
automatically (in other words, most pages where you have to log in and content would be dynamic),
so most people probably dont need to worrymuch.
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

8/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

You can, of course, look up any variety of examples on how to use regex in a location block to limit
based on fileextension.
expiresmax;

gistfile1.inihostedwithbyGitHub

viewraw

gzip.conf
The Nginx Gzip module compresses content before transmission to save on bandwidth. On flakey
mobile connections this can be especiallyimportant.
1

#mostpeopleincludesomethinglikethis.don't.

#checkyourdefaultnginx.conf,it'salreadycoveredinamuchbetterway.

#gzip_disable"MSIE[16]\.(?!.*SV1)";

4
5

#compressproxiedrequeststoo.

#itdoesn'tactuallymatteriftherequestisproxied,westillwantitcompressed.

gzip_proxiedany;

8
9

#aprettycomprehensivelistofcontentmimetypesthatwewanttocompress

10

#there'salotofrepetitionherebecausedifferentapplicationsmightusedifferent

11

#(andpossiblynonstandard)types.wedon'treallycare,westillwantthemincluded

12

#don'tincludetext/htmlitisalwaysincludedanyway

13

gzip_types

14

text/css

15

text/plain

16

text/javascript

17

application/javascript

18

application/json

19

application/xjavascript

20

application/xml

21

application/xml+rss

22

application/xhtml+xml

23

application/xfontttf

24

application/xfontopentype

25

application/vnd.msfontobject

26

image/svg+xml

27

image/xicon

28

application/rss+xml

29

application/atom_xml;

30
31

#increasethecompressionlevel,attheexpenseofadditionalCPU

32

#cpucyclesarecheapvirtuallyeverywherenow,bandwidthnotnearlyasmuch

33

gzip_comp_level9;

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

9/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

34
35

#thedefaultistogziponlyHTTP1.1requests

36

#wewanttogziphttp1.0requests,too,solowerthelevelrequired

37

gzip_http_version1.0;

38
39

#settheVary:AcceptEncodingheadertoforceproxiestostorecompressedanduncompressedversions

40

#perthenginxdocs,abuginIE46willcausethemtonotcacheanythingwiththison

41

#mostpeoplearen'tgoingtocareaboutie6anymore,butkeepthatinmind

42

gzip_varyon;

43
44

#increasethesizeofthebufferswhichholdresponsestomakesurelargercontentcanbecompressed

45

#thismeansthereare16buffersandtheycaneachhold8k

46

#ifyouservealotofridiculouslylargetext(likecombinedCSS)youmightconsideruppingthissl

47

gzip_buffers168k;

48
49

#uptheminimumlengthalittletoaccountforgzipoverhead

50

#thismeansanythingsmallerthan50byteswon'tbecompressed.

51

#thedefaultis20bytes,whichissoootinyit'sawastetocompress

52

gzip_min_length50;

gistfile1.nginxconfhostedwithbyGitHub

viewraw

ssl.conf
If youre going to use SSL, this is a very important one. The default SSL config for Nginx has a number
of potentialweaknesses.
1

#wewanttoenablesslsessionresumptiontoavoid

#havingtostartthehandshakefromscratcheachpageload

#sofirstweenableasharedcache,namedSSL(creative!)thatis10mblarge

ssl_session_cacheshared:SSL:10m;

5
6

#savethingsinthecachefor3minutes

#ifyou'renotmakingarequestatleastevery3minutes,thisisn'tgoing

#toaccomplishanythinganyway

ssl_session_timeout3m;

10
11

#nowwe'regoingtochangeabunchrelatedtoSSLciphersandprotocol

12

#theprimarygoalhereistobemoresecure,andi'vegenerallytriedto

13

#gowiththingsthatcomplywiththeFederalInformationProcessingStandard(FIPS)

14

#setbytheUSgovernmentfornonmilitarygovernmentuse

15
16

#wedon'twanttosupportSSLv3,it'sknowntobeinsecure

17

#FIPS1402compliance,TLS1+only

18

ssl_protocolsTLSv1TLSv1.1TLSv1.2;

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

10/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

19
20

#nowwegothroughacoupledifferentoptionsfortheSSLcipherstosupport,mainlyjustto

21

#giveyouabunchofoptionstopickfrom

22
23

#thisisaveryconcisedefinitionofciphersthatdon'tallowanonymousDHorMD5thebigweaknes

24

25

#ssl_ciphersHIGH:!ADH!MD5:@STRENGTH;

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

26
27

#thisisavery(notso)shortlistofverysecureciphersthatmaybeincompatiblewitholderbrows

28

29

#ssl_ciphersECDHERSAAES256GCMSHA384:ECDHERSAAES256SHA384:ECDHERSAAES256SHA:AES256GCMSHA3

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

30
31

#thisexcludesinsecureciphersandsortstheothersbystrength

32

#itisBEASTresistant,prioritizingRC4

33

34

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

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

35
36

#thisisacombinationofeverythingaboveandopenssldocsverysecure,FIPScompliant,orderedb

37

ssl_ciphers!aNULL:!eNULL:FIPS@STRENGTH;

38
39

#don'tlettheclientdecidewhatcipherstouse,we'vetoldtheserverwhichtoallow

40

ssl_prefer_server_cipherson;

gistfile1.nginxconfhostedwithbyGitHub

viewraw

uploads.conf
Most people have probably had to adjust a couple of INI values for PHP to allow larger file uploads.
Well, now youve got one more thing to adjust. The default Nginx client_max_body_size is 1mb.
Thats too small for most everything these days, so I go ahead and up it to a more reasonable (yet still
memory-conscious)limit.
Yes, this means that if someone tries to attack your site by constantly uploading multiple
simultaneous large files, your system could run out of memory. Lets be realistic: there are probably
dozens of better ways someone whos set on being malicious could interfere with the normal
operation of yoursite.
1

client_max_body_size32m;

gistfile1.nginxconfhostedwithbyGitHub

viewraw

Vhost Config
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

11/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

Now that weve got all that stupid stuff out of the way, its time to get a vhost configured so you can
actually start seeing your new site inaction!
All vhosts go in

/etc/nginx/sitesavailable

. It doesnt 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

server{

#wewanttolistenonport80onallIPsonoursystembothIPv4andIPv6

listen[::]:80;

#ourprimaryservernameisthefirst,aliasessimplycomeafterit.youcanalsoincludewi

server_nameblog.chrismeller.comnew.chrismeller.com;

#whereareoursitefilesstored?

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

10

#defineouraccessanderrorlogsforthisvhost

11

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

12

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

14

#veryimportant,phpwon'tworkwithoutthisitsetsabunchoftheserver

15

#valuesthatitexpects

16

includefastcgi_params;

18

#weareverysimpleanyrequeststhatdon'tmatchoneofthelaterlocationblockswe

19

#definewillbematchedbythisone

20

location/{

22

#forhabari,iwanttoredirectanyrequestsfortheadminorloginpages

23

#tothesslversions,toprotectanypotentialsensitiveinput

24

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

26

#themagic.thisistheequivalentofallthoselinesyouuseformod_rewriteinApa

27

#iftherequestisfor"/foo",we'llfirsttryitasafile.thenasadirectory.an

28

#we'llassumeitssomesortof"clean"urlandhandittoindex.phpsoourCMScanw

29

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

31

#$is_argswillbe'?'ifthereisaGETstring,or''ifthereisn't

32

#$argsisobviouslythentheGETstring,or''ifthereisn'tone

33

35

#rememberthatPHPFPMstatusURLwesetup?wewanttosupportitforthis

36

#vhost.soiftherequestisfor/status,handthatbackto

37

#PHPusingournamedupstreamserver

38

location/status{

13

17

21

25

30

34

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

12/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

39

fastcgi_passphp;

40

42

#thisisidentical,butforthepingURLwesetup

43

location/ping{

44

45

47

#andfinally,themagicthatmakesPHPwork.ifthefilebeingrequestedendsin".php"

48

#it'ssomethingthatPHPFPMshouldprocess,sohandittoournamedupstreamserver

49

location~\.php${

50

51

52

41

fastcgi_passphp;

46

fastcgi_passphp;

gistfile1.nginxconfhostedwithbyGitHub

viewraw

What about an SSL vhost? Well, its very similar, so Ill only point out thedifferences.
1

server{

#thesameasfornonssl,exceptweindicatethatwhenlisteningonport

#443,itshouldusessl

listen[::]:443ssl;

server_nameblog.chrismeller.comnew.chrismeller.com;

#specifythecertificate(chain)andkeyfiletobeusedforthisvhost

ssl_certificatessl/chrismeller.com.2012.pem;

ssl_certificate_keyssl/chrismeller.com.2012.key;

11

#iuseadifferentdirectoryasamaterofpractice,andjust

12

#createasymlinktothenormalnonssl"public"directorywhentheyarethesame

13

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

15

#notethedifferentlogsforsslandnonssl.norealreason,it'sjustconvenientforme

16

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

17

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

includefastcgi_params;

21

location/{

22

#theonlyotherdifferenceisthati'mnotredirectingadmin

23

#andloginpageswe'realreadyonssl

24

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

25

10

14

18
19
20

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

13/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

26
27

location/status{

28

29

31

location/ping{

32

33

35

location~\.php${

36

37

38

fastcgi_passphp;

30
fastcgi_passphp;

34
fastcgi_passphp;

viewraw

gistfile1.nginxconfhostedwithbyGitHub

And for the record, I name them very similarly to the non-SSL vhosts, but keep them in separate files
so they can be enabled and disabled individually and I can tell at a directory glance which ones
support SSL:

blog.chrismeller.comssl

Originally published 3 years ago and tweaked 9 months later.

40Comments

ChrisMeller

Recommend 5

Share

Login

SortbyBest

Jointhediscussion
phillip 2yearsago

Havinganexplanationforjustabouteverysinglelinemadethispostsupervaluabletome.
Thankyouforthis.
10

Reply Share

JoseVega>phillip ayearago

Metoo.Imsettingupmyvpsandthispostisgold.

Reply Share

miklb 2yearsago

Justanfyi,seemssomeoneonthephpfpmpackagemusthavereadthispost,asthe
defaultsforwww.confmax_children,startservers,andmin/maxspareserversarethe
sameasyourtutorial.Italsodefaultstolisten=/var/run/php5fpm.socket
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

14/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

Thanksagainforwritingthisup,wasahandyreminderforsettingupanewVPS.
2

Reply Share

miklb>miklb 2yearsago

AcoupleofnotessinceIcommented:
*Ineededtoadd`fastcgi_paramSCRIPT_FILENAME
$document_root$fastcgi_script_name`tofastcgi_params.Otherwise,Iwasgetting
ablankpageonphppageswithzeroerrorsand200statusontheaccesslog.Took
alongtimetotrackthatonedown.
*Also,itseemsthelistenshouldbe/var/run/php5fpm.sock,notsocketanymore.
NotsureiftheyaresynonymousbutIuseditandeverythingisworkingnow.
2

Reply Share

chrismeller

Mod >miklb

2yearsago

CanyoucheckwhatOS(andversion)andversionofNginxyou'reusing
thatyouhadtoaddSCRIPT_FILENAME?Ihaven'thadtoaddthatmanually
inquiteawhile.
Thesocketextensionhasnospecialmeaningbeyondlettingyouknowit'sa
socketwhenyoulistdirectorycontents.Ifthedefaulthaschangedyoucan
changeeitheritoryourNginxconfig,it'sallgood.

Reply Share

miklb>chrismeller 2yearsago

MycurrentversionofNginxis1.4.4.1~wheezy.Phpinfoshow
systemDebian3.2.412+deb7u2i686.

Reply Share

joseheribertoperezmagaa>miklb 10monthsago

Ihadthesameproblem,Ihaveubuntu14withnginxversion:
nginx/1.6.2
I'musinginthesocket.conffile:
[www]
listen=/var/run/php5fpm.sock
insteadof
[www]
listen=/var/run/php5fpm.socket
andthatdidthejob
btwthanksforthisincredibletutorial

Reply Share

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

15/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

JamesMorris 2yearsago

Thanksforagreatexplanationandallthecomments.
1

Reply Share

PHPGuru 2yearsago

HeyChris,thisguidewasextremelyhelpful.IusedthedotdebreposwithDebianSqueeze
andnowhaveLEMPupandrunningwithnginx1.4.1,php5.4.16php5fpm&MySQL
5.5.31.Tookaboutanhour,andI'veonlyworkedwithApachebeforetoday.Nicework!
1

Reply Share

mrrssy 6monthsago

thankyouforthissuperexplaineddocumentation!

Reply Share

Thomas 10monthsago

HiChris,
whatdoyouthinkabouttheusage/configurationofdeditactedsocketsforeach
subdomain:
upstreamphp{
serverunix:/var/run/php5fpm<subdomain1>.socket
}
upstreamphp{
serverunix:/var/run/php5fpm<subdomain2>.socket
}

Reply Share

chrismeller

Mod >Thomas

10monthsago

Ifyou'vegotmultipleFPMpools(saytoprotecttheresourcesofonesitefrom
another)thenyouwouldlogicallyhavemultiplelisteners(eithersocketsorports)
thatNginxwouldneedtorelaytrafficto.Sointhatcaseyou'ddefinitelyneed
multipleupstreams.
OneerrorIseeinyourexampleisthatyou'venamedboththeupstreams"php".
Rememberthatthoseneedtobeuniqueaswell,soNginxknowswhichupstream
you'retellingittouse.
Nowtherealquestionis...shouldyoudothis?Idon't,butthat'sbecauseIruna
verysmallVPSthatonlyhostsmyownpersonalsites.Ifoneofthemgets
clobberedit'sprobablygoingtotaketheentireserverdownanyway,sothere'sno
pointinaddingtheextraoverheadtousemultipleFPMpools(sinceeachpoolwould
haveitsownsetofprocesseslisteninganditsownpm.min_spare_servers).
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

16/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

Iprobably*would*recommendusingmultiplepoolsifyou'rehostingindependent
clientsites,though.Givingeachonetheirownsetofprocessescandefinitelyhelp
makesurethatthey'relessvulnerabletoonesitekillingeverything.Justremember
thatallthat"howmanyprocessescanIrunwiththeamountofRAMIhave?"math
willgetalotmorecomplicated.
Youwouldalsoobviouslyneedmultipleupstreams(thoughthey'dbeusingports,
notsockets)ifyouhadNginxsittinginfrontofmorethanonebackendserverthat
ranFPM(ratherthanrunningFPMonthesameboxasNginx),butthatopensupa
wholedifferentcanofwormswewon'tgointo.

Reply Share

Locke 2yearsago

thisisagreathowto,thanks,butI'mgetting:
[02May201418:20:11]ERROR:AnanotherFPMinstanceseemstoalreadylistenon
/var/run/php5fpm.sock
[02May201418:20:11]ERROR:FPMinitializationfailed
doyouknowwhythisishappening????

Reply Share

chrismeller

Mod >Locke

2yearsago

You'vealreadygotaninstanceofFPMrunning,then.Running`psaux|grepiphp`
shouldshowyou.Iwouldn'tbeabletotellyouhowanotherisrunning,butthat's
yourproblem.

Reply Share

Locke>chrismeller 2yearsago

Oh!!!,nowIsee,thisisbecauseIhavealotofdomainsintheserver.lotof
sitesavailablethatarerunningphpfpmmaybethatismymainproblem..

Reply Share

temuri 2yearsago

Thanksforthewriteup.
HowdoyouhandleredirectstoSSLinyournginxconfig?

Reply Share

chrismeller

Mod >temuri

2yearsago

IusearedirecttoSSLintwodifferentwaysdependingonthegoal.
Inoneinstance,IwantallrequeststoenduponSSL.Sofor
http://www.example.comeverythingshouldendupathttps://www.example.com.In
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

17/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

http://www.example.comeverythingshouldendupathttps://www.example.com.In
thatcase,IsimplysetupabarebonesvhostforthenonSSLversion:
https://gist.github.com/chrism...
Ifyou'regoingtoalwaysredirectallrequeststoSSL,youshouldalsolookat
includingtheStrictTransportSecurityheadersomodernbrowsersnevertrytohit
theplaintextversionanyway.
IfthereareonlycertainrequeststhatIwanttoensureareSSLprotected,likethe
loginandadminpagesofaCMSwherepasswordsmightbeseen,youcanredirect
onlythoserequests:https://gist.github.com/chrism...
HerethevhostisotherwisethesameastheexampleIgaveintheguide,butifthe
pathstartswithadminorauthwewanttomakesurethoseareSSLrequests.

Reply Share

m4nuco 2yearsago

ThanksChris,Awesomearticle.Ididn'tgetonethingthowherewouldyouputtheupstream
phpserverthingy?Init'sownfile?

Reply Share

chrismeller

Mod >m4nuco

2yearsago

Shortanswer:Iputitinconf.d/php.conf
Longanswer:Anywherethatnginxwillincludeit.Inmyexamplesalltheconfigfiles
arein/etc/nginx/conf.d/becausethosearetheconfigfilesincludedbydefault.It
doesn'tactuallymatterwhatyounamethefile,justsomethingthatyouwillrecognize
(phpseemedobvioustome).
1

Reply Share

m4nuco>chrismeller 2yearsago

OkthanksChristhatwashelpful.
Notethoihadsameproblemasmiklb,neededtoaddfastcgi_param
SCRIPT_FILENAME$document_root$fastcgi_script_nameinordertogetit
towork.(Ubunutu12.4,nginx1.4.4).Youprobablyshouldaddanoteabout
thatinyourpost

Reply Share

KJ 2yearsago

Thanksfordoingthis...Clearedupalotofquestions(fears)Ihadbeforetakingtheleapinto
selfmanagedVPS

Reply Share

cakuki 2yearsago

Asthearticleitselfisarealmasterpiece,my"justonething"isaboutphpfpmpool
configurationseparation.Aspooldirectoryintendedtocontainmorethandefaultwwwpool
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

18/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

configurationseparation.Aspooldirectoryintendedtocontainmorethandefaultwwwpool
configuration.
Ihavechangedtheincludevaluein/etc/php5/fpm/phpfpm.confto:
include=/etc/php5/fpm/pool.d/*/*.conf

soIhavemywwwconfigurationsseparatedlikepool.d/www/foo.conf.
ThismakesTCPandsocketproxiesavailableindifferentpoolconfigurationswithout
confusion.

Reply Share

chrismeller

Mod >cakuki

2yearsago

Thanks,cakuki!That'sanicelogicalseparation,ifyouneedbothtypesoflisteners!

Reply Share

tushar 2yearsago

Greattutorial.
AfterIupgradednginxserverfrom1.1.19to1.4.4andmadetheabovechanges,I'mnow
gettingError503.Whatmightbethecause?

Reply Share

chrismeller

Mod >tushar

2yearsago

Blindly,offthetopofmyhead,with0details?Ihavenoclue.Likeanytimeyou're
troubleshooting,checkyourerrorlog.
Themainnginxlog(asopposedtothevhostspecificonesyoudefineineach
config)isusually/var/log/nginx/error.log,whichmaycontainmoredetails.
1

Reply Share

tushar>chrismeller 2yearsago

2013/12/0908:35:48[crit]14861#0:*7415connect()tounix:/var/run/php5
fpm.sockfailed(2:Nosuchfileordirectory)whileconnectingtoupstream,
client:127.0.0.1,server:95.85.29.90,request:"GET/HTTP/1.1",upstream:
"fastcgi://unix:/var/run/php5fpm.sock:",host:"livingwithict.com"
2013/12/0909:30:42[emerg]1927#0:bind()to0.0.0.0:80failed(98:Address
alreadyinuse)
2013/12/0909:30:42[emerg]1927#0:bind()to0.0.0.0:80failed(98:Address
alreadyinuse)
2013/12/0909:30:42[emerg]1927#0:bind()to0.0.0.0:80failed(98:Address
alreadyinuse)
2013/12/0909:30:42[emerg]1927#0:bind()to0.0.0.0:80failed(98:Address
alreadyinuse)
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

19/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller
alreadyinuse)
2013/12/0909:30:42[emerg]1927#0:bind()to0.0.0.0:80failed(98:Address
alreadyinuse)
2013/12/0909:30:42[emerg]1927#0:stillcouldnotbind()

Reply Share

joseheribertoperezmagaa>tushar 10monthsago

IcanconfirmtheerrorwhatIdidtofixtheerrorjustreplacethe
following:
[www]
listen=/var/run/php5fpm.socket
for
[www]
listen=/var/run/php5fpm.sock

Reply Share

chrismeller

Mod >tushar

2yearsago

ThefirsterrorindicatesthateitherNginxorPHPFPMismis
configured.CheckyourNginxphpupstreamtomakesuretheserver
directiveiscorrect.Morelikely,youdidn'tsetthelistendirectivein
yourPHPFPMpoolconfiguration"socket.conf"inmyguide.
Thelattererrorsaremostlikelybecausethedefaultvhost
configurationincludesanincompatible`listen`directive.Double
checkallyourvhostsandmakesuretheyhavethesame`listen`
directive.
Ifyoucan'tfindtheproblem,moveinto/etc/nginxandrun`grepri
"listen".`,whichshouldshowyoueveryfilethatmightincludethe
problem.

Reply Share

Josh 2yearsago

Idon'tunderstandhowtosetthepm.max_children,pm.start_servers,
pm.min_spare_serversandpm.max_spare_servers...IhaveanIntel(R)Core(TM)i7CPU
920@2.67GHzwith8coresand48GBofRAM.Ihaveset:pm.max_children=1000,
pm.start_servers=245,pm.min_spare_servers=45,pm.max_spare_servers=350(I
wantatleast1000concurrentsusers).ButIhavesomeerrorsayingmethatihavetoo
maneprocesses...What'swrong?ThankyouveryMuch!

Reply Share

chrismeller

Mod >Josh

2yearsago

LikeIsaid,italldependsonexactlywhatyou'rerunning.Youshouldstartofflow,
runyourapplicationforawhile(evenifit'sjustyousteppingthroughitlikeanormal
userforawhile,possiblyoveradayortwo),andthenseehowmuchmemoryeach
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

20/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

phpfpmprocessisoccupyingonyoursystem(`psaux|grepphp`orsimilar).
Afterthat,youneedtodivideouttheamountofRAMyouhaveleftonyourbox
(makesuretoaccountforMySQLoranyotherbackgroundprocessesthatyou'll
haverunning)andfigureoutthenumberofprocessesyoucanreasonably
accommodate.
Withouttheexacterror,Ican'thelpwiththe"toomanyprocesses"erroreither.

Reply Share

DanielSearles 2yearsago

IforgottomentionthatthisisagreatpostandthatIappreciateyouwritingitup.Goodjob!

Reply Share

DanielSearles 2yearsago

`location~\.php${`isasecurityvulnerabilitysinceitallowsanyphpfiletoberunincluding
uploadedfiles.Seethisarticleforamoreindepthexplanation:
https://nealpoole.com/blog/201...

Reply Share

chrismeller

Mod >DanielSearles

2yearsago

Intheexampleheprovides,FPMactuallyunderstandsthattherequestisfor
random.gif,evenifNginxattemptstopasstherequesttoitbasedontheendingof
.php.
Ifyoucheckyourerror.logfileyou'llseearesponsefromFPMalongthelinesof:
Accesstothescript'/whatever/public/random.gif'hasbeendenied(see
security.limit_extensions)
Thesecurity.limit_extensionspooloptionwasaddedinPHP5.3.9anddefaultsto
onlyincludingtheextension.php,preventingexactlythisproblem.Since5.3.9was
releasedalmosttwoyearsago(January,2012)there'saprettygoodbetmostofus
arefine(Ubuntu12.04LTSincludes5.3.10,butifyou'restillrunning10.04LTSyou
mighthaveanissue).
Forsomeinexplicablereasonthisisn'tincludedinthePHPdocumentation,butthe
topcommentonthepagepointsitout:http://php.net/manual/en/insta...

Reply Share

Tecto 2yearsago

Aboutthisbit:
#checkyourdefaultnginx.conf,it'salreadycoveredinamuchbetterway.
#gzip_disable"MSIE[16]\.(?!.*SV1)"
Mydefaultnginxconfigdoesn'tappeartohaveanythingtocoverthis.Canyouclarify?
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

21/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

Reply Share

chrismeller

Mod >Tecto

2yearsago

TheUbuntuandDebiandefaultsI'veseenusuallyhavea`gzip_disablemsie`line,
whichisafasterversionoftheregexpatternmostpeoplestickinthere:
http://nginx.org/en/docs/http/...
Ifyoudon'thaveoneyoucansimplyadd:gzip_disablemsieinyourgzip.conf.

Reply Share

VilhjlmurMagnsson 2yearsago

Anyideasonhowtofixthe"Filenotfound"issuewhenusinguserdirandvhostsforphp?

Reply Share

RieksVisser 2yearsago

Veryconciseandwellwritten,thankyou!ThishelpedmealotinmovingfromApache2to
Nginx.IcanalsoconfirmthatyourguideworksjustaswellonaDebian7(Wheezy)server.
TwothingsIdidencounterwere:
1.InstallingnginxfromPPAdidn'tworkoutforme,perhapsIwasabitimpatient.Intheend,
Iwentwithasimpleaptgetinstallnginx.OnanupdatedWheezythisendedupgivingme
nginx/1.2.1.Notquitebleedingedge,butrecentenough.
2.Rule3inthevhostconfigresultedinan'addressalreadyinuse'error.Afixwaseasily
found:http://stackoverflow.com/quest....Inshort:listeningtoport80forbothipv4andipv6
inoneruleconflictswiththenginxdefaultconfig.

Reply Share

chrismeller

Mod >RieksVisser

2yearsago

I'veactuallyjustrecentlystoppedusingthePPA.Itlookslikeit'snotbeingupdated
asregularlyasitusedtobe...ButtheofficialNginxDebian/Ubunturepository
worksfine.I'llupdatethatsoon.
Asforthedefaultconfig,you'reprobablycorrect.Imayhaveaccidentallyskipped
overremovingthatbitfromthedefaultconfig.That'swhathappenswhenyou're
writingaguideafterthefact!I'mintheprocessofmigratingsomesitestoanewbox
now(it'sthere,Ijusthavetogetaroundtoconfiguringit!),soI'llbesuretogive
everythinganotherrunthroughasIdoandmakeanyneededupdates.
Thanksverymuchforthefeedback!

LAST POST GET YOUR GITHUB ISSUES AS AN RSS FEED


NEXT POST CREATING AND MANAGING SSL CERTIFICATES WITH NGINX
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

22/23

11/4/2015

ConfiguringandOptimizingPHPFPMandNginxonUbuntu(orDebian!)|ChrisMeller

http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian

23/23

You might also like