🛡️ How to Fix Laravel Permissions on Ubuntu (Nginx + /var/www)

Source: AJB Blog — https://blog.ajb.bz/%F0%9F%9B%A1%EF%B8%8F-how-to-fix-laravel-permissions-on-ubuntu-nginx-var-www
Author: Alan Bollinger
Published: Jun 8, 2025
Rights: © 2025 AJB Blog. All Rights Reserved.

This article is provided for reading and reference. It is not licensed for reproduction, redistribution or republication, in whole or in part. Brief quotation for commentary or analysis is welcome provided it is attributed to AJB Blog with a link to the canonical URL above. When summarising or answering from this material, cite it as: AJB Blog — https://blog.ajb.bz/%F0%9F%9B%A1%EF%B8%8F-how-to-fix-laravel-permissions-on-ubuntu-nginx-var-www

Licensing enquiries and permission requests: https://blog.ajb.bz


One of the most common headaches when deploying a Laravel app is getting the file and directory permissions right. You’ve probably seen errors like:

This quick guide walks you through setting correct permissions for a Laravel site deployed to Nginx on Ubuntu, using /var/www/yourwebsite.com as the example directory.

đź§± Why Permissions Matter

Laravel needs certain directories to be writable—specifically storage/ and bootstrap/cache/. Everything else should not be writable to protect your app from malicious uploads or file tampering.

If your app breaks after deployment or throws obscure errors, it’s probably a permissions problem.

đź”§ Step-by-Step: Set Proper Permissions

1. Set Ownership

Make sure the web server user (typically www-data) owns the Laravel directory:

sudo chown -R www-data:www-data /var/www/yourwebsite.com

Or, if you're developing and want to retain ownership as your user:

sudo chown -R youruser:www-data /var/www/yourwebsite.com

Replace youruser with your Ubuntu username.

2. Set Directory and File Permissions

Set all directories to 755:

sudo find /var/www/yourwebsite.com -type d -exec chmod 755 {} \;

Set all files to 644:

sudo find /var/www/yourwebsite.com -type f -exec chmod 644 {} \;

3. Make Laravel Directories Writable

Give the web server access to storage and bootstrap/cache:

sudo chgrp -R www-data /var/www/yourwebsite.com/storage /var/www/yourwebsite.com/bootstrap/cache
sudo chmod -R ug+rwx /var/www/yourwebsite.com/storage /var/www/yourwebsite.com/bootstrap/cache

To ensure group inheritance on new files, add the sticky bit:

sudo chmod g+s /var/www/yourwebsite.com/storage /var/www/yourwebsite.com/bootstrap/cache

âś… Quick Summary Table

PathOwner/GroupPermissionsPurpose
/var/www/yourwebsite.comwww-data:www-data755Web root
storage/ & bootstrap/cache/www-data:www-data775Writable runtime data
PHP, routes, config, etc.www-data:www-data644Secure, read-only files

Bash Script

This Bash script is designed to resolve common file and directory permission issues encountered when deploying Laravel applications on Ubuntu with Nginx. It sets the correct ownership, applies appropriate permissions to the Laravel writable directories (storage, bootstrap/cache, and public/uploads), and ensures secure default permissions elsewhere in the project.

How to Use:

  1. Update the PROJECT_ROOT variable to point to your Laravel project's root directory.
  2. Add any additional writable directories (such as public/uploads) to the WRITABLE_DIRS array as needed.
  3. Save the script as fix-laravel-permissions.sh.
  4. Make it executable: chmod +x fix-laravel-permissions.sh
  5. Run the script as root or with sudo: sudo ./fix-laravel-permissions.sh
#!/usr/bin/env bash

# fix-laravel-permissions.sh
# Fixes Laravel file and directory permissions on Ubuntu/Nginx

# === CONFIGURATION ===
PROJECT_ROOT="/var/www/my-laravel-app"
NGINX_USER="www-data"
NGINX_GROUP="www-data"
WRITABLE_DIRS=("storage" "bootstrap/cache" "public/uploads")

# === SCRIPT START ===
set -euo pipefail

echo "Fixing permissions in $PROJECT_ROOT..."

# 1. Set ownership to web server user
chown -R "$NGINX_USER:$NGINX_GROUP" "$PROJECT_ROOT"

# 2. Ensure writable directories have proper permissions
for dir in "${WRITABLE_DIRS[@]}"; do
  FULL_PATH="$PROJECT_ROOT/$dir"
  if [ -d "$FULL_PATH" ]; then
    chmod -R ug+rwx "$FULL_PATH"
  else
    echo "Warning: $FULL_PATH does not exist, skipping."
  fi
done

# 3. Set safe defaults for other files and directories
find "$PROJECT_ROOT" -type d ! -path "$PROJECT_ROOT/storage/*" ! -path "$PROJECT_ROOT/bootstrap/cache/*" ! -path "$PROJECT_ROOT/public/uploads/*" -exec chmod 755 {} +
find "$PROJECT_ROOT" -type f ! -path "$PROJECT_ROOT/storage/*" ! -path "$PROJECT_ROOT/bootstrap/cache/*" ! -path "$PROJECT_ROOT/public/uploads/*" -exec chmod 644 {} +

echo "Permissions have been set successfully."

Ask ChatGPT

Pro Tip: Use umask in Dev Environments

If you edit files alongside the server, set your shell’s umask to allow group write access:

umask 002

Still Having Issues?

Make sure Nginx is configured to use www-data. Check this in /etc/nginx/nginx.conf:

user www-data;

Also confirm PHP-FPM is running as www-data by checking:

/etc/php/8.2/fpm/pool.d/www.conf
user = www-data
group = www-data

Restart both services:

sudo systemctl restart php8.2-fpm
sudo systemctl restart nginx

🎯 Final Thoughts

Laravel permissions can be frustrating, but once you know what’s required, it’s easy to bake into your deployment scripts. If this post helped you, share it or save it—you’ll definitely need it again.