esedark
engineer reviewing nginx and laravel deployment configuration on a workstation

nginx / laravel / php-fpm / deployment / production

Nginx for Laravel: basic configuration and common mistakes

A Laravel server does not usually fail because Nginx is complicated. It fails because a few small mistakes around document root, FastCGI, cache headers or deploy flow stay invisible until production traffic arrives.

If you are searching for a solid Nginx setup for Laravel, start with one principle: Nginx should expose the app cleanly, not hide backend confusion. A good config gives you predictable routing, static asset delivery, sane PHP handling and enough logs to debug incidents quickly.

That matters even more when the Laravel app also feeds APIs, queues or operational dashboards like the kind described in clean Laravel APIs for mobile apps. If web requests, jobs and deploys share one fragile host, every configuration shortcut becomes a production risk.

The baseline Nginx idea for Laravel

Laravel wants Nginx to point to the public directory, serve static files directly and pass PHP requests to PHP-FPM. Everything else should be explicit.

server {
    listen 80;
    server_name example.com;
    root /var/www/app/current/public;
    index index.php;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_read_timeout 60;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

You may need different sockets, SSL blocks or cache rules, but the structure should stay boring. Boring is good here.

What Nginx is responsible for and what it is not

Nginx is responsible for request routing, static file serving, headers, buffering, TLS termination and log visibility. It is not responsible for fixing slow SQL, broken queue jobs or a deployment process with no rollback path.

That distinction matters because many teams try to solve application instability inside web-server config. If the app blocks because a queue runs synchronously, or if a report endpoint times out because it should have been queued, the fix belongs in app architecture, not in bigger timeout values.

Common mistakes

The first mistake is pointing the server root at the Laravel project root instead of public. That exposes files that should never be web-accessible.

The second mistake is using fragile deploy paths. If SCRIPT_FILENAME points at a symlink badly, zero-downtime releases become random 502 incidents.

The third mistake is mixing file permission problems with Nginx problems. If storage or bootstrap/cache is wrong, the error may look like web-server trouble when the real cause is deploy ownership.

The fourth mistake is turning off logs or leaving them too vague. You want enough access and error information to correlate latency, upstream failures and bad deploys.

The fifth mistake is assuming public endpoints mean careless endpoints. If Laravel exposes public data feeds, lead forms or ingestion flows, rate limits, request logging and retention rules still matter for traceability and compliance.

Practical checklist for Laravel + Nginx

  • set root to the Laravel public directory only
  • use try_files so missing files fall through to index.php cleanly
  • point FastCGI to the correct PHP-FPM socket or upstream
  • store logs per site and review both access and error logs
  • deny access to hidden files and sensitive paths
  • serve static assets directly with sensible cache headers
  • keep deploy users, file ownership and writable paths documented
  • separate web timeouts from queue design decisions
  • test reloads and rollbacks before traffic depends on them
  • record what public endpoints exist and what limits apply

Cache, headers and stability

Nginx helps most when it keeps simple things simple. CSS, JS and images should not hit PHP. Security headers should be explicit. Request IDs and real client IP handling should be consistent if Cloudflare or another proxy sits in front.

If you use Cloudflare, reverse proxies or team VPN access, keep those trust boundaries documented. That is the same operational mindset behind safe client SSH access and remote access without opening ports: stability improves when network assumptions are visible.

Make deployment issues traceable

Most Nginx pain in Laravel projects is really deploy pain. A healthy setup makes it obvious which release is serving traffic, which PHP-FPM pool handled the request and whether a 502 came from bad config, bad permissions or an unavailable upstream.

{
  "request_id": "web-7d21",
  "release": "2026-07-06-01",
  "vhost": "app.example.com",
  "upstream": "php8.3-fpm",
  "status": 502,
  "path": "/admin/reports"
}

That evidence is what stops incident response from turning into guessing across Nginx, PHP-FPM and Laravel at the same time.

When hiring a technical person makes sense

If your Laravel app is already live, deploys feel risky, Nginx changes are made by trial and error and no one can explain where web-server responsibility ends and app responsibility begins, the issue is not one missing directive. The issue is operational ownership.

That is where technical services or direct help through fractional CTO work becomes useful. The value is usually not a giant rebuild. It is tightening deployment flow, boundaries between Nginx and app code, logging, public-endpoint limits and rollback discipline.

Final takeaway

A good Laravel Nginx configuration is simple, explicit and observable. It serves the right directory, hands PHP to the right upstream, keeps sensitive files closed and gives you enough evidence when production misbehaves.

If your current setup still produces random 404s, 502s or permission problems after every deploy, use contact and bring the current vhost, deploy flow and the last failure pattern. That is enough to see whether the real problem is Nginx, PHP-FPM or the release process around them.