Files
composes/paseo
tiennm99 23b9bf8bf6 docs: describe current state only, and fill in the stub READMEs
Drop the history and roadmap asides: which services predate the collection's
conventions, the unwired Open Web UI plan, the generic clone-and-troubleshoot
boilerplate. Services that publish ports or set `restart:` now simply say so.

couchbase, openvpn-as and traffmonetizer had two-line READMEs; give them the
ports, variables and storage the root README promises. traffmonetizer reads
${TOKEN} and had no .env.example, so add one.
2026-09-16 20:45:18 +07:00
..

paseo

Paseo — self-hosted daemon and web UI for running coding agents. Built from a local Dockerfile that adds six agent CLIs, gh, Go, Python, and shell tooling to the official image, which ships none of it.

Setup

  1. Set the variables from .env.example in Coolify or Dokploy.

  2. Point the domain at port 6767 and deploy.

  3. Open the domain. At the pairing screen enter the host with the port, then the PASEO_PASSWORD value:

    paseo.example.com:443
    
  4. In a terminal inside Paseo, log in once per tool you use — see Agents — plus gh auth login.

The port must be typed by hand. The UI rejects a bare hostname, and the auto-connect hint does not help: the daemon builds it from the Host header, browsers drop the default :443, and the UI discards a hint with no port. What you see instead is its localhost:6767 placeholder, which in a browser means your own machine.

If it stays on localhost:6767 after you enter the address, clear site data — the old entry is cached in localStorage.

Environment

Variable Purpose
PASEO_PASSWORD Web UI and API login, and the paseo user's sudo password. Generate with openssl rand -base64 24.
PASEO_HOSTNAMES Domains allowed to reach the daemon, comma-separated. Your domain must be listed.
PASEO_TRUSTED_PROXIES Set to uniquelocal, or the UI loads but never connects.
PASEO_LABEL Container hostname, shown as the host label in the UI. Without it the label is a random container ID.
GIT_NAME / GIT_EMAIL Git author and committer identity for agents and terminals.
TZ Timezone for logs and agent shells.
SHELL Shell for Paseo's terminals. Paseo reads $SHELL and falls back to /bin/sh, ignoring the login shell, so chsh has no effect.

PASEO_TRUSTED_PROXIES matches the proxy's source IP, so hostnames are rejected. The daemon trusts X-Forwarded-Proto from loopback only, but Coolify's Traefik reaches it from the Docker bridge network — so it reads the request as plain HTTP, tells the UI to use ws:// on an https:// page, and the browser blocks that as mixed content. uniquelocal covers the private ranges Docker uses. An exact CIDR works too, but Coolify assigns a fresh subnet per project.

Networking

Listens on 6767, published nowhere — the platform maps the domain to it, so localhost:6767 on the host refuses connections. See the root README for why.

Agents

Agent Command Package Log in with
Claude Code claude @anthropic-ai/claude-code claude
Codex codex @openai/codex codex login
opencode opencode opencode-ai opencode auth login
Copilot CLI copilot @github/copilot /login inside copilot
Pi pi @earendil-works/pi-coding-agent pi
Oh My Pi omp @oh-my-pi/pi-coding-agent omp

All six come from npm, so another provider is one more entry on the npm install line. Pi and Oh My Pi are separate projects sharing an ancestor; their commands do not collide.

Storage

Volume Mount Holds
paseo-home /home/paseo Daemon state, agent configs, credentials (.claude, .codex, .config/*)
paseo-workspace /workspace Code the agents work on

Every agent CLI and gh keep their config under /home/paseo, so all logins survive a redeploy — the base image points CLAUDE_CONFIG_DIR, CODEX_HOME and the XDG_* variables into it. Dotfiles live there too, so a .zshrc or oh-my-zsh install persists. Anything written outside $HOME (chsh, apt install) is lost on rebuild.

Image

Tool Source Why not apt
Agent CLIs (see above) npm —
Bun Official bun.sh install script Debian does not package it
gh GitHub's signed apt repo Debian does not package it
Go (GO_VERSION) Official go.dev tarball Debian 12 ships 1.19
Python (PYTHON_VERSION) uv python install Debian 12 ships 3.11
less nano jq unzip zip lsof psmisc ugrep bfs zsh sudo apt —

Bump a language with a build arg, e.g. --build-arg GO_VERSION=1.27.1. uv itself is installed too.

Constraints worth knowing before changing the Dockerfile:

  • $HOME is /home/paseo, a volume that masks anything the build writes there. Hence /opt/python and /usr/local/go rather than the defaults, and hence npm rather than each vendor's curl | bash installer, which writes to $HOME/.local. npm delivers the same native binaries regardless — every one of these packages is a thin launcher with the real binary as a per-platform optional dependency.
  • Bun exists for omp alone, whose bin opens with #!/usr/bin/env bun. Node runs the other five.
  • The agent CLIs cannot auto-update, since paseo cannot write /usr/local. Claude Code shows a notice at startup. Rebuild to update.
  • The image stays root: the entrypoint chowns the volumes, then drops to the paseo user (uid 1000) with gosu.
  • entrypoint.sh sets the paseo password from PASEO_PASSWORD on every start, while still root. /etc/shadow is not on a volume, so it reverts on each recreate. An empty PASEO_PASSWORD leaves the account locked and sudo unusable.
  • sudo resets PATH to its secure_path, which excludes /usr/local/go/bin. Use sudo env PATH="$PATH" go ... or the full path.