From 9d8c45a341da37b9a5cf971fddcfb16595662b0a Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 29 May 2026 10:54:13 -0700 Subject: [PATCH 1/4] Run container as non-root stellar user. --- Dockerfile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index f757986..5aa1320 100644 --- a/Dockerfile +++ b/Dockerfile @@ -83,11 +83,19 @@ RUN apt-get update \ libudev1 \ && rm -rf /var/lib/apt/lists/* RUN rustup target add wasm32v1-none -COPY --from=builder /out/bin/stellar /usr/local/bin/stellar -RUN chmod +x /usr/local/bin/stellar -ENV STELLAR_CONFIG_HOME=/config \ - STELLAR_DATA_HOME=/data +RUN useradd --create-home --home-dir /stellar --uid 1000 --shell /bin/bash stellar \ + && mkdir -p /source /config /data \ + && chown stellar:stellar /source /config /data + +COPY --from=builder --chown=root:root --chmod=0755 /out/bin/stellar /usr/local/bin/stellar + +ENV CARGO_HOME=/stellar/.cargo \ + HOME=/stellar \ + STELLAR_CONFIG_HOME=/config \ + STELLAR_DATA_HOME=/data \ + STELLAR_NO_UPDATE_CHECK=1 +USER stellar WORKDIR /source ENTRYPOINT ["stellar"] From 1711c73e5d37463fe50af0b3848ae03220ad99c5 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 29 May 2026 10:54:44 -0700 Subject: [PATCH 2/4] Run repro builds as host user; simplify cleanup. --- scripts/repro_test.py | 33 ++++++++------------------------- 1 file changed, 8 insertions(+), 25 deletions(-) diff --git a/scripts/repro_test.py b/scripts/repro_test.py index c1cf29b..b9db093 100755 --- a/scripts/repro_test.py +++ b/scripts/repro_test.py @@ -8,7 +8,7 @@ import argparse import atexit -import contextlib +import os import re import shutil import sys @@ -46,6 +46,10 @@ def build_and_hash(image: str, contract_dir: Path) -> str: "docker", "run", "--rm", + "--user", + f"{os.getuid()}:{os.getgid()}", + "-e", + "CARGO_HOME=/tmp/cargo", "--entrypoint", "bash", "-v", @@ -103,35 +107,14 @@ def clone(repo: str, rev: str, workdir: Path) -> None: runner.run(["git", "-C", str(workdir), "checkout", "-q", "FETCH_HEAD"]) -def make_cleanup(image: str, workdir: Path, keep: bool): +def make_cleanup(workdir: Path, keep: bool): def cleanup() -> None: if keep: common.log(f"keeping workdir on exit: {workdir}") return if not workdir.exists(): return - # Files inside may be root-owned by the container builds. Wipe via - # docker so this works on Linux CI; fall back to host rm. - wipe = runner.run( - [ - "docker", - "run", - "--rm", - "--entrypoint", - "sh", - "-v", - f"{workdir}:/work", - image, - "-c", - "find /work -mindepth 1 -delete", - ], - check=False, - capture_output=True, - ) - if wipe.returncode != 0: - shutil.rmtree(workdir, ignore_errors=True) - with contextlib.suppress(OSError): - workdir.rmdir() + shutil.rmtree(workdir, ignore_errors=True) return cleanup @@ -142,7 +125,7 @@ def main(argv: list[str] | None = None) -> int: contracts = args.contracts or list(DEFAULT_CONTRACTS) workdir = Path(tempfile.mkdtemp(prefix="repro-test.")) - atexit.register(make_cleanup(args.image, workdir, args.keep_workdir)) + atexit.register(make_cleanup(workdir, args.keep_workdir)) clone(args.repo, args.rev, workdir) From f7ca1d4cfa531dcd04fcd0cc52d5ef66a22dcf96 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 29 May 2026 10:55:02 -0700 Subject: [PATCH 3/4] Document runtime paths and the new non-root user. --- README.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/README.md b/README.md index 61d3b1c..70cf339 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,33 @@ Build a contract by mounting the contract directory at `/source`: docker run --rm -v "$PWD:/source" docker.io/stellar/stellar-cli:latest contract build --locked ``` +The image exposes four well-known paths: + +| Path | What | +| ---------- | ------------------------------------------------------------------------------------- | +| `/source` | `WORKDIR`. Bind-mount your contract here. | +| `/config` | `STELLAR_CONFIG_HOME`. Mount to persist network and identity configuration. | +| `/data` | `STELLAR_DATA_HOME`. Mount to persist CLI data. | +| `/stellar` | Home for user `stellar` (UID 1000). Mount to persist the cargo cache (see below). | + +The image runs as user `stellar` (UID 1000) with `/stellar` as the home +directory. `CARGO_HOME` resolves to `/stellar/.cargo` inside the +container, which is wiped on exit by default. + +To reuse cargo's registry index, git checkouts, and crate sources across +runs — and to make the image work under `--user "$(id -u):$(id -g)"` on +Linux hosts whose UID is not 1000 — mount a writable host directory at +`/stellar`: + +```sh +mkdir -p /tmp/myproject +docker run --rm \ + --user "$(id -u):$(id -g)" \ + -v /tmp/myproject:/stellar \ + -v "$PWD:/source" \ + docker.io/stellar/stellar-cli:latest contract build --locked +``` + ## Verifiable builds ([SEP-58](https://github.com/stellar/stellar-protocol/blob/master/ecosystem/sep-0058.md)) For verifiable references, **always pin to a per-arch single-architecture From 34058922aabfc14e96b87f4a81bd3b5a8042e859 Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 29 May 2026 10:59:21 -0700 Subject: [PATCH 4/4] Format markdown file. --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 70cf339..34419a3 100644 --- a/README.md +++ b/README.md @@ -33,12 +33,12 @@ docker run --rm -v "$PWD:/source" docker.io/stellar/stellar-cli:latest contract The image exposes four well-known paths: -| Path | What | -| ---------- | ------------------------------------------------------------------------------------- | -| `/source` | `WORKDIR`. Bind-mount your contract here. | -| `/config` | `STELLAR_CONFIG_HOME`. Mount to persist network and identity configuration. | -| `/data` | `STELLAR_DATA_HOME`. Mount to persist CLI data. | -| `/stellar` | Home for user `stellar` (UID 1000). Mount to persist the cargo cache (see below). | +| Path | What | +| ---------- | --------------------------------------------------------------------------------- | +| `/source` | `WORKDIR`. Bind-mount your contract here. | +| `/config` | `STELLAR_CONFIG_HOME`. Mount to persist network and identity configuration. | +| `/data` | `STELLAR_DATA_HOME`. Mount to persist CLI data. | +| `/stellar` | Home for user `stellar` (UID 1000). Mount to persist the cargo cache (see below). | The image runs as user `stellar` (UID 1000) with `/stellar` as the home directory. `CARGO_HOME` resolves to `/stellar/.cargo` inside the