Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Running Moltis in Docker

Moltis is available as a multi-architecture Docker image supporting both linux/amd64 and linux/arm64. The image is published to GitHub Container Registry on every release.

Quick Start

docker run -d \
  --name moltis \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -v moltis-config:/home/moltis/.config/moltis \
  -v moltis-data:/home/moltis/.moltis \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

Open https://localhost:13131 in your browser and configure your LLM provider to start chatting.

For unattended bootstraps, add MOLTIS_PASSWORD, MOLTIS_PROVIDER, and MOLTIS_API_KEY before first start. That pre-configures auth plus one LLM provider so you can skip the browser setup wizard entirely.

Ports

PortPurpose
13131Gateway (HTTPS) — web UI, API, WebSocket
13132HTTP — CA certificate download for TLS trust
1455OAuth callback — required for OpenAI Codex and other providers with pre-registered redirect URIs

Trusting the TLS certificate

Moltis generates a self-signed CA on first run. Browsers will show a security warning until you trust this CA. Port 13132 serves the certificate over plain HTTP so you can download it:

# Download the CA certificate
curl -o moltis-ca.pem http://localhost:13132/certs/ca.pem

# macOS — add to system Keychain and trust it
sudo security add-trusted-cert -d -r trustRoot \
  -k /Library/Keychains/System.keychain moltis-ca.pem

# Linux (Debian/Ubuntu)
sudo cp moltis-ca.pem /usr/local/share/ca-certificates/moltis-ca.crt
sudo update-ca-certificates

After trusting the CA, restart your browser. The warning will not appear again (the CA persists in the mounted config volume).

Note

When accessing from localhost, no authentication is required. If you access Moltis from a different machine (e.g., over the network), a setup code is printed to the container logs for authentication setup:

docker logs moltis

Volume Mounts

Moltis uses two directories that should be persisted:

PathContents
/home/moltis/.config/moltisConfiguration files: moltis.toml, credentials.json, mcp-servers.json
/home/moltis/.moltisRuntime data: databases, sessions, memory files, logs

You can use named volumes (as shown above) or bind mounts to local directories for easier access to configuration files:

docker run -d \
  --name moltis \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -v ./config:/home/moltis/.config/moltis \
  -v ./data:/home/moltis/.moltis \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

With bind mounts, you can edit config/moltis.toml directly on the host.

Docker Socket (Sandbox Execution)

Moltis runs LLM-generated shell commands inside isolated containers for security. When Moltis itself runs in a container, it needs access to the host’s container runtime to create these sandbox containers.

# Recommended for full container isolation
-v /var/run/docker.sock:/var/run/docker.sock

Without the socket mount, Moltis automatically falls back to the restricted-host sandbox, which provides lightweight isolation by clearing environment variables, restricting PATH, and applying resource limits via ulimit. Commands will execute successfully inside the Moltis container but without filesystem or network isolation.

For full container-level isolation (filesystem boundaries, network policies), mount the Docker socket.

If Moltis is itself running in Docker and your data_dir() mount is backed by a different host path than /home/moltis/.moltis, Moltis will try to discover that host path automatically from docker inspect/podman inspect. If that lookup fails, add this to /home/moltis/.config/moltis/moltis.toml inside the container:

[tools.exec.sandbox]
host_data_dir = "/absolute/host/path/to/data"

For a bind mount like -v ./data:/home/moltis/.moltis, use the resolved host path to ./data. Restart Moltis after changing the config so new sandbox containers pick up the corrected mount source.

Security Consideration

Mounting the Docker socket gives the container full access to the Docker daemon. This is equivalent to root access on the host for practical purposes. Only run Moltis containers from trusted sources (official images from ghcr.io/moltis-org/moltis).

Docker Compose

See examples/docker-compose.yml for a complete example:

services:
  moltis:
    image: ghcr.io/moltis-org/moltis:latest
    container_name: moltis
    restart: unless-stopped
    ports:
      - "13131:13131"
      - "13132:13132"
      - "1455:1455"   # OAuth callback (OpenAI Codex, etc.)
    volumes:
      - ./config:/home/moltis/.config/moltis
      - ./data:/home/moltis/.moltis
      - /var/run/docker.sock:/var/run/docker.sock

Coolify (Hetzner/VPS)

For Coolify service stacks, use examples/docker-compose.coolify.yml. It is preconfigured for reverse-proxy deployments (--no-tls) and includes the Docker socket mount for sandboxed command execution.

Key points:

  • Set MOLTIS_PASSWORD in the Coolify UI before first deploy.
  • Set SERVICE_FQDN_MOLTIS_13131 to your app domain.
  • Keep Moltis in --no-tls mode behind Coolify’s reverse proxy. If requests are redirected to :13131, check that TLS is disabled in Moltis.
  • Keep /var/run/docker.sock:/var/run/docker.sock mounted if you want sandbox isolation for exec tools.

Start with:

docker compose up -d
docker compose logs -f moltis  # watch for startup messages

Browser Sandbox in Docker

When Moltis runs inside Docker and launches a sandboxed browser, the browser container is a sibling container on the host. By default, Moltis connects to 127.0.0.1 which only reaches its own loopback, not the browser.

Add container_host to your moltis.toml so Moltis can reach the browser container through the host’s port mapping:

[tools.browser]
container_host = "host.docker.internal"

On Linux, add --add-host to the Moltis container so host.docker.internal resolves to the host:

docker run -d \
  --name moltis \
  --add-host=host.docker.internal:host-gateway \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -v moltis-config:/home/moltis/.config/moltis \
  -v moltis-data:/home/moltis/.moltis \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

Alternatively, use the Docker bridge gateway IP directly (container_host = "172.17.0.1" on most Linux setups).

Podman Support

Moltis works with Podman using its Docker-compatible API. Mount the Podman socket instead of the Docker socket:

# Podman rootless
podman run -d \
  --name moltis \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -v moltis-config:/home/moltis/.config/moltis \
  -v moltis-data:/home/moltis/.moltis \
  -v /run/user/$(id -u)/podman/podman.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

# Podman rootful
podman run -d \
  --name moltis \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -v moltis-config:/home/moltis/.config/moltis \
  -v moltis-data:/home/moltis/.moltis \
  -v /run/podman/podman.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

You may need to enable the Podman socket service first:

# Rootless
systemctl --user enable --now podman.socket

# Rootful
sudo systemctl enable --now podman.socket

Environment Variables

VariableDescription
MOLTIS_CONFIG_DIROverride config directory (default: ~/.config/moltis)
MOLTIS_DATA_DIROverride data directory (default: ~/.moltis)

Example:

docker run -d \
  --name moltis \
  -p 13131:13131 \
  -p 13132:13132 \
  -p 1455:1455 \
  -e MOLTIS_CONFIG_DIR=/config \
  -e MOLTIS_DATA_DIR=/data \
  -v ./config:/config \
  -v ./data:/data \
  -v /var/run/docker.sock:/var/run/docker.sock \
  ghcr.io/moltis-org/moltis:latest

API Keys and the [env] Section

Features like web search (Brave), embeddings, and LLM provider API calls read keys from process environment variables (std::env::var). In Docker, there are three ways to provide these:

Option 1: Generic first-run LLM bootstrap (best for one provider)

Use this when you want a minimal docker compose file with one chat provider and no manual setup:

services:
  moltis:
    image: ghcr.io/moltis-org/moltis:latest
    environment:
      MOLTIS_PASSWORD: "change-me"
      MOLTIS_PROVIDER: "openai"
      MOLTIS_API_KEY: "sk-..."

MOLTIS_PROVIDER must be a Moltis provider name such as openai, anthropic, gemini, groq, openrouter, or mistral. The shorter aliases PROVIDER and API_KEY also work, but the MOLTIS_* names are preferred because they are less likely to collide with other containers.

Option 2: Provider-specific docker -e flags (takes precedence for that provider)

docker run -d \
  --name moltis \
  -e BRAVE_API_KEY=your-key \
  -e OPENROUTER_API_KEY=sk-or-... \
  ...
  ghcr.io/moltis-org/moltis:latest

Option 3: [env] section in moltis.toml

Add an [env] section to your config file. These variables are injected into the Moltis process at startup, making them available to all features:

[env]
BRAVE_API_KEY = "your-brave-key"
OPENROUTER_API_KEY = "sk-or-..."

If a variable is set both via docker -e and [env], the Docker/host environment value wins — [env] never overwrites existing variables.

Settings UI env vars

Environment variables set through the Settings UI (Settings > Environment) are stored in SQLite. At startup, Moltis injects them into the process environment so they are available to all features (search, embeddings, provider API calls), not just sandbox commands.

Precedence order (highest wins):

  1. Host / docker -e environment variables
  2. Config file [env] section
  3. Settings UI environment variables

Building Locally

To build the Docker image from source:

# Single architecture (current platform)
docker build -t moltis:local .

# Multi-architecture (requires buildx)
docker buildx build --platform linux/amd64,linux/arm64 -t moltis:local .

OrbStack

OrbStack on macOS works identically to Docker — use the same socket path (/var/run/docker.sock). OrbStack’s lightweight Linux VM provides good isolation with lower resource usage than Docker Desktop.

Troubleshooting

“Cannot connect to Docker daemon”

The Docker socket is not mounted or the Moltis user doesn’t have permission to access it. Verify:

docker exec moltis ls -la /var/run/docker.sock

Setup code not appearing in logs (for network access)

The setup code only appears when accessing from a non-localhost address. If you’re accessing from the same machine via localhost, no setup code is needed. For network access, wait a few seconds for the gateway to start, then check logs:

docker logs moltis 2>&1 | grep -i setup

OAuth authentication error (OpenAI Codex)

If clicking Connect for OpenAI Codex shows “unknown_error” on OpenAI’s page, port 1455 is not reachable from your browser. Make sure you published it:

-p 1455:1455

If you’re running Moltis on a remote server (cloud VM, VPS) and accessing it over the network, localhost:1455 on the browser side points to your local machine — not the server. In that case, authenticate via the CLI instead:

docker exec -it moltis moltis auth login --provider openai-codex

The CLI opens a browser on the machine where you run the command and handles the OAuth callback locally. If automatic callback capture fails, Moltis prompts you to paste the callback URL (or code#state) into the terminal. Tokens are saved to the config volume and picked up by the running gateway automatically.

Permission denied on bind mounts

When using bind mounts, ensure the directories exist and are writable:

mkdir -p ./config ./data
chmod 755 ./config ./data

The container runs as user moltis (UID 1000). If you see permission errors, you may need to adjust ownership:

sudo chown -R 1000:1000 ./config ./data