Docs/ Deployment/ Deploy Hooks

Deploy Hooks

Run custom scripts and send notifications at every stage of your deployment pipeline. Hooks let you run database migrations, clear caches, notify your team, and more.

What Are Deploy Hooks

Deploy hooks are commands or HTTP requests that sh0 executes at specific points in the deployment lifecycle. They allow you to integrate custom logic into your deployment pipeline without modifying your application code.

Common use cases include:

  • Running database migrations after a new version is deployed
  • Clearing CDN or application caches
  • Sending deployment notifications to Slack or Discord
  • Running test suites before switching traffic
  • Backing up the database before deploying
  • Triggering external CI/CD pipelines

Hook Types

sh0 supports four hook types, each executed at a different stage of the deployment process:

Deployment lifecycle diagram showing the four hook execution points

Pre-Build Hooks

Executed before the Docker image build starts. Use these to prepare the build environment, download dependencies, or validate configuration.

Pre-build hook example
# Download private packages from artifact registry
aws s3 cp s3://my-artifacts/private-pkg.tgz ./vendor/
# Validate environment
test -n "$DATABASE_URL" || exit 1
Note
If a pre-build hook exits with a non-zero code, the entire deployment is cancelled. This is useful for enforcing preconditions.

Post-Build Hooks

Executed after the Docker image is built but before the new container starts. Use these to run tests against the newly built image or to push the image to an external registry.

Post-build hook example
# Run unit tests in the newly built image
docker run --rm $IMAGE_NAME npm test
# Push to backup registry
docker tag $IMAGE_NAME registry.example.com/myapp:$DEPLOY_SHA
docker push registry.example.com/myapp:$DEPLOY_SHA

Pre-Deploy Hooks

Executed after the new container starts but before traffic is switched to it. The new container is running and accessible internally, but not receiving public traffic yet. This is the ideal place for database migrations.

Pre-deploy hook example
# Run database migrations
docker exec $CONTAINER_NAME npx prisma migrate deploy
# Warm up caches
curl -s http://localhost:$INTERNAL_PORT/api/warmup
Warning
If a pre-deploy hook fails, sh0 stops the new container and keeps the previous version running. No traffic is ever sent to a container that failed its pre-deploy hooks.

Post-Deploy Hooks

Executed after the traffic switch is complete and the new version is live. Use these for cleanup, notifications, or post-deployment validation.

Post-deploy hook example
# Clear CDN cache
curl -X POST https://api.cloudflare.com/purge_cache \
  -H "Authorization: Bearer $CF_TOKEN"
# Remove old Docker images to free disk space
docker image prune -f

Configuring Hooks

Hooks are configured per app in the dashboard under App Settings → Hooks. Each hook has the following settings:

  • Type: Pre-build, post-build, pre-deploy, or post-deploy
  • Command: Shell command to execute
  • Timeout: Maximum execution time (default: 300 seconds)
  • Fail on error: Whether a non-zero exit code should cancel the deployment
Hook configuration form in the sh0 dashboard

You can also configure hooks via the API:

Create a hook via API
curl -X POST https://your-sh0-server.com:9000/api/apps/{app_id}/hooks \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "hook_type": "post_deploy",
    "command": "npx prisma migrate deploy",
    "timeout": 120,
    "fail_on_error": true
  }'

You can add multiple hooks of the same type. They execute in the order they were created.

Notification Hooks

In addition to shell commands, sh0 supports notification hooks that send deployment status updates to external services. These are configured separately from script hooks.

Notification hooks configuration with Slack, Discord, and webhook options

Supported notification channels:

  • Slack: Provide an incoming webhook URL. Messages include the app name, deploy status, commit SHA, and a link to the build log.
  • Discord: Provide a Discord webhook URL. The message format is similar to Slack with embedded rich content.
  • Email: Receive deployment notifications at one or more email addresses. Configurable for success only, failure only, or both.
  • Custom webhook: Send a JSON payload to any URL. The payload includes full deployment metadata.
Custom webhook payload
{
  "event": "deploy.completed",
  "app_id": "abc123",
  "app_name": "my-api",
  "status": "success",
  "deploy_id": "deploy_xyz",
  "commit_sha": "a1b2c3d",
  "commit_message": "Fix authentication bug",
  "duration_seconds": 42,
  "timestamp": "2026-03-21T14:30:00Z"
}
Tip
Notification hooks are triggered on both successful and failed deployments by default. You can configure them to fire only on specific events using the notification settings.

Hook Execution Logs

Every hook execution is logged with its full output, exit code, and duration. You can view hook logs from the Deployments tab by expanding a specific deployment.

Hook execution log showing command output and exit status

Hook logs include:

  • Standard output and standard error (combined)
  • Exit code
  • Execution duration
  • Timestamp of execution
  • Whether the hook caused the deployment to be cancelled (if fail-on-error was enabled)
Note
Hook logs are retained alongside deployment logs. You can access them for any historical deployment from the deployment history.