mirror of
https://github.com/tiennm99/composes.git
synced 2026-10-11 03:13:16 +00:00
feat(paseo): add Go, Python, shell tooling, hostname and timezone
Go 1.26.8 from the official tarball and Python 3.12 via uv, since Debian 12 carries 1.19 and 3.11. Both land outside $HOME, which the paseo-home volume would otherwise mask. Hostname and timezone come from the environment rather than being fixed in the compose file. Paseo uses the container hostname as the host label in its web UI, so without one the UI shows a random container ID.
This commit is contained in:
1 parent
6590c59f40
commit
5a4348cde7
5 files changed
+69
-16
No files matched your search
@@ -11,6 +11,18 @@ shorter one. Existing services that still use `docker-compose.yml` stay as
|
|||||||
they are; do not rename them, not even while touching the file for something
|
they are; do not rename them, not even while touching the file for something
|
||||||
else.
|
else.
|
||||||
|
|
||||||
|
## Installing software in an image
|
||||||
|
|
||||||
|
Follow the upstream project's own documented install method, or the one the
|
||||||
|
community has settled on. In order of preference: the vendor's signed package
|
||||||
|
repository, the vendor's official tarball or install script, then a well-known
|
||||||
|
community installer. Do not hand-roll a download, and do not take a stale
|
||||||
|
distro package just because `apt install` is shorter — check what version it
|
||||||
|
actually gives you first.
|
||||||
|
|
||||||
|
State the reason in a comment when the obvious route is the wrong one, so the
|
||||||
|
next person does not "simplify" it back.
|
||||||
|
|
||||||
The root `README.md` is an index only — it covers the shared conventions and
|
The root `README.md` is an index only — it covers the shared conventions and
|
||||||
links out to each service. Per-service detail (variables, ports, storage)
|
links out to each service. Per-service detail (variables, ports, storage)
|
||||||
belongs in that service's README, not the root one. Adding a service means
|
belongs in that service's README, not the root one. Adding a service means
|
||||||
|
|||||||
@@ -16,3 +16,10 @@ PASEO_HOSTNAMES=
|
|||||||
# ws://...:6767 from an HTTPS page -- which the browser blocks.
|
# ws://...:6767 from an HTTPS page -- which the browser blocks.
|
||||||
# `uniquelocal` covers the private ranges Docker bridge networks use.
|
# `uniquelocal` covers the private ranges Docker bridge networks use.
|
||||||
PASEO_TRUSTED_PROXIES=uniquelocal
|
PASEO_TRUSTED_PROXIES=uniquelocal
|
||||||
|
|
||||||
|
# Container hostname. Paseo shows it as the host label in the web UI, so
|
||||||
|
# without it you get a random container ID.
|
||||||
|
PASEO_LABEL=paseo
|
||||||
|
|
||||||
|
# Timezone for logs and agent shells.
|
||||||
|
TZ=Asia/Ho_Chi_Minh
|
||||||
+28
-10
@@ -1,18 +1,20 @@
|
|||||||
# The official image ships no agent CLIs. Add Claude Code globally under
|
# The official image ships no agent CLIs or language toolchains. Add them here.
|
||||||
# /usr/local, where the unprivileged paseo user can run it.
|
|
||||||
#
|
|
||||||
# npm here delivers the same native binary as the standalone installer -- it is
|
|
||||||
# not a Node wrapper. Do not swap this for the `curl | bash` installer: that
|
|
||||||
# writes to $HOME/.local, and $HOME is /home/paseo, a volume mount that masks
|
|
||||||
# anything baked in at build time.
|
|
||||||
#
|
#
|
||||||
# Stays root: the entrypoint needs root to chown the mounted volumes, then
|
# Stays root: the entrypoint needs root to chown the mounted volumes, then
|
||||||
# drops to paseo with gosu itself.
|
# drops to paseo with gosu itself. Nothing installs into $HOME -- that is
|
||||||
|
# /home/paseo, a volume mount that masks anything baked in at build time.
|
||||||
FROM ghcr.io/getpaseo/paseo:latest
|
FROM ghcr.io/getpaseo/paseo:latest
|
||||||
|
|
||||||
|
ARG GO_VERSION=1.26.8
|
||||||
|
ARG PYTHON_VERSION=3.12
|
||||||
|
|
||||||
|
# npm here delivers the same native binary as Anthropic's standalone installer;
|
||||||
|
# it is not a Node wrapper. Do not swap it for the `curl | bash` installer,
|
||||||
|
# which writes to $HOME/.local.
|
||||||
RUN npm install -g @anthropic-ai/claude-code
|
RUN npm install -g @anthropic-ai/claude-code
|
||||||
|
|
||||||
# gh is not in the Debian repos, so pull it from GitHub's own signed one.
|
# Everyday shell tooling, plus gh from GitHub's own signed repo since Debian
|
||||||
|
# does not package it.
|
||||||
RUN install -d -m 0755 /etc/apt/keyrings \
|
RUN install -d -m 0755 /etc/apt/keyrings \
|
||||||
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
&& curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
|
||||||
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
-o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
|
||||||
@@ -20,5 +22,21 @@ RUN install -d -m 0755 /etc/apt/keyrings \
|
|||||||
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
|
||||||
> /etc/apt/sources.list.d/github-cli.list \
|
> /etc/apt/sources.list.d/github-cli.list \
|
||||||
&& apt-get update \
|
&& apt-get update \
|
||||||
&& apt-get install -y --no-install-recommends gh \
|
&& apt-get install -y --no-install-recommends \
|
||||||
|
gh less jq unzip zip lsof psmisc ugrep bfs zsh \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
# Python via uv (astral.sh/uv), which fetches a standalone CPython build.
|
||||||
|
# Debian 12 only carries 3.11, and both dirs are kept outside $HOME.
|
||||||
|
ENV UV_INSTALL_DIR=/usr/local/bin \
|
||||||
|
UV_PYTHON_INSTALL_DIR=/opt/python \
|
||||||
|
UV_PYTHON_BIN_DIR=/usr/local/bin
|
||||||
|
RUN curl -fsSL https://astral.sh/uv/install.sh | sh \
|
||||||
|
&& uv python install "${PYTHON_VERSION}" --default
|
||||||
|
|
||||||
|
# Go from the official tarball. Debian 12 carries 1.19, far too old.
|
||||||
|
ENV PATH=/usr/local/go/bin:$PATH
|
||||||
|
RUN curl -fsSL "https://go.dev/dl/go${GO_VERSION}.linux-$(dpkg --print-architecture).tar.gz" \
|
||||||
|
-o /tmp/go.tar.gz \
|
||||||
|
&& tar -C /usr/local -xzf /tmp/go.tar.gz \
|
||||||
|
&& rm /tmp/go.tar.gz
|
||||||
+20
-6
@@ -1,12 +1,13 @@
|
|||||||
# paseo
|
# paseo
|
||||||
|
|
||||||
[Paseo](https://paseo.sh) — self-hosted daemon and web UI for running coding
|
[Paseo](https://paseo.sh) — self-hosted daemon and web UI for running coding
|
||||||
agents. Built from a local `Dockerfile` that adds Claude Code and `gh` to the
|
agents. Built from a local `Dockerfile` that adds Claude Code, `gh`, Go,
|
||||||
[official image](https://paseo.sh/docs/docker), which ships neither.
|
Python, and shell tooling to the [official image](https://paseo.sh/docs/docker),
|
||||||
|
which ships none of it.
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Set the three variables from `.env.example` in Coolify or Dokploy.
|
1. Set the variables from `.env.example` in Coolify or Dokploy.
|
||||||
2. Point the domain at port `6767` and deploy.
|
2. Point the domain at port `6767` and deploy.
|
||||||
3. Open the domain. At the pairing screen enter the host **with the port**:
|
3. Open the domain. At the pairing screen enter the host **with the port**:
|
||||||
|
|
||||||
@@ -33,6 +34,8 @@ the old entry is cached in `localStorage`.
|
|||||||
| `PASEO_PASSWORD` | Web UI and API login. Generate with `openssl rand -base64 24`. |
|
| `PASEO_PASSWORD` | Web UI and API login. Generate with `openssl rand -base64 24`. |
|
||||||
| `PASEO_HOSTNAMES` | Domains allowed to reach the daemon, comma-separated. Your domain must be listed. |
|
| `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_TRUSTED_PROXIES` | Set to `uniquelocal`, or the UI loads but never connects. |
|
||||||
|
| `PASEO_LABEL` | Container hostname. Paseo shows it as the host label in the UI; without it you get a random container ID. |
|
||||||
|
| `TZ` | Timezone for logs and agent shells. |
|
||||||
|
|
||||||
`PASEO_TRUSTED_PROXIES` matches the *source IP* of the proxy, so hostnames are
|
`PASEO_TRUSTED_PROXIES` matches the *source IP* of the proxy, so hostnames are
|
||||||
rejected. By default the daemon believes `X-Forwarded-Proto` only from
|
rejected. By default the daemon believes `X-Forwarded-Proto` only from
|
||||||
@@ -60,14 +63,22 @@ a redeploy.
|
|||||||
|
|
||||||
## Image
|
## Image
|
||||||
|
|
||||||
Claude Code comes from npm; `gh` from GitHub's signed apt repo, since Debian
|
| Tool | Source | Why not apt |
|
||||||
does not package it. Add other agent providers to the `npm install` line:
|
| --- | --- | --- |
|
||||||
|
| Claude Code | npm | — |
|
||||||
|
| `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 jq unzip zip lsof psmisc ugrep bfs zsh` | apt | — |
|
||||||
|
|
||||||
|
Bump a language with a build arg, e.g. `--build-arg GO_VERSION=1.27.1`. Add
|
||||||
|
other agent providers to the `npm install` line:
|
||||||
|
|
||||||
```dockerfile
|
```dockerfile
|
||||||
RUN npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai
|
RUN npm install -g @anthropic-ai/claude-code @openai/codex opencode-ai
|
||||||
```
|
```
|
||||||
|
|
||||||
Notes for anyone tempted to change it:
|
`uv` itself is installed too. Notes for anyone tempted to change things:
|
||||||
|
|
||||||
- npm installs the same native binary as Anthropic's standalone installer.
|
- npm installs the same native binary as Anthropic's standalone installer.
|
||||||
Don't swap in `curl | bash` — it writes to `$HOME/.local`, and `$HOME` is
|
Don't swap in `curl | bash` — it writes to `$HOME/.local`, and `$HOME` is
|
||||||
@@ -76,3 +87,6 @@ Notes for anyone tempted to change it:
|
|||||||
a notice at startup. Rebuild to update.
|
a notice at startup. Rebuild to update.
|
||||||
- The image stays root on purpose: the entrypoint chowns the volumes, then
|
- The image stays root on purpose: the entrypoint chowns the volumes, then
|
||||||
drops to the `paseo` user (uid 1000) with `gosu`.
|
drops to the `paseo` user (uid 1000) with `gosu`.
|
||||||
|
- Nothing installs into `$HOME`. That is `/home/paseo`, a volume mount that
|
||||||
|
hides anything baked in at build time — hence `/opt/python` and
|
||||||
|
`/usr/local/go` rather than the defaults.
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
services:
|
services:
|
||||||
paseo:
|
paseo:
|
||||||
build: .
|
build: .
|
||||||
|
hostname: ${PASEO_LABEL}
|
||||||
environment:
|
environment:
|
||||||
|
- TZ=${TZ}
|
||||||
- PASEO_PASSWORD=${PASEO_PASSWORD}
|
- PASEO_PASSWORD=${PASEO_PASSWORD}
|
||||||
- PASEO_HOSTNAMES=${PASEO_HOSTNAMES}
|
- PASEO_HOSTNAMES=${PASEO_HOSTNAMES}
|
||||||
- PASEO_TRUSTED_PROXIES=${PASEO_TRUSTED_PROXIES}
|
- PASEO_TRUSTED_PROXIES=${PASEO_TRUSTED_PROXIES}
|
||||||
|
|||||||
Reference in new issue
Block a user