Web Hosting Talk







View Full Version : nginx + php-fpm + debian squeeze tutorial - the fastest way to host php!


AltruHost
02-22-2011, 12:11 AM
Here is a quick howto for setting up nginx and php-fpm on a Debian 6 VPS. We will be using the dotdeb repository for this so a big thanks goes to the dotdeb guys for building such reliable Debian packages.

This has been tested on a Debian 6 OpenVZ minimal template:

First add the dotdeb repo to your sources.list file:
nano /etc/apt/sources.list

add this to the bottom of the file:
deb http://packages.dotdeb.org stable all

Next, add the GnuPG key to your distribution:
wget http://www.dotdeb.org/dotdeb.gpg
cat dotdeb.gpg | sudo apt-key add -
rm dotdeb.gpg

Update APT:
apt-get update

Install php and php-fpm plus some common addons:
apt-get install php5 php5-fpm php-pear php5-common php5-mcrypt php5-mysql php5-cli php5-gd

Install nginx:
apt-get install nginx

Tweak the php-fpm configuration:
nano /etc/php5/fpm/php5-fpm.conf

The following tweaks have been customized for a 512MB-1GB VPS. You can use the same numbers here or come up with your own. This is just what I have found to be the most resource friendly for a lightly used VPS:
pm.max_children = 25
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 10
pm.max_requests = 500

This line is optional but I highly suggest you use it. Basically it's saying that if a php-fpm process hangs it will terminate it if it continues to hang for 30 seconds. This will add stability and reliability to your php application in the event there is a problem:
request_terminate_timeout = 30s

restart php-fpm:
/etc/init.d/php5-fpm restart

Tweak your nginx configuration:
nano /etc/nginx/nginx.conf

The client_max_body_size option changes the max from the 1MB default (which is a must for most php apps):
client_max_body_size 20M;
client_body_buffer_size 128k;

Remove the default vhost symlink:
cd /etc/nginx/sites-enabled
rm default

Create a fresh and clean vhost file:
nano /etc/nginx/sites-available/www.website.com

server {
listen 80;
server_name website.com www.website.com;

access_log /var/log/nginx/website.access_log;
error_log /var/log/nginx/website.error_log;

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

location ~ .php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/www.website.com$fastcgi_script_name;
include fastcgi_params;
}
}

Create a new symlink for the new vhost under sites-enabled:
ln -s /etc/nginx/sites-available/www.website.com /etc/nginx/sites-enabled/www.website.com

Restart nginx:
/etc/init.d/nginx restart

That's it. You should now have a clean installation of nginx and php-fpm with a single vhost running on port 80. If you want to have the same vhost running with ssl on port 443, copy and paste the entire vhost code into the bottom of the vhost file, change 'listen' to 443:
listen 443;

Then add these lines that will point to your ssl certs:
ssl on;
ssl_certificate /path/to/certificate/www.website.com.crt;
ssl_certificate_key /path/to/certificate_key/www.website.com.key;

Please let me know if there is anything I missed or anything that might need to be changed.

yugongtian
02-27-2011, 01:55 AM
Thanks for share.:)

computerwis
02-27-2011, 03:19 AM
Good information for beginners or ones that need help.

I hope you continue to share more.

deejk
02-28-2011, 05:51 PM
thanks for sharing, it certinaly helped me out

AltruHost
02-28-2011, 09:55 PM
You are all most welcome! I hope more people can benefit from tutorials like this. I plan on posting more here in the future.

Aaryn015
04-25-2011, 04:21 AM
Hey, Thanks for the nice tut.

I'm not a Linux noob, but I'm new to Dotdeb and some of the steps here are new to me. Namely this one


Tweak the php-fpm configuration:

nano /etc/php5/fpm/php5-fpm.conf



I followed your steps from the start, and I don't have this file in the /etc/php5/fpm/ directory. But there is a php-fpm.conf file there. Should I be adding these settings to that file, or creating php5-fpm.conf?

Cheers
Aaron

acjohnson
04-25-2011, 09:56 AM
Hey thanks for pointing that out. That might actually be a typo. I'll have to look at my configs later to see but typically the file is called php-fpm.conf. Try editing that file and continue on. You shouldn't have any more problems from there.

acjohnson
04-26-2011, 01:25 AM
Okay, so I've checked my configuration and my servers actually have a file called 'php5-fpm.conf' so perhaps the dotdeb binaries have changed to use the 'php-fpm.conf' file name instead... Try editing that file and if you could report back if it works that would be great. If not then just copy the file or symlink it and see if that works as well.

thomas01155
05-22-2011, 03:16 PM
What else would I need to install other than MySQL to get wordpress working?

Thanks

XSLTel
05-22-2011, 03:31 PM
@OP thanks for this informative tutorial
@thomas01155 nothing else (nginx + php-fpm + mysql) is what you need to run Wordpress

thomas01155
05-22-2011, 04:06 PM
Thanks, I have my wordpress site working now. I keep getting 502 bad gate way errors when I update stuff on the site however. Do you know how to fix this?

Thanks,
Tom

dmmcintyre3
05-22-2011, 04:12 PM
Security issue:

http://scott.yang.id.au/2011/04/securing-php-fastcgi-on-nginx/

thomas01155
05-22-2011, 04:41 PM
OK so now its but I'm still getting the same error :(

location ~ .php$ {
if (-f $request_filename) {
fastcgi_pass 127.0.0.1:9000;
}
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/*removed*.com$fastcgi_script_name;
include fastcgi_params;
}

2011/05/23 00:43:40 [error] 1987#0: *15 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/index.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/profile.php"
2011/05/23 00:43:42 [error] 1987#0: *15 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/edit.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/index.php"
2011/05/23 00:43:44 [error] 1987#0: *15 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/post.php?post=1&action=edit HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/edit.php"
2011/05/23 00:43:46 [error] 1987#0: *21 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 11.111.11.11, server: *remove*.com, request: "POST /wp-admin/post.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/post.php?post=1&action=edit"
2011/05/23 00:43:48 [error] 1987#0: *21 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET / HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com"
2011/05/23 00:43:51 [error] 1987#0: *21 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/profile.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/"
2011/05/23 00:43:53 [error] 1987#0: *21 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/edit.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/profile.php"
2011/05/23 00:43:57 [error] 1987#0: *21 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/edit.php?post_type=page HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/edit.php"
2011/05/23 00:43:59 [error] 1987#0: *21 readv() failed (104: Connection reset by peer) while reading upstream, client: 11.111.11.11, server: *remove*.com, request: "GET /wp-admin/post.php?post=5&action=edit HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/edit.php?post_type=page"
2011/05/23 00:44:00 [error] 1987#0: *21 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: 11.111.11.11, server: *remove*.com, request: "POST /wp-admin/post.php HTTP/1.1", upstream: "fastcgi://127.0.0.1:9000", host: "*remove*.com", referrer: "http://*remove*.com/wp-admin/post.php?post=5&action=edit"

netstat -nl
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:9000 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:587 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp6 0 0 :::22 :::* LISTEN
raw6 0 0 :::1 :::* 7
Active UNIX domain sockets (only servers)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 716910858 /var/run/mysqld/mysqld.sock
unix 2 [ ACC ] STREAM LISTENING 716887395 /var/run/saslauthd/mux
unix 2 [ ACC ] STREAM LISTENING 716887911 /var/run/sendmail/mta/smcontrol

Thanks,
Tom

thomas01155
05-22-2011, 05:21 PM
Here are some more logs if anyone can help me solve this problem :)

php5-fpm.log
[23-May-2011 01:16:49] WARNING: [pool www] child 3574 exited on signal 11 (SIGSEGV) after 62.058702 seconds from start
[23-May-2011 01:16:49] NOTICE: [pool www] child 3597 started
[23-May-2011 01:16:57] WARNING: [pool www] child 3575 exited on signal 11 (SIGSEGV) after 67.750219 seconds from start

user.log
May 22 23:47:51 V-1040 suhosin[3173]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)
May 22 23:47:53 V-1040 suhosin[3177]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)
May 22 23:53:26 V-1040 suhosin[3175]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)
May 22 23:53:27 V-1040 suhosin[3178]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)
May 22 23:53:29 V-1040 suhosin[3184]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)
May 22 23:53:31 V-1040 suhosin[3186]: ALERT - script tried to increase memory_limit to 268435456 bytes which is above the allowed value (attacker 'xx.xxx.xx.xx', file '/var/www/xx***********/wp-admin/admin.php', line 109)

Thanks

AltruHost
05-22-2011, 10:26 PM
Did you see this thread:
http://serverfault.com/questions/178671/nginx-php-fpm-504-gateway-time-out-error-with-almost-zero-load-on-a-test-ser

It suggests that this could be a configuration problem and that this line in nginx.conf will fix it:
request_terminate_timeout = 30s

The above is in the walkthough but it is suggested as optional so perhaps you opted to ignore that part of the config.

Also, how much memory do you have and how much is free? Simply run:
free -m

The suhosin error messages look familiar and depending on the configuration I think it can be ignored (but don't quote me on that)

If you are still experiencing problems after triple checking your configs and free memory I'd be glad to help you further.

AltruHost
05-23-2011, 12:53 AM
Also I am noting that you have this in your configuration:

location ~ .php$ {
if (-f $request_filename) {
fastcgi_pass 127.0.0.1:9000;
}

If you are indeed running Debian 6 then your version of nginx should support the 'try_files' directive and as long as you are proxying to php-fpm locally then you should be good to use it.

You should no longer use the depreciated if statements inside of a location block as per this article on the nginx wiki:

http://wiki.nginx.org/IfIsEvil

It explicitly says on the above page:

The only safe things may be done inside if in location context are:

return ...;
rewrite ... last;

Anything else may cause unpredictable results up to SIGSEGV.

...so most likely this is the cause of your problem

thomas01155
05-23-2011, 04:22 AM
OK, this is my new virtual host config file for my site:
location ~ .php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /var/www/xxxxxxxxxx.co.cc$fastcgi_script_name;
include fastcgi_params;
}

I have these 3 files in /etc/php5/fpm/

/etc/php5/fpm/php5-fpm.conf
pm.max_children = 25
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 10
pm.max_requests = 500
request_terminate_timeout = 30s

/etc/php5/fpm/php-fpm.conf
http://pastebin.com/RzJjMK6K
I noticed this ;include=/etc/php5/fpm/*.conf is commented. I tried uncommenting it but php5-fpm fails to restart when I do that. So is it even reading my php5-fpm.conf?
Restarting PHP5 FastCGI Process Manager: php5-fpm failed!

I moved the php.ini from cli to here
/etc/php5/fpm/php.ini


free -m
total used free shared buffers cached
Mem: 2048 190 1857 0 0 0
-/+ buffers/cache: 190 1857
Swap: 0 0 0

Thanks again,
Tom

PS: I very new to all of this, so thank you again for your help : )

thomas01155
05-23-2011, 04:54 AM
This is my nginx.conf if it helps: http://pastebin.com/3Qv084Jw
Do I need a block with upstream php {}?

I can't get my site to load at all, I just get 502 Bad Gateway everytime now. I don't know why it managed to load for a bit yesterday.

Thanks

thomas01155
05-23-2011, 09:59 AM
Is php5-fpm.conf meant to be in /etc/php5/fpm/pool.d/ folder?

I have /etc/php5/fpm/pool.d/www.conf inside the pool.d folder.

I'm so :confused:

thomas01155
05-23-2011, 12:30 PM
OK, I have it working after all day trying to get it to xD I put all the tweaks in: /etc/php5/fpm/pool.d/www.conf and the line php_admin_value[memory_limit] = 256M

Thanks xx

AltruHost
05-23-2011, 01:07 PM
Is php5-fpm.conf meant to be in /etc/php5/fpm/pool.d/ folder?

NO php5-fpm.conf should be left in its default location!

It sounds like you may have it working now but if you need any help please respond back to this thread.

thomas01155
05-23-2011, 03:14 PM
NO php5-fpm.conf should be left in its default location!

It sounds like you may have it working now but if you need any help please respond back to this thread.

Is there a better way other than using line php_admin_value[memory_limit] = 256M I don't even know what it does, it just seems to work.

I'm using like 600mb of RAM with like 0 visitors.

thomas01155
05-23-2011, 03:38 PM
My used memory just seems to keep increasing till I get the gateway error :(

total used free shared buffers cached
Mem: 2048 703 1344 0 0 0
-/+ buffers/cache: 703 1344
Swap: 0 0 0

thomas01155
05-23-2011, 04:22 PM
My used memory just seems to keep increasing till I get the gateway error :(

total used free shared buffers cached
Mem: 2048 703 1344 0 0 0
-/+ buffers/cache: 703 1344
Swap: 0 0 0

Some of my server min and max settings were wrong seems to be holding around 275MB at the moment.

AltruHost
05-23-2011, 06:28 PM
No you do not need to set php_admin_value[memory_limit] to any value. Just leave this line commented out for the default value to take affect. Also, you are right about the min and max server count. If you leave the default setting for child processes as dynamic:
pm = dynamic

then you will need to make sure your pm.start_servers pm.min_spare_servers and pm.max_spare_servers values are appropriate for your memory configuration.

There are example values for those settings in the walkthough on page 1 of this thread and if you have 2GB of memory like your posts show then those values should work quite nicely.

However, if you are experiencing high memory usage simply adjust each of those settings down until you get an exceptable amount of memory usage.

You can also check to see exactly how many php-fpm processes are being spawned with this command:

ps -A | grep php-fpm

Also, you can see how much memory each process is taking up by running:

top

You can switch column by pressing shift + > or shift + <

Typically when using top, the RES column is the most accurate for actual memory usage whether it's cached, shared, etc.

Thompson2
06-01-2011, 01:24 AM
Have you tried installing ionCube loader on this configuration?

I followed your guide and Nginx and PHP work great. Thank you! BUT...I can't get ionCube loader to work on this set up.

IonCube loader's wizard says it installed successfully and it's listed in the output from phpinfo() as an installed component, but when trying to view an encoded pages, they're just pure white or read "This encoded file cannot be run. Please run the file ioncube-loader-helper.php for more information." I don't *think* my test files are corrupted.

(Our set ups are identical with one exception. I configured PHP to listen on a unix socket instead of over TCP, based on another guide I read too, which I can share those steps if you're interested to save on the TCP overhead.)

AltruHost
06-01-2011, 04:18 PM
Honestly I have never used IonCube loader so I will have to test it and get back to you. I've never had the need to run anything but open source unencrypted applications on PHP before.

I doubt the unix sockets would cause the issue but we'll see after I test it. I don't know anything about IonCube. Is there an application you can suggest that I can use to test it with?

Thompson2
06-01-2011, 07:04 PM
I'm not sure what I changed, but I *just* got it working! I used the ioncube loader-wizard.php that comes in the download package over & over many times and lots of trial and error. I must have bungled it up and then eventually ironed out the issues. But it works.

p.s. I keep trying to post my how-to over unix sockets, but the forum won't let me. It keeps saying I need 5 posts to use vb features such as smilies or links. Though I don't have any of either. hmm Maybe I'll just go post 3 more times then come back.

Thompson2
06-01-2011, 07:17 PM
It thinks my code are links apparently. Even without [ code ] it still blocks it without 5 posts.

Thompson2
06-01-2011, 08:08 PM
Alright. I went out and made a bunch of posts ;) Got 5 now. Let's try this again.


To connect PHP to nginx over a unix socket, avoiding the TCP overhead and squeezing out every last drop of performance (at least that's the goal), this is what I did:

Paste this within the server block of each vhost file:

# connects nginx & PHP-FPM over unix socket (matches in /etc/php5/fpm/pool.d/www.conf)
location ~ .php$ {
fastcgi_pass unix:/tmp/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

Then...

sudo nano /etc/php5/fpm/pool.d/www.conf

Find listen = 127.0.0.1:9000 and replace it with listen = /tmp/php-fpm.soc Then save & exit with CTRL + X, "Y", & enter.
(I'm sure you know how to save out of nano. But it caused me so much frustration the first time I tried that I figured it better to mention it for anyone else that comes along.)

Have you tried Varnish too? That's the only other thing I can thing to make it faster. (I've already got APC installed.) I've ready mixed reviews about varnish on nginx, but figure that once I finish the essentials like phpmyadmin, I'll give it a try.

inso
06-08-2011, 10:11 AM
thanks, and sudo is not exsit in debian, i think

Thompson2
06-08-2011, 07:00 PM
Sure it does. I'm on Debian 6.0. But if you're logged in as the root user, you won't need to use sudo. Only if you're logged in using a non-root account.

SaffronSolutions
07-24-2011, 12:52 PM
well mate am done installing naginx , but am not able to install wordpress , seems some rewrite rule is creating problem i think

SaffronSolutions
07-25-2011, 01:01 PM
thanks for sharing