User Tools

Site Tools


web:litespeed

# LiteSpeed

Web server on kaburusvr.uk, managed via CyberPanel. Serves all client WordPress sites.

Version: OpenLiteSpeed 1.9.0-2

## Key paths

Path Purpose
—————
`/usr/local/lsws/` LiteSpeed installation
`/usr/local/lsws/bin/lswsctrl` Start / stop / restart / status
`/usr/local/lsws/conf/httpd_config.conf` Main config
`/usr/local/lsws/conf/vhosts/` Per-site vhost configs
`/usr/local/lsws/lsphp81/bin/lsphp` PHP 8.1 binary
`/usr/local/lsws/lsphp83/bin/lsphp` PHP 8.3 binary
`/usr/local/lsws/lsphp84/bin/lsphp` PHP 8.4 binary
`/usr/local/lsws/lsphp85/bin/lsphp` PHP 8.5 binary

## Management

```bash # Graceful restart (use this — sends SIGUSR1, no dropped connections) /usr/local/lsws/bin/lswsctrl restart

# Status /usr/local/lsws/bin/lswsctrl status ```

## ModSecurity WAF (OWASP CRS)

WAF runs on kaburusvr since 2026-08-15 (OWASP CRS v4.28). Blocks are triaged by `/usr/local/bin/modsec-classify.py` (classify, don't count).

### Custom exclusions - File: `/usr/local/lsws/conf/owasp/modsec_custom_rules.conf` (survives the Sunday 04:30 CRS auto-update — never put custom rules in `rules/`) - Wired into: `/usr/local/lsws/conf/owasp/modsec_includes.conf` (included after CRS rules) - Known FPs whitelisted: 944120 (FastPixel cache writeback), 932235 on `_wp_original_http_referer`/`referredby`, 941180 on `content` (Gutenberg `<!–` comments)

### Classifier - Script: `/usr/local/bin/modsec-classify.py [hours]` — parses `/usr/local/lsws/logs/error.log`, groups by (rule, field, uri), buckets into SUPPRESSED (known FP) / ATTACK (LFI/RFI/RCE/SQLi/PHP-inj/scanner + secret-file probes) / REVIEW (new signatures). - Wired into: `/home/kaburu/.hermes/scripts/snmp-trap-check.sh` — emits `🛡️ ModSecurity WAF (24h): N attack, M new` only when N or M > 0. - No CyberPanel GUI exists — CyberPanel ships only an install toggle + raw audit-log viewer (textarea). Triage is classifier-driven.

### New-block workflow When REVIEW shows a new signature: pull the block from `error.log`, decide FP-vs-attack, update the classifier's WHITELIST/ATTACK lists, re-deploy via scp (base64 corrupts — use scp), re-run.

## PHP configuration — per-vhost overrides

PHP settings are applied per-site via the `phpIniOverride` block in each vhost config, not by editing php.ini globally. This keeps changes scoped to the affected site and survives CyberPanel/LiteSpeed updates.

### Standard baseline (applied to all sites — 2026-05-27)

Every PHP site on the server has the following minimum settings in its `phpIniOverride` block:

``` php_value upload_max_filesize 64M php_value post_max_size 128M php_value memory_limit 256M php_value max_execution_time 300 php_value max_input_time 300 ```

These were applied in bulk on 2026-05-27 after dm-ph.com reported `upload_max_filesize` errors (global php.ini default was 2M). All 25 PHP vhosts were patched in one pass.

Sites with this baseline confirmed:

Site Notes
————-
24hrresponse.com
aberdeenrda.co.uk
bankhousecatering.co.uk
billing.myretonmarquees.co.uk
chippy.kaburu.co.uk Also has `memory_limit 512M` in `.user.ini` (Divi)
claybusters.scot
dm-ph.com Trigger site — PHP 8.1
doctorfin.co.uk
friendscic.org
ggsgenerators.co.uk
invoice.kaburu.co
jafricasafari.com
kaburu.co
kaburu.co.uk
kaburusvr.uk
l8.kaburu.co.uk
l8waterhygiene.co.uk
myretonmarquees.co.uk
panel.kaburu.cc
pilates-edinburgh.co.uk
stats.kaburu.co
test.kaburu.cc
test1.kaburu.cc
touchwell.co.uk
womenunlimited.africa Has debug.log deny context (2026-07-31 security fix)

Sites with no PHP handler (no override needed):

Site Reason
————–
kaburu.cc Proxy/monitor site — no PHP
search.kaburu.cc Pure SearXNG reverse proxy

### Editing a vhost PHP override

```bash # Edit nano /usr/local/lsws/conf/vhosts/SITE/vhost.conf

# Then graceful restart /usr/local/lsws/bin/lswsctrl restart ```

The `phpIniOverride` block sits near the top of vhost.conf, just after `scripthandler`. Sites with `open_basedir` set look like:

``` phpIniOverride { php_admin_value open_basedir “/tmp:$VH_ROOT” php_value upload_max_filesize 64M php_value post_max_size 128M php_value memory_limit 256M php_value max_execution_time 300 php_value max_input_time 300 } ```

Sites without `open_basedir` (e.g. invoice.kaburu.co, stats.kaburu.co):

``` phpIniOverride { php_value upload_max_filesize 64M php_value post_max_size 128M php_value memory_limit 256M php_value max_execution_time 300 php_value max_input_time 300 } ```

### Bumping limits for a specific site

If a site needs more than the baseline (e.g. video uploads, WooCommerce imports):

```bash nano /usr/local/lsws/conf/vhosts/SITE/vhost.conf # Change php_value upload_max_filesize to e.g. 256M # Change php_value post_max_size to e.g. 512M /usr/local/lsws/bin/lswsctrl restart ```

### Adding a new site

New sites created via CyberPanel get the global php.ini defaults (2M upload, 8M post). Always add the baseline `phpIniOverride` values immediately after site creation. This is part of the site migration checklist — see site-migration.

## Blocking specific files via vhost context

To block a specific file from being served (return 403), add an exact-path `context` block to the vhost config. Regex `~` context blocks are unreliable for arbitrary filenames — `\\.user\\.ini$` and `wp-config\\.php$` work, but `debug\\.log$` did NOT match on womenunlimited.africa. Use exact-path form:

``` context /wp-content/debug.log {

allowBrowse  0
accessControl {
  deny *
}

} ```

After editing `/usr/local/lsws/conf/vhosts/SITE/vhost.conf`, run `/usr/local/lsws/bin/lswsctrl fullrestart` (not just graceful `restart` — graceful SIGUSR1 does NOT reliably pick up new contexts) and verify with `curl -sI https://SITE/path/to/file`.

For Cloudflare-proxied sites, also purge the URL via the CF API (`/zones/{zone_id}/purge_cache`) — single-URL purges can take 30s+ to propagate; `{“purge_everything”:true}` is more reliable for urgent fixes.

## What does NOT block log files (verified 2026-07-31)

Tested on womenunlimited.africa + friendscic.org — these approaches do NOT reliably block `.log` files:

Approach Result
`<FilesMatch “\.(log\sql\bak\backup\gz\tar)$”>Require all denied</FilesMatch>` in `.htaccess` Ignored — file served with 200
`<IfModule mod_rewrite.c>RewriteEngine On; RewriteRule .*\.(log\…)$ - [F,L]</IfModule>` in `.htaccess` Ignored — file served with 200
Same RewriteRule at vhost.conf level Ignored — file served with 200
`context ~ “/wp-content/.*\\.log$”` in vhost.conf Ignored — regex `~` not matching arbitrary patterns
`context /wp-content/debug.log` (exact path) in vhost.conf WORKS — returns 403

Only the exact-path vhost context works for blocking specific files. For each log file type that needs blocking, you need a separate `context /wp-content/NAME.log { deny * }` block. For most sites, the existing `context ~ “wp-config\\.php$”` rule handles wp-config, and Wordfence WAF intercepts requests for `/wp-content/debug.log` by exact filename match — but other log files (plugin logs, error.log, etc.) are NOT automatically blocked.

Update 2026-07-31: All 25 WP sites now have the explicit `context /wp-content/debug.log { deny * }` block in vhost.conf (backups at `vhost.conf.bak-20260731-0501`). Vhost block is the primary defence; Wordfence is now belt-and-braces rather than sole protection.

If you need broad log-file protection on a site (no Wordfence, or want to block more than just debug.log), add individual `context` blocks per filename in vhost.conf. There is no clean way to do “all .log files” via LiteSpeed config alone.

## ⚠ Known quirks

1. public_html must be chmod 755 — LiteSpeed will not serve files otherwise (403 errors) 2. PHP path in vhosts — Must be `lsphp83` not `lsphpPHP83` — CyberPanel CLI gets this wrong, always verify after creation 3. SSL after DNS cutover — Re-issue via CyberPanel after pointing DNS; Cloudflare proxy means initial cert may be self-signed 4. Dotfiles (.user.ini) — `FilesMatch` .htaccess blocks are ineffective on LiteSpeed for dotfiles. Use `chmod 640` instead. Must be re-applied after each site migration (see hardening) 5. phpIniOverride `php_admin_value` — `open_basedir` uses `php_admin_value` (cannot be overridden by site). Other settings use `php_value`. Don't mix them up or LiteSpeed silently ignores the line 6. `.htaccess` `<Files>` with Apache 2.2 syntax — `Order deny,allow` / `Deny from all` is silently ignored by LiteSpeed. Use `<IfModule mod_authz_core.c>Require all denied</IfModule>` form, or block at vhost context level (more reliable)

web/litespeed.txt · Last modified: (external edit)

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki