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

Chron's avatar
Level 6

shared hosting laravel files

\---htdocs
	\---css/
	\---js/
	\---fonts/
	\---images/
	\---project-name/
	\---.htaccess
	\---.htaccess-from-host
	\---.htaccess-from-host
	\---favicon.ico
	\---index.php
	\---mix-manifest.json
	\---robots.txt

I don't have SSH so I uploaded my files through FTP, I moved the files of project-name/public/ to /htdocs/ so they're on the same level. I just want to ask, is the hierarchy fine?

0 likes
18 replies
jlrdw's avatar

Can you see your .env? Like yoursite.com/.env. if so your site is not secure.

You should be serving through public as document root, or even better have Main laravel out of, above htdocs.

Chron's avatar
Level 6

Main laravel out of, above htdocs.

I tried that earlier, but it didn't let me. It's giving me permission errors, and there's file named 'DO NOT UPLOAD FILES HERE' in a level above htdocs.

jlrdw's avatar

How about the .env, if you bring that up can you see the credentials.

jlrdw's avatar

Since you cannot move files above htdocs, you should be using public as your document root.

You should restore the out of the box file structure, in my opinion.

If this is not a virtual host, you could write a second htaccess file, just a small one that points to public.

And inside public that htaccess file and index.php will do their thing.

Give me a couple of minutes I have an example.

Edit: see this post for an example:

https://laracasts.com/discuss/channels/general-discussion/nginx-point-to-public

it has an Apache example also.

Chron's avatar
Level 6

I restored the original file structure, public folder is in the project folder.

\---htdocs
	\---project-name/
		\---public/
			\---css/
			\---js/
			\---fonts/
			\---images/
			\---.htaccess
			\---.htaccess-from-host
			\---.htaccess-from-host
			\---favicon.ico
			\---index.php
			\---mix-manifest.json
			\---robots.txt
		\---....other project files

I made an .htaccess inside /htdocs/ that points to /project-name/public but it doesn't work, it gives me 403.

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

    RewriteEngine On
    RewriteBase /project-name/public/ <-----------------------

    # 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 ^ index.php [L]
</IfModule>
jlrdw's avatar

In your project folder the small htaccess only should have:

    RewriteEngine On
    RewriteRule ^(.*)$ public/
    RewriteRule ^ server.php
Chron's avatar
Level 6

Should I remove htaccess inside the htdocs folder?

jlrdw's avatar

The one I showed goes inside of your project folder, it points to public. Leave the index.php and htaccess that ships with laravel alone.

If your project name is myproject.

htdocs
    \---myproject/
           \--.htaccess    //  small one that points to public.
           \--laravel goes here like installed, folder structure, unchanged.

Under my project is the small htaccess.

However with a host where you can make folders above htdocs, the best install is like this guide: http://novate.co.uk/deploy-laravel-5-on-shared-hosting-from-heart-internet/

But you did mention on this host you cannot do that.

Chron's avatar
Level 6

So it kinda works now, I can access the site thru domain.com/myproject/

But the .env is still accessible for the public.

jlrdw's avatar

It shouldn't be if your htaccess files are right.

Remember use the folder structure that comes with laravel.

Chron's avatar
Level 6

Here are the .htaccess

//  /htdocs/myproject/.htaccess

    RewriteEngine On
    RewriteRule ^(.*)$ public/
    RewriteRule ^ server.php



// /htdocs/myproject/public/.htaccess

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

I restored the structure.

\---htdocs
	\---project-name/
		\---app/
		\---bootstrap/
		\---database/
		\---migrations/
		\---public/
			\---css/
			\---js/
			\---fonts/
			\---images/
			\---.htaccess
			\---.htaccess-from-host
			\---.htaccess-from-host
			\---favicon.ico
			\---index.php
			\---mix-manifest.json
			\---robots.txt
		\---.htaccess <---------- { RewriteEngine On
					    RewriteRule ^(.*)$ public/
					    RewriteRule ^ server.php }
		\---....other project files

But .env is still accessible.

jlrdw's avatar

I get 404 not found.

Take another look at the htaccess examples here: https://laracasts.com/discuss/channels/general-discussion/nginx-point-to-public. The one in public:

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

    RewriteEngine On
    RewriteBase /laravel842/    // only modified line

    # 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]

    # Send Requests To Front Controller...
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteRule ^ index.php [L]
    # RewriteRule ^(.*)$ public/ [L]
</IfModule>

Perhaps add a rewrite base:

RewriteBase /laravel842/    // use your site.

Your env should not show if all is correct.

Note the RewriteBase I like, I don't have to use a leading slash in routing, etc.

You can experiment:

RewriteBase /mysite.com/

or

RewriteBase /mysite.com

etc.

I do not know where the problem is, but I have never had .env show when web server's document / web root is public.

Also note, normally I have main laravel above htdocs.

Even the documentation states:

After installing Laravel, you should configure your web server's document / web root to be the public directory. The index.php in this directory serves as the front controller for all HTTP requests entering your application.

An option is to get better hosting where you have full control or, look at something like digitalocean.

Chron's avatar
Level 6

{{ asset('css/styles.css') }} doesn't point to site.com/public/css/styles.css anymore, it now points to site.com/css/styles. Same for images and js. Is there a way to change it back because renaming them takes much time?

Chron's avatar
Level 6

Ohh, I can't access it anymore.

However, the assets are not loaded, it doesn't include the public folder.

jlrdw's avatar

@chron on your shared host, if you have restrictions, you can make an img folder right in public, and do:

<img src="{{ asset('public/img/imgdogs/abbie173.jpg') }}" alt="">
or
<img src="{{ asset('/public/img/imgdogs/abbie173.jpg') }}" alt="">

Try with and without leading slash, but this works perfect.

Note, this is example, I always put main laravel above webroot.

It sounds like you just need to learn how to resolve paths and url's.

In some apps I have images and files well out of webroot and out of laravel and serve with a script:

    public function displayImage()
    {
        $basedir = '/stohere/uploads';
        $imagedir = Request::input('dir');
        $image = Request::input('img');
        $file = $basedir . '/' . $imagedir . '/' . $image;

        $string = $image;
        $str = (int) Cln::findId($string, "_", ".");

        If (Auth::id() != $str) {
            exit(0);
        }

         header('Content-Type: image/jpeg');
          ob_clean();

          readfile($file);
          exit(0);
    }

Used like:

<img src="<?php echo 'image?dir=imgdogs&img=' .  $row->dogpic; ?>" alt="" class="image">

or use blade. You have a route to ImageController.

But again, with restrictions with your host, maybe change host.

Chron's avatar
Level 6

on your shared host, if you have restrictions, you can make an img folder right in public

Yes, I have multiple folders in public like css, js, img, so it should be returning site.com/public/img/ex.jpg when I output {{ asset('img/ex.jpg') }}, like in a local server, but it's only returning site.com/img/ex.jpg

jlrdw's avatar

Use

<img src="{{ asset('/public/img/ex.jpg') }}" alt="">

Just resolve your url.

Please or to participate in this conversation.