Markus Michalski FAQ

Server Tools: Virtual Hosts

Virtual hosts with Server Tools: create and delete PHP-FPM and reverse proxy VHosts for Apache and Nginx, switch PHP version, redirects, logrotate and VHost audit, with all checks and special cases.

Deutsche Version

Back to overview


Virtual Hosts

The VHost module creates Apache or Nginx configurations, enables them and reloads the webserver. The backend is determined globally by ST_WEBSERVER, not per VHost. The generated configurations are shown under Technical details.

Apache Nginx
Configuration file <ST_APACHE_SITES_AVAILABLE>/<domain>.conf <ST_NGINX_SITES_AVAILABLE>/<domain> (no extension)
Enable a2ensite Symlink to <ST_NGINX_SITES_ENABLED>/<domain>
Modules a2enmod headers proxy_fcgi (PHP) or headers proxy proxy_http (proxy) not needed
Reload apache2ctl configtest, then systemctl reload apache2 nginx -t, then systemctl reload nginx
SSL: ssl create, ssl delete, ssl renew supported not supported
SSL: ssl wildcard runs runs
vhost audit (template check) supported not implemented

Regardless of the backend, the logs of each domain are located at /var/www/<domain>/logs/ (access.log, error.log).

Create a PHP VHost

server-tools vhost create --domain example.com --php 8.3
server-tools vhost create --domain example.com --aliases "www.example.com cdn.example.com" --docroot /var/www/example.com/public
Option Meaning
--domain Required, valid domain name
--php PHP version, default ST_DEFAULT_PHP_VERSION. Allowed: 7.4, 8.0, 8.1, 8.2, 8.3, 8.4
--aliases Additional names, separated by spaces in one argument. Each name is checked as a domain
--docroot Custom DocumentRoot, must be located under ST_ALLOWED_DOCROOT_PATHS. Default /var/www/<domain>/html
--type php (default) or proxy

Flow:

  1. Domain, aliases and PHP version are checked. The FPM socket /run/php/php<version>-fpm.sock must exist, otherwise the command aborts and lists the versions it found.
  2. If the VHost file already exists, the tool warns and asks Overwrite existing configuration?.
  3. DocumentRoot and /var/www/<domain>/logs are created and given to www-data, the DocumentRoot gets mode 755.
  4. The logrotate file /etc/logrotate.d/vhost-<domain> is written.
  5. A welcome page index.php is written into the DocumentRoot.
  6. The configuration is written with mode 640, the site is enabled and the webserver is reloaded.
  7. If the reload fails, the site is disabled again. The written files and directories remain.

If you create a VHost again for an existing domain, the tool overwrites the VHost file and the index.php in the DocumentRoot. With --yes this happens without a prompt. An existing index.php of your site is lost.

Create a reverse proxy VHost

server-tools vhost create --domain app.example.com --type proxy --backend http://localhost:3000
server-tools vhost create --domain ws.example.com --type proxy --backend http://localhost:3000 --websocket
Option Meaning
--backend Required. URL with http:// or https://, host, optionally port and path
--websocket Enables WebSocket forwarding
--preserve-host The value false turns ProxyPreserveHost off, any other value leaves it on. Default from ST_PROXY_PRESERVE_HOST

For proxy VHosts, --php and --docroot are not evaluated, there is no DocumentRoot, only the log directory. The effects in detail:

--preserve-host off, as the help text puts it, is not recognized and leaves ProxyPreserveHost on. Use false.

Delete

server-tools vhost delete --domain example.com

Flow:

  1. The VHost must exist.
  2. If the domain has an assigned SSH user (home /var/www/<domain>, UID 1000 or higher), the command aborts. Delete the user first, see SSH users.
  3. With ST_AUTO_BACKUP=true the VHost file is saved as vhost_<domain>_<timestamp>.tar.gz in ST_BACKUP_DIR, before the prompt.
  4. Prompt Delete virtual host '<domain>'? (y/N):.
  5. Disable the site, on Apache also <domain>-le-ssl, remove configuration files and the logrotate file.
  6. If the tool finds a DocumentRoot in the configuration (PHP VHosts), the prompt Also delete DocumentRoot (/var/www/<domain>)? follows. On "yes" the entire directory /var/www/<domain> is deleted recursively, that is DocumentRoot, logs and everything else in it, without a backup. Proxy VHosts have no DocumentRoot, so this prompt does not appear for them and nothing is deleted.
  7. Reload the webserver.

For VHosts with a DocumentRoot, --yes also answers the second prompt with "yes": vhost delete --yes then deletes the directory /var/www/<domain> including its content. For proxy VHosts nothing is deleted. Only the VHost file is backed up. A certificate under /etc/letsencrypt remains, remove it with ssl delete if needed.

List and info

server-tools vhost list
server-tools vhost info --domain example.com

list shows "Active sites" (files in sites-enabled) and "Available sites" (files in sites-available). On Apache only *.conf files count.

info shows domain, type (php or proxy, detected from the file content), for PHP the DocumentRoot and PHP version, for proxy the backend and WebSocket, SSL and status. On Apache, SSL counts as active if <domain>-le-ssl.conf exists. On Nginx it shows not applicable (nginx).

Switch the PHP version

server-tools vhost php --domain example.com --version 8.4

The tool checks domain and version, requires the FPM socket of the target version, saves the file to /tmp, replaces the socket path and reloads the webserver. If the reload fails, it restores the old file and reloads again.

The switch only changes the file <domain>.conf. If certbot created its own <domain>-le-ssl.conf for the domain, that file keeps the old PHP version until you adjust it there yourself.

Redirect VHost

server-tools vhost redirect --from old.example.com --to https://new.example.com/ --code 301

Creates a separate VHost for the source domain that redirects to the target URL. --code is 301 (default) or 302. If a configuration already exists for the domain, the command aborts. Apache uses Redirect <code> / <url>, Nginx return <code> <url>;. Neither a DocumentRoot nor logrotate is created, and there is no rollback if the reload fails.

www and HTTPS redirect (menu only)

In the menu "Virtual Host Management", "Add www redirect" and "Force HTTPS redirect" add a block to an existing VHost. The tool saves the file to /tmp, inserts the block before the first </VirtualHost> (Apache) or before the last line } (Nginx), reloads and restores the file on an error.

Both actions only change <domain>.conf and do not check whether the block is already present. A second call inserts it a second time.

VHost audit

server-tools vhost audit
server-tools vhost audit --domain example.com

Checks Apache VHosts against the template the tool generates. There are four checks per VHost:

Check Meaning
X-Forwarded-Proto Header is present in the file
X-Forwarded-Port Header is present in the file
ErrorLog Points to /var/www/<domain>/logs/error.log
CustomLog Points to /var/www/<domain>/logs/access.log

The example shows the format:

Vhost: example.com
  [OK]    X-Forwarded-Proto header present
  [OK]    X-Forwarded-Port header present
  [OK]    ErrorLog matches canonical path (rotated via /etc/logrotate.d/vhost-example.com)
  [DRIFT] CustomLog does not match canonical path /var/www/example.com/logs/access.log (found: CustomLog /var/log/apache2/access.log combined)

Pure redirect VHosts are skipped with [SKIP]. Without --domain the command checks all *.conf in sites-available except *-le-ssl.conf, 000-default, default-ssl and default. The exit code is 1 as soon as one VHost deviates, otherwise 0. This makes the audit usable in a cron job. The audit changes nothing.

With ST_WEBSERVER=nginx, vhost audit --domain prints the line [SKIP] template audit not yet implemented for nginx and vhost audit without --domain prints the line (template audit not yet implemented for nginx, see #13). Both end with exit code 0.

Next