Deploy Laravel to Linux Server (Nginx/Apache) Without Errors
The ultimate step‑by‑step guide for a smooth, error‑free production deployment — 2026 edition
🔍 Introduction
Deploying a Laravel application to a Linux server should be a straightforward process, but many developers encounter frustrating errors — permission denied, 500 Internal Server Error, missing extensions, or configuration mismatches. This guide will walk you through every step to ensure a smooth, error‑free deployment on Nginx or Apache.
Whether you're using Ubuntu, CentOS, or any other Linux distribution, we'll cover the essential setup, configuration, and troubleshooting tips. By the end, you'll have a production‑ready Laravel application running reliably.
php -m to check installed extensions.
📋 Prerequisites
Before you start, make sure you have:
- Linux server (Ubuntu 20.04+ or CentOS 7+) with root/sudo access.
- Nginx (≥1.18) or Apache (≥2.4) installed.
- PHP 8.1 or higher (8.2/8.3 recommended).
- Composer installed globally.
- Git installed (for cloning your repository).
- A database server (MySQL 5.7+ / MariaDB 10.2+ / PostgreSQL 10+).
- Domain name (or IP) pointed to your server.
- SSL certificate (optional but recommended via Let's Encrypt).
🖥️ Server Environment Setup
Start with a clean server and update packages:
sudo apt update && sudo apt upgrade -y # Ubuntu/Debian
sudo yum update -y # CentOS/RHEL
Install essential tools:
sudo apt install -y git curl wget unzip software-properties-common
Set the correct timezone:
sudo timedatectl set-timezone UTC # or your region
⚡ PHP & Extensions
Install PHP and the required extensions:
sudo apt install -y php8.3 php8.3-fpm php8.3-common php8.3-mysql \
php8.3-pgsql php8.3-sqlite3 php8.3-curl php8.3-intl php8.3-mbstring \
php8.3-xml php8.3-zip php8.3-bcmath php8.3-gd php8.3-redis php8.3-bz2
For Nginx, ensure php-fpm is running:
sudo systemctl start php8.3-fpm && sudo systemctl enable php8.3-fpm
For Apache, install libapache2-mod-php and enable:
sudo apt install libapache2-mod-php8.3
🌐 Nginx Configuration
Create a new server block for your Laravel application:
sudo nano /etc/nginx/sites-available/laravel
Paste the following configuration (adjust server_name and root):
server {
listen 80;
server_name your-domain.com;
root /var/www/laravel/public;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
index index.php;
charset utf-8;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location = /favicon.ico { access_log off; log_not_found off; }
location = /robots.txt { access_log off; log_not_found off; }
error_page 404 /index.php;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Enable the site and test configuration:
sudo ln -s /etc/nginx/sites-available/laravel /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
🌐 Apache Configuration
Create a virtual host file:
sudo nano /etc/apache2/sites-available/laravel.conf
<VirtualHost *:80>
ServerName your-domain.com
DocumentRoot /var/www/laravel/public
<Directory /var/www/laravel/public>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Enable the site and enable mod_rewrite:
sudo a2ensite laravel.conf
sudo a2enmod rewrite
sudo systemctl reload apache2
🗄️ Database Setup
Create a database and user for your Laravel application:
sudo mysql -u root -p
CREATE DATABASE laravel_db;
CREATE USER 'laravel_user'@'localhost' IDENTIFIED BY 'your_password';
GRANT ALL PRIVILEGES ON laravel_db.* TO 'laravel_user'@'localhost';
FLUSH PRIVILEGES;
EXIT;
For PostgreSQL:
sudo -u postgres psql
CREATE DATABASE laravel_db;
CREATE USER laravel_user WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE laravel_db TO laravel_user;
⚙️ Laravel Environment & Permissions
Set up the Laravel application directory:
sudo mkdir -p /var/www/laravel
sudo chown -R $USER:$USER /var/www/laravel
Clone your repository or copy files:
git clone your-repo-url /var/www/laravel
cd /var/www/laravel
Install dependencies and generate key:
composer install --no-dev --optimize-autoloader
cp .env.example .env
php artisan key:generate
Set correct permissions:
sudo chown -R www-data:www-data /var/www/laravel
sudo chmod -R 775 /var/www/laravel/storage /var/www/laravel/bootstrap/cache
Update .env with your database credentials and app URL:
APP_URL=https://your-domain.com
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel_user
DB_PASSWORD=your_password
🚀 Deployment Steps
Now run the final deployment commands:
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan optimize
Set up a cron job for the scheduler (if needed):
* * * * * cd /var/www/laravel && php artisan schedule:run >> /dev/null 2>&1
Set up a queue worker with Supervisor:
sudo apt install supervisor
sudo nano /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/laravel/artisan queue:work --tries=3
autostart=true
autorestart=true
user=www-data
numprocs=2
redirect_stderr=true
stdout_logfile=/var/www/laravel/storage/logs/worker.log
sudo supervisorctl reread && sudo supervisorctl update && sudo supervisorctl start laravel-worker:*
🛑 Common Errors & Fixes
- 500 Internal Server Error – Check storage permissions and
php.inierror reporting. - 403 Forbidden – Ensure
index.phpis accessible and directory permissions are correct. - Class not found – Run
composer dump-autoloadand clear cached classes. - Unable to write file – Set
storageandbootstrap/cachewritable by web user. - PDOException – Verify database credentials and extension installed.
- Key path error – Generate new key with
php artisan key:generate. - Nginx 502 Bad Gateway – Check PHP-FPM service status and socket path.
- Apache mod_rewrite not working – Enable
mod_rewriteand setAllowOverride All. - Composer out of memory – Increase memory limit in
php.inior useCOMPOSER_MEMORY_LIMIT=-1. - Migration fails – Check database connection and table permissions.
- Missing .env variables – Ensure
.envis loaded; cache config withconfig:cache. - Scheduler not running – Verify cron entry and permissions.
- Queue workers not picking jobs – Check Supervisor configuration and logs.
- Session issues – Set
SESSION_DRIVERtoredisordatabasefor production. - SSL certificate error – Use Let's Encrypt with
certbot.
📊 Monitoring & Maintenance
- Monitor server logs:
tail -f /var/log/nginx/error.logor Apache error logs. - Monitor Laravel logs:
tail -f /var/www/laravel/storage/logs/laravel.log. - Use
php artisan horizon:statusif using Horizon. - Set up Uptime monitoring with services like UptimeRobot.
- Use
php artisan tinkerto test code interactively. - Regularly update dependencies with
composer update(test first). - Backup database and files regularly.
- Implement deployment rollbacks (e.g., using symlinks).
- Use environment variables for sensitive data (never commit .env).
- Enable
OPcacheand JIT for PHP performance. - Use a CDN for static assets.
- Set up a staging environment for testing before production.
❓ Frequently Asked Questions
Click any question to reveal the answer — animated for a smooth experience.
📌 Key Takeaways
- Install all required PHP extensions before deploying.
- Configure Nginx/Apache with proper root and PHP handling.
- Set correct file permissions (775 for storage/bootstrap/cache).
- Use
.envfor environment-specific settings. - Run
php artisan optimizeafter deployment. - Set up a queue worker and scheduler via cron.
- Monitor logs to catch and fix errors quickly.
- Test your deployment on a staging server first.
- Keep your server and applications updated.
🚀 Still stuck? Reach out to us at FreeLearning365.com@gmail.com for personalized assistance.
0 Comments
thanks for your comments!