One Apache instance on your-web-host serves many sites — books, git, music, wiki, adi, and the apex domains — all on port 80. Apache picks the right site from the request's Host header, matched against each vhost's ServerName. Traffic arrives via the Cloudflare Tunnel.
A minimal vhost
/etc/apache2/sites-available/wiki.thelabsource.com.conf:
<VirtualHost *:80>
ServerName wiki.thelabsource.com
DocumentRoot /var/www/wiki.thelabsource.com/public
<Directory /var/www/wiki.thelabsource.com/public>
Options -Indexes +FollowSymLinks
AllowOverride All # let .htaccess do rewrites
Require all granted
</Directory>
<IfModule mod_remoteip.c>
RemoteIPHeader CF-Connecting-IP # real client IP behind Cloudflare
</IfModule>
ErrorLog ${APACHE_LOG_DIR}/wiki_error.log
CustomLog ${APACHE_LOG_DIR}/wiki_access.log combined
</VirtualHost>
Enable and reload:
sudo a2ensite wiki.thelabsource.com.conf
sudo apache2ctl configtest # ALWAYS test before reload
sudo systemctl reload apache2
Conventions on this box
| Convention | Value |
|---|---|
| Docroot | /var/www/<hostname>/public (or /public_html) |
| One conf file per site | sites-available/<hostname>.conf |
| Real client IP | mod_remoteip + CF-Connecting-IP |
| Per-site rewrites | .htaccess with AllowOverride All |
Gotchas
configtestbefore every reload. A syntax error in one vhost (a stray quote, a bad directive) prevents Apache from reloading and can take down every site at once.
- The first vhost Apache loads is the default for any unmatched Host header — keep a sane default or a catch-all.
mod_rewrite,mod_headers,mod_remoteipmust be enabled (a2enmod) or the directives silently do nothing.- Keep TLS off Apache here — Cloudflare terminates HTTPS; Apache only needs
*:80. See Tailscale Serve on 443 While Apache Stays on 80.
See also: MariaDB Socket Auth vs TCP Users.