Web servers and engines
This section is for system administrators and product managers at hosting companies who must decide what serves an Exponential site on their machines, and set it up. It answers: which web servers and engines Exponential runs behind, which one the project recommends, which one fits which hosting model, and where the exact settings are.
Warning
.htaccess slows down every request. When .htaccess files are enabled (AllowOverride anything but None), let alone
used, Apache looks for them and reads and evaluates them on every request, in every directory of the path, and
page loading times go up drastically (measured). The only real fix is to switch the feature off for
the virtual host: AllowOverride None in the HTTPS virtual host, and the rules in the virtual host's own
configuration as mod_rewrite rules. That is far faster in production speed tests and well worth the time it takes
to optimize a production configuration. Switch over right away: copy the rules of the
example HTTPS virtual host into your virtual host (with the static cache, also
staticcache_offload.conf), set AllowOverride None, run apachectl configtest, reload Apache and
test the site. The same rules for other servers: nginx, LiteSpeed,
Caddy, IIS, Velocity (built in); where virtual host rules go in a control
panel: Plesk, cPanel, DirectAdmin, ISPConfig.
On LiteSpeed or OpenLiteSpeed, the server's own page cache can also answer anonymous visitors and crawlers without PHP: Page caching with LiteSpeed and OpenLiteSpeed.
Back to Hosting companies: start here.
Contents
- The short answer
- The servers at a glance
- Pages in this section
- What every setup has in common
- Related pages
The short answer
- Exponential Velocity (the
qbixengine) is the project's recommended way to serve a site at every stage, from development to production. It is a web server written in PHP that keeps the application loaded in persistent workers, answers repeat pages from its own response cache and serves HTTPS itself (Chapter 8). - FrankenPHP, driven by the same
exp:velocitycommand, is the production-ready alternative. - Apache with PHP-FPM and nginx with PHP-FPM are the traditional setups. They remain fully supported and are
what shared hosting usually offers, because Velocity needs a long-running process that shared hosting usually does
not allow (
README.md, "When a traditional server is still the right answer"). - Any other web server that can pass a request to PHP and rewrite a URL to
index.phpserves Exponential too (Operating system support, Web servers).
The servers at a glance
The tiers come from Operating system support.
| Server | Status in the sources | Typical hosting model | Page |
|---|---|---|---|
Exponential Velocity (qbix) | recommended for every stage; tier 1 | VPS, dedicated, containers, managed | Velocity for hosts |
| Apache httpd 2.4 with PHP-FPM | tier 1 | shared, panels, VPS | Apache with PHP-FPM |
FrankenPHP (through exp:velocity) | production-ready alternative | VPS, dedicated, containers | FrankenPHP |
| nginx with PHP-FPM | tier 2 | VPS, dedicated | nginx with PHP-FPM |
| LiteSpeed, OpenLiteSpeed | tier 3 | shared hosting on LiteSpeed | LiteSpeed |
| Caddy with PHP-FPM | tier 3 | VPS | Caddy |
| Microsoft IIS with FastCGI | tier 3 | Windows hosting | IIS |
| PHP's built-in server | development only | never for visitors | Choosing a web server |
Note
Tier 3 means "expected to work": a reasoned expectation, not a test result (The four tiers). Test a tier 3 server on a staging machine before you sell a plan that depends on it.
Pages in this section
| Page | What it answers |
|---|---|
| Choosing a web server | Which server or engine fits which plan, with a decision table |
| Apache with PHP-FPM | The classic setup: .htaccess_root, the virtual host, PHP-FPM pools, Plesk |
| nginx with PHP-FPM | The derived server block, rule for rule, and how to check it |
| Caddy | What the sources say about Caddy, and the routing to reproduce |
| LiteSpeed | LiteSpeed and OpenLiteSpeed with the shipped Apache rules |
| IIS | Windows hosting with IIS, FastCGI and the URL Rewrite module |
| Velocity for hosts | Installing, configuring and running Velocity on a hosting server |
| Velocity workers and pools | Pool size, the dynamic pool, instances, memory measured as PSS |
| Velocity HTTPS certificates | Your own certificates, Let's Encrypt, the self-signed stand-in, HSTS |
| FrankenPHP | The verified binary, its embedded PHP and its limits |
| Velocity beside Apache or nginx | Running both on the same files, behind a proxy or during a migration |
| Recipe: run a public demo on LiteSpeed and Plesk | A public demo in demo mode (EXP_DEMO_MODE=1), rebuilt from the current code every two hours |
What every setup has in common
Whatever serves the site, the same rules apply (Chapter 8, How a request is served):
- The document root is the installation root, the directory that holds
index.php. - The routing is written down once, in
.htaccess_root. Velocity's engines and the generated FrankenPHP configuration implement the same list rule for rule. Apache (withAllowOverride All) and LiteSpeed Enterprise read it as.htaccess, which./console exp:setup:htaccess --applycopies into place; OpenLiteSpeed reads only its rewrite rules (withautoLoadHtaccess, after a restart); nginx, Caddy and IIS never read it (Setting up .htaccess and config.php from the console). - No PHP file runs because its path was asked for, except the front controllers at the root (
index.php,index_rest.php,index_treemenu.php, andindex_soap.phpwhen SOAP is on; it wassoap.phpbefore 6.0.15, see the SOAP entry script is now index_soap.php). - WebDAV, when you switch it on, needs a rule of its own for
index_webdav.php(its name since 6.0.15;webdav.phponly forwards to it until a later major version) on Apache, nginx or IIS, in the HTTPS virtual host too. Velocity does not serve it. See The WebDAV entry script is now index_webdav.php. - Only listed asset paths are sent as files;
settings/site.ini, the SQLite database or a kernel source requested by path reachindex.php, never the file. - The user that runs PHP must be able to write
var/and thesettings/directories, and one user (or one group) should write them, whichever server runs (Chapter 8, File permissions and ownership).
Check the routing on any server with the four requests of chapter 8, replacing the address with your own:
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/.git/config # 404 (403 from qbix)
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/kernel/classes/ezcontentobject.php # 404
curl -s -o /dev/null -w '%{http_code}\n' https://example.com/robots.txt # 200 when the file exists
curl -s https://example.com/settings/site.ini | grep -c '^\[DatabaseSettings\]' # 0A 200 for the .git or kernel request means the rules are not active. Stop and fix that before the site is
reachable from outside.
Related pages
- Hosting companies: start here
- Performance
- Chapter 8: Serving the site
- Operating system support
- Velocity engines
- Setting up .htaccess and config.php from the console
- Free documentation: this page is free to copy, translate and improve under the GNU FDL 1.3.
Become an Exponential Partner
Partners share their information, provide funding, contribute back and develop the products with us, and that is how Exponential grows. A partner website and dashboard are planned for mid-2027: please become a partner today to speed up our growth rate and land new features faster.