User

Laravel Document Root

Why Laravel's web root must point at the public/ subdirectory and how Opterius handles this automatically on install.

Last updated 1775606400

Laravel's web server must be pointed at the public/ directory, not the project root. The public/ directory contains index.php — every request routes through it. The project root contains .env, composer.json, application source code, and database migrations, none of which should be web-accessible.

What Opterius Sets on Install

When you install Laravel via the panel, the agent automatically sets the domain's document root to:

/home/{username}/{domain.com}/public_html/laravel-app/public/

You do not need to configure this manually after a panel install.

Deploying Manually

If you are deploying a Laravel project yourself (via Git, SFTP, or SCP), follow this structure:

  1. Place your Laravel project at:
/home/username/domain.com/laravel-app/

The name laravel-app/ is a convention — use whatever directory name makes sense for your project.

  1. In the panel, go to Hosting Mode → Domains → [domain] → Document Root.
  2. Set the document root to:
laravel-app/public

The panel resolves this relative to the domain's base directory (/home/username/domain.com/), so the full server path becomes /home/username/domain.com/laravel-app/public/.

  1. Click Save. The Nginx vhost is rewritten and reloaded automatically.

See Document Root Structure for how document roots work in Opterius.

Why This Matters

[!WARNING] If you point the document root at the Laravel project root instead of public/, your .env file (containing database credentials, APP_KEY, and any API secrets) is directly downloadable by anyone who knows to request it. This is a critical security exposure.

With the document root at the project root, an attacker can fetch:

https://yourdomain.com/.env
https://yourdomain.com/composer.json
https://yourdomain.com/composer.lock

With the document root correctly set to public/, none of those paths are web-accessible.

Confirming the Configuration

# SSH: check the Nginx vhost root directive for your domain
grep -n "root" /etc/nginx/sites-enabled/username_domain.com.conf

The root line should end with .../laravel-app/public;, not .../laravel-app;.

# PHP: confirm index.php is being served from public/
ls /home/username/domain.com/laravel-app/public/index.php

Storage and Symlinks

Laravel writes uploaded files and cached views to storage/. The public/storage symlink (created by php artisan storage:link) must point from public/storage/ to storage/app/public/. This symlink works correctly when the document root is public/.

php artisan storage:link --path=/home/username/domain.com/laravel-app/