laravel.log could not be opened: Permission denied
On Tanzahost, Laravel's storage folder is a permanent folder your app can write to. Keep storage in your app's permanent folders, and never chmod 777.
Updated 22 Oct 20262 min read
The whole message:
The stream or file "storage/logs/laravel.log" could not be opened in append mode: Failed to open stream: Permission deniedThe fix on Tanzahost: make sure storage is one of your app's Permanent folders. It is by default for Laravel, so this error almost always means the list was changed and storage left out.
Open the app. Under Build and run, find Permanent folders.
If it's empty, we use Laravel's default,
storage. If you typed your own folders there, addstorageto them, separated by commas, likestorage, public/uploads.Choose Save and build.
Don't run chmod -R 777 storage. You don't need it here, and it lets any program change your files.
Why it happens
On Tanzahost your app's code is read-only while it runs, so a version can't be changed after it's built, even by someone who breaks into it. Only a few places are writable:
| Folder | What it's for | Kept across deploys |
|---|---|---|
storage, and any permanent folder you add | Laravel's logs, sessions, cache files and uploads | Yes. The first deploy fills it from your code, later ones keep what's there. |
bootstrap/cache | Laravel's cached config, routes and services | No: it starts empty, up to 64 MB, on every start |
/tmp | Short-lived files | No |
Laravel writes storage/logs/laravel.log as soon as it logs anything. If storage isn't permanent, it's read-only like the rest of the code, and PHP says "Permission denied" or "Read-only file system".
The list you type replaces Laravel's default rather than adding to it. That's how storage usually goes missing: someone adds public/uploads and nothing else. The same goes for permanent in tanzahost.json:
{
"permanent": ["storage", "public/uploads"]
}How to check
Under Build and run, read Permanent folders.
In the file manager, your app's permanent folders show at the top level, writable. If
storageisn't there, it isn't permanent.If your repository has no
storage/logsorstorage/frameworkfolders, because a.gitignoreleft them out, Laravel can't find them either. Laravel's own skeleton keeps them in Git with an empty.gitignorefile in each: commit those.