> ## Documentation Index
> Fetch the complete documentation index at: https://docs.memanto.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-Hosting Memanto Server

> Run the Memanto FastAPI REST server as a long-lived service with Docker, Compose, or systemd — on-prem or cloud.

# Self-Hosting Memanto Server

`memanto serve` runs the same FastAPI server that powers the [REST API](/api-reference/authentication). 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`](https://github.com/astral-sh/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

```bash theme={null}
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:

```json theme={null}
{
  "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.

```bash theme={null}
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):

```bash theme={null}
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

```bash theme={null}
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:

```yaml theme={null}
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:

```bash theme={null}
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`:

```ini theme={null}
[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:

```bash theme={null}
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:

```bash theme={null}
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:

| Endpoint      | Purpose                                               | Notes                                                                                         |
| ------------- | ----------------------------------------------------- | --------------------------------------------------------------------------------------------- |
| `GET /health` | Full health, including Moorcheh connectivity.         | Returns 200 only when Moorcheh is reachable; use for readiness gating before sending traffic. |
| `GET /ready`  | Lightweight check; always 200 once the process is up. | Use for liveness probes — does not depend on Moorcheh.                                        |
| `GET /live`   | Same as `/ready`.                                     | Kept for Kubernetes idiom.                                                                    |
| `GET /docs`   | Swagger UI for the REST API.                          |                                                                                               |
| `GET /redoc`  | ReDoc rendering of the OpenAPI spec.                  |                                                                                               |
| `GET /ui`     | Web 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:

```bash theme={null}
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:

```bash theme={null}
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.

```bash theme={null}
# 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

* [Kubernetes Deployment](./kubernetes) — manifests for a clustered install.
* [Security & Operations](./security) — TLS, secrets management, hardening.
* [Troubleshooting](./troubleshooting) — common deployment failure modes.
