View Categories

Updating RackHelm

A RackHelm update replaces the application files, brings the database schema up to date, rebuilds the front-end assets and restarts the background worker. There is no self-updater — you run the steps yourself, in a fixed order, and the order matters.

Before you start #

  • Take a full backup. See Backing up and restoring. Migrations change the schema and are not always reversible.
  • Read the release notes for the version you are moving to. A major version number change signals a breaking change to the installer or to an integration contract, or a migration that cannot be rolled back cleanly.
  • Pick a quiet window. Provisioning, payments and invoicing all stop while the worker is down.

Warning: Do not update straight onto a production box you have not backed up. If a migration fails halfway you are left with a partially applied schema, which is far harder to recover from than a restore.

The update, in order #

1. Put the site into maintenance mode #

cd /var/www/rackhelm
sudo -u www-data php artisan down

Customers see a maintenance page instead of a half-migrated portal.

2. Back up #

mysqldump --single-transaction --routines --triggers rackhelm > /root/rackhelm-pre-update.sql
tar -czf /root/rackhelm-pre-update.tar.gz -C /var/www rackhelm

3. Replace the application files #

Extract the new release over the existing tree, keeping .env, storage/ and the public/storage symlink:

tar -xzf rackhelm-1.1.0.tar.gz -C /var/www/rackhelm --strip-components=1

Then clear the compiled caches that may have travelled inside the archive or been left by the previous build:

rm -f bootstrap/cache/packages.php bootstrap/cache/services.php bootstrap/cache/config.php

Note: Skipping this step is the usual cause of Class LaravelPailPailServiceProvider not found immediately after an update — a manifest generated when development dependencies were present, loaded by a build that no longer has them.

4. Update the PHP dependencies #

composer install --no-dev --optimize-autoloader

5. Rebuild the front end #

npm install
npm run build

Skipping this leaves the browser loading asset files the new templates no longer reference, which usually shows up as an unstyled page or a dead button rather than an error.

6. Run the migrations #

sudo -u www-data php artisan migrate --force

--force is required because the application is in the production environment.

7. Rebuild the view cache #

sudo -u www-data php artisan view:clear
sudo -u www-data php artisan view:cache

Warning: Never run php artisan optimize, route:cache or config:cache on RackHelm. Route caching serialises closure-based routes, and closure serialisation needs PHP source that the ionCube encoder removes — the cached routes then fail at runtime with Call to a member function bindTo() on null. Config caching freezes the licence key, which is read from .env at runtime. View caching is the only one that is safe, because Blade templates ship as plain text.

8. Re-apply permissions #

Extracting an archive as root leaves new files root-owned. Restore the ownership model (use nginx on RHEL):

chown -R root:www-data /var/www/rackhelm
chmod -R u=rwX,g=rX,o= /var/www/rackhelm
chown -R www-data:www-data storage bootstrap/cache
chmod -R u=rwX,g=rX,o= storage bootstrap/cache
chown root:www-data .env
chmod 640 .env

9. Restart the background worker #

sudo -u www-data php artisan horizon:terminate

Horizon holds the code it started with, so without this the queue keeps running the previous build. Supervisor restarts it automatically. Confirm with supervisorctl status rackhelm-horizon.

10. Reload PHP-FPM #

sudo systemctl reload php8.5-fpm

OPcache holds compiled files in memory keyed by path and modification time. A reload guarantees the new code is picked up rather than relying on OPcache noticing.

11. Bring the site back #

sudo -u www-data php artisan up

After the update #

  1. Load the portal front page and sign in to the admin area.
  2. Check the version in the admin sidebar footer matches the release you installed.
  3. Open the Horizon dashboard and confirm workers are running and no jobs are failing.
  4. Skim storage/logs/laravel.log for new errors.
  5. Place a small test order end to end if the release touched checkout or provisioning.

If something goes wrong #

The safe rollback is a restore, not a partial undo — a database that has been migrated forward will not work with the previous code. Restore the database dump and the file tree from step 2 together, then restart the worker and PHP-FPM. If the failure happened before the migrations ran, restoring the files alone is enough.

Troubleshooting #

Symptom Cause and fix
Class LaravelPailPailServiceProvider not found Stale bootstrap/cache/packages.php. Delete the three cache files and re-run composer install --no-dev.
Call to a member function bindTo() on null Someone ran route:cache or optimize. Run php artisan route:clear and never run those commands again on this platform.
Licence key appears empty after an update config:cache was run and froze the value. Run php artisan config:clear.
Pages render unstyled npm run build was skipped, or public/build is root-owned and unreadable by the web-server user.
Background jobs still show old behaviour Horizon was not restarted. Run php artisan horizon:terminate.
Permission-denied errors writing logs or uploads Step 8 was skipped. storage and bootstrap/cache must be owned by the web-server user.
Migration fails partway through Stop. Restore the database dump rather than re-running — a partially applied batch is what makes recovery hard.