Jump to content

NGINX HOWTO FTW


Recommended Posts

Installed NGINX out of desperation last night over my 20-70 load average running IPB on Apache. After install, load average is 0.5-5 SOLID!

Connection lag went from 4-8 seconds to 200-600ms. Forum index page load time went from 35 seconds to 6 seconds

From This Tuesday:

top - 11:27:08 up 18 days, 23:31, 3 users, load average: 49.27, 34.30, 29.08
Tasks: 205 total, 63 running, 141 sleeping, 0 stopped, 1 zombie
Cpu(s): 93.6%us, 4.3%sy, 0.0%ni, 0.0%id, 0.0%wa, 0.3%hi, 1.8%si, 0.0%st
Mem: 6106800k total, 5816160k used, 290640k free, 74148k buffers
Swap: 4063224k total, 154532k used, 3908692k free, 2885856k cached

To This Thursday:

top - 14:38:43 up 21 days, 2:43, 4 users, load average: 2.49, 2.52, 2.23
Tasks: 166 total, 2 running, 164 sleeping, 0 stopped, 0 zombie
Cpu(s): 21.8%us, 1.7%sy, 0.0%ni, 75.3%id, 0.0%wa, 0.2%hi, 1.0%si, 0.0%st
Mem: 6106800k total, 6019984k used, 86816k free, 243576k buffers
Swap: 4063224k total, 94448k used, 3968776k free, 4721308k cached

With this:

1094 active user(s) (in the past 30 minutes)
532 members, 535 guests, 27 anonymous users | Show by: Last Click or Member Name

If you run Apache+mod_php, stop. Here is how:

Follow these instructions (assuming you use CENTOS 5.5):

http://rob.olmos.name/2010/08/centos-5-5-php-5-3-3-php-fpm-nginx-rpms/ noting that the php RPMs are actually named php53u not php53

This is what I did (from instructions above):

$ sudo service httpd stop

# saving old list of php packages
$ sudo yum list php* | grep installed > ~/old_php_packages_list.txt

$ sudo yum remove php*

$ sudo yum install php53u php53u-cli php53u-common php53u-devel php53u-fpm php53u-gd php53u-mbstring php53u-mysql php53u-pdo php53u-pear php53u-pecl-apc php53u-xml nginx

If you have nexus or need zend optimizer or ioncube then install the right versions for php 5.3.5, php53u-ioncube-loader for example.

Fixup/copy from php.ini.rpmsave your php.ini and your php.d/*.ini files. Again, if you have extensions there you will need to get versions that will work with php 5.3.5. make sure you php.ini do not have apc.include_once_override = "1", it is fail.

$ sudo chkconfig httpd off
$ sudo chkconfig nginx on
$sudo chkconfig php-fpm on

Create a nginx config for your site like /etc/nginx/conf.d/mysite.conf. Here is mine (with support for .htaccess FURLs enabled in ACP):


upstream php {

	server unix:/tmp/php-cgi.sock

}


server {

	root                    /where/your/docroot/is;

	index                   index.php index.html;


	location ~ \.php$ {

	        fastcgi_pass    php;

	        fastcgi_param   SCRIPT_FILENAME $document_root$fastcgi_script_name;

	        include         fastcgi_params;

	}


	location /forums {

	        try_files       $uri $uri/ /forums/index.php;

	}


	location ~ /\.ht {

	        deny            all;

	}


	location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {

	        expires 	max;

	        log_not_found 	off;

	}

}



Edit /etc/php-fpm.d/www.conf

You need to change the 'listen =' line of the php-fpm configuration to match the socket in the upstream php part. It's the first config item under [www]

$ sudo service php-fpm start
$ sudo service nginx start

Salvation!

:wub: NGINX :wub:

Link to comment
Share on other sites

Hello,

Quick note about nginx.

This is the suggested method for fastcgi:

 location ~ .php$ {                                       		

    fastcgi_split_path_info ^(.+\.php)(.*)$;

    fastcgi_pass   php;

    fastcgi_index  index.php;

    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;

    include fastcgi_params;

 }

and this will protect your folders:

location ~* ^/(?:cache|hooks|public/style_css|public/style_images|uploads)/.*\.(?:pl|php[345]*)$ {

    return 404; # or 403

 }



Quick note ... nginx with apache+mod_php it's also a very stable option and that's what I'm using,

Link to comment
Share on other sites

http://www.howtoforge.com/installing-php-5.3-nginx-and-php-fpm-on-ubuntu-debian

The lack of .htaccess support means that making changes requires modifying the configuration file, which means nginx probably won't work well in a hosting environment where people are used to having .htaccess available at the subdirectory level.



And the unfixable PHP security vulnerability is a head-spinner.



Is that true or that guy is just BS'ing?
Link to comment
Share on other sites

Seems I can't update the first post :/

Thanks for the config contributions. I added some comments and embedded instructions. Here is the updated basic config:


upstream php {

        server unix:/tmp/php-cgi.sock

}


server {

        root /where/your/docroot/is;

        index index.php;


	# Deny access (403) access to all perl or php scripts in certain locations.

        location ~* /(?:cache|hooks|public/style_css|public/style_images|uploads)/.*\.(?:pl|php[345]*)$ {

                return 403;

        }


	# Deny access (403) to all .ht{passwd|access|etc} files

        location ~* /\.ht.*$ {

                deny all;

        }


	# Handle PHP via FactCGI

        location ~ \.php$ {

                fastcgi_split_path_info ^(.+\.php)(.*)$;


                # send php requests to php backend

                fastcgi_pass    php;


                # Add index.php to $fastcgi_script_name if URL ends with /

                fastcgi_index index.php;


                # Set SCRIPT_FILENAME relative to document root

                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


		# Set rest of factcgi params from server defaults

                include fastcgi_params;

        }


	# Cache static files and don't both logging 404 requests for them.

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {

                expires max;

                log_not_found off;

        }


	# IPB in your root? Use this:

	# Rewrite all requests which aren't files or directories to /index.php

	#location / {

	#	try_files $uri $uri/ /index.php;

	#}


	# IPB in subdir? Use this (change subdir to suit):

	# Rewrite all requests which aren't files or directories to /forums/index.php

        location /forums {

                try_files $uri $uri/ /forums/index.php;

        }

}



Reminder, this is a BASIC starter config that is supposed to work with a normal IPB install right out of the box. It is not optimized or complete for YOUR installation and may not even work if you install is a little oddball. Start here and build. The knowledge base about NGINX and IPB is zilch. Please contribute back to make it easier for those who follow.

Link to comment
Share on other sites


http://www.howtoforge.com/installing-php-5.3-nginx-and-php-fpm-on-ubuntu-debian



Is that true or that guy is just BS'ing?




First, I have not used the tutorial you linked to so I can't say anything there.

.Nuno. Added the security fix.

There is no .htaccess support in nginx. If you are using .htaccess and your server is slow, now you know why. If you use shared hosting you can't use this anyway so it's not exactly a limitation right? If you can install it, you can configure it, easy.
Link to comment
Share on other sites


There is no .htaccess support in nginx. If you are using .htaccess and your server is slow, now you know why. If you use shared hosting you can't use this anyway so it's not exactly a limitation right? If you can install it, you can configure it, easy.




so does that mean you wouldn't be able to use the url rewrites for friendly urls ?
Link to comment
Share on other sites


.Nuno. Added the security fix.




I'd also add that I tested it on my server, there is no exploit there with this config. I get 403 Forbidden trying because the config prevents access to php files (real or not) in the upload directories. Protect access to any .php or .pl files in places where people can upload files to. The exploit is based on how php figures out which php file to run. The link has all the info and the developer of nginx is on there too.
Link to comment
Share on other sites

The security problem you may have if you don't protect the directories with right permission it's because some configurations/applications/scripts will let you upload a php file, renamed as a .jpg and then execute locally.


Note: I've not tested this with any IP products.

Link to comment
Share on other sites

I want to thank the op for this topic. I've been looking for a way to scale our web application and found issues with Apache + FastCGI + Any Opcode cache engine. I saw this topic before I started my research and the name stuck in my mind. Trying to investigate a way to solve the problem, I saw Nginx mentioned a few times and remembered this topic. I decided to check it out, and after going through their Wiki and reading other comments I've pretty much decided to abandon Apache all together.

As far as the security issue I can explain that fairly well since I've pretty much read all the documentation.

Nginx is a proxy server first, and an http server second. This means that it doesn't care about files. You just have to tell it where to map the URI. If you tell it to map anything that ends in ".php" to the php engine it will map "/path/to/uploaded.jpg/fake.php" to PHP and php will know that "fake.php" doesn't exist but "uploaded.jpg" does. The result is "uploaded.jpg" will be executed as PHP. To fix this problem you have to set cgi.fix_pathinfo=0 in php.ini. This will, however, prevent you from doing something like "/path/to/index.php/pretty-url". In that case you would have to use an if statement to check if the file exists before sending it to php. It is important to note that Nginx heavily discourages the use of if statements because they are not efficient.

I highly recommend reading this page http://wiki.nginx.org/Pitfalls and this page http://wiki.nginx.org/IfIsEvil and especially this page http://wiki.nginx.or...pache-htaccess.

Link to comment
Share on other sites

ok, after a lot of problems and fixes here is my conf...




upstream php {

    	server unix:/var/run/php5-fpm.sock;

}


server {

server_tokens off;

autoindex off;


keepalive_timeout 60;

keepalive_requests 300;


client_header_buffer_size 4k;

large_client_header_buffers 4 32k;

fastcgi_buffers 128 4k;


output_buffers 2 32k;

postpone_output 1460;





	listen 190.122.192.4;

	root /var/www/nginx/web_grupoandroid_com;

	access_log /var/log/nginx/access_log.web_grupoandroid_com.log;

	error_log /var/log/nginx/error_log.web_grupoandroid_com.log warn;


    	index index.php index.htm index.html;


    	# Deny access (403) access to all perl or php scripts in certain locations.

    	location ~* /(?:cache|hooks|public/style_css|public/style_images|uploads)/.*.(?:pl|php[345]*)$ {

            	return 403;

    	}


    	# Deny access (403) to all .ht{passwd|access|etc} files

    	location ~* /.ht.*$ {

            	deny all;

    	}


    	# Handle PHP via FactCGI

    	location ~ .php$ {

            	fastcgi_split_path_info ^(.+.php)(.*)$;


            	# send php requests to php backend

            	fastcgi_pass	php;


            	# Add index.php to $fastcgi_script_name if URL ends with /

            	fastcgi_index index.php;


            	# Set SCRIPT_FILENAME relative to document root

            	fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


            	# Set rest of factcgi params from server defaults

            	include fastcgi_params;

    	}


    	# Cache static files and don't both logging 404 requests for them.

    	location ~* .(js|css|png|jpg|jpeg|gif|ico)$ {

            	expires max;

            	log_not_found off;

    	}





    	location / {


## vb threads to ipb rewrite

	rewrite /[0-9]+.+/([0-9]+)-.+.html /showthread.php?t=$1;


## without this i have member profiles on a redirect loop ##

	rewrite /user/([0-9]+)-.+ /index.php?showuser=$1;

    	try_files $uri $uri/ /index.php?q=$uri&$args;


    	}



location /nginx_status {

  stub_status on;

  access_log   off;

}



location ~ ^/(fpm_status|fpm_ping)$ {

	include fastcgi_params;

	fastcgi_pass php;

     fastcgi_param SCRIPT_FILENAME $fastcgi_script_name;

}



}




i think its fine, any advice?

also, anyone got problems with member profiles?

Link to comment
Share on other sites

Luis, are you asking if it is OK or are you saying this is a working configuration? If it is working for you then it is working, even if not perfect.

If you are having issues can I ask that you start a new topic specific to the problem? I am hoping to maintain this topic as one with working configurations/information and not broken configurations needing work. I started it because all of the NGINX config topics I found on here contain exactly that: "here is my broken config how do I fix it?" and not "here is a viable and working config".

:thumbsup:

Link to comment
Share on other sites

Adding one thing to the basic config:

client_max_body_size needed to set the max size of a request. This should be set the same as post_max_size from php.ini


upstream php {

        server unix:/tmp/php-cgi.sock

}


server {

        root /where/your/docroot/is;

        index index.php;


        # set to match php.ini post_max_size parameter or you'll get 413 errors when uploading images or attachments

        client_max_body_size	20M;


        # Deny access (403) access to all perl or php scripts in certain locations.

        location ~* /(?:cache|hooks|public/style_css|public/style_images|uploads)/.*\.(?:pl|php[345]*)$ {

                return 403;

        }


        # Deny access (403) to all .ht{passwd|access|etc} files

        location ~* /\.ht.*$ {

                deny all;

        }


        # Handle PHP via FactCGI

        location ~ \.php$ {

                fastcgi_split_path_info ^(.+\.php)(.*)$;


                # send php requests to php backend

                fastcgi_pass    php;


                # Add index.php to $fastcgi_script_name if URL ends with /

                fastcgi_index index.php;


                # Set SCRIPT_FILENAME relative to document root

                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;


                # Set rest of factcgi params from server defaults

                include fastcgi_params;

        }


        # Cache static files and don't both logging 404 requests for them.

        location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {

                expires max;

                log_not_found off;

        }


        # IPB in your root? Use this:

        # Rewrite all requests which aren't files or directories to /index.php

        #location / {

        #       try_files $uri $uri/ /index.php;

        #}


        # IPB in subdir? Use this (change subdir to suit):

        # Rewrite all requests which aren't files or directories to /forums/index.php

        location /forums {

                try_files $uri $uri/ /forums/index.php;

        }

}

Link to comment
Share on other sites


i think its fine, any advice?



also, anyone got problems with member profiles?




I suggest you change your location / { ... } to:


location / {

  try_files $uri $uri/ /index.php;

}


## vb threads to ipb rewrite

location ~ \/[0-9]+.+\/([0-9]+)-.+\.html {

  set $tid $1;

  rewrite ^ /showthread.php?t=$tid;

}


## without this i have member profiles on a redirect loop ##

location ~ \/user\/([0-9]+)-.+ {

  set $mid $1;

  rewrite ^ /index.php?showuser=$mid;

}


Link to comment
Share on other sites


BTW, look in my example, im using $args or some functions of ip.content wont work




NGINX rewrite module will append $args to the destination unless you end it with ? like this -> /index.php?

I haven't hooked up IP.Content yet so I can't offer anything specific. Do you have examples of the URLs that cause problems?
Link to comment
Share on other sites

May I suggest:

gzip  on;

gzip_types text/plain text/css text/xml application/x-javascript application/atom+xml application/rss+xml;



If you don't do "gzip_types" it will only do content with the text/html mime type. This declaration adds to "text/html" so you don't have to have it in there (nginx warns you otherwise).

Keep in mind that, depending on placement, this will also gzip the output of PHP files as well. So if your PHP script is gziping it's output you should turn it off or disable it on the application side. If you don't want nginx to gzip PHP files and want the app to handle it then place it inside of your location blocks instead of your http block. I would recommend letting nginx do it though because it'll be faster for it to handle it verses the PHP application.

Also gziping images or any binary file is pretty much useless. Should only gzip text files, like html css js or xml.

Does anyone know what's up with the "sendfile" declaration. It was on in the default config and from what I've read people say you should leave it on (not releated to X-Sendfile, but actually the sendfile() function on an OS).

Link to comment
Share on other sites


May I suggest:



gzip  on;

gzip_types text/plain text/css text/xml application/x-javascript application/atom+xml application/rss+xml;



If you don't do "gzip_types" it will only do content with the text/html mime type. This declaration adds to "text/html" so you don't have to have it in there (nginx warns you otherwise).

Keep in mind that, depending on placement, this will also gzip the output of PHP files as well. So if your PHP script is gziping it's output you should turn it off or disable it on the application side. If you don't want nginx to gzip PHP files and want the app to handle it then place it inside of your location blocks instead of your http block. I would recommend letting nginx do it though because it'll be faster for it to handle it verses the PHP application.

Also gziping images or any binary file is pretty much useless. Should only gzip text files, like html css js or xml.

Does anyone know what's up with the "sendfile" declaration. It was on in the default config and from what I've read people say you should leave it on (not releated to X-Sendfile, but actually the sendfile() function on an OS).



If you serve anything over NFS you should not use sendfile. sendfile is more efficient but only works with files on a local disk.

How does turning gzip on in the server config interact with enabling gzip in IPB? Is it harmless to turn it on for everything or are their tricks and traps to avoid?

I can't see gzip in the server adding much if IPB is already compressing the text/html content unless you serve a significant amount of static text. We are talking about text/html, text/css and text/javascript being the only beneficiaries of gzip compression.
Link to comment
Share on other sites

The general rule of thumb is anything in C is faster than PHP. That's why it's better for Nginx to do the compression instead of IPB doing it. If you have Nginx do it you need to turn it off on IPB. Don't want it to be double encoded. You can add this to your Nginx config to prevent most PHP applications from doing gzip themselves:

fastcgi_param  HTTP_ACCEPT_ENCODING "";



But I don't think IPB checks that header so I think you'd have to turn it off with a setting (don't remember where exactly).

Link to comment
Share on other sites


NGINX rewrite module will append $args to the destination unless you end it with ? like this -> /index.php?



I haven't hooked up IP.Content yet so I can't offer anything specific. Do you have examples of the URLs that cause problems?




here you go:

Unlike rewrite, $args are not automatically preserved if the fallback is not a named location. If you need args preserved, you must do so explicitly


Link to comment
Share on other sites

Not sure on your worker or connections but NGINX loves more workes less connections if you spread it out.

So for an example if your config has:

nginx_workers=1
nginx_connections=5000

That basicly means one worker can use 5000, Now if you adjust those values to:

nginx_workers=5
nginx_connections=1000

you have exactly the same values and connection, But you will see better performance overall.

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...