forked from letta-ai/letta-app-server-deployment
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDockerfile
More file actions
90 lines (83 loc) · 5.07 KB
/
Copy pathDockerfile
File metadata and controls
90 lines (83 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
FROM oven/bun:slim
# Install Letta Code
# git: required at runtime for memory sync
# python3: required at runtime for skills (e.g. Discord)
# curl/wget: common in tool and skill examples for fetching remote assets/APIs
# jq: common in API/debug examples for inspecting JSON responses
# nodejs: required by the installed letta CLI entrypoint
# npm: fallback package manager for channel runtime installs and remote shell use.
# It is installed with Bun below instead of Debian's npm package to avoid
# pulling a large extra dependency tree into the runtime image.
ENV BUN_INSTALL_GLOBAL_DIR=/opt/letta-code
# The CLI is installed with Bun into /opt, so path-based package-manager
# detection would otherwise fall back to npm. Prefer Bun for channel runtime
# installs while still shipping npm as a compatibility fallback.
ENV LETTA_PACKAGE_MANAGER="bun"
# The GitHub workflow keeps this file at the latest published npm version.
# Railway services connected to this repo can then auto-deploy from Git commits
# instead of staying pinned to the version baked into the first build.
ARG LETTA_CODE_VERSION=""
COPY letta-code-version.txt /tmp/letta-code-version.txt
RUN set -eux; \
apt-get update; \
apt-get install -y git python3 curl wget jq make g++ unzip; \
# Node 22 via NodeSource. Node 20 lacks webidl.markAsUncloneable, which the
# undici bundled in node-gyp@latest requires to compile node-pty (a native
# dependency of letta-code). On Node 20 the letta-code install fails with
# "webidl.util.markAsUncloneable is not a function".
curl -fsSL https://deb.nodesource.com/setup_22.x | bash -; \
apt-get install -y nodejs; \
version="${LETTA_CODE_VERSION:-$(cat /tmp/letta-code-version.txt)}"; \
bun install -g "@letta-ai/letta-code@${version}" "npm@10"; \
apt-get purge -y make g++; \
apt-get autoremove -y; \
rm -rf /var/lib/apt/lists/*
# Pinned CLI versions (bumped automatically by Renovate — see renovate.json).
# renovate: datasource=github-releases depName=supabase/cli
ARG SUPABASE_VERSION=2.108.0
# renovate: datasource=npm depName=vercel
ARG VERCEL_VERSION=54.18.2
# Agent toolchain: GitHub, Supabase, and Vercel CLIs baked into the image.
# Runtime installs (e.g. via brew) land on the ephemeral overlay and are wiped
# on every container restart; baking them here makes them durable and keeps the
# small /root volume free. Auth/secrets for these stay out of the image and are
# provided at runtime (Letta /secret or env vars).
RUN set -eux; \
# GitHub CLI (official apt repo)
curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
-o /usr/share/keyrings/githubcli-archive-keyring.gpg; \
chmod go+r /usr/share/keyrings/githubcli-archive-keyring.gpg; \
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
> /etc/apt/sources.list.d/github-cli.list; \
apt-get update; \
apt-get install -y gh; \
rm -rf /var/lib/apt/lists/*; \
# Supabase CLI (pinned release, SHA256-verified against the release checksums)
arch="$(dpkg --print-architecture)"; \
sb_base="https://github.com/supabase/cli/releases/download/v${SUPABASE_VERSION}"; \
sb_tar="supabase_${SUPABASE_VERSION}_linux_${arch}.tar.gz"; \
curl -fsSL -o "/tmp/${sb_tar}" "${sb_base}/${sb_tar}"; \
curl -fsSL -o /tmp/supabase_checksums.txt "${sb_base}/checksums.txt"; \
(cd /tmp && grep " ${sb_tar}\$" supabase_checksums.txt | sha256sum -c -); \
tar -xz -C /usr/local/bin -f "/tmp/${sb_tar}" supabase; \
rm -f "/tmp/${sb_tar}" /tmp/supabase_checksums.txt; \
# Vercel CLI (pinned, bun global -> same bin dir as letta, /usr/local/bin)
bun install -g "vercel@${VERCEL_VERSION}"; \
# Composio CLI. Its installer drops the binary + helper files in
# $HOME/.composio; redirect HOME to /opt so it lands OUTSIDE /root (the
# volume mounts at /root and would otherwise mask it), then symlink onto
# PATH. Runtime config/session still uses $HOME/.composio (=/root/.composio,
# on the volume) so a one-time `composio login` persists across restarts.
# NOTE: composio publishes no pinned binary URL; this curl|bash script is its
# only supported install. Accepted as a TLS-trusted source (same installer
# used on developer machines). Revisit if a versioned artifact is published.
HOME=/opt sh -c 'curl -fsSL https://composio.dev/install | bash'; \
ln -sf /opt/.composio/composio /usr/local/bin/composio; \
# sanity checks (fail the build if any CLI is missing from PATH)
gh --version; supabase --version; vercel --version; composio --version
ENV ENV_NAME="cloud"
ENV LETTA_RESTORE_ENABLED_CHANNELS="1"
# Run the agent's shell work from a volume-backed dir so files persist across
# restarts. The volume mounts at /root, masking any build-time dir, so the
# workspace is created at runtime. ~/.letta state already persists via /root.
CMD ["sh", "-c", "mkdir -p /root/workspace && cd /root/workspace && rm -rf /root/.letta/channels/*/auth/*/.session-lock 2>/dev/null; letta server --env-name \"$ENV_NAME\" --debug --channels whatsapp"]