Deployment Hooks
Learn how to configure deployment hooks in Devpilot — the commands and actions that run at each stage of the deployment lifecycle.
Deployment Hooks
Deployment hooks are the commands and file-sync actions that Devpilot executes during each stage of the deployment lifecycle. They define what happens when your code is deployed — from installing dependencies to restarting services. Every application in Devpilot has its own set of hooks that you configure to match your build and release process.
How hooks work
When you trigger a deployment, Devpilot moves through the deployment lifecycle in order: Pre Execution, Pre Source Control, Post Source Control, Post Setup, Post Release. At each stage, Devpilot runs the Active hooks assigned to that stage in priority order. If a hook fails (returns a non-zero exit code), the deployment stops and is marked as Failed. Hooks that never ran in that deployment are marked Skipped.
Each hook has:
- A name — A short label that shows up in the deployment log.
- A stage — When the hook runs in the lifecycle.
- An action type — What the hook does (run a shell command, sync a file, or sync a directory).
- Metadata — Stage-specific configuration, such as the command to run or the path to sync.
- A priority — The position of the hook within its stage. Hooks run in ascending priority order.
- A status — Either Active (runs during deployment) or Inactive (stored but skipped).
Hook stages explained
Devpilot's deployment lifecycle has five stages:
| Stage | When it runs | Common uses |
|---|---|---|
| Pre Execution | Before anything runs in the deployment. | Pre-flight checks, "deployment starting" notifications, preparing server paths. |
| Pre Source Control | Right before Devpilot fetches your code. | Last-minute branch checks, pausing traffic, announcing the upcoming release. |
| Post Source Control | Right after the repository has been fetched into a new release directory. | Installing Composer dependencies, syncing environment or vendor files, copying shared assets, running tests. |
| Post Setup | After the app's runtime is set up (dependencies installed, assets built). | Running migrations and seeders, clearing and rebuilding framework caches, syncing storage or public directories, setting folder permissions. |
| Post Release | After the new release is made live. | Restarting queue workers, reloading Docker containers, running post-release migrations, restarting the app. |
Hook action types
Devpilot supports three action types for hooks:
Shell Command
Runs a shell command on the server. This is the most common action type. The command executes in a bash shell in the context of the current release directory. You enter the command in the hook's Command field.
Examples seen across live templates:
composer install --no-interaction --no-devphp artisan migrate --forcephp artisan optimizenpm installnpm run buildphp artisan horizon:terminatephp artisan cache:clearSync File
Persists a single file across releases and symlinks it into each new release. Use this for configuration files, environment files, or a SQLite database that shouldn't be committed to the repository. Configure it with the file's relative path (for example .env) in the hook's Path field, plus optional Rsync Flags (defaults to -az).
This hook seeds the persisted copy only once: the first time it runs for an app, if no persisted copy exists yet, Devpilot copies the file out of the release into a persistent location at the same relative path under the app's root. On every deployment after that, the persisted copy is left untouched — Devpilot just removes the file from the new release and symlinks it back to the persisted copy. Edits made to the file on the server (or written by the running app) survive every future deployment; the version in your repository only ever seeds the first copy.
Sync Directory
Persists a directory across releases and symlinks it into each new release. Use this for directories that should survive redeployment, such as storage, vendor, public, or an uploads folder — it avoids re-installing large dependency trees and preserves user-generated files. Configure it with the directory's relative path in the hook's Path field, plus optional Rsync Flags (defaults to -r -t -O -v -c -S -u -q --no-times).
Unlike Sync File, this hook runs on every deployment, and it merges rather than overwrites. Each run:
- Copies (via
rsync) the new release's version of the directory into the persistent location at the same relative path under the app's root. This is a merge: files that exist only in the persisted copy are left alone (there is no delete step), files new to this release are added, and files present in both are only replaced if the release's version is checksum-different and not older than the persisted one. - Removes the now-redundant copy from the release.
- Symlinks the release path to the persistent directory, so the running app reads and writes the persisted directory directly from that point on.
Because existing files are never deleted from the persisted copy, removing a file from your repository will not remove it from the server — clean up stale files on the server directly if you need that.
Creating hooks with the visual editor
Open the hooks editor
Navigate to your application and open the Deployment Hooks tab.
Select a stage
The editor groups hooks by stage: Pre Execution, Pre Source Control, Post Source Control, Post Setup, and Post Release. Click Add Hook under the stage where the hook should run.
Configure the hook
- Enter a Name for the hook (this appears in deployment logs).
- Select the Action Type: Shell Command, Sync File, or Sync Directory.
- For Shell Command, enter the command.
- For Sync File or Sync Directory, enter the relative path to sync, and optionally custom rsync flags.
- Leave the hook Active to include it in deployments, or switch it to Inactive to keep the definition without running it.
Order your hooks
Reorder the hooks within each stage to set their priority. Hooks within the same stage run sequentially in ascending priority order.
Save
Save your hooks. The changes apply to the next deployment.
Example configurations
These examples mirror the hook patterns used by Devpilot's built-in Laravel template and by real production applications deployed through the platform.
Laravel application
- Post Source Control
- Shell Command — "Install Composer Dependencies":
composer install --no-interaction --no-dev
- Shell Command — "Install Composer Dependencies":
- Post Setup
- Sync Directory — "Sync Storage Directory" with path
storage - Shell Command — "Run migration":
php artisan migrate --force - Shell Command — "Artisan optimize":
php artisan optimize - Shell Command — "Storage link":
php artisan storage:link
- Sync Directory — "Sync Storage Directory" with path
- Post Release
- Shell Command — "Restart Horizon":
php artisan horizon:terminate
- Shell Command — "Restart Horizon":
Node.js / JavaScript application
- Post Source Control
- Shell Command — "Install NPM dependencies":
npm install
- Shell Command — "Install NPM dependencies":
- Post Setup
- Shell Command — "Build":
npm run build
- Shell Command — "Build":
- Post Release
- Shell Command — "Restart app":
pm2 restart ecosystem.config.js
- Shell Command — "Restart app":
Adding persistent directories
For any application, configure a Sync Directory hook in Post Setup for directories that should survive across releases — uploads, generated files, caches, or a shared vendor folder. This is how Devpilot templates handle paths like storage, public, and vendor on Laravel apps.
Best practices
- Keep hooks focused. Each hook should do one thing. Instead of chaining multiple commands with
&&in a single hook, create separate hooks so each runs with its own status, duration, and exit code in the deployment log. - Use meaningful names. Hook names appear in every deployment log. Clear names like "Install Composer Dependencies" or "Run migration" make logs easier to scan.
- Keep definitions but pause them when needed. Switch a hook from Active to Inactive to skip it temporarily without deleting the configuration.
- Start from a template. If you have a hook configuration that works, save it as a pipeline template to reuse across applications.
- Test commands on the server first. Before promoting a command to a hook, run it manually on the server via the Web Terminal to verify it works in the deployment environment.
Repository Scan
How Devpilot inspects your repository to detect the framework, language, services, and environment variables — and uses the results to generate a ready-to-run deployment pipeline.
Pipeline Templates
Use and create pipeline templates in Devpilot to provision deployment hooks for common platforms like Laravel and React in a single click.