Recently I’ve encountered a special case scenario where Nginx strict configuration rules seemed to be unable to accommodate the specific directions I wanted them to carry. From that point, one thing led to another and all of a sudden I found myself researching open source web (http) servers in order to find the one that could provide me with high performance while being flexible at the same time.
Below you’ll find the fruits of my labor, after making lots of vigorous testings and tweaking in order to find the ultimate server which I set out to find.
Oh, and for the curious among you, here’s the Nginx “riddle” I was facing. See if you can solve the following configuration task before you finish reading the article. I’ll reveal the answer at the end of the article:
[Nginx Configuration Riddle]
Nginx rules structure ordered by priority:
- = (exactly) : location = /path
- ^~ (forward match) : location ^~ /path
- ~ (regular expression case sensitive) : location ~ /path/
- ~* (regular expression case insensitive) : location ~* .(jpg|png|bmp)
- / : location /path
Your mission is to be able to direct all http requests to https as long as they do not contain the phrase “no_redirection” in them. Requests that do contain “no_redirection” are to return a 410 error page.
So urls such as:
http://iwf1.com
http://iwf1.com/no_apache-vs-nginx-vs-lighttpd_redirection
http://iwf1.com/apache-vs-nginx-vs-lighttpd?redirection_no
are valid for redirection, whereas urls such as:
http://iwf1.com/no_redirection
http://iwf1.com/no_redirection/http_servers_comparison
http://iwf1.com/no_redirection?apache-vs-nginx-vs-lighttpd
are invalid, and should return error 410.
My starting point was these rules:
if ($scheme = http) {
return 301 https://$server_name$request_uri;
}
and
location ~ /no_redirection {
return 410;
}
Needles to say the rules above couldn’t deliver the required behavior.
And now, on to the comparison.
The Servers
Apache
Apache made its first appearance on 1995, continuing another http server project (the public domain HTTP daemon) which development started to stall after the main developer had left the project. A group of aspiring webmasters then got together in order to coordinate their patches and bugfixes to the server and thus Apache was forged (a Patchy server).
With over twenty years of experience, Apache gained popularity[1] and accumulated lots of features along the way, possibly to the point where it may have become bloated, some would say.
Claim to fame: feature-packed, most popular web server.
Myths to shatter: resource-hog, slow.
Lighttpd
Lighttpd (pronounced “lighty”) was first introduced to the world on 2003. Originally it was a proof of concept that the C10k problem can be solved, i.e. that one server can be made to handle 10,000 connections in parallel. Thanks to that proof, the high performance server later became quite popular that at some point it was even adopted by large scale sites such as YouTube, Reddit, ThePirateBay and so on (all three seem to have moved on to other servers by now though).
Upon gaining popularity, the large userbase had inevitably started filling the role of testing Lighttpd – a role which the small developers team apparently couldn’t cover fully. Some bug reports were filled regarding allegedly found memory leaks, most prominently concerning the F/CGI implementation which gave rise to rumors about Lighttpd being unstable.
Claim to fame: fast, solves the C10k problem.
Myths to shatter: buggy, contains memory leaks.
Nginx
Nginx (pronounced Engine X) was first publicly released on 2004. Just like Lighttpd, Nginx was also set out to solve the C10k problem, but being published a year after Lighttpd, it wasn’t credited for it. Its main premise however, became a lot more dominant as time went by: using asynchronous event-driven approach to handle requests.
The same approach have made it one of the most high performance servers out there today, being the second most popular in the world, according to recent statistics[1]. Yet Nginx strive for high performance comes with a price, the server has a set of rules which priority is unconfigurable, it also doesn’t allow for overriding systemwide access settings on a per-file basis (more on that below).
Claim to fame: asynchronous, event-driven.
Myths to shatter: limiting, strict.
Features
It is widely known that when it comes to features, Apache is one of the leading web servers out there to supply you with the feature you want. But how does it compare to Nginx and Lighttpd?
Before you, are lists of modular features each server can be compiled with. These features can be used either as plug-able modules which you can then set the server configuration to use, or, these features can also be compiled statically, meaning not as modules but rather built-into the server instead.
Note: the lists are scroll-able.
[ + + means installed, – – means not installed. ]
Apache-2.4.27-r1:
Installed | Feature | Description |
---|---|---|
– – | apache2_modules_access_compat | Group authorizations based on host (name or IP address). Available as a compatibility module with previous versions. |
+ + | apache2_modules_actions | Provides for executing CGI scripts based on media type or request method |
+ + | apache2_modules_alias | Provides for mapping different parts of the host filesystem in the document tree and for URL redirection |
– – | apache2_modules_asis | Sends files that contain their own HTTP headers |
+ + | apache2_modules_auth_basic | Basic authentication |
– – | apache2_modules_auth_digest | User authentication using MD5 Digest Authentication |
+ + | apache2_modules_authn_alias | Provides the ability to create extended authentication providers based on actual providers |
– – | apache2_modules_authn_anon | Allows “anonymous” user access to authenticated areas |
+ + | apache2_modules_authn_core | Provides core authentication capabilities common to all authentication providers (functionality provided by authn_alias in previous versions). |
– – | apache2_modules_authn_dbd | User authentication using an SQL database |
– – | apache2_modules_authn_dbm | User authentication using DBM files |
– – | apache2_modules_authn_file | User authentication using text files |
+ + | apache2_modules_authz_core | Provides core authorization capabilities to various authorization/authorization modules, such as authn_file and authz_user. |
– – | apache2_modules_authz_dbd | Provides authorization capabilities via SQL database so that authenticated users can be allowed or denied access to portions of the web site by group membership. |
– – | apache2_modules_authz_dbm | Group authorization using DBM files |
– – | apache2_modules_authz_groupfile | Group authorization using plaintext files |
+ + | apache2_modules_authz_host | Group authorizations based on host (name or IP address) |
– – | apache2_modules_authz_owner | Authorization based on file ownership |
– – | apache2_modules_authz_user | User Authorization |
+ + | apache2_modules_autoindex | Generates directory indexes, automatically, similar to the Unix ls command |
+ + | apache2_modules_cache | Content cache keyed to URIs |
– – | modules_cache_disk | Disk based storage module for the HTTP caching filter (similar to mem_cache in previous versions). |
– – | apache2_modules_cache_socache | Shared object cache (socache) based storage module for the HTTP caching filter. |
– – | apache2_modules_cern_meta | CERN httpd metafile semantics |
– – | apache2_modules_cgi | Enable CGI module (used by non-multithreaded MPMs, for eg. prefork) |
– – | apache2_modules_cgid | Enable CGI module (used by multithreaded MPMs, for eg. worker) |
– – | modules_charset_lite | Specify character set translation or recoding |
– – | apache2_modules_dav | Distributed Authoring and Versioning (WebDAV) functionality |
– – | apache2_modules_dav_fs | filesystem provider for mod_dav |
– – | apache2_modules_dav_lock | generic locking module for mod_dav |
– – | apache2_modules_dbd | Manages SQL database connections |
+ + | apache2_modules_deflate | Compress content before it is delivered to the client |
+ + | apache2_modules_dir | Provides for “trailing slash” redirects and serving directory index files |
– – | apache2_modules_dumpio | Dumps all I/O to error log as desired |
– – | apache2_modules_env | Modifies the environment which is passed to CGI scripts and SSI pages |
+ + | apache2_modules_expires | Generation of Expires and Cache-Control HTTP headers according to user-specified criteria |
– – | apache2_modules_ext_filter | Pass the response body through an external program before delivery to the client |
– – | apache2_modules_file_cache | Caches a static list of files in memory |
+ + | apache2_modules_filter | Context-sensitive smart filter configuration module |
+ + | apache2_modules_headers | Customization of HTTP request and response headers |
+ + | apache2_modules_http2 | Enable http2/alpn module |
– – | apache2_modules_ident | RFC 1413 ident lookups |
– – | apache2_modules_imagemap | Server-side imagemap processing |
+ + | apache2_modules_include | Server-parsed html documents (Server Side Includes) |
– – | apache2_modules_info | Provides a comprehensive overview of the server configuration |
– – | apache2_modules_lbmethod_bybusyness | Pending request counting load balancer scheduler algorithm for proxy_balancer. |
– – | apache2_modules_lbmethod_byrequests | Request counting load balancer scheduler algorithm for proxy_balancer. |
– – | apache2_modules_lbmethod_bytraffic | Weighted traffic counting load balancer scheduler algorithm for proxy_balancer. |
– – | apache2_modules_lbmethod_heartbeat | Heartbeat traffic counting load balancer scheduler algorithm for proxy_balancer. |
+ + | apache2_modules_log_config | Logging of the requests made to the server |
– – | modules_log_forensic | Forensic Logging of the requests made to the server |
– – | apache2_modules_logio | Logging of input and output bytes per request |
– – | apache2_modules_macro | Macros for the Apache config file. |
+ + | apache2_modules_mime | Associates the requested filename’s extensions with the file’s behavior (handlers and filters) and content (mime-type, language, character set and encoding) |
+ + | apache2_modules_mime_magic | Determines the MIME type of a file by looking at a few bytes of its contents |
– – | apache2_modules_negotiation | Provides for content negotiation |
+ + | apache2_modules_proxy | HTTP/1.1 proxy/gateway server |
– – | apache2_modules_proxy_ajp | AJP support module for mod_proxy |
– – | apache2_modules_proxy_balancer | mod_proxy extension for load balancing |
– – | apache2_modules_proxy_connect | mod_proxy extension for CONNECT request handling |
+ + | apache2_modules_proxy_fcgi | FCGI support module for mod_proxy. |
– – | apache2_modules_proxy_ftp | FTP support module for mod_proxy |
– – | apache2_modules_proxy_html | Module to rewrite links in html pages behind a reverse proxy |
– – | apache2_modules_proxy_http | HTTP support module for mod_proxy |
– – | apache2_modules_proxy_scgi | SCGI gateway module for mod_proxy |
– – | apache2_modules_proxy_wstunnel | Provides support for the tunnelling of web socket connections to a backend websockets server. |
– – | apache2_modules_ratelimit | Ratelimit module for transfer rate management |
– – | apache2_modules_remoteip | Remotip module for logging |
– – | apache2_modules_reqtimeout | Set timeout and minimum data rate for receiving requests |
+ + | apache2_modules_rewrite | Provides a rule-based rewriting engine to rewrite requested URLs on the fly |
– – | apache2_modules_setenvif | Allows the setting of environment variables based on characteristics of the request |
– – | apache2_modules_slotmem_shm | Slot-based shared memory provider. |
+ + | apache2_modules_socache_shmcb | A shared object cache provider using a high-performance cyclic buffer inside a shared memory segment. |
– – | apache2_modules_speling | Attempts to correct mistaken URLs that users might have entered by ignoring capitalization and by allowing up to one misspelling |
– – | apache2_modules_status | Provides information on server activity and performance |
– – | apache2_modules_substitute | Perform search and replace operations on response bodies |
+ + | apache2_modules_unique_id | Provides an environment variable with a unique identifier for each request |
+ + | apache2_modules_unixd | Basic (required) security for Unix-family platforms. |
– – | apache2_modules_userdir | User-specific directories |
– – | apache2_modules_usertrack | Clickstream logging of user activity on a site |
– – | apache2_modules_version | Version dependent configuration |
– – | apache2_modules_vhost_alias | Provides for dynamically configured mass virtual hosting |
– – | apache2_modules_xml2enc | Enable xml2 encoding module |
+ + | apache2_mpms_event | An experimental variant of the standard worker MPM |
– – | apache2_mpms_prefork | Implements a non-threaded, pre-forking web server |
– – | apache2_mpms_worker | Multi-Processing Module implementing a hybrid multi-threaded multi-process web server |
– – | debug | Enable extra debug codepaths, like asserts and extra output. If you want to get meaningful backtraces see https://wiki.gentoo.org/wiki/Project:Quality_Assurance/Backtraces |
– – | doc | Add extra documentation (API, Javadoc, etc). It is recommended to enable per package instead of globally |
– – | ldap | Add LDAP support (Lightweight Directory Access Protocol) |
– – | libressl | Use dev-libs/libressl as SSL provider (might need ssl USE flag), packages should not depend on this USE flag |
+ + | ssl | Add support for Secure Socket Layer connections |
– – | static | Link in apache2 modules statically rather then plugins |
– – | suexec | Install suexec with apache |
+ + | threads | Add threads support for various packages. Usually pthreads |
Total of 94 modular features
Nginx-1.12.1:
Installed | Feature | Description |
---|---|---|
– – | aio | Enables file AIO support |
– – | debug | Enable extra debug codepaths, like asserts and extra output. If you want to get meaningful backtraces see https://wiki.gentoo.org/wiki/Project:Quality_Assurance/Backtraces |
+ + | http | Enable HTTP core support |
+ + | http-cache | Enable HTTP cache support |
+ + | http2 | Enable HTTP2 module support |
+ + | ipv6 | Add support for IP version 6 |
– – | libatomic | Use libatomic instead of builtin atomic operations |
– – | libressl | Use dev-libs/libressl as SSL provider (might need ssl USE flag), packages should not depend on this USE flag |
– – | luajit | Use dev-lang/luajit instead of dev-lang/lua for lua support when building the lua http module. |
+ + | nginx_modules_http_access | This module provides a simple host-based access control. |
+ + | nginx_modules_http_addition | This module adds contents of other locations before and after the current location’s content. |
– – | nginx_modules_http_auth_basic | This module protects your site or parts of it with username and password based on HTTP Basic Authentication. |
– – | nginx_modules_http_auth_ldap | LDAP module for nginx which supports authentication against multiple LDAP servers. |
+ + | nginx_modules_http_auth_pam | This module provides authentication via PAM. |
– – | nginx_modules_http_auth_request | Module implementing client authorization based on the result of a subrequest. |
+ + | nginx_modules_http_autoindex | This module provides automatic directory listings. |
+ + | nginx_modules_http_browser | This module creates variables, the values of which depend on the request header “User-agent”. |
– – | nginx_modules_http_cache_purge | External module adding ability to purge content from nginx’s FastCGI and proxy caches. |
+ + | nginx_modules_http_charset | This module can reencode data of one encoding into another. |
– – | nginx_modules_http_dav | This module adds the HTTP and WebDAV methods PUT, DELETE, MKCOL, COPY and MOVE. |
– – | nginx_modules_http_dav_ext | Add missing WebDAV methods PROPFIND & OPTIONS to the existing WebDAV module. |
– – | nginx_modules_http_degradation | Allows to return 204 or 444 code for some locations on low memory condition (reliable on FreeBSD only) |
+ + | nginx_modules_http_echo | Brings shell-style goodies to Nginx config file. |
– – | nginx_modules_http_empty_gif | This module keeps a 1×1 transparent GIF in memory that can be served very quickly. |
– – | nginx_modules_http_fancyindex | This module makes possible the generation of file listings, like the built-in autoindex module does, but adding a touch of style. |
+ + | nginx_modules_http_fastcgi | This module allows Nginx to interact with FastCGI processes and control what parameters are passed to the process. |
– – | nginx_modules_http_flv | This module provides the ability to seek within FLV (Flash) files using time-based offsets. |
+ + | nginx_modules_http_geo | This module creates variables, whose values depend on the IP-address of the client. |
– – | nginx_modules_http_geoip | This module creates variables based on the IP-address of the client matched against the MaxMind GeoIP binary files. |
+ + | nginx_modules_http_gunzip | Permits to decompress gzip’ed files on-the-fly for clients not supporting the gzip encoding method. |
+ + | nginx_modules_http_gzip | This module allows for on-the-fly gzip compression. |
+ + | nginx_modules_http_gzip_static | Before serving a file from disk to a gzip-enabled client, this module will look for a precompressed file in the same location. |
+ + | nginx_modules_http_headers_more | Set and clear input and output headers |
+ + | nginx_modules_http_image_filter | This module is a filter for transforming JPEG, GIF and PNG images. |
+ + | nginx_modules_http_limit_conn | This module makes it possible to limit the number of simultaneous connections for the assigned session |
+ + | nginx_modules_http_limit_req | This module allows you to limit the number of requests for a given session. |
– – | nginx_modules_http_lua | Embed the power of Lua into nginx |
+ + | nginx_modules_http_map | This module allows you to classify, or map a set of values into a different set of values and store the result in a variable. |
– – | nginx_modules_http_memc | An extended version of the standard memcached module that supports set, add, delete, and many more memcached commands. |
+ + | nginx_modules_http_memcached | You can use this module to perform simple caching. |
– – | nginx_modules_http_metrics | Module to export various metrics in easy-parseable JSON. |
– – | nginx_modules_http_mogilefs | Enable support for MogileFS. |
– – | nginx_modules_http_mp4 | This module adds pseudo-streaming |
– – | nginx_modules_http_naxsi | An open source, high performance, low rules maintenance, Web Application Firewall module for Nginx. |
– – | nginx_modules_http_perl | This module makes it possible to execute Perl directly within Nginx and call Perl via SSI. |
+ + | nginx_modules_http_proxy | This module makes it possible to transfer requests to another server. |
– – | nginx_modules_http_push_stream | Push Stream module, supporting EventSource, WebSocket, Long Polling, and Forever Iframe. |
+ + | nginx_modules_http_random_index | Pick a random directory index from a directory. |
– – | nginx_modules_http_realip | This module allows to change the client’s IP address to value from request header (e. g. X-Real-IP or X-Forwarded-For). |
+ + | nginx_modules_http_referer | This module makes it possible to block access to the site with the incorrect values of line “Referer” in the request header. |
+ + | nginx_modules_http_rewrite | This module makes it possible to change URI using regular expressions (PCRE), and to redirect and select configuration depending on variables. |
+ + | nginx_modules_http_scgi | An implementation of the Simple Common Gateway Interface. |
– – | nginx_modules_http_secure_link | This module computes and checks request URLs for a required security token. |
– – | nginx_modules_http_security | Web application firewall and Intrusion Detection System. |
+ + | nginx_modules_http_slice | A filter that splits a request into subrequests, each returning a certain range of response |
+ + | nginx_modules_http_slowfs_cache | This module adds the ability to cache static files |
– – | nginx_modules_http_spdy | This module provides an SPDY implementation. (Deprecated, use IUSE=”http2″ instead) |
– – | nginx_modules_http_split_clients | This module provides A/B testing support. |
+ + | nginx_modules_http_ssi | This module provides a filter which processes Server-Side Includes (SSI) in the input. |
– – | nginx_modules_http_sticky | Module to always forward clients to the same upstream server (via sticky cookies) |
+ + | nginx_modules_http_stub_status | This module provides the ability to get some status from nginx. |
– – | nginx_modules_http_sub | This module can search and replace text in the nginx response. |
+ + | nginx_modules_http_upload_progress | This module adds the ability to track POST upload progress via JSON API |
– – | nginx_modules_http_upstream_check | Add health check support for upstream servers. |
– – | nginx_modules_http_upstream_hash | This module provides the ability to distribute upstream requests based on hashed key value. |
– – | nginx_modules_http_upstream_ip_hash | This module provides the ability to distribute upstream requests based on the IP-address of the client. |
– – | nginx_modules_http_upstream_keepalive | Thiis module provides the ability to cache connections to upstream servers. |
– – | nginx_modules_http_upstream_least_conn | This module provides the ability to distribute upstream requests using load balancing methods. |
– – | nginx_modules_http_upstream_zone | This module makes it possible to define a shared memory zone that keeps the group’s configuration and run-time state that are shared between worker processes. |
+ + | nginx_modules_http_userid | This module gives out cookies for identification of clients. |
– – | nginx_modules_http_uwsgi | External module for the uWSGI protocol for python web apps. |
– – | nginx_modules_http_xslt | This module is a filter which converts an XML response with the aid of one or more XSLT templates. |
– – | nginx_modules_mail_imap | This module provides IMAP proxy capability. |
– – | nginx_modules_mail_pop3 | This module provides POP3 proxy capability. |
– – | nginx_modules_mail_smtp | This module provides SMTP proxy capability. |
– – | nginx_modules_stream_access | This module allows limiting access to certain client addresses. |
– – | nginx_modules_stream_geo | This module creates variables, whose values depend on the IP-address of the client. |
– – | nginx_modules_stream_geoip | This module creates variables based on the IP-address of the client matched against the MaxMind GeoIP binary files. |
– – | nginx_modules_stream_limit_conn | This module is used to limit the number of connections per the defined key. |
– – | nginx_modules_stream_map | This module allows you to classify, or map a set of values into a different set of values and store the result in a variable. |
– – | nginx_modules_stream_realip | This module allows to change the client’s IP address to value from request header (e. g. X-Real-IP or X-Forwarded-For). |
– – | nginx_modules_stream_return | This module allows sending a specified value to the client and then closing the connection. |
– – | nginx_modules_stream_split_clients | This module provides A/B testing support. |
– – | nginx_modules_stream_ssl_preread | This module allows extracting information from the ClientHello message without terminating SSL/TLS. |
– – | nginx_modules_stream_upstream_hash | This module provides the ability to distribute upstream requests based on hashed key value. |
– – | nginx_modules_stream_upstream_least_conn | This module provides the ability to distribute upstream requests using load balancing methods. |
– – | nginx_modules_stream_upstream_zone | This module makes it possible to define a shared memory zone that keeps the group’s configuration and run-time state that are shared between worker processes. |
+ + | pcre | Add support for Perl Compatible Regular Expressions |
– – | pcre-jit | Enable JIT for pcre |
+ + | rtmp | NGINX-based Media Streaming Server |
+ + | ssl | Enable HTTPS module for http. Enable SSL/TLS support for POP3/IMAP/SMTP for mail. |
+ + | threads | Add threads support for various packages. Usually pthreads |
– – | vim-syntax | Pulls in related vim syntax scripts |
Total of 93 modular features
Lighttpd-1.4.45:
Installed | Feature | Description |
---|---|---|
+ + | bzip2 | Use the bzlib compression library |
– – | doc | Add extra documentation (API, Javadoc, etc). It is recommended to enable per package instead of globally |
+ + | fam | Enable FAM (File Alteration Monitor) support |
+ + | gdbm | Add support for sys-libs/gdbm (GNU database libraries) |
+ + | ipv6 | Add support for IP version 6 |
– – | kerberos | Add kerberos support |
– – | ldap | Add LDAP support (Lightweight Directory Access Protocol) |
+ + | libev | Enable fdevent handler |
– – | libressl | Use dev-libs/libressl as SSL provider (might need ssl USE flag), packages should not depend on this USE flag |
– – | lua | Enable Lua scripting support |
– – | memcached | Add support for memcached |
– – | minimal | Install a very minimal build (disables, for example, plugins, fonts, most drivers, non-critical features) |
– – | mmap | Use mmap with files owned by lighttpd. This is a dangerous option as it may allow local users to trigger SIGBUS crashes. |
+ + | mysql | Add mySQL Database support |
+ + | pcre | Add support for Perl Compatible Regular Expressions |
– – | php | Include support for the PHP language |
– – | rrdtool | Enable rrdtool support via mod_rrdtool |
+ + | ssl | Add support for Secure Socket Layer connections |
– – | test | Workaround to pull in packages needed to run with FEATURES=test. Portage-2.1.2 handles this internally, so don’t set it in make.conf/package.use anymore |
– – | webdav | Enable webdav properties |
+ + | xattr | Add support for extended attributes (filesystem-stored metadata) |
+ + | zlib | Add support for zlib (de)compression |
Total of 22 modular features
Quite surprisingly, when looking at the total sum of each list, it seem as though Nginx has managed to almost catch up with Apache’s feature set. Lighttpd on the other hand is still lagging behind, and perhaps it’s for the better because the name Lighttpd do suggests lightweight-ness.
Also, here are some things that aren’t being reflected by the lists above –
- First of all, let’s start by mentioning that most users won’t even need all these features in the first place. For instance, Apache’s “xml2enc” module or Nginx’ “uwsgi” http module would probably not be part of any standard installation. It’s good to have them there as options, but it probably won’t make any difference for many users if they weren’t.
- Another point I want to emphasize is that some of these features’ names do not reveal their actual nature, and what I mean by that is, for example, Apache’s http2 implementation also allows you to use the “h2c” directive which can upgrade http/1.1 connections to http/2 (note that web-browsers only supports http2 over ssl, i.e. https), whereas Nginx’ http2 implementation allows for setting http/2 connection only (meaning no connection upgrade, either the connection is v. 1.1 or 2.0).
- Thirdly, neither Nginx nor Lighttpd have any equivalent to Apache’s decentralized approach, where one could use “.htaccess” files to override systemwide directives. Apparently, the centralized approach is more geared towards performance as some of the tuning advice for Apache you’ll find in many online resources like to suggest – turning off htaccess support by using the directive:
AllowOverride None
in httpd.conf. That said, without htaccess (or equivalent) shared hosting would probably be a real flop.
Now personally, the features I cared about, besides the basics of course – rewrite, redirect, include, etc…, were: support for ssl, http/2 connections, php-fpm, and of course flexibility and speed (but we’ll get to that later on).
I found that both Apache and Nginx could accommodate my requirements but as for Lighttpd, I would have to compromise on http/2.
Configuration Syntax
Before ending up the Features section and moving on to the next topic, I’d like to draw your attention to each server’s configuration syntax as a feature in its own. While most readers may be familiar to some extent with Apache’s configuration syntax or Nginx’s, many are probably unfamiliar with Lighttpd’s one, and more importantly – how does the syntax actually serves as a feature of the server.
So starting with the most widely known one – Apache. Apache’s configuration syntax is quite broad and well structured it uses predetermined directives to enable the user an easy way to configure the server (instead of, for example, requiring the user to write code). It also allows the user to include wildcards within the scope of each directive, or use a dedicated regex directives instead. Apache does not prioritizes clear-text syntax over regex one. The priority of directives is then determined by order of placement or by closer match (regardless if the match is reached by regex or plain text), for example:
<Files "index.html">
Require all granted
</Files>
<Directory "/mydir">
Require all denied
</Directory>
The above configuration will deny anyone from accessing files inside “mydir” directory unless the file requested is “index.html”, and that’s depite the fact that “Require all denied” is set after “Require all granted”.
Similarly to Apache, Nginx also comes with directives and dedicated directives for regex built-in as part of its syntax, however, whereas Apache does not prioritizes clear-text over regex Nginx on the other hand does, since an exact match cannot equal a regex expression (see Nginx Configuration Riddle above for the rules priority order).
Lastly we have Lighttpd which have a rather small range of directives (compared to Apache for instance) and within those directives the user is mostly required to use either a predefined value, for example:
server.event-handler = "linux-sysepoll"
or, in some places where it fits, the user is encouraged to use regex, for instance:
url.redirect = (
"^/wishlist/(.+)" => "http://localhost/$1"
)
The prioritization is then made by order of placement.
Considering all three approaches, it seems Lighttpd is both the most minimal as well as the most open one as it doesn’t have regex directives separated from clear-text nor does it prioritizes any directive in particular. Priority is basically trusted in the user’s hands which can be controlled merely by order of placement. In that regard Apache could be considered as having the second most open approach as it does require dedicated regex directives and lastly, Nginx’s approach is a little more strict than the others, having the priorities predefined by the server.
Category Rankings
1 Apache
2 Nginx, Lighttpd