---
title: Deploy a Letta server with Docker | Letta Docs
description: Manage your own Letta server using Docker
---

The Docker image is no longer an actively maintained or supported Letta product surface. If you want to use local models or OpenAI-compatible local providers, use [Letta Code local mode](/letta-code/local-mode/index.md) instead.

## Prerequisites

To install Docker, see [Docker’s installation guide](https://docs.docker.com/get-docker/). For issues with installing Docker, see [Docker’s troubleshooting guide](https://docs.docker.com/desktop/troubleshoot-and-support/troubleshoot/).

## Running the Letta API proxy server

To run the Letta API proxy server with Docker, run the command:

Terminal window

```
# replace `~/.letta/.persist/pgdata` with wherever you want to store your agent data
docker run \
  -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
  -p 8283:8283 \
  -e OPENAI_API_KEY="your_openai_api_key" \
  letta/letta:latest
```

This will run the Letta API server with the OpenAI provider enabled, and store all data in the folder `~/.letta/.persist/pgdata`. If you have many different LLM API keys, you can also set up a `.env` file instead and pass that to `docker run`:

Terminal window

```
# using a .env file instead of passing environment variables
docker run \
  -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
  -p 8283:8283 \
  --env-file .env \
  letta/letta:latest
```

Once the server is running, you can access it via port `8283` (e.g. sending REST API requests to `http://localhost:8283/v1`).

## Enabling additional model providers

Trying to combine Docker with Letta Code?

Although Letta Code can technically be run with any open weights model (e.g. via Ollama), it is a very demanding agent harness, and you are unlikely to get good performance with most open weights models outside of the very best ones (e.g. GLM-4.7, MiniMax M2.1).

We strongly recommend new Letta Code users first experiment with frontier models (e.g. Claude Opus 4.5 or GPT-5.2) to understand Letta Code’s capabilities before experimenting with open weights models.

The Letta server can be connected to various LLM API backends ([OpenAI](https://docs.letta.com/models/openai), [Anthropic](https://docs.letta.com/models/anthropic), [Ollama](https://docs.letta.com/models/ollama), etc.). To enable access to these LLM API providers, set the appropriate environment variables when you use `docker run`:

Terminal window

```
# replace `~/.letta/.persist/pgdata` with wherever you want to store your agent data
docker run \
  -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
  -p 8283:8283 \
  -e OPENAI_API_KEY="your_openai_api_key" \
  -e ANTHROPIC_API_KEY="your_anthropic_api_key" \
  -e OLLAMA_BASE_URL="http://host.docker.internal:11434/v1" \
  letta/letta:latest
```

**Linux users:** Use `--network host` and `localhost` instead of `host.docker.internal`: `sh docker run \ -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \ --network host \ -e OPENAI_API_KEY="your_openai_api_key" \ -e ANTHROPIC_API_KEY="your_anthropic_api_key" \ -e OLLAMA_BASE_URL="http://localhost:11434/v1" \ letta/letta:latest`

The example above will make all compatible models running on OpenAI, Anthropic, and Ollama available to your Letta server.

## Configuring embedding models

When using Docker, you **must** specify an embedding model when creating agents. Letta uses embeddings for archival memory search and retrieval.

### Supported embedding providers

When creating agents on your Docker server, specify the `embedding` parameter:

- [Python](#tab-panel-257)
- [TypeScript](#tab-panel-258)

```
from letta_client import Letta
import os


# Connect to your Docker server
client = Letta(base_url="http://localhost:8283")


# Create agent with explicit embedding configuration
agent = client.agents.create(
  model="openai/gpt-4o-mini",
  embedding="openai/text-embedding-3-small", # Required when using Docker
)
```

```
import Letta from "@letta-ai/letta-client";


// Connect to your Docker server
const client = new Letta({
  baseURL: "http://localhost:8283",
});


// Create agent with explicit embedding configuration
const agent = await client.agents.create({
  model: "openai/gpt-4o-mini",
  embedding: "openai/text-embedding-3-small", // Required when using Docker
});
```

**Letta API difference:** When using the Letta API, the `embedding` parameter is optional and managed automatically. Docker servers require explicit embedding configuration.

## Password protection

When running a Letta server in Docker in a production environment (i.e. with untrusted users), make sure to enable both password protection (to prevent unauthorized access to your server over the network) and tool sandboxing (to prevent malicious tools from executing in a privileged environment).

To password protect your server, include `SECURE=true` and `LETTA_SERVER_PASSWORD=yourpassword` in your `docker run` command:

Terminal window

```
# If LETTA_SERVER_PASSWORD isn't set, the server will autogenerate a password
docker run \
  -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
  -p 8283:8283 \
  --env-file .env \
  -e SECURE=true \
  -e LETTA_SERVER_PASSWORD=yourpassword \
  letta/letta:latest
```

With password protection enabled, you will have to provide your password in the bearer token header in your API requests:

- [TypeScript](#tab-panel-259)
- [Python](#tab-panel-260)
- [curl](#tab-panel-261)

```
// install letta-client with `npm install @letta-ai/letta-client`
import Letta from "@letta-ai/letta-client";


// create the client with the token set to your password
const client = new Letta({
  baseURL: "http://localhost:8283",
  apiKey: "yourpassword",
});
```

```
# install letta_client with `pip install letta-client`
from letta_client import Letta
import os


# create the client with the token set to your password
client = Letta(
  base_url="http://localhost:8283",
  api_key="yourpassword"
)
```

Terminal window

```
curl --request POST \
  --url http://localhost:8283/v1/agents/$AGENT_ID/messages \
  --header 'Content-Type: application/json' \
  --header 'Authorization: Bearer yourpassword' \
  --data '{
  "messages": [
    {
      "role": "user",
      "text": "hows it going????"
    }
  ]
}'
```

## Tool sandboxing

To enable tool sandboxing, set the `E2B_API_KEY` and `E2B_SANDBOX_TEMPLATE_ID` environment variables (via [E2B](https://e2b.dev/)) when you use `docker run`. When sandboxing is enabled, all custom tools (created by users from source code) will be executed in a sandboxed environment. This does not include MCP tools, which are executed outside of the Letta server (on the MCP server itself), or built-in tools (like `memory_insert`), whose code cannot be modified after server startup.

## Connecting your own Postgres instance

You can set `LETTA_PG_URI` to connect your own Postgres instance to Letta. Your database must have the `pgvector` vector extension installed.

You can enable this extension by running the following SQL command:

```
CREATE EXTENSION IF NOT EXISTS vector;
```

## Configuring MemFS

To enable MemFS (the git-backed memory filesystem) on your Docker server, set `LETTA_MEMFS_SERVICE_URL=local`:

Terminal window

```
docker run \
  -v ~/.letta/.persist/pgdata:/var/lib/postgresql/data \
  -p 8283:8283 \
  -e LETTA_MEMFS_SERVICE_URL=local \
  -e OPENAI_API_KEY="your_key" \
  letta/letta:latest
```

The `local` value is a sentinel that tells the server to use local filesystem storage for memory repositories instead of a remote memfs sidecar service. Memory repos are stored at `/root/.letta/memfs` inside the container.

When MemFS initializes successfully, you’ll see this in the server logs:

```
Memory repo manager using local filesystem storage
```

If you see `"Memory repo manager not configured"` instead, the environment variable is not reaching the server process.

MemFS is opt-in per agent. To enable it, add the `git-memory-enabled` tag when creating an agent. If you’re connecting [Letta Code](/letta-code/index.md) to your local server, set `LETTA_MEMFS_LOCAL=1` to enable MemFS during agent creation.

### Local mode vs full git sync

With `LETTA_MEMFS_SERVICE_URL=local`, MemFS operates at the API level: agents can read, write, and patch memory blocks through the Letta server. This is sufficient for agents using the memory block tools (`memory`, `memory_apply_patch`, etc.).

However, Letta Code’s full MemFS experience also relies on git HTTP transport. When an agent has MemFS enabled, Letta Code clones the memory repo locally so the agent can edit memory files directly via bash and commit/push changes. In local mode, the git HTTP proxy endpoint returns 501, so this clone/push/pull flow is unavailable.

If you need full git sync, you can run a sidecar that implements the git smart HTTP protocol and set `LETTA_MEMFS_SERVICE_URL` to its URL (e.g. `http://localhost:8285`). The sidecar receives proxied requests from the Letta server’s `/v1/git/` endpoint and serves bare git repos from your local filesystem using Git’s built-in `git http-backend` CGI handler. A community example of this approach is [local\_letta\_memfs\_magic](https://github.com/Corykidios/local_letta_memfs_magic).

The git sidecar approach is not officially supported. It requires a compatible Git installation and may need adjustments as the MemFS protocol evolves.

## Connecting the ADE to your server

The Agent Development Environment (ADE) can only connect to remote servers running on `https`.

The ADE is only able to connect to remote servers running on `https` - the only exception is `localhost`, for which `http` is allowed (except for Safari and newer versions of Chrome, where it is also blocked).

Most cloud services have ingress tools that will handle certificate management for you and you will automatically be provisioned an `https` address (for example Railway will automatically generate a static `https` address for your deployment).

### Using a reverse proxy to generate an `https` address

If you are running your Letta server on self-hosted infrastructure, you may need to manually create an `https` address for your server. This can be done in numerous ways using reverse proxies:

1. Use a service like [ngrok](https://ngrok.com/) to get an `https` address (on ngrok) for your server
2. Use [Caddy](https://github.com/caddyserver/caddy) or [Traefik](https://github.com/traefik/traefik) as a reverse proxy (which will manage the certificates for you)
3. Use [nginx](https://nginx.org/) with [Let’s Encrypt](https://letsencrypt.org/) as a reverse proxy (manage the certificates yourself)

### Port forwarding to localhost

Alternatively, you can also forward your server’s `http` address to `localhost`, since the `https` restriction does not apply to `localhost` (on browsers other than Safari):

Terminal window

```
ssh -L 8283:localhost:8283 your_server_username@your_server_ip
```

If you use the port forwarding approach, then you will not need to “Add remote server” in the ADE, instead the server will be accessible under “Local server”.
