Skip to main content

Self-Hosting Memanto Server

memanto serve runs the same FastAPI server that powers the REST API. For development, running it from the CLI is enough — but for shared environments you’ll want it under a process manager that survives logouts and restarts. This page covers Docker, Docker Compose, systemd, and a manual long-running process. All four options work for both backends — set MEMANTO_BACKEND=on-prem to talk to your local Moorcheh server, or leave it cloud (default) for Moorcheh Cloud.

Image: What Memanto Ships

The Memanto repository includes a production-ready Dockerfile:
  • Base: python:3.12-slim
  • Runs as a non-root user (memanto, UID 1001)
  • Exposes port 8000
  • Builds dependencies via uv for fast, deterministic installs
  • Built-in HEALTHCHECK polling /ready (a lightweight endpoint that does not call Moorcheh)
  • Entry point: uvicorn memanto.app.main:app --host 0.0.0.0 --port 8000

Option 1: Docker

Cloud backend

docker build -t memanto:latest .

docker run -d \
  --name memanto \
  -p 8000:8000 \
  -e MOORCHEH_API_KEY=mk_your_key \
  -e LOG_LEVEL=INFO \
  --restart unless-stopped \
  memanto:latest

curl http://localhost:8000/health
Expected response:
{
  "status": "healthy",
  "service": "MEMANTO",
  "version": "0.1.x",
  "moorcheh_connected": true
}

On-prem backend

Memanto’s container needs to reach the Moorcheh on-prem container running on the same host. On Linux/macOS, use host.docker.internal; on Linux without Docker Desktop, use --network host instead.
docker run -d \
  --name memanto \
  -p 8000:8000 \
  -e MEMANTO_BACKEND=on-prem \
  -e MOORCHEH_ONPREM_URL=http://host.docker.internal:8080 \
  -e LOG_LEVEL=INFO \
  --restart unless-stopped \
  memanto:latest
Or, if Moorcheh and Memanto are on the same user-defined Docker network (recommended):
docker network create memanto-net
# (start moorcheh container attached to memanto-net as 'moorcheh')

docker run -d \
  --name memanto \
  --network memanto-net \
  -p 8000:8000 \
  -e MEMANTO_BACKEND=on-prem \
  -e MOORCHEH_ONPREM_URL=http://moorcheh:8080 \
  memanto:latest

Option 2: Docker Compose

The Memanto repo ships a docker-compose.yml for the cloud backend. Drop in an .env file and you’re done.

Cloud backend

cp .env.example .env
# Edit .env:
# MOORCHEH_API_KEY=mk_your_key
# ALLOWED_ORIGINS=https://yourdomain.com
# LOG_LEVEL=INFO

docker compose up -d
docker compose logs -f

On-prem backend

Extend the compose file to add the Moorcheh server and (optionally) Ollama:
services:
  memanto:
    build: .
    image: memanto:latest
    container_name: memanto
    depends_on:
      moorcheh:
        condition: service_healthy
    environment:
      MEMANTO_BACKEND: "on-prem"
      MOORCHEH_ONPREM_URL: "http://moorcheh:8080"
      LOG_LEVEL: "INFO"
    ports:
      - "8000:8000"
    restart: unless-stopped

  moorcheh:
    image: moorcheh/moorcheh:latest    # or build from your moorcheh-client
    container_name: moorcheh
    ports:
      - "8080:8080"
    volumes:
      - moorcheh-data:/data
      - ~/.moorcheh:/root/.moorcheh    # for embedding/LLM config
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 5

  ollama:                              # only if your provider is ollama
    image: ollama/ollama:latest
    container_name: ollama
    volumes:
      - ollama-data:/root/.ollama
    restart: unless-stopped

volumes:
  moorcheh-data:
  ollama-data:
Bring it up:
docker compose up -d
docker compose ps
docker compose logs -f memanto

Option 3: systemd (Linux)

For a single-host install without Docker, run Memanto under systemd. Save as /etc/systemd/system/memanto.service:
[Unit]
Description=Memanto REST API
After=network.target docker.service
Wants=docker.service

[Service]
Type=simple
User=memanto
Group=memanto
WorkingDirectory=/opt/memanto
Environment=MEMANTO_BACKEND=on-prem
Environment=MOORCHEH_ONPREM_URL=http://127.0.0.1:8080
Environment=LOG_LEVEL=INFO
EnvironmentFile=/etc/memanto/memanto.env
ExecStart=/opt/memanto/.venv/bin/memanto serve --host 0.0.0.0 --port 8000
Restart=on-failure
RestartSec=5
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
Then:
sudo useradd --system --home-dir /opt/memanto --shell /usr/sbin/nologin memanto
sudo mkdir -p /opt/memanto && sudo chown memanto:memanto /opt/memanto
sudo -u memanto python -m venv /opt/memanto/.venv
sudo -u memanto /opt/memanto/.venv/bin/pip install memanto

sudo mkdir -p /etc/memanto
sudo install -m 600 /dev/stdin /etc/memanto/memanto.env <<'EOF'
# Empty file is fine on-prem (no MOORCHEH_API_KEY needed).
# For cloud, set:
# MOORCHEH_API_KEY=mk_...
EOF

sudo systemctl daemon-reload
sudo systemctl enable --now memanto
sudo systemctl status memanto
journalctl -u memanto -f
The on-prem Moorcheh container (moorcheh up) should be managed by a separate systemd unit or by Docker’s own --restart unless-stopped so it comes back automatically.

Option 4: Manual / Background

For one-off testing on a remote host:
nohup memanto serve --host 0.0.0.0 --port 8000 > memanto.log 2>&1 &
Stop it with pkill -f "memanto serve". Not recommended for production — use systemd or Docker.

Endpoints to Probe

All deployment modes expose the same operational endpoints:
EndpointPurposeNotes
GET /healthFull health, including Moorcheh connectivity.Returns 200 only when Moorcheh is reachable; use for readiness gating before sending traffic.
GET /readyLightweight check; always 200 once the process is up.Use for liveness probes — does not depend on Moorcheh.
GET /liveSame as /ready.Kept for Kubernetes idiom.
GET /docsSwagger UI for the REST API.
GET /redocReDoc rendering of the OpenAPI spec.
GET /uiWeb dashboard.Available when running memanto ui or with MEMANTO_UI_MODE=true.

Performance & Concurrency

For more than a handful of concurrent agents, run Memanto with multiple uvicorn workers behind a reverse proxy:
uvicorn memanto.app.main:app \
  --host 0.0.0.0 --port 8000 \
  --workers 4 \
  --proxy-headers
Recommended starting point for a single host:
  • 2 workers per CPU core (Memanto is I/O-bound).
  • Reverse proxy (Nginx, Caddy, or Traefik) terminating TLS and forwarding to 127.0.0.1:8000.
  • Rate limits at the proxy if exposing publicly.

CORS

By default, ALLOWED_ORIGINS=*. Restrict in production:
export ALLOWED_ORIGINS="https://app.yourdomain.com,https://admin.yourdomain.com"

Logs

Structured JSON logging is enabled by default. Memory operations are logged with content redaction so payloads never end up in your log aggregator.
# Docker
docker logs -f memanto

# systemd
journalctl -u memanto -f

# Local
memanto serve  # logs to stdout
Set LOG_LEVEL=DEBUG for detailed request/response traces during troubleshooting.

Next Steps