How to Redirect a Laravel App to the Public Folder Using .htaccess

When you upload a Laravel application to shared hosting, the project may open only when you visit a URL like:

https://yourdomain.com/public

That is not ideal for a production website.

Your visitors should be able to open:

https://yourdomain.com

without adding /public to the URL.

This guide explains how to redirect or rewrite a Laravel application to the public folder using .htaccess.

Why Laravel Uses a Public Folder

Laravel keeps its public entry point inside the public directory.

The main file that handles incoming web requests is:

public/index.php

The public folder also contains public assets such as:

  • CSS files

  • JavaScript files

  • Images

  • Favicon files

  • Built frontend assets

Other Laravel folders should normally not be directly accessible from the web.

These include:

  • app

  • bootstrap

  • config

  • database

  • resources

  • routes

  • storage

  • vendor

For this reason, the best Laravel hosting setup is to point the domain's document root directly to the public folder.

However, some shared hosting providers do not allow you to change the document root easily. In that case, you can use .htaccess.

Typical Laravel Folder Structure on Shared Hosting

Your Laravel project may look like this:

public_html/
├── app/
├── bootstrap/
├── config/
├── database/
├── public/
│   ├── index.php
│   ├── .htaccess
│   └── build/
├── resources/
├── routes/
├── storage/
├── vendor/
├── .env
├── artisan
└── composer.json

If your domain points to:

public_html

then Laravel's index.php is one level deeper inside:

public_html/public

This is why the application may only work when you visit:

https://yourdomain.com/public

Method 1: Redirect Laravel to Public Using Root .htaccess

Create a new .htaccess file inside the main Laravel project directory.

For example:

public_html/.htaccess

Add this code:

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

This tells Apache to internally route requests through the Laravel public directory.

After adding this file, visiting:

https://yourdomain.com

should load the Laravel application.

How This .htaccess Rule Works

The first line checks whether Apache's rewrite module is available:

<IfModule mod_rewrite.c>

Then it enables URL rewriting:

RewriteEngine On

This condition prevents Apache from repeatedly adding /public:

RewriteCond %{REQUEST_URI} !^/public/

Finally, all requests are internally rewritten to the public folder:

RewriteRule ^(.*)$ public/$1 [L]

The visitor still sees:

https://yourdomain.com

instead of:

https://yourdomain.com/public

Make Sure Laravel's Public .htaccess Exists

Laravel normally includes another .htaccess file inside:

public/.htaccess

A typical Laravel Apache configuration looks like this:

<IfModule mod_rewrite.c>
    <IfModule mod_negotiation.c>
        Options -MultiViews -Indexes
    </IfModule>

    RewriteEngine On

    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    RewriteCond %{HTTP:X-XSRF-TOKEN} .
    RewriteRule .* - [E=HTTP_X_XSRF_TOKEN:%{HTTP:X-XSRF-TOKEN}]

    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
</IfModule>

Do not remove this file unless you know exactly why you are changing it.

This file is responsible for sending Laravel routes to index.php.

Configure APP_URL

Open your Laravel .env file.

Set:

APP_URL=https://yourdomain.com

Do not set:

APP_URL=https://yourdomain.com/public

if you want your application to run from the main domain.

After updating .env, clear Laravel's cached configuration.

Run:

php artisan optimize:clear

You can also run:

php artisan config:clear
php artisan route:clear
php artisan view:clear

Method 2: Point the Domain Document Root Directly to Public

If your hosting panel allows it, this is usually the cleaner solution.

Instead of pointing the domain to:

/home/username/public_html

set the document root to:

/home/username/public_html/public

Then Apache loads Laravel directly from the correct directory.

This avoids the need for a root-level rewrite.

Which Method Is Better?

Document Root Method

Use this when your hosting panel lets you change the domain root.

Advantages:

  • Cleaner configuration

  • Better Laravel security

  • No extra root rewrite

  • Public files are served directly

  • Private Laravel files remain outside the web root

.htaccess Rewrite Method

Use this when:

  • Shared hosting forces the domain to use public_html

  • You cannot change the document root

  • Your Laravel project is already inside public_html

  • You need a quick compatible setup

Avoid Moving index.php Unless Necessary

Some tutorials suggest moving:

public/index.php

into the Laravel project root.

This can work with additional path changes, but it is usually not the preferred deployment approach.

Laravel is designed to use the public folder as the web-accessible directory.

Keeping that structure makes future upgrades and maintenance easier.

Do Not Expose the .env File

Your .env file can contain sensitive information such as:

DB_DATABASE=
DB_USERNAME=
DB_PASSWORD=
APP_KEY=
MAIL_PASSWORD=

It should never be publicly accessible.

Test this URL:

https://yourdomain.com/.env

It should return an error, forbidden response, or not found page.

It should never display the contents of your .env file.

Check File and Folder Permissions

Laravel needs write access to certain directories.

Common directories that must be writable are:

storage/
bootstrap/cache/

Typical Linux permissions may be:

chmod -R 775 storage
chmod -R 775 bootstrap/cache

The correct owner and permissions depend on your hosting environment.

Avoid using 777 unless your hosting provider specifically requires it and you understand the security implications.

Create the Laravel Storage Link

If your application stores uploaded files using Laravel's public disk, create the storage symbolic link:

php artisan storage:link

This normally creates:

public/storage

pointing to:

storage/app/public

Then files can be accessed using URLs such as:

https://yourdomain.com/storage/image.jpg

If public/storage Already Exists

You may see an error like:

The [public/storage] link already exists.

First check whether it is a symbolic link:

ls -l public/storage

If it is a normal directory instead of a symbolic link, you may need to remove or rename that directory before running:

php artisan storage:link

Be careful before deleting anything if the directory contains uploaded customer files.

Fix Laravel Assets Loading From /public

If your CSS, JavaScript, or images are trying to load from URLs such as:

https://yourdomain.com/public/css/app.css

check your asset configuration.

Use Laravel helpers such as:

{{ asset('css/app.css') }}

instead of hardcoding:

/public/css/app.css

For Vite applications, use Laravel's Vite integration where appropriate.

Laravel Routes Return 404

If the home page works but routes such as:

/login

/dashboard

/products

return 404 errors, Apache rewriting may not be enabled.

Check that:

  • mod_rewrite is enabled

  • public/.htaccess exists

  • Apache allows .htaccess overrides

  • Your document root is correct

If you manage the Apache server directly, the virtual host may need:

<Directory /var/www/example/public>
    AllowOverride All
    Require all granted
</Directory>

Then restart Apache.

Laravel Shows 500 Internal Server Error

A 500 error can be caused by:

  • Incorrect PHP version

  • Missing PHP extensions

  • Incorrect file permissions

  • Invalid .htaccess

  • Missing Composer dependencies

  • Wrong .env settings

  • Missing APP_KEY

  • Laravel cache permissions

Check the Laravel log:

storage/logs/laravel.log

If you have SSH access, you can also check the server error log.

Run Composer Install

After uploading a Laravel application, make sure dependencies are installed.

Run:

composer install --no-dev --optimize-autoloader

For production, you can also run:

php artisan optimize

Generate APP_KEY

If your .env file does not already contain a valid application key, run:

php artisan key:generate

Do not regenerate the key on an existing production application without understanding the impact, because encrypted data and sessions can be affected.

Configure the Database

Update your .env file:

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=your_database
DB_USERNAME=your_username
DB_PASSWORD=your_password

Then test the application.

If required, run migrations:

php artisan migrate --force

Only run production migrations when you know they are appropriate for that deployment.

Enable HTTPS

Once the domain is working, install or enable SSL.

Update:

APP_URL=https://yourdomain.com

Then clear the application cache:

php artisan optimize:clear

Your site should load through:

https://yourdomain.com

Recommended Laravel Deployment Checklist

Before considering your Laravel application ready, check:

  • Domain points to the correct server

  • Document root points to public, or root .htaccess rewrites to public

  • .env is not publicly accessible

  • Composer dependencies are installed

  • APP_KEY exists

  • Database configuration is correct

  • storage is writable

  • bootstrap/cache is writable

  • Storage link is configured if required

  • SSL is enabled

  • APP_URL uses the correct HTTPS domain

  • Laravel caches are refreshed

  • Login and application routes work

  • CSS and JavaScript files load correctly

Example Complete Setup

Suppose your Laravel application is located here:

/home/ceylonweb/public_html/

and the project contains:

/home/ceylonweb/public_html/public/index.php

Your root .htaccess would be:

<IfModule mod_rewrite.c>
    RewriteEngine On

    RewriteCond %{REQUEST_URI} !^/public/
    RewriteRule ^(.*)$ public/$1 [L]
</IfModule>

Your .env would contain:

APP_URL=https://example.com

Then clear Laravel's caches:

php artisan optimize:clear

Now opening:

https://example.com

should load the Laravel application without showing /public in the browser address.

Frequently Asked Questions

Why does my Laravel website only work with /public?

Your domain is probably pointing to the Laravel project root instead of the public directory.

The correct document root should normally be the Laravel public folder.

Can I remove /public from a Laravel URL using .htaccess?

Yes.

A root .htaccess rule can internally rewrite requests to the public folder when you cannot change your domain's document root.

Should I redirect or rewrite to public?

An internal rewrite is usually preferable because visitors continue seeing the clean domain URL.

For example:

https://example.com

instead of:

https://example.com/public

Is it safe to put Laravel inside public_html?

It can work, but the preferred setup is to expose only Laravel's public directory to the web.

If the complete project is under public_html, make sure sensitive files such as .env are protected.

What is the best Laravel document root?

The document root should normally point to:

/path/to/laravel/public

Why do Laravel routes return 404 on shared hosting?

The most common causes are missing Apache rewrite support, an incorrect .htaccess file, or an incorrect document root.

Why are Laravel CSS and JavaScript files not loading?

Check your asset URLs and make sure they are not hardcoded with /public.

Use Laravel's asset or Vite helpers where appropriate.

Do I need to run php artisan storage?

You need it if your application uses Laravel's public storage disk and must expose files from storage/app/public.

Need Laravel Hosting Help?

If you are hosting a Laravel application and need a suitable hosting environment, Ceylon Web Servers provides hosting options for websites and web applications.

Available options include:

  • Shared Hosting

  • Reseller Hosting

  • VPS Hosting

For larger Laravel applications or projects that require more server control, a VPS may be more suitable.

Website: ceylonwebservers.com

Call / WhatsApp: 070 244 7722