Emjey23
Emjey23

Reputation: 367

Laravel + Heroku: Accessing image in Heroku returns 403 (Forbidden)

I deployed my Laravel app in Heroku and gladly it is working nice but the app can't access the image inside the /storage/app/public/uploads/. I also run php artisan storage:link, a symbolic link of /storage/ folder to /public/ directory which results to creation of /public/storage/uploads/.

Heroku Logs

This is the portion of logs in heroku.

2-11-06T01:47:03.064600+00:00 app[web.1]: 10.101.243.98 - - [06/Nov/2018:01:47:03 +0000] "GET /storage/uploads/mobile-cabinet.jpg HTTP/1.1" 403 243 "http://somename.herokuapp.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36

2018-11-06T01:47:03.225408+00:00 app[web.1]: [Tue Nov 06 01:47:03.224875 2018] [core:error] [pid 97:tid 139829891245824] [client 10.65.51.99:29323] AH00037: Symbolic link not allowed or link target not accessible: /app/public/storage, referer: http://somename.herokuapp.com/

Question

Upvotes: 1

Views: 714

Answers (1)

Joel Clermont
Joel Clermont

Reputation: 365

The filesystem on a Heroku dyno is meant to be ephemeral. So if you manually create a symlink, it will be destroyed when the dyno is restarted or on your next deploy. In addition, if you are running something like heroku php artisan storage:link that command is being executed in a different context from your web dyno. As soon as that command finishes running, that symlink will be destroyed.

For example, heroku run "php artisan storage:link; ls -la public" does what you'd expect:

heroku run "php artisan storage:link; ls -la public"
Running php artisan storage:link; ls -la public on ⬢ glacial-ocean-62163... up, run.9596 (Free)
The [public/storage] directory has been linked.
total 28
drwx------  4 u28609 dyno 4096 Feb 27 19:39 .
drwx------ 14 u28609 dyno 4096 Feb 27 19:39 ..
-rw-------  1 u28609 dyno  593 Feb 27 19:32 .htaccess
drwx------  2 u28609 dyno 4096 Feb 27 19:32 css
-rw-------  1 u28609 dyno    0 Feb 27 19:32 favicon.ico
-rw-------  1 u28609 dyno 1823 Feb 27 19:32 index.php
drwx------  2 u28609 dyno 4096 Feb 27 19:32 js
-rw-------  1 u28609 dyno   24 Feb 27 19:32 robots.txt
lrwxrwxrwx  1 u28609 dyno   23 Feb 27 19:39 storage -> /app/storage/app/public

However, if you then run heroku run ls -la public again, that symlink is gone:

Running ls -la public on ⬢ glacial-ocean-62163... up, run.7351 (Free)
total 28
drwx------  4 u54238 dyno 4096 Feb 27 19:32 .
drwx------ 14 u54238 dyno 4096 Feb 27 19:40 ..
-rw-------  1 u54238 dyno  593 Feb 27 19:32 .htaccess
drwx------  2 u54238 dyno 4096 Feb 27 19:32 css
-rw-------  1 u54238 dyno    0 Feb 27 19:32 favicon.ico
-rw-------  1 u54238 dyno 1823 Feb 27 19:32 index.php
drwx------  2 u54238 dyno 4096 Feb 27 19:32 js
-rw-------  1 u54238 dyno   24 Feb 27 19:32 robots.txt

In fact, it never existed on your web dyno.

Understanding that the file system is ephemeral also should cause you to rethink using the storage folder for user uploads. Those uploads will also be lost when your dyno restarts. Instead, store your user uploads in Amazon S3, or some other form of off-site storage. This will allow you to scale or destroy your dynos at will without risking user data. More information about this in the Heroku documentation.

Upvotes: 4

Related Questions