agent-containers 0.1.0.dev0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent_containers/__init__.py +1 -0
- agent_containers/__main__.py +6 -0
- agent_containers/_assets/agent-images/adal/Dockerfile +103 -0
- agent_containers/_assets/agent-images/adal/examples/egress-allowlist.txt +10 -0
- agent_containers/_assets/agent-images/adal/packages-apt.txt +13 -0
- agent_containers/_assets/agent-images/adal/packages-npm.txt +2 -0
- agent_containers/_assets/agent-images/adal/packages-uv.txt +6 -0
- agent_containers/_assets/agent-images/adal/tools-uv.txt +4 -0
- agent_containers/_assets/agent-images/agent-gateway/Dockerfile +50 -0
- agent_containers/_assets/agent-images/agent-gateway/entrypoint.sh +28 -0
- agent_containers/_assets/agent-images/agent-gateway/sshd_config.agent-gateway +11 -0
- agent_containers/_assets/agent-images/aider/Dockerfile +114 -0
- agent_containers/_assets/agent-images/aider/examples/egress-allowlist.txt +16 -0
- agent_containers/_assets/agent-images/aider/packages-apt.txt +16 -0
- agent_containers/_assets/agent-images/aider/packages-npm.txt +7 -0
- agent_containers/_assets/agent-images/aider/packages-uv.txt +9 -0
- agent_containers/_assets/agent-images/aider/tools-uv.txt +9 -0
- agent_containers/_assets/agent-images/claude-code/Dockerfile +171 -0
- agent_containers/_assets/agent-images/claude-code/entrypoint.sh +22 -0
- agent_containers/_assets/agent-images/claude-code/examples/egress-allowlist.txt +14 -0
- agent_containers/_assets/agent-images/claude-code/examples/settings.local-model.json +7 -0
- agent_containers/_assets/agent-images/claude-code/packages-apt.txt +16 -0
- agent_containers/_assets/agent-images/claude-code/packages-npm.txt +7 -0
- agent_containers/_assets/agent-images/claude-code/packages-uv.txt +9 -0
- agent_containers/_assets/agent-images/claude-code/plugin-marketplaces.txt +23 -0
- agent_containers/_assets/agent-images/claude-code/plugins.txt +13 -0
- agent_containers/_assets/agent-images/claude-code/proxy-ca.d/.keep +1 -0
- agent_containers/_assets/agent-images/claude-code/tools-uv.txt +9 -0
- agent_containers/_assets/agent-images/codex/Dockerfile +147 -0
- agent_containers/_assets/agent-images/codex/codex-wrapper.sh +13 -0
- agent_containers/_assets/agent-images/codex/examples/egress-allowlist.txt +10 -0
- agent_containers/_assets/agent-images/codex/packages-apt.txt +13 -0
- agent_containers/_assets/agent-images/codex/packages-npm.txt +2 -0
- agent_containers/_assets/agent-images/codex/packages-uv.txt +6 -0
- agent_containers/_assets/agent-images/codex/plugin-marketplaces.txt +2 -0
- agent_containers/_assets/agent-images/codex/plugins.txt +2 -0
- agent_containers/_assets/agent-images/codex/proxy-ca.d/.keep +1 -0
- agent_containers/_assets/agent-images/codex/tools-uv.txt +4 -0
- agent_containers/_assets/agent-images/hermes/Dockerfile +122 -0
- agent_containers/_assets/agent-images/hermes/entrypoint.sh +49 -0
- agent_containers/_assets/agent-images/hermes/packages-apt.txt +16 -0
- agent_containers/_assets/agent-images/hermes/packages-npm.txt +7 -0
- agent_containers/_assets/agent-images/hermes/packages-uv.txt +9 -0
- agent_containers/_assets/agent-images/hermes/proxy-ca.d/.keep +1 -0
- agent_containers/_assets/agent-images/hermes/tools-uv.txt +9 -0
- agent_containers/_assets/agent-images/kilo-code/Dockerfile +101 -0
- agent_containers/_assets/agent-images/kilo-code/examples/egress-allowlist.txt +7 -0
- agent_containers/_assets/agent-images/kilo-code/packages-apt.txt +5 -0
- agent_containers/_assets/agent-images/kilo-code/packages-npm.txt +1 -0
- agent_containers/_assets/agent-images/kilo-code/packages-uv.txt +4 -0
- agent_containers/_assets/agent-images/kilo-code/tools-uv.txt +4 -0
- agent_containers/_assets/agent-images/opencode/Dockerfile +126 -0
- agent_containers/_assets/agent-images/opencode/examples/egress-allowlist.txt +6 -0
- agent_containers/_assets/agent-images/opencode/packages-apt.txt +13 -0
- agent_containers/_assets/agent-images/opencode/packages-npm.txt +2 -0
- agent_containers/_assets/agent-images/opencode/packages-uv.txt +6 -0
- agent_containers/_assets/agent-images/opencode/proxy-ca.d/.keep +1 -0
- agent_containers/_assets/agent-images/opencode/tools-uv.txt +4 -0
- agent_containers/_assets/agent-images/qwen-code/Dockerfile +104 -0
- agent_containers/_assets/agent-images/qwen-code/examples/egress-allowlist.txt +10 -0
- agent_containers/_assets/agent-images/qwen-code/packages-apt.txt +13 -0
- agent_containers/_assets/agent-images/qwen-code/packages-npm.txt +2 -0
- agent_containers/_assets/agent-images/qwen-code/packages-uv.txt +6 -0
- agent_containers/_assets/agent-images/qwen-code/tools-uv.txt +4 -0
- agent_containers/_assets/agent-images/shared/egress-allowlist.sh +138 -0
- agent_containers/_assets/agent-images/shared/install-additional-packages.sh +79 -0
- agent_containers/_assets/agent-images/shared/install-workload-base.sh +46 -0
- agent_containers/_assets/agent-images/shared/workload-entrypoint.sh +82 -0
- agent_containers/_assets/agent-images/volume-bridge/Dockerfile +37 -0
- agent_containers/_assets/agent-images/volume-bridge/entrypoint.sh +29 -0
- agent_containers/_assets/agent-images/volume-bridge/serve.sh +66 -0
- agent_containers/assets.py +38 -0
- agent_containers/build_context.py +116 -0
- agent_containers/cli.py +212 -0
- agent_containers/creation.py +177 -0
- agent_containers/docker.py +562 -0
- agent_containers/lifecycle.py +325 -0
- agent_containers/planner.py +99 -0
- agent_containers/profile.py +377 -0
- agent_containers/shortcuts.py +159 -0
- agent_containers/state.py +154 -0
- agent_containers-0.1.0.dev0.dist-info/METADATA +195 -0
- agent_containers-0.1.0.dev0.dist-info/RECORD +86 -0
- agent_containers-0.1.0.dev0.dist-info/WHEEL +4 -0
- agent_containers-0.1.0.dev0.dist-info/entry_points.txt +3 -0
- agent_containers-0.1.0.dev0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Default/optional apt packages installed at build time, one per line.
|
|
2
|
+
# Blank lines and lines starting with '#' are ignored. Edit freely and
|
|
3
|
+
# rebuild the image — this is separate from the Dockerfile's own
|
|
4
|
+
# required-infra apt list (git, iptables, gosu, etc.), which this file
|
|
5
|
+
# cannot remove packages from.
|
|
6
|
+
gh
|
|
7
|
+
jq
|
|
8
|
+
ripgrep
|
|
9
|
+
fd-find
|
|
10
|
+
tree
|
|
11
|
+
unzip
|
|
12
|
+
less
|
|
13
|
+
file
|
|
14
|
+
lsof
|
|
15
|
+
yq
|
|
16
|
+
miller
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Optional global npm packages installed at build time (via `npm install -g`),
|
|
2
|
+
# one per line. Blank lines and lines starting with '#' are ignored. Empty by
|
|
3
|
+
# default — there's no "everyone wants this" global npm CLI the way there is
|
|
4
|
+
# for apt utilities.
|
|
5
|
+
#
|
|
6
|
+
# Example:
|
|
7
|
+
# @some-scope/some-cli
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Optional Python libraries installed into the system Python at build time
|
|
2
|
+
# (via `uv pip install --system`), one per line. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. Empty by default. Unlike tools-uv.txt, these
|
|
4
|
+
# land in the one shared system Python rather than an isolated venv, so
|
|
5
|
+
# they're importable by whatever runs inside the image — a CLI-only package
|
|
6
|
+
# with no importable module of its own belongs in tools-uv.txt instead.
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# langfuse
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Additional plugin marketplaces to add at build time, one per line.
|
|
2
|
+
# Blank lines and lines starting with '#' are ignored.
|
|
3
|
+
#
|
|
4
|
+
# Each line is passed as-is to `claude plugin marketplace add <source>`.
|
|
5
|
+
# Accepted forms of <source>:
|
|
6
|
+
# owner/repo GitHub shorthand
|
|
7
|
+
# owner/repo@branch-or-tag GitHub shorthand, pinned to a ref
|
|
8
|
+
# https://git-host/team/plugins.git Any git URL
|
|
9
|
+
# https://git-host/team/plugins.git#ref Git URL, pinned to a ref
|
|
10
|
+
# https://example.com/marketplace.json Raw marketplace.json URL
|
|
11
|
+
# /absolute/or/./relative/path Local filesystem path
|
|
12
|
+
#
|
|
13
|
+
# The official Anthropic marketplace (claude-plugins-official) is added
|
|
14
|
+
# automatically and must not be listed here.
|
|
15
|
+
#
|
|
16
|
+
# NOTE: the name used in plugins.txt as "<plugin>@<marketplace-name>" is
|
|
17
|
+
# whatever that marketplace's own .claude-plugin/marketplace.json declares as
|
|
18
|
+
# its "name" field -- it is NOT necessarily derived from the owner/repo slug
|
|
19
|
+
# or URL above. Check the marketplace's manifest (or its docs) to find the
|
|
20
|
+
# right suffix to use in plugins.txt.
|
|
21
|
+
#
|
|
22
|
+
# Example:
|
|
23
|
+
# my-org/my-claude-marketplace
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
clangd-lsp@claude-plugins-official
|
|
2
|
+
claude-md-management@claude-plugins-official
|
|
3
|
+
code-review@claude-plugins-official
|
|
4
|
+
gopls-lsp@claude-plugins-official
|
|
5
|
+
playground@claude-plugins-official
|
|
6
|
+
playwright@claude-plugins-official
|
|
7
|
+
pydantic-ai@claude-plugins-official
|
|
8
|
+
remember@claude-plugins-official
|
|
9
|
+
rust-analyzer-lsp@claude-plugins-official
|
|
10
|
+
security-guidance@claude-plugins-official
|
|
11
|
+
skill-creator@claude-plugins-official
|
|
12
|
+
superpowers@claude-plugins-official
|
|
13
|
+
typescript-lsp@claude-plugins-official
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Profile-specific CA certificates are injected into this directory by the onboarding CLI.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Optional Python CLI tools installed at build time (via `uv tool install`),
|
|
2
|
+
# one per line, each into its own isolated venv. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. Empty by default — there's no "everyone
|
|
4
|
+
# wants this" uv-installed CLI the way there is for apt utilities. A plain
|
|
5
|
+
# importable library (no console-script entry point of its own) belongs in
|
|
6
|
+
# packages-uv.txt instead.
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# ruff
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
FROM python:3.14-slim-trixie AS base
|
|
2
|
+
|
|
3
|
+
ARG TARGETARCH
|
|
4
|
+
|
|
5
|
+
# Shared Node.js, containment, gateway-client, and cloudflared baseline for
|
|
6
|
+
# the first-party Python-and-Node workload images.
|
|
7
|
+
COPY --from=shared install-workload-base.sh /usr/local/lib/agent/install-workload-base.sh
|
|
8
|
+
RUN TARGETARCH="$TARGETARCH" bash /usr/local/lib/agent/install-workload-base.sh
|
|
9
|
+
|
|
10
|
+
# Optional profile-managed organisational CAs; see claude-code/Dockerfile.
|
|
11
|
+
COPY proxy-ca.d/ /tmp/agent-containers-proxy-ca/
|
|
12
|
+
RUN set -eu; \
|
|
13
|
+
mkdir -p /usr/local/share/ca-certificates/custom; \
|
|
14
|
+
found=0; \
|
|
15
|
+
for cert in /tmp/agent-containers-proxy-ca/*; do \
|
|
16
|
+
[ -f "$cert" ] || continue; \
|
|
17
|
+
name="$(basename "$cert")"; \
|
|
18
|
+
[ "$name" = ".keep" ] && continue; \
|
|
19
|
+
case "$name" in *.crt) ;; *) name="${name%.*}.crt" ;; esac; \
|
|
20
|
+
cp "$cert" "/usr/local/share/ca-certificates/custom/$name"; \
|
|
21
|
+
found=1; \
|
|
22
|
+
done; \
|
|
23
|
+
if [ "$found" -eq 1 ]; then update-ca-certificates; fi; \
|
|
24
|
+
rm -rf /tmp/agent-containers-proxy-ca
|
|
25
|
+
|
|
26
|
+
COPY --from=shared install-additional-packages.sh /usr/local/lib/agent/install-additional-packages.sh
|
|
27
|
+
COPY packages-apt.txt /tmp/packages-apt.txt
|
|
28
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
29
|
+
&& install_apt_packages /tmp/packages-apt.txt' \
|
|
30
|
+
&& rm -f /tmp/packages-apt.txt
|
|
31
|
+
|
|
32
|
+
# Keep Python tooling available for Python-based MCP servers and project work,
|
|
33
|
+
# matching the other first-party CLI workload image.
|
|
34
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
|
|
35
|
+
|
|
36
|
+
# packages-uv.txt — general Python libraries (not CLI tools; see
|
|
37
|
+
# tools-uv.txt below), installed via `uv pip install --system` into this
|
|
38
|
+
# system Python. Runs as root, before the codex user exists, since it writes
|
|
39
|
+
# into the image's system site-packages rather than $HOME.
|
|
40
|
+
COPY packages-uv.txt /tmp/packages-uv.txt
|
|
41
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
42
|
+
&& install_uv_packages /tmp/packages-uv.txt' \
|
|
43
|
+
&& rm -f /tmp/packages-uv.txt
|
|
44
|
+
|
|
45
|
+
RUN npm install -g @openai/codex \
|
|
46
|
+
&& codex_path="$(command -v codex)" \
|
|
47
|
+
&& codex_target="$(readlink -f "$codex_path")" \
|
|
48
|
+
&& ln -s "$codex_target" /usr/local/bin/codex-cli \
|
|
49
|
+
&& rm -f "$codex_path"
|
|
50
|
+
|
|
51
|
+
COPY codex-wrapper.sh /usr/local/bin/codex
|
|
52
|
+
RUN chmod +x /usr/local/bin/codex
|
|
53
|
+
|
|
54
|
+
# The codex account is created here, at a fixed placeholder UID/GID
|
|
55
|
+
# (1000:1000), purely so the root-only installers below (npm, uv tool) have
|
|
56
|
+
# a real non-root account to run as. `final` remaps this account to the
|
|
57
|
+
# operator's actual host UID/GID instead of recreating it, so a rebuild for
|
|
58
|
+
# a different host user reuses everything installed below unchanged rather
|
|
59
|
+
# than reinstalling it over the network.
|
|
60
|
+
RUN groupadd -g 1000 codex \
|
|
61
|
+
&& useradd -m -u 1000 -g 1000 -s /bin/bash codex \
|
|
62
|
+
&& mkdir -p /home/codex/.codex /workspace \
|
|
63
|
+
&& chown -R codex:codex /home/codex /workspace
|
|
64
|
+
|
|
65
|
+
ENV HOME=/home/codex
|
|
66
|
+
ENV npm_config_prefix=/home/codex/.npm-global
|
|
67
|
+
# Home-managed installations intentionally precede profile-managed tools. The
|
|
68
|
+
# latter are image-owned under /opt so a populated home volume cannot hide a
|
|
69
|
+
# rebuilt profile image's requested versions.
|
|
70
|
+
ENV PATH="/home/codex/.local/bin:/home/codex/.npm-global/bin:/opt/agent-tools/bin:/opt/agent-tools/npm/bin:${PATH}"
|
|
71
|
+
|
|
72
|
+
# $HOME (uv's default cache location) and /workspace are deliberately
|
|
73
|
+
# separate mounts in this containment model, so uv's hardlink/reflink
|
|
74
|
+
# optimisation can never apply between them — declare the copy fallback
|
|
75
|
+
# explicit rather than have uv warn about it on every install.
|
|
76
|
+
ENV UV_LINK_MODE=copy
|
|
77
|
+
|
|
78
|
+
COPY packages-npm.txt /tmp/packages-npm.txt
|
|
79
|
+
COPY tools-uv.txt /tmp/tools-uv.txt
|
|
80
|
+
RUN mkdir -p /opt/agent-tools/npm /opt/agent-tools/uv-tools /opt/agent-tools/bin \
|
|
81
|
+
&& chown -R codex:codex /opt/agent-tools \
|
|
82
|
+
&& gosu codex env \
|
|
83
|
+
npm_config_prefix=/opt/agent-tools/npm \
|
|
84
|
+
UV_TOOL_DIR=/opt/agent-tools/uv-tools \
|
|
85
|
+
UV_TOOL_BIN_DIR=/opt/agent-tools/bin \
|
|
86
|
+
bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
87
|
+
&& install_npm_packages /tmp/packages-npm.txt \
|
|
88
|
+
&& install_uv_tools /tmp/tools-uv.txt' \
|
|
89
|
+
&& rm -f /tmp/packages-npm.txt /tmp/tools-uv.txt
|
|
90
|
+
|
|
91
|
+
COPY plugin-marketplaces.txt /tmp/plugin-marketplaces.txt
|
|
92
|
+
COPY plugins.txt /tmp/plugins.txt
|
|
93
|
+
RUN while IFS= read -r marketplace; do \
|
|
94
|
+
case "$marketplace" in ''|'#'*) continue ;; esac; \
|
|
95
|
+
gosu codex codex-cli plugin marketplace add "${marketplace}"; \
|
|
96
|
+
done < /tmp/plugin-marketplaces.txt \
|
|
97
|
+
&& while IFS= read -r plugin; do \
|
|
98
|
+
case "$plugin" in ''|'#'*) continue ;; esac; \
|
|
99
|
+
gosu codex codex-cli plugin add "${plugin}"; \
|
|
100
|
+
done < /tmp/plugins.txt \
|
|
101
|
+
&& rm -f /tmp/plugin-marketplaces.txt /tmp/plugins.txt
|
|
102
|
+
|
|
103
|
+
# Everything above this line is UID/GID-independent and layer-cacheable
|
|
104
|
+
# across hosts: the codex account exists at the fixed placeholder UID/GID
|
|
105
|
+
# only so the installers above have a non-root account to run as. From here
|
|
106
|
+
# down, `final` remaps that account to the operator's actual host UID/GID
|
|
107
|
+
# with --build-arg UID=$(id -u) --build-arg GID=$(id -g) — the base stage
|
|
108
|
+
# above is reused unchanged from cache, and nothing installed above is
|
|
109
|
+
# reinstalled, rather than rebuilding per host user.
|
|
110
|
+
FROM base AS final
|
|
111
|
+
ARG UID=1000
|
|
112
|
+
ARG GID=1000
|
|
113
|
+
|
|
114
|
+
# Only remap when the caller supplied a different UID/GID than the fixed
|
|
115
|
+
# placeholder baked into `base` above — usermod/groupmod plus a chown -R
|
|
116
|
+
# walk over already-installed content is far cheaper than rerunning the
|
|
117
|
+
# npm/uv-tool installs above, but it's skippable entirely for the common
|
|
118
|
+
# case where the caller never overrides UID/GID. Deliberately no -o:
|
|
119
|
+
# without it, usermod/groupmod refuse to reuse an ID already assigned to
|
|
120
|
+
# another account, so a caller can never remap codex onto UID/GID 0 (root)
|
|
121
|
+
# or collide it with another in-image identity — the build fails instead of
|
|
122
|
+
# silently succeeding.
|
|
123
|
+
RUN if [ "$UID" != "1000" ] || [ "$GID" != "1000" ]; then \
|
|
124
|
+
groupmod -g "$GID" codex \
|
|
125
|
+
&& usermod -u "$UID" -g "$GID" codex \
|
|
126
|
+
&& chown -R "$UID":"$GID" /home/codex /workspace /opt/agent-tools; \
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
COPY --from=shared egress-allowlist.sh /usr/local/lib/agent/egress-allowlist.sh
|
|
130
|
+
COPY --from=shared workload-entrypoint.sh /usr/local/lib/agent/workload-entrypoint.sh
|
|
131
|
+
RUN chmod +x /usr/local/lib/agent/workload-entrypoint.sh
|
|
132
|
+
|
|
133
|
+
# Strip setuid/setgid bits from the base image and every package installed
|
|
134
|
+
# above — required infra (install-workload-base.sh), packages-apt.txt,
|
|
135
|
+
# packages-npm.txt, packages-uv.txt, and tools-uv.txt — run last so nothing
|
|
136
|
+
# installed by any of those is missed. NoNewPrivs=1 (set by every documented
|
|
137
|
+
# run invocation) already makes these bits inert on execve, but that's an
|
|
138
|
+
# argument for stripping them, not against: if any single control ever
|
|
139
|
+
# regresses, a setuid-root `mount` becomes a live escalation primitive. None
|
|
140
|
+
# of these binaries are needed at runtime, so none should ship
|
|
141
|
+
# exploitable-shaped.
|
|
142
|
+
RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} + || true
|
|
143
|
+
|
|
144
|
+
WORKDIR /workspace
|
|
145
|
+
|
|
146
|
+
ENTRYPOINT ["/usr/local/lib/agent/workload-entrypoint.sh", "codex", "codex"]
|
|
147
|
+
CMD ["codex"]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
# The outer container provides the filesystem and process sandbox. Avoid
|
|
4
|
+
# starting Codex's nested sandbox, which cannot create its required namespaces
|
|
5
|
+
# under the container's deliberately restricted runtime security flags. Keep
|
|
6
|
+
# an explicit caller-selected sandbox mode intact.
|
|
7
|
+
for arg in "$@"; do
|
|
8
|
+
case "$arg" in
|
|
9
|
+
--sandbox|--sandbox=*|-s) exec /usr/local/bin/codex-cli "$@" ;;
|
|
10
|
+
esac
|
|
11
|
+
done
|
|
12
|
+
|
|
13
|
+
exec /usr/local/bin/codex-cli --sandbox danger-full-access "$@"
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Hosts/IPs the container is allowed to reach outbound, one per line.
|
|
2
|
+
# Blank lines and lines starting with '#' are ignored. Mount this file at
|
|
3
|
+
# /etc/agent/egress-allowlist.txt; it takes precedence over
|
|
4
|
+
# $AGENT_ALLOWED_EGRESS. If neither is set, outbound traffic is denied.
|
|
5
|
+
#
|
|
6
|
+
# The documented default supports ChatGPT-account authentication and the
|
|
7
|
+
# `codex_apps` MCP integration, both of which need all three hosts.
|
|
8
|
+
api.openai.com
|
|
9
|
+
auth.openai.com
|
|
10
|
+
chatgpt.com
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Optional Python libraries installed into the system Python at build time
|
|
2
|
+
# via `uv pip install --system`, one per line. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. Unlike tools-uv.txt, these land in the one
|
|
4
|
+
# shared system Python rather than an isolated venv, so they're importable
|
|
5
|
+
# by whatever runs inside the image — a CLI-only package with no importable
|
|
6
|
+
# module of its own belongs in tools-uv.txt instead.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Profile-specific CA certificates are injected into this directory by the onboarding CLI.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
# Optional Python CLI tools installed at build time via `uv tool install`,
|
|
2
|
+
# each into its own isolated venv, one per line. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. A plain importable library (no
|
|
4
|
+
# console-script entry point of its own) belongs in packages-uv.txt instead.
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
FROM nousresearch/hermes-agent:latest
|
|
2
|
+
|
|
3
|
+
ARG TARGETARCH
|
|
4
|
+
|
|
5
|
+
# iptables/ipset/dnsmasq/dnsutils enforce the in-container egress allowlist;
|
|
6
|
+
# openssh-client/sshuttle are the gateway-client tunnel (see entrypoint.sh);
|
|
7
|
+
# curl fetches cloudflared below. Upstream's own Node/Python/Playwright
|
|
8
|
+
# toolchain and its s6-overlay boot sequence are untouched by any of this —
|
|
9
|
+
# it only adds the network-containment layer claude-code also has.
|
|
10
|
+
RUN apt-get update \
|
|
11
|
+
&& apt-get upgrade -y \
|
|
12
|
+
&& apt-get install -y --no-install-recommends \
|
|
13
|
+
ca-certificates \
|
|
14
|
+
curl \
|
|
15
|
+
iptables \
|
|
16
|
+
ipset \
|
|
17
|
+
dnsmasq \
|
|
18
|
+
dnsutils \
|
|
19
|
+
openssh-client \
|
|
20
|
+
sshuttle \
|
|
21
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
22
|
+
|
|
23
|
+
# Optional profile-managed organisational CAs; see claude-code/Dockerfile.
|
|
24
|
+
COPY proxy-ca.d/ /tmp/agent-containers-proxy-ca/
|
|
25
|
+
RUN set -eu; \
|
|
26
|
+
mkdir -p /usr/local/share/ca-certificates/custom; \
|
|
27
|
+
found=0; \
|
|
28
|
+
for cert in /tmp/agent-containers-proxy-ca/*; do \
|
|
29
|
+
[ -f "$cert" ] || continue; \
|
|
30
|
+
name="$(basename "$cert")"; \
|
|
31
|
+
[ "$name" = ".keep" ] && continue; \
|
|
32
|
+
case "$name" in *.crt) ;; *) name="${name%.*}.crt" ;; esac; \
|
|
33
|
+
cp "$cert" "/usr/local/share/ca-certificates/custom/$name"; \
|
|
34
|
+
found=1; \
|
|
35
|
+
done; \
|
|
36
|
+
if [ "$found" -eq 1 ]; then update-ca-certificates; fi; \
|
|
37
|
+
rm -rf /tmp/agent-containers-proxy-ca
|
|
38
|
+
|
|
39
|
+
# User-configurable default software (gh, jq, ripgrep, ...) — see
|
|
40
|
+
# packages-apt.txt. Kept as a separate RUN from the baseline block above so
|
|
41
|
+
# the required-infra list stays untouched by editing that file.
|
|
42
|
+
COPY --from=shared install-additional-packages.sh /usr/local/lib/agent/install-additional-packages.sh
|
|
43
|
+
COPY packages-apt.txt /tmp/packages-apt.txt
|
|
44
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
45
|
+
&& install_apt_packages /tmp/packages-apt.txt' \
|
|
46
|
+
&& rm -f /tmp/packages-apt.txt
|
|
47
|
+
|
|
48
|
+
# packages-uv.txt — general Python libraries (not CLI tools; see
|
|
49
|
+
# tools-uv.txt below), installed via `uv pip install --system` into
|
|
50
|
+
# upstream's system Python (already on PATH in this base image — no
|
|
51
|
+
# separate uv/uvx COPY needed here, unlike claude-code). Runs as root, since
|
|
52
|
+
# it writes into the image's system site-packages rather than $HOME.
|
|
53
|
+
COPY packages-uv.txt /tmp/packages-uv.txt
|
|
54
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
55
|
+
&& install_uv_packages /tmp/packages-uv.txt' \
|
|
56
|
+
&& rm -f /tmp/packages-uv.txt
|
|
57
|
+
|
|
58
|
+
# Unlike claude-code, this image has no build-time privilege-drop tool
|
|
59
|
+
# installed (upstream's own runtime drop uses s6-setuidgid, not gosu) — `su`,
|
|
60
|
+
# already present in the base image, does the same job here without adding a
|
|
61
|
+
# new apt dependency. HOME/npm_config_prefix/PATH point at /opt/data
|
|
62
|
+
# (upstream's HERMES_HOME, already owned by the hermes user at this layer)
|
|
63
|
+
# so npm/uv installs below, and any further installs the hermes user makes
|
|
64
|
+
# at runtime, land there instead of under root's home or the read-only
|
|
65
|
+
# rootfs.
|
|
66
|
+
ENV HOME=/opt/data
|
|
67
|
+
ENV npm_config_prefix=/opt/data/.npm-global
|
|
68
|
+
# Home-managed installations intentionally precede profile-managed tools. The
|
|
69
|
+
# latter are image-owned under /opt so a populated data volume cannot hide a
|
|
70
|
+
# rebuilt profile image's requested versions.
|
|
71
|
+
ENV PATH="/opt/data/.local/bin:/opt/data/.npm-global/bin:/opt/agent-tools/bin:/opt/agent-tools/npm/bin:${PATH}"
|
|
72
|
+
|
|
73
|
+
# $HOME (uv's default cache location) and /workspace are deliberately
|
|
74
|
+
# separate mounts in this containment model, so uv's hardlink/reflink
|
|
75
|
+
# optimisation can never apply between them — declare the copy fallback
|
|
76
|
+
# explicit rather than have uv warn about it on every install.
|
|
77
|
+
ENV UV_LINK_MODE=copy
|
|
78
|
+
|
|
79
|
+
# packages-npm.txt / tools-uv.txt — see packages-apt.txt above. These managed
|
|
80
|
+
# tools are deliberately separate from /opt/data, the upstream persistent home.
|
|
81
|
+
COPY packages-npm.txt /tmp/packages-npm.txt
|
|
82
|
+
COPY tools-uv.txt /tmp/tools-uv.txt
|
|
83
|
+
RUN mkdir -p /opt/agent-tools/npm /opt/agent-tools/uv-tools /opt/agent-tools/bin \
|
|
84
|
+
&& chown -R hermes:hermes /opt/agent-tools \
|
|
85
|
+
&& su hermes -s /bin/bash -c 'export \
|
|
86
|
+
npm_config_prefix=/opt/agent-tools/npm \
|
|
87
|
+
UV_TOOL_DIR=/opt/agent-tools/uv-tools \
|
|
88
|
+
UV_TOOL_BIN_DIR=/opt/agent-tools/bin; \
|
|
89
|
+
. /usr/local/lib/agent/install-additional-packages.sh \
|
|
90
|
+
&& install_npm_packages /tmp/packages-npm.txt \
|
|
91
|
+
&& install_uv_tools /tmp/tools-uv.txt' \
|
|
92
|
+
&& rm -f /tmp/packages-npm.txt /tmp/tools-uv.txt
|
|
93
|
+
|
|
94
|
+
# cloudflared is always installed but only invoked (see entrypoint.sh) when
|
|
95
|
+
# AGENT_GATEWAY_ACCESS_HOSTNAME is set, as an alternative to reaching the
|
|
96
|
+
# gateway by direct TCP — TARGETARCH is supplied automatically by Buildx and
|
|
97
|
+
# matches cloudflared's own release-asset naming (amd64/arm64/386/...).
|
|
98
|
+
RUN curl -fsSL "https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-${TARGETARCH}" \
|
|
99
|
+
-o /usr/local/bin/cloudflared \
|
|
100
|
+
&& chmod +x /usr/local/bin/cloudflared
|
|
101
|
+
|
|
102
|
+
COPY --from=shared egress-allowlist.sh /usr/local/lib/agent/egress-allowlist.sh
|
|
103
|
+
|
|
104
|
+
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
|
|
105
|
+
RUN chmod +x /usr/local/bin/entrypoint.sh
|
|
106
|
+
|
|
107
|
+
# Strip setuid/setgid bits picked up from upstream's base image and the
|
|
108
|
+
# packages installed above (mount, passwd, su, ...). --security-opt
|
|
109
|
+
# no-new-privileges (every documented run invocation) already makes these
|
|
110
|
+
# inert on execve; stripping them removes the exploitable shape instead of
|
|
111
|
+
# relying solely on that flag never regressing. Safe after this point:
|
|
112
|
+
# upstream's runtime privilege drop is s6-setuidgid, which runs as root
|
|
113
|
+
# under the container's own granted CAP_SETUID/CAP_SETGID rather than
|
|
114
|
+
# through any setuid-bit binary.
|
|
115
|
+
RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} + || true
|
|
116
|
+
|
|
117
|
+
# No useradd/UID build-arg here (unlike claude-code): upstream already
|
|
118
|
+
# ships its own non-root user (hermes, UID 10000, home /opt/data) and its
|
|
119
|
+
# own privilege-drop chain; see entrypoint.sh. CMD is deliberately left at
|
|
120
|
+
# whatever upstream's own image sets it to, so every documented invocation
|
|
121
|
+
# shape keeps working unmodified.
|
|
122
|
+
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
if [ -n "${AGENT_GATEWAY_HOST:-}" ]; then
|
|
5
|
+
echo "[entrypoint] AGENT_GATEWAY_HOST=$AGENT_GATEWAY_HOST — tunneling all egress through the gateway." >&2
|
|
6
|
+
if [ -n "${AGENT_ALLOWED_EGRESS:-}" ] || [ -f /etc/agent/egress-allowlist.txt ]; then
|
|
7
|
+
echo "[entrypoint] AGENT_ALLOWED_EGRESS/egress-allowlist.txt are ignored in gateway mode — set the allowlist on the gateway container instead." >&2
|
|
8
|
+
fi
|
|
9
|
+
if [ -n "${AGENT_GATEWAY_BOOTSTRAP_ALLOW:-}" ]; then
|
|
10
|
+
echo "[entrypoint] Seeding a bootstrap allow rule for ${AGENT_GATEWAY_BOOTSTRAP_ALLOW} until the tunnel is up." >&2
|
|
11
|
+
iptables -P OUTPUT DROP
|
|
12
|
+
iptables -A OUTPUT -m addrtype --dst-type LOCAL -j ACCEPT
|
|
13
|
+
iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
14
|
+
ip6tables -P OUTPUT DROP
|
|
15
|
+
ip6tables -A OUTPUT -m addrtype --dst-type LOCAL -j ACCEPT
|
|
16
|
+
ip6tables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
|
|
17
|
+
IFS=',' read -ra BOOTSTRAP_ALLOW <<< "$AGENT_GATEWAY_BOOTSTRAP_ALLOW"
|
|
18
|
+
for addr in "${BOOTSTRAP_ALLOW[@]}"; do
|
|
19
|
+
if [[ "$addr" == *:* ]]; then
|
|
20
|
+
ip6tables -A OUTPUT -d "$addr" -j ACCEPT
|
|
21
|
+
else
|
|
22
|
+
iptables -A OUTPUT -d "$addr" -j ACCEPT
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
fi
|
|
26
|
+
install -m 600 /etc/agent/gateway-key /tmp/gateway-key
|
|
27
|
+
SSH_CMD="ssh -i /tmp/gateway-key -o StrictHostKeyChecking=yes -o UserKnownHostsFile=/etc/agent/gateway-known-hosts"
|
|
28
|
+
if [ -n "${AGENT_GATEWAY_ACCESS_HOSTNAME:-}" ]; then
|
|
29
|
+
echo "[entrypoint] Reaching the gateway via Cloudflare Access hostname ${AGENT_GATEWAY_ACCESS_HOSTNAME}." >&2
|
|
30
|
+
SSH_CMD="$SSH_CMD -o ProxyCommand='cloudflared access ssh --hostname ${AGENT_GATEWAY_ACCESS_HOSTNAME}'"
|
|
31
|
+
fi
|
|
32
|
+
sshuttle -r "${AGENT_GATEWAY_USER:-tunnel}@${AGENT_GATEWAY_HOST}:${AGENT_GATEWAY_PORT:-2222}" \
|
|
33
|
+
0.0.0.0/0 ::/0 --dns --daemon --pidfile=/tmp/sshuttle.pid \
|
|
34
|
+
-e "$SSH_CMD"
|
|
35
|
+
else
|
|
36
|
+
source /usr/local/lib/agent/egress-allowlist.sh
|
|
37
|
+
configure_egress_allowlist
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
# Root has done its network setup above; hand off to upstream's own boot
|
|
41
|
+
# sequence unmodified. /init runs the s6-rc service tree (including
|
|
42
|
+
# stage2-hook.sh, which chowns /opt/data to the hermes user on first boot —
|
|
43
|
+
# hence this image needing CAP_CHOWN under --cap-drop=ALL) and its own
|
|
44
|
+
# s6-setuidgid drop to the unprivileged hermes user, so no gosu/privilege
|
|
45
|
+
# drop is needed on our side. DAC_OVERRIDE is also required under
|
|
46
|
+
# --cap-drop=ALL: 02-reconcile-profiles registers the main-hermes/dashboard
|
|
47
|
+
# services after the static supervise trees are already chowned, so
|
|
48
|
+
# s6-supervise can't open their supervise/lock files without it.
|
|
49
|
+
exec /init /opt/hermes/docker/main-wrapper.sh "$@"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Default/optional apt packages installed at build time, one per line.
|
|
2
|
+
# Blank lines and lines starting with '#' are ignored. Edit freely and
|
|
3
|
+
# rebuild the image — this is separate from the Dockerfile's own
|
|
4
|
+
# required-infra apt list (iptables, dnsmasq, sshuttle, etc.), which this
|
|
5
|
+
# file cannot remove packages from.
|
|
6
|
+
gh
|
|
7
|
+
jq
|
|
8
|
+
ripgrep
|
|
9
|
+
fd-find
|
|
10
|
+
tree
|
|
11
|
+
unzip
|
|
12
|
+
less
|
|
13
|
+
file
|
|
14
|
+
lsof
|
|
15
|
+
yq
|
|
16
|
+
miller
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Optional global npm packages installed at build time (via `npm install -g`),
|
|
2
|
+
# one per line. Blank lines and lines starting with '#' are ignored. Empty by
|
|
3
|
+
# default — there's no "everyone wants this" global npm CLI the way there is
|
|
4
|
+
# for apt utilities.
|
|
5
|
+
#
|
|
6
|
+
# Example:
|
|
7
|
+
# @some-scope/some-cli
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Optional Python libraries installed into the system Python at build time
|
|
2
|
+
# (via `uv pip install --system`), one per line. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. Empty by default. Unlike tools-uv.txt, these
|
|
4
|
+
# land in the one shared system Python rather than an isolated venv, so
|
|
5
|
+
# they're importable by whatever runs inside the image — a CLI-only package
|
|
6
|
+
# with no importable module of its own belongs in tools-uv.txt instead.
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# langfuse
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Profile-specific CA certificates are injected into this directory by the onboarding CLI.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Optional Python CLI tools installed at build time (via `uv tool install`),
|
|
2
|
+
# one per line, each into its own isolated venv. Blank lines and lines
|
|
3
|
+
# starting with '#' are ignored. Empty by default — there's no "everyone
|
|
4
|
+
# wants this" uv-installed CLI the way there is for apt utilities. A plain
|
|
5
|
+
# importable library (no console-script entry point of its own) belongs in
|
|
6
|
+
# packages-uv.txt instead.
|
|
7
|
+
#
|
|
8
|
+
# Example:
|
|
9
|
+
# ruff
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
FROM python:3.14-slim-trixie AS base
|
|
2
|
+
|
|
3
|
+
ARG TARGETARCH
|
|
4
|
+
|
|
5
|
+
# Shared Node.js, containment, gateway-client, and cloudflared baseline for
|
|
6
|
+
# the first-party Python-and-Node workload images.
|
|
7
|
+
COPY --from=shared install-workload-base.sh /usr/local/lib/agent/install-workload-base.sh
|
|
8
|
+
RUN TARGETARCH="$TARGETARCH" bash /usr/local/lib/agent/install-workload-base.sh
|
|
9
|
+
|
|
10
|
+
COPY --from=shared install-additional-packages.sh /usr/local/lib/agent/install-additional-packages.sh
|
|
11
|
+
COPY packages-apt.txt /tmp/packages-apt.txt
|
|
12
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
13
|
+
&& install_apt_packages /tmp/packages-apt.txt' \
|
|
14
|
+
&& rm -f /tmp/packages-apt.txt
|
|
15
|
+
|
|
16
|
+
COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /usr/local/bin/
|
|
17
|
+
|
|
18
|
+
# packages-uv.txt — general Python libraries (not CLI tools; see
|
|
19
|
+
# tools-uv.txt below), installed via `uv pip install --system` into this
|
|
20
|
+
# system Python. Runs as root, before the kilo user exists, since it writes
|
|
21
|
+
# into the image's system site-packages rather than $HOME.
|
|
22
|
+
COPY packages-uv.txt /tmp/packages-uv.txt
|
|
23
|
+
RUN bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
24
|
+
&& install_uv_packages /tmp/packages-uv.txt' \
|
|
25
|
+
&& rm -f /tmp/packages-uv.txt
|
|
26
|
+
|
|
27
|
+
RUN npm install -g @kilocode/cli
|
|
28
|
+
|
|
29
|
+
# The kilo account is created here, at a fixed placeholder UID/GID
|
|
30
|
+
# (1000:1000), purely so the root-only installers below (npm, uv tool) have
|
|
31
|
+
# a real non-root account to run as. `final` remaps this account to the
|
|
32
|
+
# operator's actual host UID/GID instead of recreating it, so a rebuild for
|
|
33
|
+
# a different host user reuses everything installed below unchanged rather
|
|
34
|
+
# than reinstalling it over the network.
|
|
35
|
+
RUN groupadd -g 1000 kilo \
|
|
36
|
+
&& useradd -m -u 1000 -g 1000 -s /bin/bash kilo \
|
|
37
|
+
&& mkdir -p /home/kilo/.config/kilo /workspace \
|
|
38
|
+
&& chown -R kilo:kilo /home/kilo /workspace
|
|
39
|
+
|
|
40
|
+
ENV HOME=/home/kilo
|
|
41
|
+
ENV npm_config_prefix=/home/kilo/.npm-global
|
|
42
|
+
ENV PATH="/home/kilo/.local/bin:/home/kilo/.npm-global/bin:${PATH}"
|
|
43
|
+
|
|
44
|
+
# $HOME (uv's default cache location) and /workspace are deliberately
|
|
45
|
+
# separate mounts in this containment model, so uv's hardlink/reflink
|
|
46
|
+
# optimisation can never apply between them — declare the copy fallback
|
|
47
|
+
# explicit rather than have uv warn about it on every install.
|
|
48
|
+
ENV UV_LINK_MODE=copy
|
|
49
|
+
|
|
50
|
+
COPY packages-npm.txt /tmp/packages-npm.txt
|
|
51
|
+
COPY tools-uv.txt /tmp/tools-uv.txt
|
|
52
|
+
RUN gosu kilo bash -c '. /usr/local/lib/agent/install-additional-packages.sh \
|
|
53
|
+
&& install_npm_packages /tmp/packages-npm.txt \
|
|
54
|
+
&& install_uv_tools /tmp/tools-uv.txt' \
|
|
55
|
+
&& rm -f /tmp/packages-npm.txt /tmp/tools-uv.txt
|
|
56
|
+
|
|
57
|
+
# Everything above this line is UID/GID-independent and layer-cacheable
|
|
58
|
+
# across hosts: the kilo account exists at the fixed placeholder UID/GID
|
|
59
|
+
# only so the installers above have a non-root account to run as. From here
|
|
60
|
+
# down, `final` remaps that account to the operator's actual host UID/GID
|
|
61
|
+
# with --build-arg UID=$(id -u) --build-arg GID=$(id -g) — the base stage
|
|
62
|
+
# above is reused unchanged from cache, and nothing installed above is
|
|
63
|
+
# reinstalled, rather than rebuilding per host user.
|
|
64
|
+
FROM base AS final
|
|
65
|
+
ARG UID=1000
|
|
66
|
+
ARG GID=1000
|
|
67
|
+
|
|
68
|
+
# Only remap when the caller supplied a different UID/GID than the fixed
|
|
69
|
+
# placeholder baked into `base` above — usermod/groupmod plus a chown -R
|
|
70
|
+
# walk over already-installed content is far cheaper than rerunning the
|
|
71
|
+
# npm/uv-tool installs above, but it's skippable entirely for the common
|
|
72
|
+
# case where the caller never overrides UID/GID. Deliberately no -o:
|
|
73
|
+
# without it, usermod/groupmod refuse to reuse an ID already assigned to
|
|
74
|
+
# another account, so a caller can never remap kilo onto UID/GID 0 (root)
|
|
75
|
+
# or collide it with another in-image identity — the build fails instead of
|
|
76
|
+
# silently succeeding.
|
|
77
|
+
RUN if [ "$UID" != "1000" ] || [ "$GID" != "1000" ]; then \
|
|
78
|
+
groupmod -g "$GID" kilo \
|
|
79
|
+
&& usermod -u "$UID" -g "$GID" kilo \
|
|
80
|
+
&& chown -R "$UID":"$GID" /home/kilo /workspace; \
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
COPY --from=shared egress-allowlist.sh /usr/local/lib/agent/egress-allowlist.sh
|
|
84
|
+
COPY --from=shared workload-entrypoint.sh /usr/local/lib/agent/workload-entrypoint.sh
|
|
85
|
+
RUN chmod +x /usr/local/lib/agent/workload-entrypoint.sh
|
|
86
|
+
|
|
87
|
+
# Strip setuid/setgid bits from the base image and every package installed
|
|
88
|
+
# above — required infra (install-workload-base.sh), packages-apt.txt,
|
|
89
|
+
# packages-npm.txt, packages-uv.txt, and tools-uv.txt — run last so nothing
|
|
90
|
+
# installed by any of those is missed. NoNewPrivs=1 (set by every documented
|
|
91
|
+
# run invocation) already makes these bits inert on execve, but that's an
|
|
92
|
+
# argument for stripping them, not against: if any single control ever
|
|
93
|
+
# regresses, a setuid-root `mount` becomes a live escalation primitive. None
|
|
94
|
+
# of these binaries are needed at runtime, so none should ship
|
|
95
|
+
# exploitable-shaped.
|
|
96
|
+
RUN find / -xdev -perm /6000 -type f -exec chmod a-s {} + || true
|
|
97
|
+
|
|
98
|
+
WORKDIR /workspace
|
|
99
|
+
|
|
100
|
+
ENTRYPOINT ["/usr/local/lib/agent/workload-entrypoint.sh", "kilo", "kilo"]
|
|
101
|
+
CMD ["kilo"]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# One hostname or IP/CIDR per line. This file takes precedence over
|
|
2
|
+
# AGENT_ALLOWED_EGRESS when mounted at /etc/agent/egress-allowlist.txt.
|
|
3
|
+
#
|
|
4
|
+
# Kilo's hosted AI Gateway. Use this only when the Kilo gateway is the selected
|
|
5
|
+
# provider; add a configured direct provider, source-control host, MCP server,
|
|
6
|
+
# and package registry explicitly as needed.
|
|
7
|
+
api.kilo.ai
|