Sign inSign up

relzhong/paseo

By relzhong

Updated 2 days ago

paseo ui and relay

Image
0

246

relzhong/paseo repository overview

paseo-tools

Self-hosted Paseo web UI and paseo-relay, so a Paseo instance (daemon) can be reached from a browser through your own relay.

Single image, single port

The recommended build is the all-in-one image (paseo-all/): web UI + relay in one container, published on one port (8080), with the relay on a subpath:

http://host:8080/          web UI (nginx static SPA)
ws://host:8080/ws          relay WebSocket (nginx -> relay on 127.0.0.1:4000)
http://host:8080/health    relay liveness
http://host:8080/ready     relay readiness

The Paseo client protocol always connects to the relay at the /ws path, so subpath routing is transparent to both the daemon and the browser. Using one origin also avoids mixed-content (http page + ws) and CORS issues.

Browser ──► http(s)://host:8080/  (web UI)
                │
                │ ws://host:8080/ws (pairing offer pasted in browser)
                ▼
          nginx (same container)
                │
                ▼
          paseo-relay (127.0.0.1:4000)
                ▲
                │ ws://host:8080/ws  (PASEO_RELAY_ENDPOINT)
          Paseo daemon (your instance)

Build & run

cd paseo-tools
./build.sh            # resolves latest paseo tag + relay commit, builds relzhong/paseo:latest
nerdctl run -d --name paseo -p 8080:8080 relzhong/paseo:latest

# or with compose:
cp .env.example .env  # set RELAY_PUBLIC_ENDPOINT to your LAN IP
nerdctl compose up -d --build

The Dockerfiles clone from GitHub at build time, so every build pulls the newest upstream code with no manual bumping. build.sh resolves the exact latest release tag (web UI) and commit (relay) before invoking the build and passes them as build args, which makes BuildKit's layer cache effective: rebuilding while nothing changed is near-instant, and a new upstream version only redoes the changed stage (deps are cached with BuildKit cache mounts). Pin a version with --build-arg PASEO_TAG=v0.3.1 / --build-arg RELAY_REF=<sha>.

Note: the first build is heavy (npm workspaces + Expo export + Elixir release) and can take 10-30 minutes depending on network; subsequent builds are fast.

Network mirror defaults (CN-friendly)

The builds default to mirrors that are fast in China; override per environment:

Build argDefaultPurpose
APT_MIRRORmirrors.tuna.tsinghua.edu.cnapt sources (set deb.debian.org elsewhere)
NPM_REGISTRYhttps://registry.npmmirror.comnpm registry (set https://registry.npmjs.org elsewhere)
HTTPS_PROXYunsetoptional proxy for GitHub clones / hex.pm (build.sh forwards your env)
What gets built (web UI only)

The web UI build runs npm ci --workspace=@getpaseo/app, installing only the app and the workspaces it depends on (@getpaseo/client, @getpaseo/highlight, @getpaseo/protocol, @getpaseo/expo-two-way-audio). The desktop, server, CLI and website workspaces — including the heavy electron binary download — are intentionally skipped.

Point your Paseo instance at the relay

On the machine running the daemon (paseo CLI / ghcr.io/getpaseo/paseo image), first enable the relay, then set the endpoint:

# enable: fresh install, or restart an existing daemon with the relay on
paseo onboard --relay
paseo daemon restart --relay

# set the endpoint (env vars, taken on daemon start)
export PASEO_RELAY_ENDPOINT=paseo.your-domain.com        # daemon -> relay connection
export PASEO_RELAY_PUBLIC_ENDPOINT=paseo.your-domain.com # advertised to browsers
export PASEO_RELAY_USE_TLS=true
export PASEO_RELAY_PUBLIC_USE_TLS=true
paseo daemon restart

<host>:<port> is the relay address from the daemon's perspective. With a public domain + TLS reverse proxy in front of the relay, use wss:// by setting USE_TLS=true; on a plain LAN use ws:// (USE_TLS=false). The protocol appends the /ws path automatically.

Equivalent persisted config at ~/.paseo/config.json:

{ "daemon": { "relay": {
  "enabled": true,
  "endpoint": "paseo.your-domain.com",
  "useTls": true,
  "publicEndpoint": "paseo.your-domain.com",
  "publicUseTls": true
} } }

Note: paseo daemon restart --relay only toggles enabled; the endpoint always comes from env vars or the persisted config.

CLI on another machine (through the relay)

The paseo CLI connects through the relay too — just point it at the daemon's pairing offer URL (no port forwarding needed):

npm install -g @getpaseo/cli
export PASEO_HOST="https://app.paseo.sh/#offer=<paste the offer from 'paseo onboard --relay'>"
paseo ls
paseo run "implement the auth flow"

The offer embeds the relay endpoint, TLS, serverId and the daemon's E2EE public key, so the CLI reaches the daemon via wss://paseo.your-domain.com/ws.

Alternative (no relay, direct TCP): the daemon must listen on a reachable interface (PASEO_LISTEN=0.0.0.0:6767), then on the client: export PASEO_HOST=<ip>:6767 and export PASEO_PASSWORD=... if auth is set.

Connect from the browser

  1. Open the web UI: http://paseo.iriscv.com:8080 (plain http is fine — the relay itself is reached as wss://).
  2. Print the daemon's pairing link: paseo onboard --relay (or the QR shown at first start).
  3. Paste the pairing link into the web UI. It embeds PASEO_RELAY_PUBLIC_ENDPOINT/USE_TLS, so the browser connects through your relay to the instance.

Standalone images

paseo-relay/ and paseo-webui/ build the two components separately, in case you want to scale the relay independently:

nerdctl build -t relzhong/paseo-relay:latest ./paseo-relay   # port 4000
nerdctl build -t relzhong/paseo-webui:latest ./paseo-webui   # port 80

Volumes

The relay is stateless (route ownership and metrics live in BEAM memory; clients simply reconnect), so the all-in-one image needs no volume. The state that matters is:

  • Your Paseo daemon — mount its home and workspace, e.g. -v paseo-home:/home/paseo -v "$PWD:/workspace".
  • Web UI — host profiles live in the browser (localStorage/IndexedDB), not on the server.

Optional: persist BEAM crash dumps / log files with -v paseo-relay-data:/opt/paseo-relay/log.

Notes

  • The relay does not terminate TLS. Plain http:// web UI + ws:// relay works on your LAN. If you expose the web UI over HTTPS you must also put a TLS proxy in front of it so browsers can use wss:// for /ws.
  • The web UI stores host profiles in the browser (localStorage/IndexedDB).
  • Build times: the web UI build is heavy (npm workspaces + Expo export); rebuilds reuse nerdctl's build cache for everything except the clone steps.
  • If the relay stops compiling after an upstream change, bump ELIXIR_IMAGE in the Dockerfiles to the tag used by the upstream paseo-relay Dockerfile.

Tag summary

Content type

Image

Digest

sha256:2d315bdec

Size

47.9 MB

Last updated

2 days ago

docker pull relzhong/paseo