.htaccess is 30 years old and it is still in my critical path.
The annoying thing about .htaccess was never the syntax. It is that it is a config file with near-root power, scattered across the document tree, parsed on every request, and it is where every PHP application puts its security rules. You inherit a site and there are two hundred lines of rewrite and access rules that you did not write, cannot confidently delete, and are about to lose the moment you change web server.
The migration trap
Move a WordPress, Laravel or Drupal site off Apache onto something faster and those rules either come with you or they do not. Usually they do not.
OpenLiteSpeed is fast, free and light, and it does not process .htaccess the way Apache does. Applications that depend on it either break outright or — worse — keep working while the security rules quietly do nothing. A Require all denied that was protecting an admin path is simply not there any more, and nothing in the logs tells you that.
So the options were: stay on Apache, hand-translate every rule into OLS configuration, or find a shim.
What LiteHTTPD does
LiteHTTPD is that shim. It is an Apache .htaccess compatibility layer for OpenLiteSpeed, built from an LSIAPI module (litehttpd_htaccess.so) plus, in the Full edition, a patched OLS binary.
The numbers from its own documentation: 80 supported directives — 83 if you believe the README, the first of several places where the project disagrees with itself. On a compatibility test against a WordPress install with 19 plugins it scores 18 out of 18 and calls that 90%+, against 100% for LSWS Enterprise and 8 out of 18 for stock OpenLiteSpeed. That last figure is the one to sit with: stock OLS passed 44% of the tests, which means the majority of what you had written in .htaccess was being ignored.
It hooks into OLS at two phases: URI_MAP for access control, authentication, redirects, rewrite rules, PHP config and environment variables, and SEND_RESP_HEADER for response headers, Expires and Cache-Control, content type and conditionals. It reads .htaccess from the document root down to the requested path, merges with AllowOverride filtering, and executes in Apache’s order.
On performance their benchmark — AlmaLinux 9.5, WordPress with 19 plugins — puts it at 22,104 requests per second on static files against Apache’s 11,082, with .htaccess parsing overhead of minus 0.7% against minus 18.8% for stock OLS. Their numbers on their hardware, and they contradict each other elsewhere on the same site, so read them as directional.
Two editions, both GPLv3. Thin is the module alone on an unmodified OLS and covers 70+ directives, for the cases where you cannot replace the server binary. Full adds the patched binary and gives you actual RewriteRule execution.
The honest trade-offs
Start with the one that can take your site down. Rules that were inert become live. Stock OLS was ignoring most of your .htaccess, so Require all denied, FilesMatch denies and Header set were doing nothing at all. Switch LiteHTTPD on and they start working. That is the entire point, but it also means an .htaccess nobody has read since 2019 can now return 403 on your own site. The documentation says to review your rules before deploying to production, and that is not boilerplate.
- Then there is the history, and it is the most important item here. The 2.1.4 changelog records a critical fix:
Require userandRequire groupwere silently dropped, so a directory protected byAuthType Basicwas served to anyone who asked. The same release fixed anAuthUserFilepath escape usable as a password-test oracle against files such as/etc/shadow, plus header spoofing and a denial of service. All fixed, and found by the maintainer rather than an attacker — but it is exactly the failure mode this article is about, a security rule that silently does not apply, inside the tool you installed to prevent it. Pin a version whose changelog you have read. - Thin cannot execute
RewriteRule. It parses them and falls back to OLS’s nativeRewriteFilehandling, which copes with basic WordPress permalinks and not much else. If you have a chain of 301s, you need Full — and Full means replacing the OLS binary. - It is not 100%.
RewriteRuleinside an<If>block is unsupported.AddHandler,SetHandler,RemoveHandlerandActionare parsed but do nothing, because OLS maps handlers throughscriptHandlerin the vhost instead. - Response header names come back lowercased. That is legal under RFC 7230 and required by HTTP/2, and it will still break anything doing a case-sensitive string match on a header name.
Options +ExecCGIis silently ignored, deliberately, as a security restriction. Defensible, but it is a behaviour change if you were relying on it.- Full replaces the OpenLiteSpeed binary. You are no longer running stock OLS, which means your upgrade path for the web server is somebody else’s release schedule. In practice it also means the package conflicts with the distribution’s own
openlitespeed, and a control panel upgrade can overwrite the patched binary underneath you. - The headroom is not uniform. Their own compatibility notes put WordPress permalink routes at roughly 1–4 requests per second against Apache’s roughly 70, which they attribute to an OpenLiteSpeed limitation rather than something the module can fix. If your site is permalink-heavy, measure before you migrate.
- The project is young and thin: one contributor, a handful of commits, a few stars, no tagged releases on GitHub, and version numbers that disagree between the homepage, the changelog, the benchmark page and the package repository. The licence is GPLv3, though the repository’s licence file contains only the preamble and a link — the kind of detail that matters if you are shipping this inside something.
- And the honest summary: this is a shim, not Apache. You are buying compatibility you did not have, not equivalence you can stop thinking about.
Who should care, and who should not
If you inherit PHP sites with .htaccess files you cannot safely rewrite, and you want OpenLiteSpeed’s throughput, this removes the blocker that usually decides the argument in favour of staying on Apache. A specific situation, but a common one.
If you are greenfield on nginx or Caddy with no .htaccess anywhere, you do not need it. Compatibility layers are debt with a purpose, and there is no purpose when there is nothing to be compatible with.
It is a sub-project of the Web.Casa panel, which is a useful signal about who maintains it and where the effort comes from.
.htaccess is technical debt you cannot delete, because it is load-bearing for applications you did not write. The realistic goal is to keep paying the interest without rewriting the principal.