Jetty

Documentation for Jetty

Sharing local sites

Jetty exposes HTTP traffic you can reach on your own machine to the internet over HTTPS. The CLI registers a tunnel with Bridge, then (with the Go CLI and jetty-edge) forwards requests from the public URL to your local upstream.

There are several ways to point Jetty at the site you want to share.


Share by port (default)

The usual pattern is to pass the TCP port your app listens on. Jetty forwards to 127.0.0.1 and that port by default.

jetty share 8000

Examples:

  • Laravel php artisan serve on port 8000 → jetty share 8000
  • Next.js or Vite dev server on 3000 → jetty share 3000

Composer / PHAR (same command name):

jetty share 8000

Keep the process running while you test. Your public URL appears in the CLI output and under Bridge → Tunnels.


Share a specific upstream (local site / bind address)

If your app is not on 127.0.0.1, or you use a .test / .dev hostname (for example Laravel Herd or Valet), set --site to that hostname or IP and pass the port your stack serves HTTP on. Equivalent flags: --bind=, --local=, --local-host=. --host= still works but is deprecated (it used to be overloaded with other meanings).

This is the Jetty equivalent of Expose’s expose share http://127.0.0.1:3000 or expose share https://my-local-site.dev: you choose the upstream explicitly.

# Same machine, explicit loopback
jetty share 3000 --site=127.0.0.1

# Another device on your LAN
jetty share 8080 --site=192.168.2.100

# Herd/Valet-style local site (resolve to 127.0.0.1 in DNS or /etc/hosts)
jetty share 80 --site=my-site.test
jetty share 443 --site=my-site.test

Use the port where that host actually serves plain HTTP for tunneling, unless your stack is configured for HTTPS locally—in that case you may still proxy via HTTP on another port or adjust your local setup.


Stable subdomain (reserved label)

To reuse the same public hostname across reconnects (for example webhooks), pass --subdomain when your team allows reserved labels (see Bridge → Domains).

jetty share 8000 --subdomain=my-app

If the label is already taken, registration fails and you can pick another or release the old tunnel first.


Which Jetty deployment (server name)

jetty config set server <name> chooses which Jetty Bridge / API you talk to—the server names listed in Bridge → Getting started for this product. That is different from Expose’s --server=us-2 style flags on a single vendor network.

jetty config set server your-server-name
jetty config set token your-token-here

Operators can define multiple entries in JETTY_CLI_SERVERS on the app so teams see more than one named server in the dashboard.


Go CLI vs PHP client

  • jetty share — full path with WebSocket to jetty-edge when your stack returns edge details (typical for local or self-hosted edge).
  • PHP build of jetty — HTTP registration and heartbeats; does not run the edge WebSocket agent. Use the Go jetty binary when you need the edge WebSocket agent on the same machine.

Local HTTPS: *.tunnel.jetty.test shows the Jetty Bridge (wrong site)

Browsers load https://YOUR-LABEL.tunnel.jetty.test. That traffic must reach jetty-edge (default 127.0.0.1:8090), which proxies to your Go jetty share agent and then to your app (e.g. Vite on 5173 or beacon on another Valet host).

What goes wrong: On Laravel Valet, hostnames like something.tunnel.jetty.test often match no dedicated site and fall through to Valet’s default PHP router, so you see the Jetty Laravel app (welcome/dashboard) instead of the tunneled upstream.

Fix (Valet on macOS):

  1. Run jetty-edge (same machine as the CLI agent), with JETTY_EDGE_SECRET and Laravel APP_URL matching your Bridge .env.
  2. Issue a wildcard certificate for the tunnel zone (Valet’s per-site certs do not cover arbitrary subdomains):
    brew install mkcert && mkcert -install
    cd ~/.config/valet/Certificates
    mkcert "*.tunnel.jetty.test" "tunnel.jetty.test"
    
  3. Copy deploy/nginx/valet-jetty-tunnel-wildcard.conf to ~/.config/valet/Nginx/, edit the two ssl_certificate paths to the mkcert files it printed (often _*wildcard*+1.pem).
  4. valet restart

Then https://reef-….tunnel.jetty.test is proxied to jetty-edge with the correct Host header, and your beacon (or Vite) upstream is reached via the agent.

Quick smoke test without browser TLS: curl -sS -H "Host: YOUR-LABEL.tunnel.jetty.test" http://127.0.0.1:8090/ should hit the edge (not the Bridge PHP app).

Generic nginx (non-Valet): see deploy/nginx/jetty-tunnel-wildcard-local.conf.example.

For more install paths, see Installation.