14 Commits
Author SHA1 Message Date
tiennm99 bfd9fdbfd3 refactor(paseo): install gh, glab, uv and Python into home
Drop them from the image; the README gives the commands to install each
into ~/.local/bin on the home volume. System packages stay in the image.
2026-10-06 17:22:20 +07:00
tiennm99 c20aed29cb feat(paseo)!: drop go and sdkman, rename AGENT_CLIS to AGENTS
The image installs python, gh, glab, build-essential, sudo, zsh and nano
only; go or a jvm goes into $HOME from a terminal instead.

SHELL and TZ are written into compose.yml rather than read from .env, so
the deploying shell's own values can no longer win over them.

The entrypoint calls chpasswd, chown and gosu by absolute path, tolerates
a chpasswd failure instead of taking the start down with it, turns
globbing off around the agent loop, and counts an agent as installed only
when its binary actually runs.
2026-09-18 11:39:09 +07:00
tiennm99 f02de334e5 feat(paseo): install SDKMAN on start, and rename the wrapper entrypoint
SDKMAN goes into ~/.sdkman whenever that directory is missing, the same way
the agent CLIs arrive: as paseo, through gosu, onto the volume, where `sdk
install` can write and the candidates persist. No variable gates it.

The chown of /home/paseo moves out of the AGENT_CLIS guard, since SDKMAN now
needs it even when no agent is named, and the agent loop reads AGENT_CLIS into
a local first so `set -u` does not trip on it being unset.

SDKMAN_DIR is set in the image, and the current/bin of java, scala, gradle,
maven and sbt joins PATH: `sdk` itself is a shell function from the rc hook and
so exists in terminals only, while the daemon and an agent's non-interactive
commands read no rc file and need the binaries on PATH.

paseo-sudo-entrypoint was named for the one thing it used to do. It is
/usr/local/bin/entrypoint now, matching the source file.
2026-09-17 14:21:25 +07:00
tiennm99 f39ca227ce feat(paseo): put the agent CLI install dirs on the image PATH
The daemon probes each provider's binary with `which` in its own
environment, which comes from the image and never sources a shell rc, so
agents installed into $HOME were reported unavailable.
2026-09-17 10:09:02 +07:00
tiennm99 55e8f7321d feat(paseo): install glab, and stop preinstalling the agent CLIs
The paseo user cannot write /usr/local, so a baked-in agent CLI can never
apply its own update — every one of them ships an updater that expects to
rewrite its own binary, and Claude Code nags about the failure at startup.
Installed under $HOME they update themselves and still persist, since that is
the paseo-home volume. The README now lists each vendor's installer.

Bun goes with them: it was only there because omp is compiled against it.

glab arrives as the .deb from GitLab's releases page, pinned by GLAB_VERSION
because the URL carries the version. GitLab runs no apt repository and calls
Homebrew its only officially supported Linux package manager.

The Dockerfile drops its explanations along the way; they are in the README.
2026-09-17 09:44:12 +07:00
tiennm99 92d24c8e64 feat(paseo): preinstall the build-essential C toolchain
The image had no compiler at all -- gcc, g++, make, cc and ld were all
missing -- so cgo, npm's node-gyp addons and Python C extensions could
not build. Goes in the existing apt layer to keep a single apt-get
update.
2026-09-16 22:55:56 +07:00
tiennm99 04ccc93969 feat(paseo): add Copilot, Pi and Oh My Pi agent CLIs
Six agents now ship in the image. All come from npm; omp additionally needs
Bun, since its bin is Bun-compiled and opens with `#!/usr/bin/env bun`.
BUN_INSTALL puts Bun in /usr/local, clear of the paseo-home volume.
2026-09-16 20:40:39 +07:00
tiennm99 65ec872e62 feat(paseo): add Codex and opencode-ai agent CLIs 2026-09-16 20:35:00 +07:00
tiennm99 d6f7eb46cd feat(paseo): preinstall nano and set the git identity from the environment
GIT_NAME and GIT_EMAIL expand into the four GIT_AUTHOR_*/GIT_COMMITTER_*
variables, the same shape code-server already uses. Passing the identity as
environment rather than running `git config` means agents and terminals commit
correctly with no setup step, and it does not depend on ~/.gitconfig surviving
in the /home/paseo volume.
2026-09-16 17:57:16 +07:00
tiennm99 cb1d38f147 feat(paseo): give the paseo user sudo, authenticated with PASEO_PASSWORD
The base image installs no sudo and leaves paseo out of the sudo group, so
add both. The password cannot be baked in at build time -- it is a secret and
would land in a layer -- and it cannot be set after the base entrypoint, which
ends in `exec gosu paseo` and never returns. Wrap that entrypoint instead and
set the password while still root, on every start: /etc/shadow lives in the
image, not on the /home/paseo volume, so it reverts on each recreate.
2026-09-16 17:21:11 +07:00
tiennm99 b796f098ca refactor(paseo): split the Dockerfile into one layer per concern
System packages, Python, Go, gh and the agent CLIs each get their own
block. Ordered least-changing first, so a Claude Code bump no longer
re-runs the toolchain installs.
2026-09-16 16:30:47 +07:00
tiennm99 5a4348cde7 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.
2026-09-16 16:24:26 +07:00
tiennm99 6590c59f40 feat(paseo): install the gh CLI
Debian does not package gh, so use GitHub's signed apt repo. Config
lands in /home/paseo/.config/gh, inside the paseo-home volume, so the
login survives a redeploy.
2026-09-16 15:59:41 +07:00
tiennm99 c1e10c3663 feat(paseo): add paseo service with Claude Code preinstalled
The upstream image ships no agent CLIs, so build from a local Dockerfile
that layers Claude Code on top. npm delivers the same native binary as
the standalone installer, which cannot be used here: it writes to
$HOME/.local, and $HOME is /home/paseo, a volume mount that masks
anything baked in at build time.

Runs as root by design -- the entrypoint chowns the mounted volumes and
then drops to the unprivileged paseo user with gosu.
2026-09-16 15:06:01 +07:00