← Back to blog

The Complete Guide to Deploy Laravel on Linux Servers

generalhow to

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:

  1. Your deploy user - the account you SSH in with to upload code
  2. 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:

  1. Directories are readable and traversable by everyone
  2. Files are readable by everyone, writable only by the owner
  3. 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:

  1. app/ - application-generated files
  2. framework/ - cache, sessions, and views
  3. logs/ - 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 / FilePermissionPurpose
All directories755Allow traversal and reading
All files644Allow reading, restrict writing
storage/775Logs, cache, sessions, uploads
bootstrap/cache/775Compiled services and packages
.env640Protect 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

  1. Never use 777 - It gives everyone full access, including malicious scripts
  2. Keep .env restricted - This file has your secrets
  3. Don’t store sensitive files in public/ - Use storage/ with symbolic links
  4. 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!