Making Laravel work on a shared hosting can be troublesome, because Laravel needs to have its document root set to the public
directory. This may not be configurable by a user or even desirable, when the server is hosting multiple websites.
Here's a simple method using only a .htaccess
file placed in Laravel's root directory - e.g. alongside app
, bootstrap
, config
, ... No changes whatsoever are necessary to your code.
The file rewrites all the requests so that requesting /file.png
would in fact return /public/file.png
and anything else is routed to /public/index.php
. This also ensures that nothing outside the public
folder can be accessed, thereby protecting any sensitive files like .env
or database/*
.
This method assumes that DOCUMENT_ROOT
is set properly by your Apache server. Try this first and use the 2nd method only if it doesn't work on your server.
.htaccess
RewriteEngine on
# serve existing files in the /public folder as if they were in /
RewriteCond %{DOCUMENT_ROOT}public%{REQUEST_URI} -f
RewriteRule (.+) /public/$1 [L]
# route everything else to /public/index.php
RewriteRule ^ /public/index.php [L]
If your server doesn't set DOCUMENT_ROOT properly, then you'll need to use an absolute path in RewriteCond. That is, an absolute path on the server's filesystem. You can get it by copying the following script to the directory where your Laravel installation will reside and visiting its URL - i.e. http://example.com/get_doc_root.php
.
get_doc_root.php
<?php
echo getcwd();
This should result in something like /var/www/example.com/web
. Use the following .htaccess
file and replace [[your path]]
with the actual path you got.
.htaccess
RewriteEngine on
# serve existing files in the /public folder as if they were in /
RewriteCond [[your path]]/public%{REQUEST_URI} -f
RewriteRule (.+) /public/$1 [L]
# route everything else to /public/index.php
RewriteRule ^ /public/index.php [L]
In our example case, the RewriteCond line would look like this:
RewriteCond /var/www/example.com/web/public%{REQUEST_URI} -f
Removing this line worked for me:
RewriteCond %{DOCUMENT_ROOT}public%{REQUEST_URI} -f
My
.htaccess
looks like this now: