Open source · MIT licensed · Single binary

Ship with zero downtime.
On your own servers.

Conveyor is a self-hosted deployment tool inspired by Laravel Envoyer. Atomic releases, health-checked rollbacks, push-to-deploy webhooks — from a single Go binary with no agents to install and no monthly bill.

Everything Envoyer does. Nothing to rent.

Built for Laravel, not limited to it — deploy steps are plain shell commands over SSH, so anything you can deploy from a GitHub repo works.

Zero-downtime releases

Each deploy builds a fresh release directory, then swaps the currentsymlink atomically. Requests never hit a half-deployed app.

Health-checked rollbacks

After activation, Conveyor polls a URL you choose. If it fails, the previous release is restored automatically.

Push to deploy

Webhooks for GitHub, GitLab, Gitea, and Forgejo — or a plain HTTP endpoint your CI can call after tests pass.

Multi-server, no agents

Deploy to any number of servers over SSH. Nothing to install or keep updated on the targets.

Encrypted env files

Edit .env files in the UI. Encrypted with AES-256-GCM at rest, gated by per-project access passwords, symlinked into every release.

Customizable pipeline

Builtin clone, activate, and purge steps plus a library of Laravel presets — composer, migrations, cache warming, queue restarts. Add, edit, and reorder freely.

Live deploy output

Watch every step stream in real time over WebSockets, per server.

No-deploy windows

Block deployments during peak hours with recurring weekly windows in each project's timezone. Rollbacks stay allowed.

One binary, one database

Go binary + SQLite. No Redis, no queue workers, no external services. Backs up with a single command.

Watch every deploy as it happens

Per-step, per-server output streams live to your browser — and every deployment keeps its full log for later.

A finished Conveyor deployment showing per-step, per-server log output

How a deployment works

  1. Download — Conveyor fetches a tarball of your branch. Only Conveyor needs a Git token.
  2. Upload — the archive is copied to each server over SCP.
  3. Extract — a new releases/<timestamp> directory, with shared .env and storage linked in immediately.
  4. Build — your steps run: composer install, migrations, cache warming, anything.
  5. Activate — the current symlink swaps atomically; health check gates the result.
  6. Purge — old releases beyond your retention limit are cleaned up.

Running in two minutes

# docker-compose.yml
services:
  conveyor:
    image: ghcr.io/smitmartijn/conveyor:latest
    ports: ["8080:8080"]
    volumes: [conveyor-data:/data]
    env_file: .env
volumes:
  conveyor-data:
$ docker run --rm ghcr.io/smitmartijn/conveyor:latest \
    /app/conveyor-cli generate-key > .env.key
$ echo "CONVEYOR_ENCRYPTION_KEY=$(cat .env.key)" >> .env
$ docker compose up -d

Then open http://localhost:8080. Theinstallation guide covers TLS, admin users, and upgrades.

Your deploys shouldn't depend on someone else's uptime.