Skip to content
New: Laravel Hosting, Node.js Hosting & GitHub DeploysSee the plans →
Products
Solutions
Developers

Guides

How to deploy from GitHub to shared hosting

Connect a GitHub repository to your site, run a build script on every push, and keep your .env and worker processes in step with each release.

Introduction

Every site in the panel may be linked to a public or private GitHub repository. Each push to the branch you choose clones the commit into the site’s container, runs your build script there, and switches the document root to the new release. The full build log is kept in the panel.

This guide covers connecting a repository, writing a build script, and the two things you must handle yourself: files that are not in git, and restarting worker processes.

Connecting Your GitHub Account

In the panel sidebar, open GitHub connection and click Connect GitHub. GitHub asks you to confirm, creates a small GitHub App under your account, and then asks which account and repositories it may read. You should grant access only to the repositories you intend to deploy.

You only need to do this once per panel login. Every site you own may then choose from those repositories.

Linking a Site

Open the site, click the GitHub tab, and fill in the following fields:

  • Repository and branch. You may use a tag instead if you release by tag.
  • Build script. The command that turns a fresh clone into a working site. For most projects, this is a short shell script committed to the repository, for example sh build.sh.
  • Publish directory. The folder the web server should serve: public for Laravel, dist or build for a static site, and empty for plain PHP.
  • Auto deploy. When on, every push deploys. When off, you press Deploy now when you are ready.

Save the form, press Deploy now once, and check the log.

Release Directory Structure

Each deploy clones into deploys/<commit>/ inside your site’s home directory and runs the build script in that folder. When the build finishes, the symlink deploys/current points at the new folder and the site’s document root is set to deploys/current/<publish directory> automatically.

Old releases stay on disk, so you may roll back by redeploying an earlier commit from the history list.

Laravel Build Script

The following build script deploys a Laravel application:

#!/bin/sh
set -e

# ~/shared holds what every release shares: .env and storage
SHARED=../../shared
mkdir -p $SHARED
[ -d $SHARED/storage ] || cp -R storage $SHARED/storage
rm -rf storage
ln -s $SHARED/storage storage

FIRST_DEPLOY=
if [ ! -f $SHARED/.env ]; then
  cp .env.example $SHARED/.env
  FIRST_DEPLOY=1
fi
ln -sf $SHARED/.env .env

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

if [ -n "$FIRST_DEPLOY" ]; then
  php artisan key:generate --force --no-interaction
  echo "First deploy: fill in ~/shared/.env, then press Deploy now again."
  exit 1
fi

php artisan migrate --force
php artisan storage:link
php artisan optimize

php artisan queue:restart
# php artisan horizon:terminate   # if you run Horizon
# php artisan reverb:restart      # if you run Reverb

Shared Files

The panel has no environment variable screen, and each release is a fresh clone, so anything not in git would be lost on the next deploy.

The script above keeps these files in ~/shared and links them into every release. All releases use one .env file and one storage/ folder, so uploads, file sessions, file cache, and logs survive a deploy, and users stay logged in. You may keep any other file that is not in git, such as an SQLite database or a downloaded binary, in ~/shared in the same way.

The First Deploy

The first deploy creates ~/shared/.env from .env.example, generates the application key, and then stops on purpose, because .env.example has no real database password. Open ~/shared/.env over SSH or in the file manager, fill in the database, mail, and APP_URL settings, and press Deploy now again. That deploy runs the migrations and goes live.

Changing Settings

To change a setting later, edit ~/shared/.env, then run php artisan config:cache in ~/deploys/current over SSH, or deploy again. The build caches the configuration, so an edit alone is not picked up.

Restarting Worker Processes

Worker processes, such as a queue worker, Horizon, Reverb, Octane, or a Node server, keep running the old release after a deploy. The panel does not restart them for you.

For Laravel, the last lines of the build script handle most of this. Uncomment the lines for the tools you run:

  • Queue workers: php artisan queue:restart. The worker finishes its current job and exits, and the panel starts it again in the new release.
  • Horizon: php artisan horizon:terminate. Horizon ignores queue:restart, so without this line it keeps running the old code.
  • Reverb: php artisan reverb:restart.

For a Node.js application, end the build script with pkill -u "$(id -u)" -x node || true. This stops the running application, and the panel starts it again on the new release within a few seconds. The full setup is in how to deploy a Node.js app.

The schedule:work command and Octane do not listen for any of those signals. For those, press Restart container on the site overview after the deploy. This restarts every worker on the site and takes a few seconds.

Checking a Deploy

The GitHub tab lists every deploy with its commit message, its trigger, and a View logs link to the build output. A failed build leaves the previous release serving, so you may fix the problem and push again.

Limitations

The build runs inside your site’s container, with the same PHP, Composer, Node, and git you get over SSH, and the same resource limits. If a build is slow here, compile heavy assets in GitHub Actions and commit or download the result.

One-click installed WordPress sites cannot be linked to a repository. Instead, create the site empty and then connect it.

Keep reading

Other guides

Start building today

Laravel apps with queues and Horizon, WordPress stores, Node.js servers. One container with SSH, deploys from GitHub and people who answer. One bill a year.

Launch my site