Learn how to secure your Laravel application for production. We'll cover disabling debug mode, masking sensitive data, and configuring trusted proxies.
Previously in this course, we covered preparing for production: Laravel optimization and security, where we focused on caching and performance. Now that your Task Manager application is performant, it's time to ensure it's locked down.
Building a web application is only half the battle; ensuring it remains secure when it hits the wild is the other. Many developers treat security as an afterthought, but in a production environment, your configuration settings act as the first line of defense against attackers.
While building your Task Manager, you’ve likely relied on the "Whoops" screen—Laravel’s detailed error page that shows you the exact line of code and stack trace where an error occurred. This is a godsend in development, but it is a massive security vulnerability in production.
If APP_DEBUG is set to true in a live environment, an attacker can intentionally trigger errors to see your database structure, environment variables, or even portions of your source code.
To disable this, open your .env file and set the value to false:
.envAPP_DEBUG=false
Once this is set, Laravel will stop exposing internal stack traces and instead show a generic 500 error page to users, while logging the actual details to your storage logs. This prevents information leakage that could lead to more complex exploits.
We've already touched on secret management best practices: secure your node.js and php apps, but it bears repeating: never hardcode credentials.
In production, your .env file should not exist in your version control system. Instead, your server environment should inject these variables. If you are using a platform like Forge or Laravel Vapor, these are handled via the dashboard. If you are on a VPS, ensure you populate the .env file manually on the server and keep it outside of your Git repository.
A common pitfall is the APP_KEY. If this key is leaked or remains the default from a fresh installation, an attacker could potentially decrypt session data or manipulate encrypted payloads. Always ensure you have run php artisan key:generate on your production server.
If your application sits behind a load balancer, a reverse proxy (like Nginx or Cloudflare), or a cloud provider's SSL terminator, your application might struggle to identify the "real" user IP address.
Laravel uses the Illuminate\Http\Middleware\TrustProxies middleware to handle this. If you don't configure this correctly, your app might treat the IP of your load balancer as the user's IP, which breaks rate limiting, logging, and security features.
To configure this, update the app/Http/Middleware/TrustProxies.php file:
PHPnamespace App\Http\Middleware; use Illuminate\Http\Middleware\TrustProxies as Middleware; use Illuminate\Http\Request; class TrustProxies extends Middleware { #6A9955">// Trust all proxies by using '*' #6A9955">// Or specify the IP address of your load balancer protected $proxies = '*'; protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO; }
By setting $proxies to *, you are telling Laravel to trust the headers provided by your proxy. This ensures request()->ip() returns the user's actual address, not the proxy's internal IP.
.env and confirm APP_DEBUG=false..env: Check for any "test" credentials or local paths left over from development. Delete them.TrustProxies middleware is configured for your specific hosting environment. If you aren't sure, check your hosting provider's documentation regarding "X-Forwarded-For" headers..env variables, always run php artisan config:clear and php artisan config:cache. Laravel caches configuration; if you don't clear it, your changes won't take effect.* is convenient for proxies, in some high-security environments, it is safer to explicitly list the IP addresses of your known load balancers rather than trusting all incoming proxy headers.config/logging.php isn't configured to log sensitive input data (like passwords) to your daily log files.Securing your environment is the final step before you can confidently deploy your application. By disabling debug mode, centralizing secret management, and correctly configuring your proxies, you've significantly hardened your Task Manager against common attack vectors.
Up next: We will look at how to compile your frontend assets for production using Vite.
Master Eloquent query scopes and accessors to write reusable, expressive database logic. Learn to clean up your controllers by shifting data handling to models.
Read moreLearn how to prevent mass assignment vulnerabilities in Laravel by using the $fillable property to secure your Eloquent models from malicious input.
Environment Security Best Practices