Nginx? No thank you... Lighttpd
Nginx is 3rd (or 2nd depending on the statistics) most popular web server. It seems that it should be one of the best servers around however, every time I have to deal with it I understand that I really don't like it.
When you look deep down into the Nginx web server you realize that it not as good as you think it is. Even though, it is a good reverse proxy and very well suited for serving static files, when it comes to dynamic content it begins to feel sloppy.
It is not uncommon that you have a web site powered by nginx and in reality it works like a load balancer or reverse proxy in front of Apache or other services.
And this is not an accident, this popular webs sever has too many flaws:
First of all it is not capable to handle CGI scripts at all.
It does not support automatic control of a lifetime of FastCGI and SCGI processes.
Basically this means that you need to prepare a separate services to run your FastCGI application instead giving this simple job to a web server.
FastCGI support was broken for a long time and only recently we got an option to setup a CGI variable
PATH_INFO
correctly as required by CGI RFC.Before that you need to do some tricks with rewriting and you could not get url-decoded
PATH_INFO
as required by RFC.SCGI support is totally broken as:
- It requires from the SCGI server to send full HTTP headers instead of parsing
Status
header. PATH_INFO
andSCRIPT_NAME
do not work in the same way they were not working with fastcgi.
- It requires from the SCGI server to send full HTTP headers instead of parsing
Basic security feature like
Options -FollowSymLinks
that is implemented in all normal web servers starting from a "fat" Apache to a small and tiny thttpd is not implemented!Short explanation: consider Alice that creates a symbolic link such that it points to /var/users/passwords file. Alice does not have permissions to read this file but web sever may have such permissions. By creating an innocent symbolic link in the document root of her web server it escalates her abilities to read any file that the web server can read.
Every modern web server has an option to track symbolic links and prevent serving files outside of the scope of the web server document root, but nginx does not have one.
The documentation quality is overall lower then the quality of documents of Lighttpd or Apache web servers. Also the configuration is generally much more complicated and verbose even for simple tasks.
I've worked with nginx in different configurations and what I get most of the times is a feeling that the development of this web server is not performed according to protocol specifications but rather according what feature is needed as this specific point.
For example, it was mentioned in nginx source code that "Apache' specific
PATH_INFO
feature was not implemented. While PATH_INFO
is
a standardized environment variable defined by CGI 1.1 specifications
and is not some "web server specific feature"
I know such note may look petty, but this is the general feeling of the level of implementation of many features.
So despite the popularity of this web server I would not choose it for serving dynamic content. If I need a high quality lightweight web server I'd always choose Lighttpd
- It has a similar asynchronous design as nginx has.
- It is very well suited for dynamic content and supports CGI, HTTP, FastCGI and SCGI protocols. The development version supports Tomcat's AJP13 protocol as well.
- It is very well documented and has a rich set of modules.
Before you jump and say:
Buy lighttpd leaks!
I'll answer: "not true, it does not leak". It is one of the well know urban legends on the Internet.
Quoting:
there are no memory leaks just stupid ways to use lighttpd.
e.g. it is really stupid to stream large files via a fastcgi app, when x-lighttpd-send-file could do a much more efficient job.
For further reading:
So if you consider using Nginx on your web site, I'd strongly recommend to take a look on Lighttpd first.
Comments
This was the straw that broke the camel's back for me:
http://redmine.lighttpd.net/issues/665
Blatant disregard for users over a fairly trivial and basic piece of functionality.
I've had many many problems with PATH_INFO and friends with lighttpd (though I believe most of them are now fixed). The attitude you see in the bug above is a good demonstration on why those fixes took so long.
As far as config goes, apache is (of course) awful, lighttpd is slightly less awful, but still powerful, and nginx is relatively sane (but limited).
I don't mind the limitations. The "throw everything in one box" is why apache is the way it is (and why we have travesties like php around now), separation of concerns is a good thing (and the unix way), and nginx is closest to getting that right.
As for me, nginx drives me crazy every time I discover that some feature that you expect to work is not implemented according to RFC specifications.
I would less care about having feature XYZ implemented. However I do explect that if it is implemented it works according to specifications, because that what makes the software portable and independent of the specific web-server platform.
And please note, I'm looking at the web server from the point of view of the framework developer that expects certain things to behave certain way. And Nginx developer looks on RFC as on "suggestion only".
About lighttpd development. There were several cases when I submitted several patches and bug reports and they were accepted and fixed.
Thanks for u'r interesting article.
Igor Sysoev, ask him why he do that.
Last lighttpd 1.5 version from 2007 year?
1.5 is development version. Stable version 1.4.30 released in Dec. 2011.
I was wondering about the performance though, using cppcms of course. Did you or are you considering doing some test ? After all cppcms is faster if the web server is faster.
As far as I remember. the performance differences are negligible between lighttpd and nginx. Also note that generally serving dynamic content is much more complex task then serving for example static file were you have nice helpers as
sendfile
system call. So the web server would unlikely be the bottle-neck for dynamic content.Dear Artyom!
First of all thank you for your great work!
Second, I share your opinion about nginx mostly based on my experience in implementing large-scale distributed systems, which of cause not only base on serve static files. I tried many times to use nginx in my projects and projects of my customers, but always had small or big problems in the implementation of the requirements using ngnix. Personaly I really like lighttpd and use it for ages without any problem. For my local tests using cppcms lighttpd better (faster) than ngnix.
Good for security and perfomance. If somebody still needs this obsolete interface, so there are a plenty of wrappers.
Lighttpd itself dosn't support it too. Basically it's a job for application server like uWSGI, Phusion Passenger, PHP-FPM, etc...
It's not true. With NGINX you have a lof of ways to set PATH_INFO. And fastcgi_split_path_info isn't the only one. Btw, this directive appeared in version 0.7.31, which was released more then 3 years ago. In terms of stagnating Lighttpd it may be "recently".
You're just wrong here. Probably you even never use nginx yourself.
I don't know much about tiny thttpd. But in Apache and Lighttpd this option is just noop, cuz of race conditions in the code. Yeah, it will protect you from teenager, but don't protect you from purposeful attack.
Btw, nginx folks implement disable_symlinks option in the recent version WITHOUT race condition in the code. Therefore, it's really safe.
Documentation maybe. But, IMHO, nginx configuration is much simpler than Apache and more flexible than lighty.
Security? How exactly
Performance? Depends on the task you do.
If is far from being obsolete
Starting, stopping, restarting on fail and handling a pool is not considered handling lifetime? Hmmm....
First of all it is the only right way. Because PATH_INFO must be urldecoded according to RFC specifications.
Have to tried to use
Status
header as expected by the CGI specifications it is based on? I assume you hadn't. Without full HTTP headers it would just not work.Second is it has same
PATH_INFO
problem as FastCGI used to have.PATH_INFO
must be URL-decoded... And it is not possible to specify it this way in Nginx.For me it is broken. Of course you can workaround it on application side... But it makes SCGI considerably less useful.
It protects if the LAST file is symbolic link, if there is a symbolic link in the path (directory) it would not handle it.
So don't tell me stories about its "safety"
Hello, may I clarify some things?
You can set PATH_INFO this way:
and it will be urldecoded. NGINX configuration syntax is very flexible.
NGINX SCGI upstream module can parse the standard response Status-Line as well as the "Status" header. If you encounter any bugs here, please, fill a bug-report.
http://trac.nginx.org/nginx/
http://nginx.org/r/disable_symlinks
"on" - If any component of the pathname is a symbolic link, access to a file is denied.
Yes it works for FastCGI (not SCGI) for latest Nginx version. It wasn't for a long time ago.
Quoting: http://wiki.nginx.org/NgxSCGIModule
And the last time I checked it was not working.
I assume you refer to this fix:
http://trac.nginx.org/nginx/changeset/4438/nginx
That was done... four weeks ago? So cool!
But this is now what is required frequently...
Hm...
doesn't work?
No, it's just some minor fix according to this ticket: http://trac.nginx.org/nginx/ticket/66
This page is about 3rd party module and was outdated, since NGINX has got buit-in SCGI module (added in nginx 0.8.42 - 21 Jun 2010), which supports the "Status" header.
Just lack of official documentation, and now we're actively working on it:
http://trac.nginx.org/nginx/timeline?repo-nginx_org=on
http://nginx.org/en/docs/
btw, actual wiki page about SCGI is here: http://wiki.nginx.org/HttpScgiModule and it is mentioned on build-in modules wiki page: http://wiki.nginx.org/Modules
hm, I don't know how you could found the old one... anyway it must be deleted.
No: it would not urldecode
PATH_INFO
I've actually tested SCGI with Nginx:
http://cppcms.com/wikipp/en/page/cppcms_1x_tut_web_server_config#Nginx..SCGI
It works only if full HTTP headers sent. It does not behave correctly with
CGI
headers... I actually tested this when I had written this wiki.SCGI is broken in Nginx... Sorry
Sorry, it works well.
Hi, sorry for necrocommenting, but I had to chime in. I'm the author of the SCGI C library (http://www.xamuel.com/scgilib/) and artyom is quite right. SCGI is broken in nginx. The following response is taken verbatim from the SCGI protocol (http://python.ca/scgi/protocol.txt):
Status: 200 OK\n\rContent-Type: text/plain\n\r\n\r42
But this causes nginx to issue an error "upstream sent invalid header while reading response header from upstream" and send the client a 502.
Nginx will happily route the intended response if it instead goes
HTTP/1.1 200 OK\n\r\n\r42
Even though this is blatantly contrary to the SCGI protocol.
This has just caused me to pull my hair out for three hours, all for something nginx's developers could've fixed in minutes. I'm deeply grateful to artyom's comments here, without them I would never have gotten to the bottom of the issue.
@Sam
Actually this bug was fixed (I hope) in nginx 1.1.17 also in any case the number of problems with nginx and scgi/fcgi is so huge that it makes me wonder why the hell on earth should be use nginx.
I personally use lighttpd in heavily loaded production environment and it works very well.
I spent Last week configuring Two VPS servers for first time . I was have two choices Lighttpd Or Nginx So I ended installing Lighttpd on server Nginx on the other I notice Lighttpd configuration alot easier then Nginx Specially to make website work for first time . Only good about Nginx configuration syntax looks similar to Apache syntax .so who moving from Apache will see it easier . Now for real comparison Nginx use More MEM then Lighttpd
This is nginx On VPS1 USER PID %CPU %MEM VSZ RSS
www-data 3718 0.0 0.5 10136 1364 www-data 3719 0.0 0.5 10136 1364
www-data 3720 0.0 0.5 10136 1364
www-data 3721 0.0 0.6 10136 1716 Total ~5.4MB this is Lighttpd On VPS2 USER PID %CPU %MEM VSZ RSS
www-data 1396 0.0 1.0 5128 1396 Totall ~1.36MB I only add single index.html file with "Hello world" contents And Lighttpd was load 200Ms faster I test it here http://browserspy.dk/webserver.php server lighttpd/1.4.31 Time to contact web server 0.343193 seconds server nginx/1.2.1 Time to contact web server 0.588151 seconds
BTW the two VPS on diffrent provider VPS2 use and E3-1240 V2@3.40GHz 128MB and VPS1 use E3-1230 V2@3.30GHz with 256MB . I'll remove nginx on VPS1 adn wi'll install Lighttpd to see the result .
Add Comment:
You must enable JavaScript in order to post comments.