Troubleshooting Matrix
When something breaks, start here. Each section is organized by symptom — not by concept.
Diagnostic First Steps (Always Run These)
# 1. Check service status
sudo systemctl status lsws
# 2. Check error log (most important)
sudo tail -50 /usr/local/lsws/logs/error.log
# 3. Check what ports are listening
sudo ss -tlnp | grep lshttpd
# 4. Test HTTP response from localhost
curl -I http://localhost/
curl -H "Host: example.com" -I http://localhost/
# 5. Check PHP workers
ps aux | grep lsphp | grep -v grep | wc -l
# 6. Check disk space (full disk causes subtle failures)
df -h /
df -h /usr/local/lsws/
# 7. Check memory
free -m
403 Forbidden
| Cause | Symptom | Fix |
|---|---|---|
| Wrong file permissions | 403 on all pages | sudo chmod -R 755 /var/www/domain.com |
| Wrong file ownership | 403 on all pages | sudo chown -R nobody:nogroup /var/www/domain.com |
| No index file in docRoot | 403 on root URL | Create index.html or index.php in web root |
| Access control deny | 403 on specific path | Check vhconf.conf accessControl block |
| .htaccess deny rule | 403 on file/path | Review .htaccess for Deny from all |
| PHP script in uploads | 403 on PHP in uploads | Correct — PHP should not run there |
# Quick permission fix
sudo chown -R nobody:nogroup /var/www/example.com/
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
sudo find /var/www/example.com -type f -exec chmod 644 {} \;
# Check what user OLS runs as
ps aux | grep lshttpd | head -2 | awk '{print $1}'
# Test file is readable by nobody
sudo -u nobody cat /var/www/example.com/public/index.php | head -3
404 Not Found
| Cause | Symptom | Fix |
|---|---|---|
| Wrong docRoot path | All pages 404 | Check docRoot in vhconf.conf |
| Domain not mapped to vhost | Default page shows | Add map in listener block |
| Missing rewrite rules | Dynamic URLs 404 | Add .htaccess with rewrite rules |
| File literally missing | Specific file 404 | Verify file exists at the path |
# Verify docRoot is correct
grep "docRoot" /usr/local/lsws/conf/vhosts/example/vhconf.conf
ls -la /var/www/example.com/public/
# Check listener domain mapping
grep -A5 "^listener" /usr/local/lsws/conf/httpd_config.conf | grep map
# Test request with specific Host header
curl -v -H "Host: example.com" http://localhost/ 2>&1 | grep -E "< HTTP|Location"
500 Internal Server Error
| Cause | Symptom | Fix |
|---|---|---|
| PHP syntax error | 500 on any PHP page | Check error.log and stderr.log |
| PHP memory exhausted | 500 on complex pages | Increase memory_limit in php.ini |
| Missing PHP extension | 500 on specific functions | Install the missing lsphp84-* package |
| Wrong socket path in extprocessor | 500 on PHP pages | Verify address in extprocessor matches socket |
| PHP process limit reached | 500 under load | Increase procSoftLimit/procHardLimit |
| Bad .htaccess rule | 500 on affected URLs | Check .htaccess for syntax errors |
| Config syntax error | 500 server-wide | Run lshttpd -t and check error.log |
# Find the actual error
sudo tail -50 /usr/local/lsws/logs/error.log
sudo tail -50 /usr/local/lsws/logs/stderr.log
# Check PHP error log
sudo tail -50 /usr/local/lsws/logs/php-error.log
# Verify socket exists (lsphp creates it at runtime)
ls -la /tmp/lshttpd/
ls /tmp/lshttpd/ | grep sock
# Test PHP directly
/usr/local/lsws/lsphp84/bin/lsphp -r "echo 'PHP OK';"
/usr/local/lsws/lsphp84/bin/lsphp -l /var/www/example.com/public/index.php
PHP Files Downloading Instead of Executing
Cause: No script handler mapped for .php extension in vhconf.conf.
# Check scripthandler in vhconf
grep -A3 "scripthandler" /usr/local/lsws/conf/vhosts/example/vhconf.conf
# If missing, add to vhconf.conf:
# scripthandler {
# add lsapi:lsphp84 php
# }
# Then reload
sudo /usr/local/lsws/bin/lswsctrl restart
SSL / HTTPS Errors
525 SSL Handshake Failed (Cloudflare)
# Cause: OLS has no valid SSL cert / listener not on 443
# Fix: Verify SSL listener is configured
grep -A10 "listener HTTPS" /usr/local/lsws/conf/httpd_config.conf
# Check cert and key files exist
ls -la /etc/ssl/private/example.key
ls -la /etc/ssl/certs/example.crt
# Verify cert is valid
openssl x509 -in /etc/ssl/certs/example.crt -noout -text | grep -E "Subject:|Not After"
# Test OLS responds on 443
openssl s_client -connect localhost:443 -servername example.com
526 Invalid SSL Certificate (Cloudflare)
# Cause: Self-signed cert but Cloudflare is in Full (Strict) mode
# Fix: Use Cloudflare Origin Certificate or Let's Encrypt
# Check cert issuer
openssl x509 -in /etc/ssl/certs/example.crt -noout -issuer
# If self-signed → install Cloudflare Origin Certificate:
# Dashboard → SSL/TLS → Origin Server → Create Certificate
# Save as example.crt and example.key
# Update keyFile/certFile in httpd_config.conf listener
Certificate Mismatch
# Check what domain the cert is issued for
openssl s_client -connect example.com:443 2>/dev/null | openssl x509 -noout -subject -subjectAltName
# Check cert expiry
openssl x509 -in /etc/ssl/certs/example.crt -noout -enddate
Server Not Starting
# Check error log for startup errors
sudo tail -50 /usr/local/lsws/logs/error.log
# Port conflict?
sudo ss -tlnp | grep ':80\|:443\|:7080'
# Test config syntax
sudo /usr/local/lsws/bin/lshttpd -t
# Try starting manually to see stderr
sudo /usr/local/lsws/bin/lshttpd
Reload Not Applying Changes
# Verify config was saved (check mtime)
ls -la /usr/local/lsws/conf/httpd_config.conf
ls -la /usr/local/lsws/conf/vhosts/example/vhconf.conf
# Force full restart
sudo systemctl restart lsws
# Check if reload was logged
grep "restart\|reload" /usr/local/lsws/logs/lsrestart.log | tail -5
# Check error log for post-reload errors
sudo tail -30 /usr/local/lsws/logs/error.log
WebAdmin Locked Out / 7080 Not Responding
# Reset admin password
sudo /usr/local/lsws/admin/misc/admpass.sh
# Check if admin process is running
ps aux | grep lshttpd | head -5
# Check if 7080 is listening
sudo ss -tlnp | grep 7080
# Admin might be on different port — check config
grep "adminPort\|7080" /usr/local/lsws/conf/httpd_config.conf
# Check firewall allows your IP to 7080
sudo ufw status | grep 7080
High Memory or CPU Usage
# Which processes are heaviest?
ps aux --sort=-%mem | head -10
ps aux --sort=-%cpu | head -10
# How many PHP workers are running?
ps aux | grep lsphp | grep -v grep | wc -l
# PHP workers consuming most memory
ps aux | grep lsphp | grep -v grep | awk '{sum += $6} END {print "Total lsphp RSS:", sum/1024, "MB"}'
# Check for memory leaks (watch over time)
watch -n5 'ps aux | grep lsphp | grep -v grep | awk "{sum+=\$6} END {print sum/1024 \" MB\"}"'
# Reduce max PHP children if OOM
# Edit httpd_config.conf: procSoftLimit and PHP_LSAPI_CHILDREN
Slow Response Times
# Measure TTFB
curl -w "TTFB: %{time_starttransfer}s\n" -o /dev/null -s https://example.com/
# Is compression working? (reduces transfer time)
curl -H "Accept-Encoding: gzip" -I https://example.com/ | grep content-encoding
# Is cache hitting?
curl -I https://example.com/ | grep -i "x-litespeed-cache\|cache-control"
# Check PHP OPcache
/usr/local/lsws/lsphp84/bin/lsphp -r "var_dump(opcache_get_status(false)['opcache_enabled']);"
# Check for slow queries (if DB-heavy app)
sudo tail -f /var/log/mysql/slow-query.log
Log Location Quick Reference
| Log | Path | What to Look For |
|---|---|---|
| Server errors | /usr/local/lsws/logs/error.log | All errors — check first |
| Access log | /usr/local/lsws/logs/access.log | Request pattern analysis |
| PHP stderr | /usr/local/lsws/logs/stderr.log | PHP fatal errors |
| Restart history | /usr/local/lsws/logs/lsrestart.log | When restarts occurred |
| Per-vhost error | /usr/local/lsws/conf/vhosts/<name>/logs/error.log | Site-specific errors |
| PHP error log | Value of error_log in php.ini | PHP-level errors |