Skip to contentNode.js on every plan · private Redis & PostgreSQLSee what's included →

Guides

How to run Laravel Horizon, Reverb and Octane on shared hosting

Run Horizon, Reverb websockets and Octane with RoadRunner as worker processes on a Litehost plan, including the proxy settings that make them reachable on your domain.

All three run as worker processes, and two of them need the panel’s HTTP proxy so the browser can reach them on your own domain. This guide assumes you have read the queue worker guide and know where the Launch button is.

Horizon

Horizon needs Redis, which is on every Laravel Hosting plan and on Business and Cloud Enterprise elsewhere. Switch it on for the site under Advanced, then set in .env:

QUEUE_CONNECTION=redis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379

Launch a Laravel worker with the command php artisan horizon and the working directory that holds artisan. No proxy. Horizon supervises its own child workers, so you do not launch a separate queue:work as well.

In the first few seconds after it starts, the log may show a handful of Worker STOPPED Interrupted lines while Horizon settles its pool. They stop on their own. Jobs process normally.

For a deploy, end the build script with php artisan horizon:terminate. Horizon exits cleanly and the panel starts it again in the new release.

Reverb

Reverb is the websocket server. Launch a Laravel worker with:

php artisan reverb:start --host=0.0.0.0 --port=8080

Switch HTTP proxy on, set the path to app and the port to 8080, and turn websocket upgrade on. The panel then forwards https://yourdomain.com/app/... to Reverb inside the container, including the websocket handshake.

One detail matters on the client side. The proxy strips the path prefix before forwarding, and Reverb itself also expects its routes under /app. So the browser has to connect to /app/app/{key}, which in Laravel Echo is:

wsPath: '/app',
wsHost: window.location.hostname,
wsPort: 443,
forceTLS: true,

Laravel itself publishes events to Reverb from the server, and that traffic should not go out through your domain. The proxy only forwards /app, while Laravel publishes to /apps/..., so point it straight at Reverb inside the container:

REVERB_HOST=127.0.0.1
REVERB_PORT=8080
REVERB_SCHEME=http

The browser side is covered by the Echo settings above, which use the page’s own hostname. For a deploy, end the build script with php artisan reverb:restart.

Octane with RoadRunner

Octane serves the whole site from a long running process. Launch a Laravel worker with:

php artisan octane:start --server=roadrunner --host=0.0.0.0 --port=8000

Switch HTTP proxy on, leave the path empty so the proxy covers the whole site, and set the port to 8000. The first start downloads the RoadRunner binary into the project folder, which takes a moment and shows in the log.

RoadRunner is the server to use here. Swoole is not installed in the container.

Two things to know about Octane and deploys. The RoadRunner binary lives in the release folder, so copy it forward in the build script with cp ../current/rr rr or let Octane download it again. And Octane does not reload on queue:restart, so press Restart container on the site overview after each deploy. It restarts every worker on the site and takes a few seconds.

Running all of them together

The test site this guide was written on runs a queue worker, the scheduler, Horizon, Reverb and Octane as five worker cards on one site, with Octane serving the site and Reverb on /app. Each card has its own log. Every worker shares the memory of your plan, so a site running five long lived processes needs a plan with the room for them.

When this is still not enough

Workers restart if they die, but a worker that dies every few seconds is restarted every few seconds, not throttled. The panel log only keeps the most recent attempt, so test commands over SSH first. If your application needs a process manager with backoff rules, health checks and alerting, that is still a VPS job.

Keep reading

Other guides