Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

1k3r's avatar
Level 6

Forge - Zero downtime deployment, when to restart fpm?

Hi,

this is my current deployment script: (based on https://gist.github.com/tonioriol/e2f7d159e8905d69d2a9bd042f7b1778)

# stop script on error signal
set -e

SITE="example.com"
DEPL="/home/forge/deployments/${SITE}"

# create directory and any intermediate directories if don't exist
mkdir -p ${DEPL}

CUR="/home/forge/${SITE}"
NEW="${DEPL}/new"
BKP="${DEPL}/backup"

# remove old deployment folders
if [ -d ${NEW} ]; then
    rm -R ${NEW}
fi
if [ -d ${BKP} ]; then
    rm -R ${BKP}
fi

cp -R ${CUR} ${NEW}

# REGULAR SCRIPT
cd ${NEW}
git pull origin master

composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev

# restart FPM
( flock -w 10 9 || exit 1
    echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock

php artisan queue:restart
# /REGULAR SCRIPT

# Switch (downtime for microseconds)
mv ${CUR} ${BKP}
mv ${NEW} ${CUR}

It seems to work but I'm not sure why, but I had to restart fpm "manually" once.

Should I restart FPM after the directories are set? (at the end of the script). Same question with queue:restart...

Thanks.

0 likes
11 replies
bugsysha's avatar

I think most zero-downtime services are creating a symbolic link. They don't move folders around. Are you sure it is a smart thing to move folders?

1k3r's avatar
Level 6

Yes, I read somewhere to use symlinks but I don't really know if that's the problem. Do you have an example where symlinks are used?

bugsysha's avatar

Are you asking for a command or which SaaS uses it?

1k3r's avatar
Level 6

A command example, I guess Envoyer uses something similar.

bugsysha's avatar

As simple as:

ln -s path/to/file_or_directory path/to/symlink
1 like
1k3r's avatar
Level 6

So you mean the deploy script is almost Ok, and instead of using "mv" commands, make the symlink.

bugsysha's avatar

I would change things. Maybe looking at deployer can give you a better idea.

Usually what is done is that you don't remove the current folder. You just create a new one and change symlink from the current to the new one. Then if you notice that something is wrong, you can quickly revert back to the previous one if you notice any issues by changing symlink.

Also, I don't see that you've covered things like storage folder and others. If you are using files for caching things you might delete them, or even worse, uploads.

I've noticed that your home folder is named forge. What exactly are you trying to achieve?

1 like
1k3r's avatar
Level 6

Nothing special. I was using the default forge script and sometimes when I deployed the app I was having a little seconds of downtime.

I try the script from the OP, and it seems to work but I'm not 100% sure that restarting the fpm BEFORE the "mv" commands affects.

In the other hand, uploads are s3, I don't use the storage:link.

I will take a look to deployer. Thanks again.

bugsysha's avatar

Do you really need zero downtime? I was looking into it years back, but now I don't think I need it at all. I just put the site down if the site is with a higher amount of visitors at that point. If I have a website that has a bunch of users, and I can't afford the downtime, at that point I set up that website in Envoyer and live a happy carefree life because saving time is more valuable than $10 per month.

1k3r's avatar
Level 6

Yep, you were right. I don't "need" at this moment zero downtime. So at the end my script is almost the "default" of laravel forge.

cd /home/forge/www.example.com
git pull origin master

composer install --no-interaction --prefer-dist --optimize-autoloader --no-dev

# restart fpm
( flock -w 10 9 || exit 1
    echo 'Restarting FPM...'; sudo -S service $FORGE_PHP_FPM reload ) 9>/tmp/fpmlock

php artisan queue:restart

Please or to participate in this conversation.