remote: deploy landrun alongside ollie-remote

The bootstrap script now also checks for and deploys the landrun
sandbox binary to ~/.cache/ollie/bin/landrun on the remote host.
Without this, ollie-remote couldn't sandbox tool execution.

Protocol extended: OLLIE_LOADER_START now includes need_landrun field.
Transfers are sequential: ollie-remote first, then landrun if needed.
Each binary has independent hash-based caching.
This commit is contained in:
Levi Neely 2026-07-31 11:13:38 +02:00
parent d597758909
commit c88ed95b94
2 changed files with 73 additions and 22 deletions

View File

@ -1,15 +1,27 @@
#!/bin/sh
# Bootstrap script for ollie-remote SSH deployment.
# Checks for cached binary by hash, downloads if needed, then execs.
# Checks for cached binaries by hash, downloads if needed, then execs.
main() {
set -e
#
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/ollie/bin"
CACHE_BIN="$CACHE_DIR/ollie-remote"
CACHE_HASH="$CACHE_DIR/ollie-remote.hash"
CACHE_LANDRUN="$CACHE_DIR/landrun"
CACHE_LANDRUN_HASH="$CACHE_DIR/landrun.hash"
#
if [ -x "$CACHE_BIN" ] && [ -f "$CACHE_HASH" ] && [ "$(cat "$CACHE_HASH")" = "@@HASH@@" ]; then
echo "OLLIE_LOADER_START {\"need_download\":false}" >&2
NEED_DOWNLOAD=false
NEED_LANDRUN=false
#
if ! [ -x "$CACHE_BIN" ] || ! [ -f "$CACHE_HASH" ] || [ "$(cat "$CACHE_HASH")" != "@@HASH@@" ]; then
NEED_DOWNLOAD=true
fi
if ! [ -x "$CACHE_LANDRUN" ] || ! [ -f "$CACHE_LANDRUN_HASH" ] || [ "$(cat "$CACHE_LANDRUN_HASH")" != "@@LANDRUN_HASH@@" ]; then
NEED_LANDRUN=true
fi
#
if [ "$NEED_DOWNLOAD" = "false" ] && [ "$NEED_LANDRUN" = "false" ]; then
echo "OLLIE_LOADER_START {\"need_download\":false,\"need_landrun\":false}" >&2
else
# Find base64 decoder
if command -v base64 >/dev/null 2>&1; then
@ -32,24 +44,41 @@ else
command -v gunzip >/dev/null 2>&1 || GUNZIP_CMD="gzip -d"
#
mkdir -p "$CACHE_DIR"
echo "OLLIE_LOADER_START {\"need_download\":true}" >&2
echo "OLLIE_LOADER_START {\"need_download\":$NEED_DOWNLOAD,\"need_landrun\":$NEED_LANDRUN}" >&2
#
# Read download size, then binary data
while IFS= read -r line; do
case "$line" in
OLLIE_DOWNLOAD\ *) BINARY_LENGTH="${line#OLLIE_DOWNLOAD }"; break ;;
esac
done
#
CACHE_TMP="$CACHE_BIN.tmp.$$"
if ! head -c "$BINARY_LENGTH" | $BASE64_CMD | $GUNZIP_CMD > "$CACHE_TMP"; then
rm -f "$CACHE_TMP"
echo "ERROR: binary transfer failed" >&2
exit 1
if [ "$NEED_DOWNLOAD" = "true" ]; then
while IFS= read -r line; do
case "$line" in
OLLIE_DOWNLOAD\ *) BINARY_LENGTH="${line#OLLIE_DOWNLOAD }"; break ;;
esac
done
CACHE_TMP="$CACHE_BIN.tmp.$$"
if ! head -c "$BINARY_LENGTH" | $BASE64_CMD | $GUNZIP_CMD > "$CACHE_TMP"; then
rm -f "$CACHE_TMP"
echo "ERROR: ollie-remote transfer failed" >&2
exit 1
fi
chmod +x "$CACHE_TMP"
mv "$CACHE_TMP" "$CACHE_BIN"
echo "@@HASH@@" > "$CACHE_HASH"
fi
#
if [ "$NEED_LANDRUN" = "true" ]; then
while IFS= read -r line; do
case "$line" in
OLLIE_DOWNLOAD\ *) BINARY_LENGTH="${line#OLLIE_DOWNLOAD }"; break ;;
esac
done
CACHE_TMP="$CACHE_LANDRUN.tmp.$$"
if ! head -c "$BINARY_LENGTH" | $BASE64_CMD | $GUNZIP_CMD > "$CACHE_TMP"; then
rm -f "$CACHE_TMP"
echo "ERROR: landrun transfer failed" >&2
exit 1
fi
chmod +x "$CACHE_TMP"
mv "$CACHE_TMP" "$CACHE_LANDRUN"
echo "@@LANDRUN_HASH@@" > "$CACHE_LANDRUN_HASH"
fi
chmod +x "$CACHE_TMP"
mv "$CACHE_TMP" "$CACHE_BIN"
echo "@@HASH@@" > "$CACHE_HASH"
echo "OLLIE_LOADER_READY" >&2
fi
#

View File

@ -77,9 +77,22 @@ func RemoteDial(ctx context.Context, cfg RemoteConfig) (*RemoteServer, error) {
hash := sha256.Sum256(binData)
hashStr := hex.EncodeToString(hash[:])
// Generate bootstrap script with hash and CWD baked in.
// Find landrun binary to deploy alongside ollie-remote.
landrunPath, err := exec.LookPath("landrun")
if err != nil {
return nil, fmt.Errorf("find landrun binary: %w", err)
}
landrunData, err := os.ReadFile(landrunPath)
if err != nil {
return nil, fmt.Errorf("read landrun binary: %w", err)
}
landrunHash := sha256.Sum256(landrunData)
landrunHashStr := hex.EncodeToString(landrunHash[:])
// Generate bootstrap script with hashes and CWD baked in.
bootstrap := bootstrapTemplate
bootstrap = strings.ReplaceAll(bootstrap, "@@HASH@@", hashStr)
bootstrap = strings.ReplaceAll(bootstrap, "@@LANDRUN_HASH@@", landrunHashStr)
cwdEscaped := shellEscape(cfg.CWD)
extraArgs := ""
if cfg.ToolsPath != "" {
@ -132,6 +145,7 @@ func RemoteDial(ctx context.Context, cfg RemoteConfig) (*RemoteServer, error) {
// Monitor stderr for bootstrap messages.
type loaderMsg struct {
NeedDownload bool `json:"need_download"`
NeedLandrun bool `json:"need_landrun"`
}
stderrScanner := bufio.NewScanner(stderrPipe)
@ -144,7 +158,7 @@ func RemoteDial(ctx context.Context, cfg RemoteConfig) (*RemoteServer, error) {
var msg loaderMsg
json.Unmarshal([]byte(after), &msg)
loaderCh <- msg
if !msg.NeedDownload {
if !msg.NeedDownload && !msg.NeedLandrun {
close(readyCh)
}
} else if line == "OLLIE_LOADER_READY" {
@ -159,8 +173,16 @@ func RemoteDial(ctx context.Context, cfg RemoteConfig) (*RemoteServer, error) {
if msg.NeedDownload {
if err := transferBinary(stdin, binData); err != nil {
cmd.Process.Kill()
return nil, fmt.Errorf("transfer binary: %w", err)
return nil, fmt.Errorf("transfer ollie-remote: %w", err)
}
}
if msg.NeedLandrun {
if err := transferBinary(stdin, landrunData); err != nil {
cmd.Process.Kill()
return nil, fmt.Errorf("transfer landrun: %w", err)
}
}
if msg.NeedDownload || msg.NeedLandrun {
// Wait for ready signal.
select {
case <-readyCh: