Zodiac Tech CRM Docs

Updates & rollback

How to update a production install safely — backup first, in-app updater or manual files, composer, migrations, cache and Filament commands, queue restart, verification and rollback.

super-admin developer Advanced ⏱ 30 min Updated 2026-10-05

Updating a live CRM touches code, the database, caches and long-running workers. The order below is the production-safe order: backup → update code → dependencies → migrate → caches → workers → verify, with a rollback plan in hand before you start.

Who this is for

  • Super-admin / hosting admin — applying releases.
  • Developer — preparing a release or recovering from a bad one.

Prerequisites: Backups & restore understood, cron running, a maintenance window.

Step 0 — Backup first (non-negotiable)

  1. Super Admin → Backups → Create backup (or php artisan leadhub:backup).
  2. Verify it (the smoke-test action) and download it off-site.
  3. If your host offers one-click full-account backups, take one of those too — code + files + DB in one.

No backup, no update Migrations are generally additive, but a rollback that needs data back is impossible without a dump. Two minutes of backup beats a day of incident response.

Step 1 — Check what you're updating to

  • In-app: the update screen checks LEADHUB_UPDATE_SERVER and compares against LEADHUB_VERSION.
  • Terminal: php artisan leadhub:check-updates.

Read the release notes for the version span (especially: new migrations, changed Filament pages, new env keys — new .env.example keys are the usual cause of post-update warnings).

Step 2 — Put the app into maintenance (optional but kind)

php artisan down --secret="your-bypass-token"

You can keep working with https://…/your-bypass-token; visitors see a maintenance page. Skip this only if the release is explicitly zero-downtime.

Step 3 — Apply the update

Run the update from the Super Admin update screen. The updater applies the release zip and then automatically:

  • clears compiled views/routes/config,
  • republishes Filament assets (filament:assets) — important because zip updates skip Composer's post-autoload-dump, so the framework's filament:upgrade never fired during the copy,
  • refreshes vendor/composer classmap metadata (classmap-authoritative installs) and resets opcache where the host allows.

Route B — Manual (file upload or git)

cd ~/crm-app
# 1. backup already taken in Step 0
# 2a. upload the release over the existing files (File Manager/FTP), or:
# 2b. git pull   (if you deploy from a repository)
# 3. dependencies (only if Terminal available):
composer install --no-dev --optimize-autoloader

Never overwrite .env or storage/ Release zips contain .env.example and the storage/ skeleton — never let an extraction clobber your live .env, storage/app/* or your public/storage symlink. Extract carefully or use the in-app updater.

The platform also ships a cache healer: after a file-copy update it detects a changed shipped version (LEADHUB_VERSION in config/leadhub.php vs the stored version stamp) and deletes stale compiled config/route/event caches on the next boot. Manual cache steps below remain the belt-and-braces.

Step 4 — Run migrations

php artisan migrate --force

--force is required in production (non-interactive). If nothing is pending it's a no-op.

Step 5 — Clear and rebuild caches

php artisan optimize:clear          # clears config, route, view, event, compiled caches
php artisan filament:clear-cached-components   # REQUIRED when the release adds/renames Filament pages
php artisan view:cache              # optional: precompile views (small speed win)

Filament cached components When Filament's component cache is enabled, newly shipped pages/resources are invisible until php artisan filament:clear-cached-components runs. "I updated but the new menu entry doesn't appear" is almost always this command.

Step 6 — Restart workers

php artisan queue:restart

Supervised workers (queue:work) keep old code in memory until restarted. The cron-based --stop-when-empty pattern picks up new code automatically on the next minute; the cron.php runner likewise.

Then bring the app back:

php artisan up

Step 7 — Verify

  1. GET /api/v1/health → {"status":"ok",...}.
  2. Load /admin, /super-admin, /docs — no 500s, styles intact.
  3. Send a test e-mail (queue → mail path).
  4. Submit the workspace's test lead (Meta/webhook path).
  5. Watch storage/logs/laravel.log and the update screen's own log for 10 minutes.
  6. Confirm failed_jobs isn't suddenly growing.

Step 8 — Rollback (if something is wrong)

Roll back in this order, and stop as soon as the app is healthy:

  1. Files: restore the previous release — your own copy of the app folder from before the update, the host's full-account backup, or your deployment system's previous revision.

  2. Database — only if the new version ran destructive migrations and data is wrong: restore the Step 0 archive (Backups & restore). Note the archive predates a few minutes of live activity; you'll lose whatever happened after the backup.

  3. Caches & workers after either rollback:

    php artisan optimize:clear
    php artisan filament:clear-cached-components
    php artisan queue:restart
    
  4. Verify with the Step 7 checks.

migrate:rollback is a dev tool here Prefer restoring from backup over rolling migrations back on production. Some migrations drop columns/tables with data that a down() cannot rebuild. If you must, run php artisan migrate:rollback --step=1 --force immediately after confirming the previous code is in place, and re-verify the schema.

Common mistakes

  • Updating without a backup (or with an old one).
  • Skipping filament:clear-cached-components after a release with new pages — features stay invisible while everything "looks fine".
  • Forgetting queue:restart with supervised workers → half the system runs old code.
  • Letting a zip extraction overwrite .env or storage/.
  • Running composer install with the wrong PHP binary (system 8.1 vs host 8.4).
  • Updating straight to the newest version across many releases without reading notes — new env keys, new permissions, new migrations stack up.

Troubleshooting

Symptom Fix
New page/menu missing after update php artisan filament:clear-cached-components
500 after update storage/logs/laravel.log; usually a stale compiled config — optimize:clear; or a missing new .env key
Styled-but-broken admin UI Re-publish Filament assets: run the in-app updater's asset step (php artisan filament:assets)
Jobs still running old code queue:restart (or wait one cron cycle on the cron-drain pattern)
Update screen can't reach the server LEADHUB_UPDATE_SERVER reachable? outbound HTTPS allowed by the host?
Migrations fail halfway Restore the backup to a consistent state; fix the cause (often MySQL version) before retrying

Technical details

  • In-app updater: App\Services\UpdaterService (applies zip, clears caches, republishes filament:assets, refreshes vendor/composer classmap metadata, opcache reset where available).
  • Cache healer: App\Support\PostUpdateCacheHealer (compares shipped version vs storage/framework/leadhub-version.stamp; purges stale compiled caches).
  • Version check: App\Console\Commands\CheckForUpdates (leadhub:check-updates).
  • Filament command: filament:clear-cached-components (Filament v4).
  • Release notes: the version also lives in config/leadhub.php (LEADHUB_VERSION).

Was this page helpful?