Upload
manuatrey1
View
66
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Configuring and Optimizing PHP-FPM and Nginx on Ubuntu (or Debian!) by Chris Meller
Citation preview
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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.
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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.
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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,
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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;
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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 supervaluable 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 phpfpm 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/php5fpm.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.
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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/php5fpm.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.412+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/php5fpm.sockinstead of[www]listen = /var/run/php5fpm.socket
and that did the job
btw thanks for this incredible tutorial
Share ›
Share ›
Share ›
Share ›
Share ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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 php5fpm & 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/php5fpm<subdomain1>.socket;
upstream php server unix:/var/run/php5fpm<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 ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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 :
[02May2014 18:20:11] ERROR: An another FPM instance seems to already listen on/var/run/php5fpm.sock
[02May2014 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 ofsitesavailable that are running phpfpm maybe that is my main problem..
• Reply •
temuri • 2 years ago
Thanks for the writeup.
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 ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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 nonSSL version:https://gist.github.com/chrism...
If you're going to always redirect all requests to SSL, you should also look atincluding the StrictTransportSecurity header so modern browsers never try to hitthe plain text version anyway.
If there are only certain requests that I want to ensure are SSLprotected, 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 intoselfmanaged VPS
cakuki • 2 years ago
As the article itself is a real masterpiece, my "just one thing" is about phpfpm poolconfiguration separation. As pool directory intended to contain more than default www pool
Share ›
Share ›
Share ›
Share ›
Share ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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/phpfpm.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 vhostspecific 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/php5fpm.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/php5fpm.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 ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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/php5fpm.socketfor[www]listen = /var/run/php5fpm.sock
• Reply •
chrismeller • 2 years agoMod > tushar
The first error indicates that either Nginx or PHPFPM is misconfigured. Check your Nginx php upstream to make sure the serverdirective is correct. More likely, you didn't set the listen directive inyour PHPFPM 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 ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 21/23
• Reply •
phpfpm 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 [16]\.(?!.*SV1)";
My default nginx config doesn't appear to have anything to cover this. Can you clarify?
Share ›
Share ›
Share ›
Share ›
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 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 aptget 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 runthrough 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
11/4/2015 Configuring and Optimizing PHPFPM and Nginx on Ubuntu (or Debian!) | Chris Meller
http://blog.chrismeller.com/configuringandoptimizingphpfpmandnginxonubuntuordebian 23/23