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

Reading Time: 4 minutes

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:

  • Permission denied
  • The stream or file could not be opened
  • mkdir(): Permission denied
  • Unable to write in the “/public/uploads” directory.

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.


Discover more from AJB Blog

Subscribe to get the latest posts sent to your email.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.