Creating a decent Laravel deploy script
A good deploy script can save you time and speed up you application, and it only takes a few minutes to set one up.
I have a standard deploy script which I use for almost all of my projects, which I'm going to break down and share with you.
Note: This article assumes that you're using Laravel Forge. If you're not, many of the settings will be applicable, but the setup steps may be a bit different.
What is a deploy script?
A deploy script is file which contains a bunch of commands (a shell script) which all get executed when you make a deployment, which is usually whenever you push code changes to your project. It makes sense that you might have a list of tasks you want performed when you do a deployment, such as clearing caches or running any new database migrations - this is exactly what a deploy script is for.
If you're using Forge, a deploy script is already set up for you and does a few things out of the box. You can find it under Site Details > Apps. We're going to take that deploy script and supercharge it.
Putting the application into maintenance mode while the new version is deployed is a good idea. Your deploy script could sometimes take a minute or so to complete and it's better to show that the site is updating rather than a potentially half broken version of the site.
At the start of the deploy script, we'll turn on maintenance mode, and at the end we'll turn it off again.
# Turn on maintenance mode php artisan down # ... Deploy script stuff # Turn off maintenance mode php artisan up
You can customize the message which is displayed by defining your own template at
There's a good chance that the changes in your deployment will invalidate items stored in the cache on your server. It's a good chance to clear them out at this point.
php artisan cache:clear
Clearing and optimising routes
Using route caching can drastically speed up your applications' performance. The artisan command
route:cache will serialize the results of your
routes.php file meaning that it doesn't have to be re-computed on every page load.
As part of our deploy script we first run
route:clear to clear out the existing route cache, before running
# Clear and cache routes php artisan route:clear php artisan route:cache
Note that this is only compatible with controller based routing. So if you're using any closures in your
routes.php file, I'm afraid you're out of luck.
Clearing and optimising the config
As well as caching routes, we can also use configuration caching to cache the config files. The performance impact here isn't as great, but it's still worth doing. Essentially all of the config files are read, serialized and then stored in a single config file which can be loaded by the framework. Thus reducing the number of file read operations from tens to one.
Again, we clear out the existing cache before creating the new one.
# Clear and cache config php artisan config:clear php artisan config:cache
Clear expired password reset tokens
When a user requests a password reset, a reset token is created in the
password_resets database table. If the user never clicks on the link they receive in the email then these just hand around forever, unless you run
auth:clear-resets. I add it to the deploy script to stop the database getting clogged up with all the unused tokens.
# Clear expired password reset tokens php artisan auth:clear-resets
Compiling front-end assets (optional)
While I'm developing, I'm going to be compiling my assets using a watcher like Mix's
npm run watch. It's fast, but it's not optimised for performance. Instead of running
npm run production before every deployment, we can get the server to do it. All we need to do is install the dependencies using
npm install and then run
npm run production.
The only downside to this is that it can slow down your deployment process.
# Install node modules npm install # Build assets using Laravel Mix npm run production
You can of course do this with the build tool of your choice e.g. Grunt, Gulp, webpack etc.
I keep this commented out by default as I don't always want to have this run on my server at deploy time. Instead, I will build the assets locally and check them into source control so that they're uploaded with the reset of the changed files.
Putting it all together
Combined with the Forge default deploy script we now end up with something like this:
# Change to the project directory cd /home/forge/domain.com # Turn on maintenance mode php artisan down # Pull the latest changes from the git repository git pull origin master # Install/update composer dependecies composer install --no-interaction --prefer-dist --optimize-autoloader # Run database migrations php artisan migrate --force # Clear caches php artisan cache:clear # Clear expired password reset tokens php artisan auth:clear-resets # Clear and cache routes php artisan route:clear php artisan route:cache # Clear and cache config php artisan config:clear php artisan config:cache # Install node modules # npm install # Build assets using Laravel Mix # npm run production # Turn off maintenance mode php artisan up
I've put this up on Github as a Gist.