Laravel Forge is a fantastic tool for rapidly spinning up servers with all the best and latest software. It also provides for easy PHP project deployment and setup. However, the default deploy script is rather lacking in a sense that it results in downtime.
Envoyer is a tool that solves this issue, but if you just want zero downtime deployments and don’t want any of the other features that it provides, it might be hard to justify shelling out for another tool.
Here’s a way to handle zero downtime deployments from Forge, in a very similar manner to Envoyer.
default Forge project is used as an example throughout this post. Remember to change it to whatever your project domain name is set to in Forge.
The below script should go into the Deploy Script section of your pre-existing Forge website.
There are 4 variables defined at the beginning of the script:
PROJECT_NAME - should be set to the domain name that you have given your website in Forge.
PROJECT_REPO - is the git repository with your project files. Should be the same repo that you provided when setting up your website for the first time. This must bet an SSH link and not HTTPS.
RELEASES_KEPT - the number of releases that you want to keep present. These will be used for rolling back, should your freshly deployed code not work as intended.
RELEASE - the naming pattern for naming your releases. By default, it’s the deployment date separated by hyphens.
The very first deployment will introduce a bit of downtime as it has to remove the directory of your project and replace it with a symlink.
Which leads into another point…
Changing the storage path
Since we’re essentially using a fresh copy of code every time we deploy, the
storage/ folder will not have any of the files that the app has added during its release lifetime.
storage/ usually holds some of the frameworks cache stuff, logs and other tidbits. In most cases, you’ll want to keep this folder untouched whenever you do a release.
This issue can be solved by changing your
storage/ path to be outside of your
PROJECT_NAME directory. So something like
/home/forge/default-storage would work.
To do this, SSH into your Forge server and run the following to create the new storage folder:
cp -rp /home/forge/default/storage /home/forge/default-storage
Now open up your
bootstrap/app.php and just before
return $app; add this:
The last step is to add
APP_STORAGE=/home/forge/default-storage to your environment variables.
Rolling back is just symlinking to an older release and then rolling back your database changes. You can do this by SSHing into your server and running the following:
ln -sfn default-releases/ROLLBACK_RELEASE_FOLDER default
And then roll back any migrations from the previous release:
ROLLBACK_RELEASE_FOLDER with whatever version of your application you want to go back to.
I don’t want to take away anything from Envoyer with this. It is a fantastic tool and if you need more control over your deployments, you should probably use it.
If you find any issues with this post, or would like to add anything to it, please get in touch via the socials on this site and let me know.