Toolbox

Proximo integration

If you use proximo to reach your local-dev apps at https://<name>.test on the host, the toolbox makes those same URLs work from inside the container — for any client (curl, git, Node, Python, Playwright/Chromium, …), with proximo's certificate trusted so no -k / ignoreHTTPSErrors is needed. This file covers why that needs toolbox plumbing, how DNS + CA trust are established, and the bridge-backed lifecycle commands.

Why .test is unreachable from a sibling container

proximo makes any labelled Docker container reachable at https://<name>.<tld> (default .test): it runs Traefik publishing :80/:443 on the host, installs a host resolver mapping *.<tld> → 127.0.0.1, and trusts a local CA in the host OS + NSS stores. That works for the host browser. It does not work from inside a toolbox container: 127.0.0.1 there is the container's own loopback, not the host where Traefik listens, so DNS resolves but the connection refuses. proximo also never injects its CA into arbitrary containers, so even a reachable endpoint fails TLS verification.

Enablement is auto-detected (tri-state proximo)

config.Config.Proximo is a *bool (proximo.Enabled): an explicit true/false wins; omitted (nil) auto-detects — on iff proximo's root CA exists on the host (proximo install wrote it under ~/.proximo). So a host with proximo installed gets .test reachability in every shell with zero per-repo opt-in, and a host without it pays nothing. proximo: false opts a project out; proximo: true forces it on even when the CA is absent (the mount then soft-skips). *bool (vs a plain bool) is what makes nil mean "auto" rather than "off" — the same tri-state shape as bridge, but with an auto rather than always-on default.

The two host-side ingredients

internal/proximo supplies both. The toolbox CLI runs on the host alongside proximo, so it can discover routed hosts directly from Docker labels — no enumeration in .toolbox.yaml, no upstream proximo change, no shared Docker network.

Concern Mechanism Seam
DNS Every running container's proximo.hosts label value is read; each hostname is pinned to the Docker host-gateway and appended to HostConfig.ExtraHosts. host-gateway resolves to the host where Traefik publishes :443, bypassing Docker networks entirely. These --add-host pins are fixed at create; the in-container proximo-hosts command re-syncs them at runtime for stacks started later (see lifecycle). discovery: container/lifecycle.go augmentProximoHosts (needs the Docker client); pure parser: proximo.ExtraHosts
Cert proximo's root CA (path queried via proximo config ca-path — the stable contract from filippolmt/proximo#20; fallback ~/.proximo/tls/ca.pem, proximo's state home since v0.3.0, filippolmt/proximo#17) is bind-mounted RO at /etc/ssl/proximo-ca.pem. entrypoint.sh then establishes seamless trust for every client (see below). NODE_EXTRA_CA_CERTS (Node uses its own bundle) and TOOLBOX_PROXIMO_CA (path pointer for the certifi gap) are also exported. mount: proximo.CAMount injected in mountplan.Merge; env: proximo.Env appended in sessionplan.Plan; trust: entrypoint.sh proximo block

Trust establishment (entrypoint, self-gated on the mount)

entrypoint.sh runs a proximo block gated purely on [ -f /etc/ssl/proximo-ca.pem ] (the mount is the signal — no extra env). It is idempotent and every step is best-effort (|| true) so a trust failure never aborts boot:

Client Trusted via Notes
curl / git / wget / python (ssl, urllib) system bundle sudo cp into /usr/local/share/ca-certificates/proximo.crt + sudo update-ca-certificates (passwordless sudo; refreshed only when the cert changes via a cmp guard)
Chromium / Firefox (incl. Playwright's bundled browsers) NSS certutil -A -t C,, -n proximo into $HOME/.pki/nssdb (libnss3-tools, base apt layer). ~/.pki is a HOME subdir, not a bind-mount → ephemeral, rebuilt from the mounted CA every shell
Node / Playwright (node API) NODE_EXTRA_CA_CERTS additive, set by proximo.Env
python-requests uses certifi, not the system store; set REQUESTS_CA_BUNDLE="$TOOLBOX_PROXIMO_CA" (this is the one non-seamless client)

The generic CA-certificate folder (~/.toolbox/certs/) shares this same system bundle: when any cert is dropped there, its entrypoint block re-points NODE_EXTRA_CA_CERTS / REQUESTS_CA_BUNDLE at the full /etc/ssl/certs/ca-certificates.crt — a superset that still contains proximo's CA, so proximo trust is unaffected. Reach for that folder for any non-proximo CA (corporate proxy, internal runtime); proximo's CA is wired automatically and needs nothing dropped there.

Lifecycle from inside the container (bridge shim)

proximo up|down|status works inside toolbox shell via the bridge: the image ships /usr/local/bin/proximo (internal/build/assets/bin/proximo, sibling of the editor shims) which POSTs {"command": "<sub>"} to the daemon's /proximo endpoint; the daemon execs the host proximo binary and returns {"exit": N, "output": "…"}, which the shim prints and propagates. Running the real binary in-container cannot work: proximo materializes its compose stack under ~/.proximo and bind-mounts those paths, which the host Docker daemon would resolve host-side where they don't exist.

Runtime host sync (proximo-hosts, automatic)

--add-host/ExtraHosts is computed once at ContainerCreate and is immutable for the container's life, so a proximo stack started after toolbox shell is invisible to those pins: <name>.test falls through to the host resolver, resolves to 127.0.0.1 (right for the host, wrong inside the container) and refuses. The in-container proximo-hosts command (internal/build/assets/bin/proximo-hosts) is the runtime complement: it re-discovers the proximo.hosts labels from the host daemon over the mounted /var/run/docker.sock (DooD — docker ps -q + docker inspect, whose .Config.Labels is a map), resolves the host-gateway IP (IPv4-first from the always-pinned host.docker.internal, with a default-route fallback), and rewrites a marker-delimited managed block in /etc/hosts (sudo, passwordless) pinning every routed hostname to that gateway. /etc/hosts is mutable at runtime, so reachability tracks the running stacks with no recreate. It is idempotent; the markers are emitted even when nothing is routed, so a brought-down stack self-clears.

It runs automatically. When proximo is enabled (the CA mount is present), entrypoint.sh launches proximo-hosts --watch in the background: an initial sync, then a re-sync on every start/die of a proximo.hosts-labelled container (docker events — a streaming long-poll, near-zero idle cost; the loop reconnects if the daemon restarts). So stacks brought up or down mid-session are pinned (or unpinned) with no manual step. Running proximo-hosts by hand stays available to force a sync. The watcher logs to ~/.toolbox-state/proximo-hosts.log.

Boundaries and caveats