Checklist Before Deploying Source Code

Your app runs perfectly on your laptop. You upload it to the server and get a blank page, a 500 error, or worse, a debug screen that shows your database password to every visitor....

Checklist Before Deploying Source Code

Your app runs perfectly on your laptop. You upload it to the server and get a blank page, a 500 error, or worse, a debug screen that shows your database password to every visitor. Most of these incidents are not caused by broken code. They are caused by a preparation step someone skipped.

This article is a checklist you can reuse every time you deploy Laravel source code, whether you wrote it yourself or bought it. It follows the real order of work: before upload, during deployment, and after the app goes live.

Why Local and Production Behave Differently

A development machine usually has a recent PHP version, every extension enabled, debug mode on, and you own every folder. A production server is often the opposite: a different PHP version, missing extensions, and a web server running as a separate user with limited permissions. That gap explains most deployment failures.

SettingLocalProduction
APP_ENVlocalproduction
APP_DEBUGtruefalse, always
Dependenciesincludes dev packagesinstalled with --no-dev
Config/route/view cacheusually offon, for faster boot
Errorsshown in the browserwritten to logs, users see a generic page
HTTPSoptionalrequired

Stage 1: Before You Upload

Match PHP version and extensions

Laravel 11 requires PHP 8.2 or newer. Also confirm the extensions most apps need: pdo_mysql (or pdo_pgsql), mbstring, openssl, tokenizer, xml, ctype, fileinfo, and bcmath if the app handles money. Run php -v and php -m on the server and compare with composer.json.

Create a production .env

Do not copy your local file. Start from .env.example and fill in production values:

APP_NAME="My Store"
APP_ENV=production
APP_DEBUG=false
APP_URL=https://mystore.com

LOG_CHANNEL=daily
LOG_LEVEL=warning

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_DATABASE=mystore_prod
DB_USERNAME=mystore_app
DB_PASSWORD=use-a-long-random-password

SESSION_DRIVER=database
SESSION_SECURE_COOKIE=true
QUEUE_CONNECTION=database

APP_DEBUG=false stops stack traces and environment values from leaking. A correct APP_URL keeps links in emails and redirects from pointing at localhost. SESSION_SECURE_COOKIE=true sends session cookies only over HTTPS. Generate APP_KEY once with php artisan key:generate. Never regenerate it on a live server, or encrypted data and existing sessions become unreadable.

Use a dedicated database user

Never run the app as root. Create a user with privileges on one database only, so a future SQL injection bug cannot reach anything else.

Stage 2: During Deployment

On a server with SSH access, keep the steps in a script so every deploy is identical:

#!/bin/bash
set -e

php artisan down --retry=60
git pull origin main
composer install --no-dev --optimize-autoloader --no-interaction
php artisan migrate --force
php artisan config:cache
php artisan route:cache
php artisan view:cache
php artisan event:cache
php artisan storage:link || true
php artisan queue:restart
php artisan up
  1. down shows a maintenance page so users never see a half-installed app.
  2. composer install --no-dev installs exactly what is in composer.lock. Never run composer update in production; it can pull package versions you have not tested.
  3. migrate --force is needed because Laravel asks for confirmation in production.
  4. config:cache and route:cache compile configuration and routes into single files for faster boot.
  5. queue:restart tells workers to reload. Without it, they keep running the old code.

One trap with config:cache: once config is cached, any env() call outside the config/ folder returns null. Move such values into a config file and read them with config(). If you deploy to shared hosting without SSH, see deploying a Laravel app to shared hosting.

Set folder permissions

Only storage/ and bootstrap/cache/ need to be writable by the web server:

sudo chown -R deploy:www-data /var/www/mystore
sudo find /var/www/mystore -type f -exec chmod 644 {} \;
sudo find /var/www/mystore -type d -exec chmod 755 {} \;
sudo chmod -R 775 /var/www/mystore/storage /var/www/mystore/bootstrap/cache

Avoid chmod 777. It hides the error but lets any process on the server write into your app.

Point the document root at public/

If the project root is exposed, .env can be downloaded from a browser. Test by opening https://yourdomain.com/.env; you should get a 403 or 404.

Stage 3: Backups and a Rollback Plan

Take the backup before you deploy. At minimum, dump the database and copy storage/app, which holds user uploads:

mysqldump -u mystore_app -p --single-transaction mystore_prod | gzip > backup_$(date +%F_%H%M).sql.gz

Write the rollback plan in a few lines: which tag is the last stable release, the command to return to it, and whether the new migrations can be reversed. A migration that drops a column cannot be undone without a backup, so split risky schema changes across several releases. More on that in safe database migrations in Laravel.

Stage 4: After Go-Live

Before announcing the link, spend 15 to 30 minutes on the critical paths:

  1. Register a new account and confirm the verification email arrives.
  2. Log in, log out, and reset a password.
  3. Complete one full transaction in sandbox mode if payments are involved.
  4. Upload a file or image and make sure it displays.
  5. Open the admin panel and the most-used report.

Then watch storage/logs for the first few hours. Problems like timeouts to third-party APIs often appear only under real traffic. If the app uses the scheduler, install the cron entry: * * * * * cd /var/www/mystore && php artisan schedule:run >> /dev/null 2>&1.

Common Errors and Fixes

SymptomLikely causeFix
500 error with no messagestorage not writable or missing APP_KEYFix permissions, set APP_KEY, read the log
.env changes ignoredconfig is cachedconfig:clear, then config:cache
CSS/JS missingassets not built or wrong APP_URLRun npm run build, upload public/build
Uploaded images return 404storage symlink missingphp artisan storage:link
419 on form submitsession cookie issue over HTTPSCheck SESSION_DOMAIN and SESSION_SECURE_COOKIE

Printable Checklist

  • [ ] Server PHP version and extensions match the app
  • [ ] Production .env: APP_ENV=production, APP_DEBUG=false, correct APP_URL
  • [ ] APP_KEY set once and never rotated casually
  • [ ] Dedicated database user, not root
  • [ ] Document root is public/, .env is not reachable
  • [ ] HTTPS enabled with HTTP redirect
  • [ ] Default demo credentials changed
  • [ ] composer install --no-dev, then config/route/view cache
  • [ ] Correct permissions on storage and bootstrap/cache, no 777
  • [ ] Database and storage/app backed up before migrating
  • [ ] Scheduler cron and queue worker running
  • [ ] Critical paths tested, logs watched for a few hours

For a broader security review, pair this list with 10 web application security best practices. The same checklist applies to any Laravel source code, including apps from GudangCode.

Yudhi
Written by
Yudhi
Founder & Lead Developer, GudangCode

Yudhi is the founder of GudangCode and a Laravel developer who has built dozens of ready-to-use business information systems — from POS and HRIS to management apps. He writes guides and articles on GudangCode to help Indonesian developers run, understand, and deploy Laravel source code correctly.

LaravelPHPMySQLSistem Informasi Bisnis See all articles by Yudhi
Want the full source code & apps?

Sign up free to download ready-to-use business applications, information systems, and Laravel source code.

Sign Up Free & Download
Deploy Source Code Source Code
Share this article
Back to Blog
📚 Free Learning Hub

Learn Coding for Free at DhieCoderWeb

Explore Laravel, PHP, JavaScript tutorials, source code, web development guides, and practical programming tips.

DhieCoderWeb
100+
Tutorials
Free
Learning
SEO
Tips
Visit Dhiecoderweb.com →

Get Full Access Now!

Join our membership and unlock exclusive access to all premium features. Fast, easy, and ready to use instantly.

Join Membership Now