Debug School

rakesh kumar
rakesh kumar

Posted on

Root Domain Serving the Blog Instead of Your Laravel App

"Why example.com Loads Your Blog but example.com/trips Loads Your App"
"Apache DocumentRoot Was Correct — So Why Did / Serve WordPress?"

Theory — three layers decide what / returns

Most people debug only the first layer. The bug usually lives in the second or third.

The key insight for the post: / is a directory request, not a file request. Laravel's standard front-controller rule is

RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L]
For /, REQUEST_FILENAME is a directory, so !-d is false and the rule never fires. mod_dir picks the index file instead. That's why / can behave completely differently from /trips — and why whatever index.php sits at the root wins outright.

  1. Problem
    https://example.com/ renders an old WordPress blog. https://example.com/trips/ renders the correct new app. Same vhost, same document root, opposite results.

  2. Errors and what each one actually meant
    Walk through the false leads — this is the most useful part for readers:

VirtualHost configuration:

ServerRoot: "/opt/lampp"
Enter fullscreen mode Exit fullscreen mode

Empty vhost list from apachectl -S. Looks catastrophic. Actually a test artifact — XAMPP wraps the SSL include in , and apachectl -S runs httpd -t without -DSSL. Real command: httpd -DSSL -D DUMP_VHOSTS -S.

488:#Include etc/extra/httpd-vhosts.conf
Enter fullscreen mode Exit fullscreen mode

A genuinely commented-out include — real bug, fixed the HTTP side, but not the symptom.

AH00112: Warning: DocumentRoot [/opt/.../public"] does not exist
Note the trailing " inside the bracket — a missing opening quote, so Apache swallowed the closing one into the path. Unrelated, but a great teaching example.

  1. The actual cause ls -la on the document root against git status:


Deployed .htaccess header:

# ROOT DOMAIN -> /blog/index.html
# TANPA BATAS UPLOAD / EKSEKUSI DARI HTACCESS
Enter fullscreen mode Exit fullscreen mode

An injected index.php at the document root, which DirectoryIndex happily served for / while every real subdirectory kept working normally — which is exactly why the symptom looked like a routing bug.

  1. Solution

Preserve evidence (tar czf the suspect files) before deleting
git status --porcelain in the document root — a git checkout enumerates tampering for free
git checkout -- .htaccess index.php, remove the unknown files
Sweep the rest of the box: grep -rl "ROOT DOMAIN ->" /opt/lampp/htdocs --include=".htaccess" and find ... -name '*.php' -newermt
Rotate everything readable from .env — DB password, APP_KEY, OIDC client secret, cloud keys
Check persistence: crontab -l, ~/.ssh/authorized_keys, last

  1. Takeaway When one path works and another doesn't under the same vhost, stop debugging the vhost. Compare the document root against source control — git status in a deployed checkout is the fastest intrusion-detection tool you already have.

Top comments (0)