Skip to main content

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

Scenariolistener map directive
Single domainmap example example.com
Domain + wwwmap example example.com, www.example.com
Wildcard subdomainmap example *.example.com
Multiple vhosts on one listenerOne map line per vhost

Common Vhost Mistakes

MistakeSymptomFix
Forgot map in listenerDefault page loadsAdd map vhostname domain.com in listener block
Wrong docRoot path404 on all pagesVerify path exists: ls -la /var/www/...
Permissions not nobody:nogroup403 Forbiddenchown -R nobody:nogroup /var/www/site
No index file in docRoot403 on root URLCreate index.html or index.php
PHP handler missing.php files downloadAdd scripthandler { add lsapi:lsphp84 php }
Vhost not in httpd_config.conf404 for domainAdd virtualhost block in main config
Didn't reload after changesOld config still runninglswsctrl 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