The Complete Guide to Deploy Laravel on Linux Servers
Deploying a Laravel application to a production server is an exciting milestone until you hit the dreaded “Permission denied” error. If you’ve ever stared at a blank screen or a 500 error after deploying, chances are file permissions were the culprit.
In this guide, I’ll walk you through exactly what permissions your Laravel project needs and why. By the end, you’ll understand not just what to do, but why you’re doing it.
Why Permissions Matter
Linux file permissions control who can read, write, and execute files. When you deploy Laravel to a web server, two users typically interact with your code:
- Your deploy user - the account you SSH in with to upload code
- The web server user - usually www-data (Ubuntu/Debian) or apache (CentOS/RHEL)
If the web server can’t read your PHP files, your app won’t load. If it can’t write to the storage folder, logging and caching will fail. Getting this balance right is crucial.
Understanding Linux Permissions
Before diving in, let’s quickly decode permission numbers:
- 7 = read (4) + write (2) + execute (1)
- 5 = read (4) + execute (1)
- 4 = read only
When you see 755, that means:
- Owner: 7 (read, write, execute)
- Group: 5 (read, execute)
- Others: 5 (read, execute)
Step-by-Step Permission Setup
Step 1: Set Ownership
First, establish who owns the files. The cleanest approach is to set your deploy user as the owner and the web server as the group:
sudo chown -R $USER:www-data /var/www/your-laravel-app
This lets you edit files while giving the web server group access.
Alternatively, if you’re not making manual edits on the server, let the web server own everything:
sudo chown -R www-data:www-data /var/www/your-laravel-app
Step 2: Set Base Permissions
Apply standard permissions to all directories and files:
# Navigate to your project
cd /var/www/your-laravel-app
# Set directory permissions to 755
sudo find . -type d -exec chmod 755 {} \;
# Set file permissions to 644
sudo find . -type f -exec chmod 644 {} \;
With these settings:
- Directories are readable and traversable by everyone
- Files are readable by everyone, writable only by the owner
- The web server can read and serve your application
Step 3: Make Storage and Cache Writable
Laravel needs to write to specific directories. These require more permissive settings:
sudo chmod -R 775 storage
sudo chmod -R 775 bootstrap/cache
The storage directory contains:
app/- application-generated filesframework/- cache, sessions, and viewslogs/- your application logs
The bootstrap/cache directory holds compiled package and service manifests.
Step 4: Secure Your Environment File
Your .env file contains sensitive data like database passwords and API keys. Lock it down:
sudo chmod 640 .env
This allows only the owner to write and the group (web server) to read - no access for anyone else.
Quick Reference Table
| Path / File | Permission | Purpose |
|---|---|---|
| All directories | 755 | Allow traversal and reading |
| All files | 644 | Allow reading, restrict writing |
storage/ | 775 | Logs, cache, sessions, uploads |
bootstrap/cache/ | 775 | Compiled services and packages |
.env | 640 | Protect sensitive configuration |
The One-Liner Setup Script
For quick deployments, here’s a script you can save and reuse:
#!/bin/bash
# set-laravel-permissions.sh
APP_PATH="/var/www/your-laravel-app"
WEB_USER="www-data"
sudo chown -R $USER:$WEB_USER $APP_PATH
sudo find $APP_PATH -type d -exec chmod 755 {} \;
sudo find $APP_PATH -type f -exec chmod 644 {} \;
sudo chmod -R 775 $APP_PATH/storage
sudo chmod -R 775 $APP_PATH/bootstrap/cache
sudo chmod 640 $APP_PATH/.env
echo "Permissions set successfully!"
Common Issues and Fixes
”Permission denied” when writing logs
The web server can’t write to storage/logs. Fix it:
sudo chmod -R 775 storage/logs
sudo chown -R www-data:www-data storage/logs
Compiled views not updating
Clear the view cache and fix permissions:
php artisan view:clear
sudo chmod -R 775 storage/framework/views
SELinux blocking writes (CentOS/RHEL)
If you’re on a system with SELinux enabled, permissions alone aren’t enough. Set the proper security context:
sudo chcon -R -t httpd_sys_rw_content_t storage
sudo chcon -R -t httpd_sys_rw_content_t bootstrap/cache
Queue worker can’t write files
If your queue runs as a different user (like root via systemd), either run it as www-data or add that user to the www-data group:
sudo usermod -a -G www-data queue-user
Deployment Tool Considerations
If you’re using deployment tools like Envoy, Deployer, or GitHub Actions, add permission commands to your deployment script. Permissions should be set after files are uploaded:
// Example Envoy task
@task('permissions')
cd /var/www/your-laravel-app
sudo chown -R www-data:www-data .
sudo chmod -R 775 storage bootstrap/cache
@endtask
Security Best Practices
- Never use 777 - It gives everyone full access, including malicious scripts
- Keep
.envrestricted - This file has your secrets - Don’t store sensitive files in
public/- Usestorage/with symbolic links - Audit permissions after updates - Composer and artisan commands can create files with wrong permissions
Conclusion
Proper file permissions might seem like a small detail, but they’re foundational to a secure, functioning Laravel deployment. Take the time to set them correctly, and you’ll avoid hours of debugging mysterious errors.
Remember the golden rule: give the minimum permissions necessary for things to work. Your directories need 755, your files need 644, and only storage and bootstrap/cache need write access for the web server.
Happy deploying!