Virtual Host Setup
A complete end-to-end reference for creating new sites in OpenLiteSpeed entirely from the CLI.
Mental Model
Listener (:80 / :443)
└── Domain mapping: "example.com" → vhost "example"
└── Virtual Host "example"
├── docRoot: /var/www/example.com/public
├── scriptHandler: .php → lsphp84 (via LSAPI)
└── rewrite rules / contexts
The listener accepts connections. The domain mapping routes by hostname. The virtual host defines what happens per site.
Step-by-Step: New Site from CLI
Step 1 — Create Directory Structure
DOMAIN="example.com"
WEB_ROOT="/var/www/$DOMAIN/public"
VH_CONF_DIR="/usr/local/lsws/conf/vhosts/$DOMAIN"
# Create dirs
sudo mkdir -p "$WEB_ROOT" "$VH_CONF_DIR"
# Set ownership (OLS worker user is nobody:nogroup by default)
sudo chown -R nobody:nogroup "/var/www/$DOMAIN"
sudo chmod -R 755 "/var/www/$DOMAIN"
# Test index page
echo "<h1>$DOMAIN on OpenLiteSpeed</h1>" | sudo tee "$WEB_ROOT/index.html"
Step 2 — Write vhconf.conf
sudo tee "$VH_CONF_DIR/vhconf.conf" > /dev/null <<CONF
docRoot $WEB_ROOT
vhDomain $DOMAIN, www.$DOMAIN
enableGzip 1
enableBr 1
index {
useServer 0
indexFiles index.php, index.html
}
scripthandler {
add lsapi:lsphp84 php
}
accessControl {
allow *
}
rewrite {
enable 1
autoLoadHtaccess 1
}
CONF
echo "[✓] vhconf.conf written"
cat "$VH_CONF_DIR/vhconf.conf"
Step 3 — Register Vhost in httpd_config.conf
Open the main config and add a virtualhost block:
sudo vim /usr/local/lsws/conf/httpd_config.conf
Add this block (replace example with your actual name):
virtualhost example {
vhRoot /usr/local/lsws/conf/vhosts/example/
configFile $VH_ROOT/vhconf.conf
allowSymbolLink 1
enableScript 1
restrained 0
}
Also add/update the listener mapping block to reference this vhost:
listener HTTP {
address *:80
secure 0
map example example.com, www.example.com
}
Step 4 — Graceful Reload and Verify
# Apply changes without downtime
sudo /usr/local/lsws/bin/lswsctrl restart
# Check for errors
sudo tail -20 /usr/local/lsws/logs/error.log
# Test the site
curl -H "Host: example.com" http://localhost/
# Should return 200 with your index page
curl -H "Host: example.com" -s http://localhost/ | head -5
WordPress-Specific vhconf.conf
vhconf.conf for WordPress
docRoot /var/www/example.com/public
vhDomain example.com, www.example.com
enableGzip 1
enableBr 1
index {
useServer 0
indexFiles index.php, index.html
}
scripthandler {
add lsapi:lsphp84 php
}
accessControl {
allow *
}
rewrite {
enable 1
autoLoadHtaccess 1
rules <<<END_RULES
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
END_RULES
}
The WordPress rewrite rules go in .htaccess:
/var/www/example.com/public/.htaccess
# BEGIN WordPress
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^index\.php$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /index.php [L]
</IfModule>
# END WordPress
Multiple PHP Versions Per Vhost
You can assign a different PHP version per virtual host by creating separate external app entries in httpd_config.conf and mapping each vhost to its version.
httpd_config.conf — two PHP versions
# PHP 8.4 external app
extprocessor lsphp84 {
type lsapi
address uds://tmp/lshttpd/lsphp84.sock
path /usr/local/lsws/lsphp84/bin/lsphp
maxConns 35
env PHP_LSAPI_CHILDREN=35
}
# PHP 8.1 external app (for legacy site)
extprocessor lsphp81 {
type lsapi
address uds://tmp/lshttpd/lsphp81.sock
path /usr/local/lsws/lsphp81/bin/lsphp
maxConns 20
env PHP_LSAPI_CHILDREN=20
}
Then in each vhost's vhconf.conf:
# For the PHP 8.4 site
scripthandler {
add lsapi:lsphp84 php
}
# For the PHP 8.1 site (different vhost file)
scripthandler {
add lsapi:lsphp81 php
}
Domain Mapping Cheatsheet
| Scenario | listener map directive |
|---|---|
| Single domain | map example example.com |
| Domain + www | map example example.com, www.example.com |
| Wildcard subdomain | map example *.example.com |
| Multiple vhosts on one listener | One map line per vhost |
Common Vhost Mistakes
| Mistake | Symptom | Fix |
|---|---|---|
Forgot map in listener | Default page loads | Add map vhostname domain.com in listener block |
Wrong docRoot path | 404 on all pages | Verify path exists: ls -la /var/www/... |
Permissions not nobody:nogroup | 403 Forbidden | chown -R nobody:nogroup /var/www/site |
| No index file in docRoot | 403 on root URL | Create index.html or index.php |
| PHP handler missing | .php files download | Add scripthandler { add lsapi:lsphp84 php } |
| Vhost not in httpd_config.conf | 404 for domain | Add virtualhost block in main config |
| Didn't reload after changes | Old config still running | lswsctrl restart |
Batch: List All Active Vhosts
# List all configured vhost names
grep -A1 "^virtualhost" /usr/local/lsws/conf/httpd_config.conf | grep -v "^--" | grep -v "^virtualhost"
# List all vhost conf dirs
ls /usr/local/lsws/conf/vhosts/
# Check domain mappings in all listeners
grep -A3 "^listener" /usr/local/lsws/conf/httpd_config.conf | grep map