Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

vishnu_sadanandan's avatar

Remove public/index.php from URL in Laravel

Remove public/index.php from URL in Laravel

I am using LAMP configuration with php 7. My .htaccess code in public folder is below.

Options -MultiViews -Indexes

RewriteEngine On

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

# Redirect Trailing Slashes If Not A Folder...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} (.+)/$
RewriteRule ^ %1 [L,R=301]

# Handle Front Controller...
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ public/ [L]

And below code is my apache2 virtual host config details.

<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    #ServerName www.example.com

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
Alias /phpmyadmin "/usr/share/phpmyadmin/"
<Directory "/usr/share/phpmyadmin/">
     Order allow,deny
     Allow from all
     Require all granted
</Directory>
    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf
</VirtualHost>

And i have no .htaccess file in root directory. Anyone can seriously help me. Thanks in advance.

0 likes
12 replies
Snapey's avatar

document root should point to your public folder

DocumentRoot /var/www/html/public
vishnu_sadanandan's avatar

Ok thank you for your replay. But I have other projects in this folder too , then how can i do it. Here is my folder structure

/var/www/html/workspace/CodeIgniterProject
/var/www/html/workspace/LaravelProject

I am calling it from the localhost like below

http://localhost/workspace/CodeIgniterProject : ( it will be the project home page)
http://localhost/workspace/LaravelProject/public : (But here i need to put 'public' folder name too)

I hope that i can present my problem . Waiting for your valuable reply. Thanks

bipin's avatar

@vishnu_sadanandan if i understand correctly you are try to put your logic(controller in another folder) and public in another folder is i m right?

Snapey's avatar

create a virtualHost per project and point the document root to each of their root folders. Your Laravel project would have document root at

DocumentRoot /var/www/html/workspace/LaravelProject/public
1 like
vishnu_sadanandan's avatar

Ok thank you for your replay. How can i create "virtualHost per project". Should i edit the virtual host file and put two DocumentRoot specifying two projects ? Or create two virtual host file ?

vishnu_sadanandan's avatar

Hey Snapey I've created a new virtual host file for my laravel project like below

<VirtualHost *:80>
    # The ServerName directive sets the request scheme, hostname and port that
    # the server uses to identify itself. This is used when creating
    # redirection URLs. In the context of virtual hosts, the ServerName
    # specifies what hostname must appear in the request's Host: header to
    # match this virtual host. For the default virtual host (this file) this
    # value is not decisive as it is used as a last resort host regardless.
    # However, you must set it for any further virtual host explicitly.
    #ServerName www.example.com

    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html/workspace/daily-stuff/public
Alias /phpmyadmin "/usr/share/phpmyadmin/"
<Directory "/usr/share/phpmyadmin/">
     Order allow,deny
     Allow from all
     Require all granted
</Directory>
    # Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
    # error, crit, alert, emerg.
    # It is also possible to configure the loglevel for particular
    # modules, e.g.
    #LogLevel info ssl:warn

    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined

    # For most configuration files from conf-available/, which are
    # enabled or disabled at a global level, it is possible to
    # include a line for only one particular virtual host. For example the
    # following line enables the CGI configuration for this host only
    # after it has been globally disabled with "a2disconf".
    #Include conf-available/serve-cgi-bin.conf
</VirtualHost>


Again without public folder name i got server not found error. Thanks in advance.

LaraStorm's avatar

Simple ! /var/www/html/workspace/LaravelProject

create a new folder called whatever ex: projectfiles and move all the files to that folder except public folder

copy all the files in /var/www/html/workspace/LaravelProject/public to /var/www/html/workspace/LaravelProject/

delete the empty public folder

edit these two lines in index.php

require __DIR__.'/projectfiles/bootstrap/autoload.php';

$app = require_once __DIR__.'/projectfiles/bootstrap/app.php';

Done !

Snapey's avatar

Virtual hosts allow one server to host multiple websites, but you need to name them.

If you specify a domain name then apache server will inspect the host headers of the request coming from the users and direct the request to the right virtual server

With this in mind, I have for instance, on the same server;

<VirtualHost *:80>

    ServerName olicence.guru
    ServerAlias www.olicence.guru

    DocumentRoot /var/www/html/olicence.guru/public

    <Directory /var/www/html/olicence.guru/public>
        AllowOverride All
        Require all granted
    </Directory>

</VirtualHost>


<VirtualHost *:80>

    ServerName tm.novate.co.uk

    DocumentRoot /var/www/html/template-mailer/Live/public

    <Directory /var/www/html/template-mailer/Live/public>
        AllowOverride All
        Require all granted
    </Directory>

</VirtualHost>

So here I have two projects on the same server

The first responds to olicence.guru or www.olicence.guru and my project code is in /var/www/html/olicence.guru/

Document root points to the public folder. This means my project is out of reach of visitors. They can only access the public folder.

The second project responds to tm.novate.co.uk and the project is in /var/www/html/template-mailer/Live/ and then again, document root is public so that my project code and in particular the .env file is not accessible.

With this setup and the .htaccess that comes with Laravel, once permissions are correct the install just works

setting the correct permissions is done with

chgrp -R www-data /var/www/html/template-mailer/Live/storage
chgrp -R www-data /var/www/html/template-mailer/Live/bootstrap/cache

chmod -R ug+rwx /var/www/html/template-mailer/Live/storage
chmod -R ug+rwx/var/www/html/template-mailer/Live/bootstrap/cache

Hope that helps

1 like
vishnu_sadanandan's avatar

Thanks for the replay. I changed my virtual host file as above and also i had a problem that i did not enabled the apache rewrite mode. I think that is why i faced the issues. Also I removed the public from url but still i cannot remove the index.php. My .htaccess in public is below

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

    RewriteEngine On

    # Handle Authorization Header
    RewriteCond %{HTTP:Authorization} .
    RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
    
    # Redirect Trailing Slashes If Not A Folder...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_URI} (.+)/$
    RewriteRule ^ %1 [L,R=301]

    # Handle Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?/ [L]
</IfModule>
Snapey's avatar

try


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

Please or to participate in this conversation.