@gjermundgaraba/clankerbox-rivet-sandbox-agent 0.19.0 → 0.20.0
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.
- package/dist/index.d.mts +7 -1
- package/dist/index.mjs +2 -2
- package/package.json +2 -2
- package/recipes/macos/setup.sh +7 -15
- package/recipes/ubuntu/setup.sh +31 -22
package/dist/index.d.mts
CHANGED
|
@@ -22,13 +22,19 @@ interface Options {
|
|
|
22
22
|
readonly namePrefix?: string | undefined;
|
|
23
23
|
/** The machine's own login user by default. */
|
|
24
24
|
readonly sshUser?: string | undefined;
|
|
25
|
+
/**
|
|
26
|
+
* The path of a public-key file, such as your `id_ed25519.pub`, whose keys the host installs for
|
|
27
|
+
* the login user after a profile's setup, as the client config's `authorizedKeys` does: the key
|
|
28
|
+
* the tunnel's ssh logs in with. A profile with a setup needs it.
|
|
29
|
+
*/
|
|
30
|
+
readonly authorizedKeys?: string | undefined;
|
|
25
31
|
/**
|
|
26
32
|
* Such as `["-i", "/path/to/key"]`. Neither these nor ssh config may fork the forward (`-f`,
|
|
27
33
|
* `-N`, `ForkAfterAuthentication`, `SessionType none`) or give it to a connection master (`-M`,
|
|
28
34
|
* `-S`): the tunnel ends with its ssh, and those would outlive it.
|
|
29
35
|
*/
|
|
30
36
|
readonly sshArguments?: ReadonlyArray<string> | undefined;
|
|
31
|
-
/** `/home/
|
|
37
|
+
/** `/home/user` by default, the login user's home, where the Ubuntu recipe runs the server. */
|
|
32
38
|
readonly cwd?: string | undefined;
|
|
33
39
|
}
|
|
34
40
|
/**
|
package/dist/index.mjs
CHANGED
|
@@ -198,7 +198,7 @@ const make = (options, ssh = "ssh") => {
|
|
|
198
198
|
machine: from.machine,
|
|
199
199
|
name: named
|
|
200
200
|
});
|
|
201
|
-
const { spec, host } = yield* specRequest("create", yield* loadProfile(from.profile), {});
|
|
201
|
+
const { spec, host } = yield* specRequest("create", yield* loadProfile(from.profile), { authorizedKeys: options.authorizedKeys });
|
|
202
202
|
const { machine } = yield* Prebuild.create(client, named, spec, {
|
|
203
203
|
host,
|
|
204
204
|
fresh: options.fresh
|
|
@@ -244,7 +244,7 @@ const provider = (options, layer, ssh) => {
|
|
|
244
244
|
const sandboxes = make(options, ssh);
|
|
245
245
|
return {
|
|
246
246
|
name,
|
|
247
|
-
defaultCwd: options.cwd ?? "/home/
|
|
247
|
+
defaultCwd: options.cwd ?? "/home/user",
|
|
248
248
|
create: () => runtime.runPromise(sandboxes.create),
|
|
249
249
|
destroy: (id) => runtime.runPromise(sandboxes.destroy(id)),
|
|
250
250
|
pause: (id) => runtime.runPromise(sandboxes.pause(id)),
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gjermundgaraba/clankerbox-rivet-sandbox-agent",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "clankerbox machines as sandboxes for Rivet's Sandbox Agent",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"access": "public"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@gjermundgaraba/clankerbox-sdk": "0.
|
|
28
|
+
"@gjermundgaraba/clankerbox-sdk": "0.20.0"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"@effect/platform-node": "4.0.5",
|
package/recipes/macos/setup.sh
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# A clankerbox setup that makes a macOS machine (Tart, a Cirrus base) a sandbox for Rivet's
|
|
3
|
-
# Sandbox Agent:
|
|
4
|
-
# a LaunchDaemon that runs the server on the guest's
|
|
5
|
-
# /etc/clankerbox/start that keeps it running. Give the provider
|
|
3
|
+
# Sandbox Agent: the Sandbox Agent's server and Claude Code under `admin`, the login user, for
|
|
4
|
+
# whom the host then installs your keys, a LaunchDaemon that runs the server on the guest's
|
|
5
|
+
# loopback, port 2468, and an /etc/clankerbox/start that keeps it running. Give the provider
|
|
6
|
+
# `cwd: "/Users/admin"`.
|
|
6
7
|
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
# where the agents it launches find their credentials.
|
|
8
|
+
# Name this directory, or a copy, as a profile's `setup.path`. An optional `agent.env` beside
|
|
9
|
+
# it, of `NAME=value` lines such as `ANTHROPIC_API_KEY=…`, becomes the server's environment,
|
|
10
|
+
# which is where the agents it launches find their credentials.
|
|
11
11
|
set -eu
|
|
12
12
|
PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
|
|
13
13
|
|
|
@@ -18,19 +18,11 @@ agent_sha256=58417cf5fa1e2dc417fc4a92d11840cc245ad599b87dd4c9a41686b05c36d877
|
|
|
18
18
|
node_version=22.23.3
|
|
19
19
|
node_sha256=23b25245dcfb9af7262f8ff142e9e2e0af025368117329e7a7458a51e5922f53
|
|
20
20
|
|
|
21
|
-
if [ ! -s authorized_keys ]; then
|
|
22
|
-
echo "this recipe needs an authorized_keys file beside setup.sh, holding your public key"
|
|
23
|
-
exit 1
|
|
24
|
-
fi
|
|
25
|
-
|
|
26
21
|
# Softnet blocks the gateway's DNS, so public resolvers come first.
|
|
27
22
|
networksetup -listallnetworkservices | tail -n +2 | sed 's/^\*//' | while IFS= read -r service; do
|
|
28
23
|
networksetup -setdnsservers "$service" 1.1.1.1 9.9.9.9
|
|
29
24
|
done
|
|
30
25
|
|
|
31
|
-
install -d -m 700 -o admin -g staff /Users/admin/.ssh
|
|
32
|
-
install -m 600 -o admin -g staff authorized_keys /Users/admin/.ssh/authorized_keys
|
|
33
|
-
|
|
34
26
|
# Downloads $1 to $3 and refuses it unless its sha256 is $2.
|
|
35
27
|
fetch() {
|
|
36
28
|
curl -fsSL "$1" -o "$3"
|
package/recipes/ubuntu/setup.sh
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/bin/sh
|
|
2
2
|
# A clankerbox setup that makes an x86_64 Ubuntu machine a sandbox for Rivet's Sandbox Agent:
|
|
3
|
-
#
|
|
4
|
-
#
|
|
3
|
+
# the login user `user` with passwordless sudo, for whom the host then installs your keys, sshd
|
|
4
|
+
# with root's login off where this recipe installs it, the Sandbox Agent's server and Claude Code
|
|
5
|
+
# under `user`, and an /etc/clankerbox/start that keeps the server running on the guest's
|
|
6
|
+
# loopback, port 2468.
|
|
5
7
|
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
9
|
-
# where the agents it launches find their credentials.
|
|
8
|
+
# Name this directory, or a copy, as a profile's `setup.path`. An optional `agent.env` beside
|
|
9
|
+
# it, of `NAME=value` lines such as `ANTHROPIC_API_KEY=…`, becomes the server's environment,
|
|
10
|
+
# which is where the agents it launches find their credentials.
|
|
10
11
|
set -eu
|
|
11
12
|
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
|
|
12
13
|
export DEBIAN_FRONTEND=noninteractive
|
|
@@ -19,17 +20,27 @@ agent_sha256=5ebefccb130cccb0aa7972eacc8ff7c55550b959b2dd682a232a21a5712d955e
|
|
|
19
20
|
node_version=22.23.3
|
|
20
21
|
node_sha256=df450af89261115ef9f9e3830c3eeb2cc9213b63c720b1af623cb5dcbe2e02de
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
exit 1
|
|
25
|
-
fi
|
|
23
|
+
# A base with its own sshd, such as boat's, keeps it as it is.
|
|
24
|
+
if [ -x /usr/sbin/sshd ]; then own_sshd=false; else own_sshd=true; fi
|
|
26
25
|
|
|
27
26
|
apt-get update -qq
|
|
28
27
|
apt-get install -y -qq --no-install-recommends \
|
|
29
|
-
openssh-server curl ca-certificates xz-utils procps >/dev/null
|
|
28
|
+
openssh-server sudo curl ca-certificates xz-utils procps >/dev/null
|
|
30
29
|
|
|
31
|
-
|
|
32
|
-
install -
|
|
30
|
+
if [ "$own_sshd" = true ]; then
|
|
31
|
+
install -d /etc/ssh/sshd_config.d
|
|
32
|
+
echo "PermitRootLogin no" >/etc/ssh/sshd_config.d/10-clankerbox.conf
|
|
33
|
+
fi
|
|
34
|
+
|
|
35
|
+
# The login user, which boat's bases already have.
|
|
36
|
+
if ! id user >/dev/null 2>&1; then
|
|
37
|
+
useradd -m -s /bin/bash user
|
|
38
|
+
fi
|
|
39
|
+
|
|
40
|
+
echo "user ALL=(ALL) NOPASSWD: ALL" >/var/tmp/sudoers-user
|
|
41
|
+
visudo -cf /var/tmp/sudoers-user >/dev/null
|
|
42
|
+
install -m 440 /var/tmp/sudoers-user /etc/sudoers.d/user
|
|
43
|
+
rm /var/tmp/sudoers-user
|
|
33
44
|
|
|
34
45
|
# Downloads $1 to $3 and refuses it unless its sha256 is $2.
|
|
35
46
|
fetch() {
|
|
@@ -47,18 +58,16 @@ fetch "https://nodejs.org/dist/v$node_version/node-v$node_version-linux-x64.tar.
|
|
|
47
58
|
tar -xJf /var/tmp/node.tar.xz -C /usr/local --strip-components=1 --no-same-owner
|
|
48
59
|
rm /var/tmp/node.tar.xz
|
|
49
60
|
|
|
50
|
-
# The agents run as
|
|
51
|
-
useradd -m -s /bin/bash sandbox
|
|
52
|
-
|
|
61
|
+
# The agents run as `user`: as root, Claude Code offers no bypass-permissions mode.
|
|
53
62
|
if [ -s agent.env ]; then
|
|
54
|
-
install -m 600 -o
|
|
63
|
+
install -m 600 -o user -g "$(id -gn user)" agent.env /etc/sandbox-agent.env
|
|
55
64
|
fi
|
|
56
65
|
|
|
57
66
|
# Claude Code at its latest release, and its adapter at the version the server pins. Other
|
|
58
67
|
# agents install the same way; `install-agent codex` hangs in its own check at this version, so
|
|
59
68
|
# give it a timeout too, and end what it leaves running. Claude's install takes about 30 s; 300 s
|
|
60
69
|
# leaves room for a slow mirror.
|
|
61
|
-
timeout 300 su -
|
|
70
|
+
timeout 300 su - user -c 'sandbox-agent install-agent claude' >/var/tmp/install-agent.log 2>&1 || {
|
|
62
71
|
tail -n 15 /var/tmp/install-agent.log
|
|
63
72
|
exit 1
|
|
64
73
|
}
|
|
@@ -94,17 +103,17 @@ answers_within() {
|
|
|
94
103
|
}
|
|
95
104
|
|
|
96
105
|
running() {
|
|
97
|
-
pgrep -u
|
|
106
|
+
pgrep -u user -f 'sandbox-agent server' >/dev/null
|
|
98
107
|
}
|
|
99
108
|
|
|
100
109
|
# A running server gets 10 s to answer, since this runs at every start, a running machine's too,
|
|
101
110
|
# before it is ended as hung: TERM, then KILL after 5 s, as a hung one may ignore TERM.
|
|
102
111
|
if running && ! answers_within 10; then
|
|
103
|
-
pkill -u
|
|
112
|
+
pkill -u user -f 'sandbox-agent server' || true
|
|
104
113
|
for tries in $(seq 40); do
|
|
105
114
|
running || break
|
|
106
115
|
if [ "$tries" -eq 20 ]; then
|
|
107
|
-
pkill -KILL -u
|
|
116
|
+
pkill -KILL -u user -f 'sandbox-agent server' || true
|
|
108
117
|
fi
|
|
109
118
|
sleep 0.25
|
|
110
119
|
done
|
|
@@ -112,7 +121,7 @@ fi
|
|
|
112
121
|
|
|
113
122
|
# The server listens on loopback alone, with no token: guest port 22 is the only way to it.
|
|
114
123
|
if ! running; then
|
|
115
|
-
su -
|
|
124
|
+
su - user -c '
|
|
116
125
|
if [ -r /etc/sandbox-agent.env ]; then set -a; . /etc/sandbox-agent.env; set +a; fi
|
|
117
126
|
setsid -f sandbox-agent server --no-token --no-telemetry >/dev/null 2>&1
|
|
118
127
|
'
|