Files
paseo/public-docs/configuration.md
Mohamed Boudra 2c9db5279c Run Paseo from an official Docker image (#1740)
* Add Docker images and agent Docker Mods

Ship official container images that run the Paseo daemon headless. One
Dockerfile parametrized by BASE_IMAGE covers Debian 12/13, Ubuntu 22.04/24.04
and Alpine; it bundles Node 22, the npm-published server + CLI, a vendored
s6-overlay as PID 1, and a small Docker Mods loader.

Agents are chosen at runtime via DOCKER_MODS (pipe-separated mod images). Each
mod is a FROM scratch image carrying only an install hook that runs
`npm install -g <agent-cli>`; the loader pulls the layers from the registry,
extracts them, and runs the hook before the daemon starts, so any requested
agent is on PATH when Paseo probes provider availability.

- docker/base: Dockerfile, install scripts, s6 services, mods loader
- docker/mods/*: claude-code, codex, copilot, opencode, pi
- docker/docker-compose.example.yml + docker/README.md
- .github/workflows/docker.yml: multi-arch (amd64/arm64) buildx matrix,
  publishes to ghcr.io/getpaseo on version tags
- docs/docker.md + CLAUDE.md docs index row

* feat(docker): print pairing QR and link on daemon startup

Add an s6 oneshot service that waits for the daemon to listen, then runs
`paseo daemon pair` so the pairing QR code and link surface in the container
logs. Best-effort: never blocks boot, skips gracefully when relay is disabled.
Opt out with PASEO_PAIRING_QR=0.

* build(docker): add Arch image support

* ci(docker): build Arch without Buildx

* docs(docker): document paseo env contract

* feat(docker): add opt-in sudo mode

* docs(docker): link env references

* fix(docker): create agent config dirs

* fix(docker): default home to /home/paseo

* docs(docker): document agent auth setup

* docs(docker): document relay port setup

* fix(docker): install Node from tarball

* docs: add Docker quick start

* docs(docker): remove legacy home example

* docs(docker): set container hostname

* fix(docker): prepare opencode storage

* fix(docker): allow paseo login shell

* fix docker opencode permissions

* ci(docker): use Node 24 actions

* fix(docker): install bzip2 runtime tools

* fix(docker): update Pi mod package

* fix(docker): quiet default daemon logs

* fix(docker): split home from state

Docker images now keep HOME at /home/paseo and store Paseo daemon state under /home/paseo/.paseo by default.

Existing volumes can keep the old layout by setting PASEO_HOME=/home/paseo.

* fix(docker): keep mods out of paseo home

* ci(docker): skip alpine arm64 builds

* fix(docker): address review findings

* fix(docker): verify s6 overlay downloads

* fix(docker): honor custom healthcheck port

* fix(docker): fail on mod extraction errors

* feat(docker): add official container image

Ship a focused daemon image with the bundled web UI enabled and document extending it with agent CLIs.

* ci(docker): publish images only on stable releases

* fix(docker): check daemon health over HTTP

---------

Co-authored-by: Herbrant <cdavide98carnemolla@gmail.com>
2026-06-26 14:48:13 +08:00

7.1 KiB

title, description, nav, order, category
title description nav order category
Configuration Configure Paseo via config.json, environment variables, and CLI overrides. Configuration 40 Configuration

Configuration

Paseo loads configuration from a single JSON file in your Paseo home directory, with optional environment variable and CLI overrides.

Where config lives

By default, Paseo uses ~/.paseo as its home directory. The configuration file is:

~/.paseo/config.json

You can change the home directory by setting PASEO_HOME or passing --home to paseo daemon start.

Precedence

Paseo merges configuration in this order:

  1. Defaults
  2. config.json
  3. Environment variables
  4. CLI flags

Lists append across sources (for example, hostnames and cors.allowedOrigins).

Example

Minimal example that configures listening address, hostnames, and MCP:

{
  "$schema": "https://paseo.sh/schemas/paseo.config.v1.json",
  "version": 1,
  "daemon": {
    "listen": "127.0.0.1:6767",
    "hostnames": ["localhost", ".localhost"],
    "mcp": { "enabled": true }
  }
}

daemon.hostnames is the primary field. The old daemon.allowedHosts name still works as a deprecated alias for backward compatibility.

Agent providers

Agent providers, both the first-class ones Paseo ships with and custom entries you add under agents.providers, are documented on their own page.

See Providers for the mental model and Supported providers for the full list of agents Paseo can launch. For pointing Claude at Anthropic-compatible endpoints (Z.AI, Alibaba/Qwen), multiple profiles, custom binaries, ACP agents, and the additionalModels merge behavior, see Custom providers. The full field reference lives on GitHub at docs/custom-providers.md.

Worktrees

New worktrees are created under $PASEO_HOME/worktrees by default. To place new worktrees somewhere else, set worktrees.root:

{
  "worktrees": {
    "root": "/mnt/fast/paseo-worktrees"
  }
}

Relative paths are resolved against PASEO_HOME. Existing worktrees remain where they are; changing this setting only changes where Paseo creates and discovers Paseo-managed worktrees going forward.

Voice

Voice is configured through features.dictation and features.voiceMode, with provider credentials under providers.

For voice philosophy, architecture, and complete local/OpenAI setup examples, see Voice docs.

Bundled web UI

The daemon can serve the browser web client from the same HTTP server. This is enabled in the official Docker image and disabled by default for normal CLI and desktop-managed daemons.

Enable it from the CLI:

paseo daemon start --web-ui

Or set the environment variable:

PASEO_WEB_UI_ENABLED=true paseo daemon start

Or persist it in config.json:

{
  "features": {
    "webUi": {
      "enabled": true
    }
  }
}

When enabled, open the daemon HTTP origin, for example http://localhost:6767/, to load the web app. Static UI files load without daemon auth; API and WebSocket requests still require the configured password.

Logging

Daemon logging uses separate console and file sinks by default:

  • Console: info and above
  • File ($PASEO_HOME/daemon.log): trace and above
  • File rotation: 10m max file size, 2 retained files total (active + 1 rotated)
{
  "log": {
    "console": {
      "level": "info",
      "format": "pretty"
    },
    "file": {
      "level": "trace",
      "path": "daemon.log",
      "rotate": {
        "maxSize": "10m",
        "maxFiles": 2
      }
    }
  }
}

Legacy fields log.level and log.format are still supported and map to the new destination settings.

Password authentication

You can require a password to connect to the daemon. When set, all HTTP and WebSocket clients must authenticate. Only the /api/health liveness endpoint is exempt, so that process supervisors and load balancers can probe without credentials.

The easiest way to set a password is with the CLI:

paseo daemon set-password

This prompts for a password, writes the bcrypt hash to config.json, and tells you to restart the daemon.

Alternatively, set the PASEO_PASSWORD environment variable (plaintext, hashed automatically at startup):

PASEO_PASSWORD=my-secret paseo daemon start

Or write the hash directly in config.json:

{
  "daemon": {
    "auth": {
      "password": "$2b$12$..."
    }
  }
}

After setting a password, restart the daemon for the change to take effect.

Connecting with a password

The CLI picks up a password from, in order:

  1. The password query parameter on a tcp:// host URI:

    paseo --host "tcp://192.168.1.10:6767?password=my-secret" ls
    
  2. The PASEO_PASSWORD environment variable, used as a fallback when the host carries no embedded password (works for localhost:6767, bare host:port, or tcp:// hosts without a password= query):

    PASEO_PASSWORD=my-secret paseo ls
    PASEO_PASSWORD=my-secret paseo --host 192.168.1.10:6767 ls
    

A password= in the URI always wins over the env var, so you can keep PASEO_PASSWORD set globally and still target a different daemon by spelling its password into the URI.

In the mobile app, enter the password in the direct connection setup screen.

Common env vars

  • PASEO_HOME, set Paseo home directory
  • PASEO_PASSWORD, on the daemon, the password to require (plaintext, hashed at startup); on the CLI, the password used to connect when the host URI doesn't include one
  • PASEO_LISTEN, override daemon.listen
  • PASEO_HOSTNAMES, override/extend daemon.hostnames
  • PASEO_ALLOWED_HOSTS, deprecated alias for PASEO_HOSTNAMES
  • PASEO_WEB_UI_ENABLED, enable or disable the daemon-served web UI
  • PASEO_WEB_UI_DIST_DIR, override the daemon web UI build directory
  • PASEO_TRUSTED_PROXIES, configure trusted reverse proxy ranges for X-Forwarded-* headers
  • PASEO_LOG_CONSOLE_LEVEL, override log.console.level
  • PASEO_LOG_FILE_LEVEL, override log.file.level
  • PASEO_LOG_FILE_PATH, override log.file.path
  • PASEO_LOG_FILE_ROTATE_SIZE, override log.file.rotate.maxSize
  • PASEO_LOG_FILE_ROTATE_COUNT, override log.file.rotate.maxFiles
  • PASEO_LOG, PASEO_LOG_FORMAT, legacy log overrides (still supported)
  • OPENAI_API_KEY, override OpenAI provider key
  • PASEO_VOICE_LLM_PROVIDER, override voice LLM provider (claude, codex, opencode)
  • PASEO_DICTATION_STT_PROVIDER, PASEO_VOICE_STT_PROVIDER, PASEO_VOICE_TTS_PROVIDER, override voice provider selection (local or openai)
  • PASEO_LOCAL_MODELS_DIR, control local model directory
  • PASEO_DICTATION_LOCAL_STT_MODEL, override local dictation STT model
  • PASEO_VOICE_LOCAL_STT_MODEL, PASEO_VOICE_LOCAL_TTS_MODEL, override local voice STT/TTS models
  • PASEO_DICTATION_LANGUAGE, PASEO_VOICE_LANGUAGE, override dictation and voice STT language
  • PASEO_VOICE_LOCAL_TTS_SPEAKER_ID, PASEO_VOICE_LOCAL_TTS_SPEED, optional local voice TTS tuning

Schema

For editor autocomplete/validation, set $schema to:

https://paseo.sh/schemas/paseo.config.v1.json