httpjet ·docs
10-track sequence 2-5 min synths
GitHub

Docs/Configuration

Running it

Raw .md

Configuration reference

httpjet is configured by a LiteSpeed-compatible XML tree selected with --root: conf/httpd_config.xml, the per-vhost files it references, and conf/mime.properties. An existing LiteSpeed or OpenLiteSpeed tree works as-is. On that base httpjet layers its own opt-in directives — marked httpjet — which LiteSpeed ignores. Operational overrides live on the command line, not in the XML.

The configuration tree

With no --root, httpjet uses /usr/local/lsws. The parser (hj-config) applies LiteSpeed value semantics faithfully:

  • Variables $SERVER_ROOT, $HOSTNAME, $VH_ROOT, $VH_NAME substitute in $VAR and ${VAR} forms.
  • Sizes accept K/M/G/B suffixes; times are bare seconds.
  • Bounded integers use OLS semantics: absent, unparsable or out-of-range values fall back to the default (never clamped). The isolation modes setUIDMode/chrootMode are the exception: out-of-range is a hard error (2026-09-16).
  • Booleans are 1, 2 or true (case-insensitive); followSymbolLink/allowSymbolLink treat 2 (owner-restricted) as fail-closed never-follow.
  • Unknown elements are ignored so real trees load; check --strict reports the ones that would silently do nothing.
layout · a server root
/usr/local/lsws/
├── conf/
│   ├── httpd_config.xml          # server, tuning, security, listeners, extProcessors, vhost declarations
│   ├── mime.properties           # mime/type = ext1, ext2   (best-effort)
│   └── vhosts/example.test.xml   # <virtualHostConfig>: docroot, contexts, rewrite, vhssl, cache, logging
└── logs/
vhost defaults +allowSymbolLink foldURI prefix routingallowOverride = 1static analysis at load

httpd_config.xml (server root)
tuning · security · listeners · extProcessorList · vhostMapList

vhosts/.xml (virtualHostConfig)
docRoot · vhssl · rewrite · cache · suEXEC · logging

prefix match (longest prefix wins)
type (static|proxy|lsapi|redirect) · maxReqBodySize · responseTimeout · bandwidthLimit · subFilter · cachePolicy

.htaccess chain (docroot → target dir, depth ≤ 64)
SetEnvIf · Order/Allow/Deny · Require · RewriteCond/Rule · Header · Expires* · CacheLookup

parse-time MemoClass verdict (httpjet check)
eligible + vary-set (Origin, UA bitmap) vs ineligible (Remote_Addr, Cookie, IP ACL)

Configuration cascade and parse-time memo classification. Server-wide defaults in httpd_config.xml cascade into each <virtualHostConfig>, then into longest-prefix <context> overrides and the per-directory .htaccess chain, where static analysis computes the MemoClass eligibility verdict reported by httpjet check.
diagram source (mermaid)
flowchart TB
  classDef srv fill:#13203a,stroke:#818cf8,color:#fff
  classDef vh fill:#0e1424,stroke:#22d3ee,color:#e8ecf6
  classDef ctx fill:#141b2e,stroke:#e879f9,color:#e8ecf6
  classDef ht fill:#0f2a24,stroke:#34d399,color:#fff
  S["httpd_config.xml (server root)<br/>tuning · security · listeners · extProcessorList · vhostMapList"]:::srv
  V["vhosts/<name>.xml (virtualHostConfig)<br/>docRoot · vhssl · rewrite · cache · suEXEC · logging"]:::vh
  C["<context> prefix match (longest prefix wins)<br/>type (static|proxy|lsapi|redirect) · maxReqBodySize · responseTimeout · bandwidthLimit · subFilter · cachePolicy"]:::ctx
  H[".htaccess chain (docroot → target dir, depth ≤ 64)<br/>SetEnvIf · Order/Allow/Deny · Require · RewriteCond/Rule · Header · Expires* · CacheLookup"]:::ht
  M["parse-time MemoClass verdict (httpjet check)<br/>eligible + vary-set (Origin, UA bitmap) vs ineligible (Remote_Addr, Cookie, IP ACL)"]:::srv
  S -- "vhost defaults + allowSymbolLink fold" --> V
  V -- "URI prefix routing" --> C
  V -- "allowOverride = 1" --> H
  H -- "static analysis at load" --> M
  click S "configuration.html#server"
  click V "configuration.html#vhosts"
  click C "configuration.html#contexts"
  click H "rewrite.html#loading"
  click M "rewrite.html#memo"

Server and tuning

DirectiveDefaultMeaning
serverName$HOSTNAMEServer identity (else localhost).
user / groupnobodyRun-as credentials (the systemd unit usually sets these).
indexFilesindex.htmlDirectory-index candidates (vhost may override).
useIpInProxyHeader2Client-IP trust: 0 never · 1 always · 2 trusted peers only (+ CF-Connecting-IP) · 3 as 2 for IP purposes · 4 always. Restart-required through the write API.
<quic><quicEnable>0HTTP/3 master switch; also drives Alt-Svc. Needs the UDP port published.
<tuning>maxConnections65000Connection cap.
connTimeout / keepAliveTimeout60 / 5 sIdle / keep-alive timeouts.
maxKeepAliveReq1000Requests per keep-alive connection (0 or 1 disables keep-alive, matching OpenLiteSpeed).
maxReqURLLen / maxReqHeaderSize8192 / 16380URL and header-block caps.
maxReqBodySize100MServer-wide request-body cap (413); per-context override below.
perIpRate · perIpRateWindowSecs httpjet0 · 1Per-client-IP request throttle (0 = off) and its fixed window. 429 on exceed; fail-open under state pressure.
bandwidthLimit httpjet0Per-connection egress throttle, bytes/s (0 = unlimited). H2 paces per connection; H3 unpaced.
maxCachedFileSize / totalInMemCacheSize4M / 4GSmall-file in-memory promotion threshold and budget (CacheCaps).
maxMMapFileSize / totalMMapCacheSize256K / 2GParsed for compatibility; the mmap file cache was removed.
fileETag28ETag bitmask (INODE|MTIME|SIZE → "size-mtime-inode;;;"); 0 = no ETag.
enable{Gzip,Br,Zstd}Compress (+Dyn)onStatic/dynamic compression per codec; zstdCompressLevel 3, brCompressLevel 5.
<expires>enableExpires, expiresByTypeoffimage/*=A604800, text/css=M86400 (A = access, M = modify). Also honored in .htaccess via ExpiresActive / ExpiresDefault / ExpiresByType (sharing the same grammar). Authenticated responses get private, no-store when no explicit policy exists.
<cache>expireInSeconds · privateExpireInSeconds · cacheStatusCode · enablePostCache900 · 0 · 200,301 · offDefault public/private TTLs and cacheable statuses. cacheStorePath is parsed but deliberately unused (see --page-cache-store-path).

Security directives

DirectiveDefaultMeaning
<security><accessControl> allow/deny—ALL or CIDR lists, most-specific wins. A trailing T on an allow rule marks a trusted proxy.
<accessDenyDir><dir>—Globs never served; a malformed glob is a hard start/reload error.
<fileAccessControl>followSymbolLinkoffFolded into each vhost's effective allowSymbolLink; 2 fails closed.
geoipDBFile · geoAllow/geoDeny · asnAllow/asnDeny httpjetnoneOffline CidrList source and label lists; deny-first, allow-only = whitelist, unknown label = build error. →
<suexec>enable · uidMin · gidMin0 · 100 · 100suEXEC master gate and floors; uid/gid 0 always rejected.
<suexec><namespace> enable, mount, pid, net, uts, ipcoffNamespace isolation for PHP workers; pid is accepted but not honored.
<CGIRLimit> CPUSoftLimit/CPUHardLimit—Parsed for compatibility; ignored on persistent lsphp workers (check warns).
lsrecaptcha, censorshipControl, permission masks—not enforced — check warns.

Listeners and TLS

DirectiveDefaultMeaning
name, address*:80ip:port / host:port. httpjet also unix:/path or uds:/path for an HTTP-over-Unix-socket listener (TLS over UDS is rejected). Listener names are the stable identity across reloads.
secure, keyFile, certFile, certChainoffTLS material; certChain=1 appends CACertFile to the served chain.
CACertFile · clientVerify · verifyDepthnone · 0 · 1Client-certificate verification (0 none · 1 optional · 2 required · 3 optional without CA) against the listener CA.
crlFile httpjetnonePEM CRL/bundle enforced by the client verifier.
enableStapling0Compatibility only; OCSP needs --features ocsp + --ocsp-responder.
proxyProtocol httpjet0PROXY v2/v1 required on this listener; fail-closed; never on a public bind.
vhostMapList/vhostMap vhost, domain—Host→vhost; domains lowercased; exact matches take precedence over longest-match leading (*.example.com) or suffix (example.*) wildcards, then the bare * catch-all.
httpd_config.xml · a TLS listener with h3
<quic><quicEnable>1</quicEnable></quic>
<listenerList>
  <listener>
    <name>https</name>
    <address>*:443</address>
    <secure>1</secure>
    <keyFile>/etc/letsencrypt/live/example.test/privkey.pem</keyFile>
    <certFile>/etc/letsencrypt/live/example.test/fullchain.pem</certFile>
    <clientVerify>0</clientVerify>
    <vhostMapList><vhostMap><vhost>example.test</vhost><domain>example.test,www.example.test</domain></vhostMap></vhostMapList>
  </listener>
</listenerList>

External processors

An <extProcessor> (server-level <extProcessorList> or per-vhost) is a reverse-proxy upstream (proxy), an LSAPI app (lsapi), or httpjet a FastCGI app (fcgi/fastcgi). <phpConfig> configures the default PHP handler with the same pool knobs. Unknown legacy types (rails, appserver, …) keep proxy behavior; cgi contexts are not executed.

DirectiveDefaultMeaning
name, typerequiredproxy · lsapi · fcgi/fastcgi httpjet.
address (repeatable)requiredip:port, host:port, uds:///path, http://, https://, and httpjet h2:// (prior knowledge) / h2s:// (TLS, ALPN fail-closed). Additional addresses form a group: ordered failover by default, load-balanced with the options below.
loadBalancePolicy httpjetprimary-firstweighted-round-robin · weighted-least-active. Invalid on non-proxy processors.
addressWeights httpjetall 1One integer 1–1000 per address.
<healthCheck> mode · path · host · interval · timeout · rise · fall · expectedStatus httpjetconnect · / · — · 10 · 2 · 2 · 3 · 200Active probes; intervals 1–3600 s, timeout ≤ interval, thresholds 1–100, status 200–599. →
maxConns100Pool cap (LSAPI: worker count source unless --php-children overrides).
initTimeout / retryTimeout / pcKeepAliveTimeout60 / 0 / 60 sConnect timeout / bad-mark cooldown (retry dials fresh; a backend timeout is 504) / idle recycle.
respBuffer0Parsed; responses always stream (check warns if set).
clientCertFile / clientKeyFile httpjetnoneUpstream mTLS client identity for https:///h2s:// targets; must lie within an admin resource root when submitted via the API.
env (repeatable)—K=V worker environment. Server-computed CGI names are protected.
path, backlog, instances, autoStart, runOnStartUp— / 100 / 1 / 0 / 0LSAPI worker binary and supervision (instances>1 warns: one fixed upstream).
phpConfig additionally: phpHandler (command, suffixes), memSoftLimit/memHardLimit, maxProcessTime (0 = unlimited; --php-max-process-time-ms overrides), procSoftLimit/procHardLimit, extMaxIdleTime, backlog default 1024, detachedMode.

Virtual hosts

Declarations live in httpd_config.xml (name, vhRoot, configFile, allowSymbolLink, enableScript, restrained); behavior lives in the referenced <virtualHostConfig>. allowSymbolLink is a tri-state override (file > declaration > server); restrained confines the vhost to vhRoot and forces symlinks off; enableScript=0 disables script handlers for the vhost.

Vhost directiveMeaning
docRoot, indexFiles, enableExpires/expiresByTypeRoot and per-vhost overrides of the server settings.
<rewrite> enable, autoLoadHtaccess, base, rulesInline rules run before the .htaccess chain.
<htAccess> allowOverride, accessFileNameallowOverride 0 kills the whole chain; the access file name defaults to .htaccess.
<vhssl> keyFile, certFile, certChain, CACertFileThe SNI identity for this vhost's domains (chain material, not a client-verify root).
<cache> enableCache, enablePublicCache, enablePrivateCachePer-vhost page-cache gates (with --page-cache-standard-vhosts a missing block gets a default public policy).
<scriptHandlerList><scriptHandler> suffix, type, handlerSuffix routing to lsapi/php handlers or a cgi handler bound to a FastCGI processor.
<websocketList><websocket> uri, addressWebSocket relay maps (plain TCP HTTP/1 upstreams).
<logging> accessLog/errorLog with useServer=0, fileName, rollingSize, keepDays, logHeaders httpjetPer-vhost log files (default roll 50 MB, keep 30 days; logHeaders 7 = combined). Log paths are boot-owned.
setUIDMode (0/1/2), chrootMode (0/1/2), chrootPath, suexecUser/suexecGroup, <namespace>Per-vhost PHP isolation (needs the server <suexec> gate). Out-of-range modes are hard errors. →
<extProcessorList>Vhost-scoped processors (distinct scope from server-level ones).

Contexts

Contexts map URI prefixes to terminals (static, proxy, redirect, php/lsapi via handler) and carry per-context overrides:

Context directiveDefaultMeaning
type, uri, location, handler, enabled—Kind, prefix, on-disk location (static), processor name (proxy/lsapi).
extraHeaders—Additional response headers for the context.
addDefaultCharset / addDefaultCharsetCustomizedoffCharset appended to text types.
cachePolicy/*oncheckPublicCache, checkPrivateCache, respectCacheable, enableCache, enablePrivateCache, enablePostCache — the six LSWS gates, enforced on both cache tiers.
maxReqBodySize httpjetinheritPer-context body cap (413) on every terminal.
responseTimeout httpjetinheritUpstream response-head deadline, seconds (proxy paths).
bandwidthLimit httpjet0Egress throttle overriding the server-wide rate.
subFilter (repeatable) · subFilterOnce · subFilterTypes · subFilterMaxBody httpjet— · 0 · text/html · 4MSEARCH => REPLACEMENT literal body substitution. The => separator is mandatory — a rule missing it disables the whole context's sub_filter with a warning. →
vhost XML · a proxied API prefix with overrides
<contextList>
  <context>
    <type>proxy</type>
    <uri>/api/</uri>
    <handler>application</handler>
    <maxReqBodySize>2M</maxReqBodySize>
    <responseTimeout>15</responseTimeout>
    <subFilter>http://internal.example => https://example.test</subFilter>
    <subFilterTypes>text/html,application/json</subFilterTypes>
  </context>
</contextList>

Checking a configuration

check
httpjet --root /abs/root check            # summary: listeners, vhost map, fast-memo verdicts, warnings
httpjet --root /abs/root check --strict   # + topology lint, missing docroots, vhost-map-fingerprint; non-zero on findings

Run the check under the intended service identity as well as as root: readable-by-root is not proof the runtime user can read certificates or write logs and sockets. The same normalization runs for the write API's in-memory bundle (parse_bundle), which additionally refuses DTDs, more than 64 nesting levels, more than 128 vhosts, and 1 MiB of XML. A config file read from disk is capped at 16 MiB per file (ConfigError::TooLarge, 2026-10-06) — a bound on all readers, check included.

Environment variables

The full list, with the flags they pair with, is on the CLI reference. The ones most often set in a unit drop-in: HTTPJET_ACCESS_LOG_FORMAT=json, HTTPJET_ERROR_LOG_FORMAT=json, HTTPJET_SYSLOG_TARGET, CF_SEND_ZSTD=1, HJ_FAST_MEMO=0, HTTPJET_OTEL=1, RUST_LOG.

httpjet · documentation · synced to the source tree on 2026-10-24 (v0.1.5).
Source: github.com/faratech/httpjet · Home: httpjet.net · Found an error? Open an issue on the repository.