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

faizankhan619's avatar

Images Not Displaying on Live Server (Shared Hosting)

Images stored in the public/storage directory are not displaying on the live server (shared hosting environment), but they work perfectly on localhost.

Relevant Code

Trainee.php Method

public function getProfilePicture()
{
  if ($this->picture && Storage::disk('public')->exists($this->picture) == 1) {
         return Storage::disk('public')->url($this->picture);
    }

    return asset('/images/blank_profile_picture.png');
}

Blade Template

<img src="{{ $trainee->getProfilePicture() }}">

filesystems.php Configuration

'disks' => [
        'local' => [
            'driver' => 'local',
            'root' => storage_path('app/private'),
            'serve' => true,
            'throw' => false,
        ],

        'public' => [
            'driver' => 'local',
            'root' => storage_path('app/public'),
            'url' => env('APP_URL').'/storage',
            'visibility' => 'public',
            'throw' => false,
        ],
],

Commands Executed on Shared Hosting (via SSH)

Below are the commands I ran to set up the symbolic link for the storage directory:

php artisan storage:link
  INFO  The [public/storage] link has been connected to [storage/app/public].
chmod -R 755 storage
chmod -R 755 public/storage

Verifications

After running the commands:

  1. The symbolic link was created successfully:
ls -l public
lrwxrwxrwx 1 user user 61 Dec 17 10:22 storage -> /home/customer/www/.../storage/app/public

... contains the app path that I'm passing in .env as APP_URL

  1. The file exists in the storage/app/public/trainee-profile-pictures directory:
ls -l storage/app/public/trainee-profile-pictures/
-rwxrwxr-x 1 user user 26990 Dec 17 07:36 gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg```

Expected Output

The getProfilePicture() method in the Trainee.php model should return the correct URL of the image, and the <img> tag in the Blade template should display the image.

Debugging Observations

Actual image path:

  • /storage/app/public/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

Values observed during debugging:

$this->picture = trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

Storage::disk('public')->exists($this->picture) = 1

$trainee->getProfilePicture() = https://.../storage/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

storage_path('app/public/'.$this->picture) =
/home/customer/www/.../storage/app/public/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

Observations:

  • The symbolic link appears to be created correctly.
  • The image exists in the specified directory.
  • Despite this, the fallback image is being returned by the getProfilePicture() method.

Request

I want to know

  1. Whether there’s an issue with the symbolic link or file permissions.
  2. Any misconfiguration in the filesystems.php or hosting environment.
  3. Steps to ensure the images display properly on the live server.
0 likes
11 replies
dumitru-caldare's avatar

Have you checked the permission of each individual file?

APP_URL is using http or https?

Try to remove the if statement and get the picture without it, maybe debug the code there to see if it's giving the image correctly.

faizankhan619's avatar

@dimka7 APP_URL is using https.

baseos | app.mysite.de | [email protected]:~/www/app.mysite.de$ ls -l storage/app/public/trainee-profile-pictures/
total 5404
-rwxr-xr-x 1 u2515-xxxx u2515-xxxx 26990 Dec 17 07:36 gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg
// Other files

Respective file have above permissions, if that how we check the file permissions

Snapey's avatar

Look in the browser generated source.

is the img tag src correct for your hosting? I would expect it to be /storage/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

Does your browser get a 404 when trying to load this image?

What URL do you need to place in the browser address bar to load the image?

faizankhan619's avatar

@Snapey I'm getting 500 for both or below URLs

mysite.de/storage/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg mysite.de/storage/app/public/trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg

Internal Server Error
The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at [no address given] to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.

Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.

But you can see if I try to look for the file in SSH I can see file is there

baseos | app.mysite.de | [email protected]:~/www/app.mysite.de$ ls -l storage/app/public/trainee-profile-pictures/
total 5404
-rwxr-xr-x 1 u2515-xxxx u2515-xxxx 26990 Dec 17 07:36 gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg
// Other files

In browser, I'm not able to see images inside the storage folder with either of above combinations

Tray2's avatar

Have you checked that your server follows symlinks? If it's configured not to, well then you might need to turn it on. If you are using apache you can probably do it in your htaccess file.

faizankhan619's avatar

@Tray2 I'm not sure hw to check if my server follows symlinks. I'm using siteground. My .htaccess file looks like below

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

    RewriteEngine On
    # Allow access to storage file
    RewriteRule ^storage/(.*)$ /storage/$1 [L]

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

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

I tried adding Options +FollowSymLinks after this line <IfModule mod_rewrite.c> following this (https://superuser.com/a/244252) answer, still same issue

faizankhan619's avatar

One more thing public files are in public_html not in public folder. So, I removed symlink created by artisan command and tried to create it with below. Still not working

php artisan storage:link

   INFO  The [public/storage] link has been connected to [storage/app/public].

rm public/storage
ln -s public_html/storage storage/app/public

In live server when I try to see the images using SSH with below I get error that directory doesn't exist.

ls -l storage/trainee-profile-pictures/
ls: cannot access 'storage/trainee-profile-pictures/': No such file or directory

But when i run below, I get files as expected. Does that mean symlink is not created in a right manner?

ls -l storage/app/public/trainee-profile-pictures/
total 5404
-rwxr-xr-x 1 u2515-xxxx u2515-xxxx 26990 Dec 17 07:36 gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg
// Other files

Below condition is also true for desired image ($this->picture = trainee-profile-pictures/gAgoBddnYT7SH0eiV2u000bqZT5j2TGQjcoedHlj.jpg). I'm so confused.

Storage::disk('public')->exists($this->picture) == 1

Tray2's avatar

@faizankhan619 Then you need to either change the document root to the public directory, or do some redirecting to it, but most important is to make sure that your .env file isn't accessible from the browser, and if it is change all your passwords on the server.

faizankhan619's avatar

@tray2 .env isn't accessible from the browser. @jlrdw main laravel project is out of public_html. How should I change document root to the public directory? Via appServiceProvider?

My project directory structure looks like below

Tray2's avatar

@faizankhan619 No, you do that in your webservers config files, so it differs a little depending on your operating system and which webserver you are using.

just google it, using something like.

change document root for <webserver> on <operating system> <host provider>

Please or to participate in this conversation.