laratusk/cloudflare-tunnel

Start and manage Cloudflare Tunnels directly from Artisan. Supports both quick (random URL) and named (static hostname) tunnels with callback hooks.

Maintainers

Package info

github.com/laratusk/cloudflare-tunnel

pkg:composer/laratusk/cloudflare-tunnel

Statistics

Installs: 3

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v0.2.0 2026-04-02 13:39 UTC

This package is auto-updated.

Last update: 2026-04-02 13:40:04 UTC


README

CI Latest Version on Packagist License

Start and manage Cloudflare Tunnels directly from Artisan. Expose your local Laravel application to the internet with a single command — using either a quick tunnel (random URL, zero config) or a named tunnel (static hostname, permanent URL).

php artisan cloudflare:tunnel

Features

  • Quick tunnels — Random *.trycloudflare.com URL, no account required
  • Named tunnels — Static hostname under your own domain (e.g. tunnel.example.com)
  • EventsTunnelConnected and TunnelDisconnected events for webhook registration, notifications, etc.
  • Graceful shutdown — Clean process termination on Ctrl+C

Requirements

  • PHP 8.2+
  • Laravel 10, 11, 12, or 13
  • The pcntl PHP extension
  • The cloudflared CLI binary

Installation

1. Install cloudflared

macOS (Homebrew):

brew install cloudflared

Linux (Debian/Ubuntu):

curl -fsSL https://pkg.cloudflare.com/cloudflare-main.gpg | sudo tee /usr/share/keyrings/cloudflare-main.gpg >/dev/null
echo "deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared $(lsb_release -cs) main" | sudo tee /etc/apt/sources.list.d/cloudflared.list
sudo apt update && sudo apt install cloudflared

Other platforms: See the official download page.

Verify the installation:

cloudflared --version

2. Install the package

composer require laratusk/cloudflare-tunnel

3. Publish the config (optional)

php artisan vendor:publish --tag=cloudflare-tunnel-config

Quick Start

Quick Tunnel (zero config)

Run the command with no additional setup — you get a random public URL instantly:

php artisan cloudflare:tunnel
 Tunnel URL: https://random-words.trycloudflare.com
 Tunnel is running. Press Ctrl+C to stop.

Named Tunnel (static hostname)

A named tunnel gives you a permanent, predictable URL under your own domain. Follow these steps once to set it up:

Step 1: Authenticate with Cloudflare

cloudflared tunnel login

This opens your browser. Select the domain you want to use and authorize cloudflared.

Step 2: Create a tunnel

cloudflared tunnel create my-app

Note the tunnel ID in the output — you'll see it in cloudflared tunnel list too.

Step 3: Route DNS to the tunnel

cloudflared tunnel route dns my-app tunnel.example.com

This creates a CNAME record pointing tunnel.example.com to your tunnel.

Step 4: Create the cloudflared config file

Create ~/.cloudflared/config.yml:

tunnel: <TUNNEL-ID>
credentials-file: /path/to/.cloudflared/<TUNNEL-ID>.json

ingress:
  - hostname: tunnel.example.com
    service: http://127.0.0.1
    originRequest:
      httpHostHeader: my-app.test
  - service: http_status:404

Replace <TUNNEL-ID> with your actual tunnel ID. The httpHostHeader should match your local development domain. The credentials file path is printed when you create the tunnel.

Step 5: Configure the package

Add to your .env:

CLOUDFLARE_TUNNEL_MODE=named
CLOUDFLARE_TUNNEL_NAME=my-app
CLOUDFLARE_TUNNEL_HOSTNAME=tunnel.example.com

Step 6: Run it

php artisan cloudflare:tunnel
 Tunnel URL: https://tunnel.example.com
 Tunnel is running. Press Ctrl+C to stop.

Configuration

Environment Variable Default Description
CLOUDFLARE_TUNNEL_MODE quick quick or named
CLOUDFLARE_TUNNEL_NAME Named tunnel name (required for named mode)
CLOUDFLARE_TUNNEL_HOSTNAME Static hostname (required for named mode)
CLOUDFLARE_TUNNEL_LOCAL_URL http://127.0.0.1 Local URL to forward traffic to
CLOUDFLARE_TUNNEL_HOST_HEADER Override the Host header for local requests
CLOUDFLARE_TUNNEL_TIMEOUT 30 Seconds to wait for tunnel connection

Events

The package dispatches two events you can hook into with standard Laravel listeners:

Event Payload When
TunnelConnected string $url, TunnelMode $mode After the tunnel is established
TunnelDisconnected string $url Before the process exits (Ctrl+C)

Example: Register a Telegram webhook

Create a listener:

php artisan make:listener RegisterTelegramWebhook --event='\Laratusk\CloudflareTunnel\Events\TunnelConnected'
namespace App\Listeners;

use Laratusk\CloudflareTunnel\Events\TunnelConnected;
use Telegram\Bot\Laravel\Facades\Telegram;

class RegisterTelegramWebhook
{
    public function handle(TunnelConnected $event): void
    {
        Telegram::setWebhook(['url' => $event->url . '/api/telegram/webhook']);
    }
}
namespace App\Listeners;

use Laratusk\CloudflareTunnel\Events\TunnelDisconnected;
use Telegram\Bot\Laravel\Facades\Telegram;

class RemoveTelegramWebhook
{
    public function handle(TunnelDisconnected $event): void
    {
        Telegram::deleteWebhook();
    }
}

Laravel auto-discovers listeners, so no manual registration is needed.

Testing

composer test

Changelog

Please see CHANGELOG for more information on what has changed recently.

License

The MIT License (MIT). Please see License File for more information.