SSD Nodes Learn 🎉 VPS mulai $5.50/bln
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-13

Self-Host mem0 di VPS: RAM, Compose, TLS, Ollama

Pelajari kebutuhan nyata self-hosting mem0: sekitar 1 GB RAM untuk tiga container, minimal 8 GB dengan Ollama, Compose localhost, dan TLS.

Biaya RAM sebenarnya untuk self-hosting mem0 pada VPS

Self-hosting mem0 berarti menjalankan tiga container: server memori FastAPI, Postgres dengan ekstensi pgvector, dan dashboard Next.js. mem0 adalah lapisan memori untuk agent. Anda mengirim percakapan ke dalamnya, model bahasa mengekstrak fakta yang bertahan lama dari percakapan tersebut, lalu fakta itu disimpan sebagai vector agar query berikutnya dapat mengambil fakta yang relevan.

Anggarkan sekitar 1 GB memori resident untuk ketiga container dan 3 hingga 4 GB ruang disk setelah image selesai dibuat. VPS 2 GB dapat menjalankan konfigurasi ini dengan baik jika model bahasa berada di tempat lain. Jika model dijalankan pada server yang sama melalui Ollama, model akan menggunakan sebagian besar resource: model 8B yang dikuantisasi hingga 4 bit memerlukan sekitar 6 GB sendiri, sehingga konfigurasi yang sepenuhnya lokal memerlukan setidaknya 8 GB.

Jangan mengambil angka tersebut dari sebuah blog, termasuk artikel ini. Ukur stack yang benar-benar Anda bangun.

docker compose ps
docker stats --no-stream
docker system df -v

docker stats mencetak memori resident untuk setiap container. docker system df -v mencetak ruang disk yang digunakan setiap image dan volume.

Kondisi stabil bukanlah kondisi puncak. docker compose up -d --build mengompilasi dashboard Next.js, dan proses build Node tersebut menggunakan resource paling besar selama seluruh instalasi. Pada VPS 1 GB, kernel menghentikannya melalui out-of-memory killer dan proses build berakhir dengan exit code 137. Pastikan penyebabnya sebelum Anda mencari masalah pada Docker:

dmesg -T | grep -i "killed process"

Jika server terasa terlalu kompleks untuk kebutuhan Anda, tersedia opsi yang lebih sederhana. penyimpanan memori agent lokal tanpa server sama sekali dan memori yang berada langsung di dalam Claude Code sama-sama tidak memerlukan database. Gunakan pendekatan ini ketika beberapa agent atau beberapa mesin perlu membaca memori yang sama.

Apakah saya memerlukan Neo4j untuk memori graf mem0?

Tidak. Jika sebuah panduan meminta Anda menambahkan container Neo4j, panduan tersebut lebih lama daripada kode yang digunakan saat ini.

Memori graf di mem0 sebelumnya berarti database graf eksternal yang dikonfigurasi di bawah kunci graph_store dengan enable_graph disetel ke true. Algoritme memori baru yang dirilis pada April 2026 menghapus kedua kunci tersebut dari SDK open source. Ekstraksi entitas kini berjalan di dalam alur add biasa, dan entitas ditulis ke koleksi pgvector kedua yang namanya sama dengan koleksi utama, dengan tambahan _entities. Tidak ada migrasi yang perlu dijalankan. Penautan entitas bawaan mulai berfungsi pada pemanggilan add berikutnya.

Menghapus penyimpanan graf menghemat satu container JVM, heap-nya, dan beberapa ratus megabyte image. Pada VPS 2 GB, penghematan ini dapat menentukan apakah sistem berjalan normal atau mulai menggunakan swap.

Berikut hal yang tidak lagi tersedia. Hasil pencarian sebelumnya membawa kolom relations yang berisi daftar edge antar-entitas. Kolom tersebut sudah dihapus. Kecocokan entitas kini meningkatkan posisi sebuah memori dalam skor gabungan, dan tidak ada struktur yang dapat Anda telusuri. Jika aplikasi Anda sebelumnya menelusuri hubungan tersebut, mem0 kini tidak lagi menyimpannya. Anda harus menyimpan database graf sendiri di luar mem0 dan mengisinya dengan kode Anda sendiri.

Berkas compose di repo ini adalah compose untuk pengembangan

server/docker-compose.yaml mendeklarasikan name: mem0-dev, dan deklarasi itu benar-benar diterapkan. Baca berkas tersebut sebelum menjalankannya, karena ada lima hal di dalamnya yang tidak sesuai untuk server.

  • Berkas ini melakukan build dari server/dev.Dockerfile dan me-mount checkout Anda ke atas image dengan .:/app, sehingga container menjalankan isi direktori tersebut, bukan hasil build yang Anda buat.
  • Perintahnya adalah rm -rf /app/packages && pip install -q --force-reinstall --no-deps mem0ai && alembic upgrade head && uvicorn main:app --reload. Perintah ini menginstal ulang mem0ai dari PyPI setiap kali start. Akibatnya, versi yang dijalankan server dapat berubah saat restart yang tidak Anda anggap sebagai upgrade.
  • Langkah pip yang sama menyebabkan restart tanpa jaringan keluar gagal sebelum uvicorn sempat berjalan. Memory server Anda kemudian tidak aktif karena PyPI tidak dapat dijangkau.
  • --reload menjalankan file watcher milik uvicorn. Fitur ini digunakan untuk me-restart proses saat Anda mengubah kode. Dalam production, fitur ini hanya menggunakan memori dan satu proses tambahan tanpa manfaat. Dockerfile untuk production juga membawa --reload di dalam CMD, sehingga Anda tetap harus mengganti perintahnya.
  • Port yang dipublikasikan adalah "8888:8000", "8432:5432", dan "3000:3000". Port yang dipublikasikan tanpa alamat di depannya akan di-bind ke 0.0.0.0. Akibatnya, Postgres dapat diakses dari Internet publik melalui port 8432 segera setelah stack dijalankan.

Poin terakhir ini memerlukan peringatan tersendiri. Docker memublikasikan port dengan menambahkan aturannya sendiri sebelum chain yang dikelola ufw. Karena itu, ufw deny 8432 tidak menutup port container yang dipublikasikan. Docker memublikasikan port langsung melewati ufw menjelaskan aturan yang terlibat.

File compose untuk server produksi

Bekerjalah di dalam server/, pertahankan init-db.sh di tempatnya, lalu ganti docker-compose.yaml dengan isi berikut.

name: mem0

services:
  mem0:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    env_file: .env
    ports:
      - "127.0.0.1:8888:8000"
    networks: [mem0_network]
    volumes:
      - mem0_history:/app/history
    depends_on:
      postgres:
        condition: service_healthy
    command: >
      sh -c "alembic upgrade head &&
             uvicorn main:app --host 0.0.0.0 --port 8000"
    environment:
      - PYTHONUNBUFFERED=1
      - DASHBOARD_URL=https://mem0.example.com
      - APP_DB_NAME=mem0_app
      - AUTH_DISABLED=false
      - MEM0_TELEMETRY=false

  postgres:
    image: pgvector/pgvector:pg17
    restart: unless-stopped
    shm_size: "128mb"
    networks: [mem0_network]
    environment:
      - POSTGRES_USER=${POSTGRES_USER:-postgres}
      - POSTGRES_PASSWORD=${POSTGRES_PASSWORD:?set POSTGRES_PASSWORD in .env}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -q -U ${POSTGRES_USER:-postgres}"]
      interval: 5s
      timeout: 5s
      retries: 5
    volumes:
      - postgres_db:/var/lib/postgresql/data
      - ./init-db.sh:/docker-entrypoint-initdb.d/init-db.sh

  mem0-dashboard:
    build: ./dashboard
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    networks: [mem0_network]
    environment:
      - NEXT_PUBLIC_API_URL=https://mem0.example.com
      - API_INTERNAL_URL=http://mem0:8000
    depends_on:
      mem0:
        condition: service_started

volumes:
  postgres_db:
  mem0_history:

networks:
  mem0_network:
    driver: bridge

Ada lima perubahan penting di sini, dan masing-masing memiliki alasan.

Setiap entri ports dimulai dengan 127.0.0.1, sehingga kernel hanya menerima koneksi tersebut dari mesin itu sendiri. Semua koneksi dari luar masuk melalui reverse proxy, yang merupakan satu-satunya komponen yang menyimpan sertifikat.

Postgres sama sekali tidak memiliki blok ports. Container mem0 mengaksesnya melalui mem0_network menggunakan nama service, sehingga memublikasikan 8432 tidak memberi manfaat apa pun dan hanya menambah port yang terbuka. Gunakan docker compose exec postgres psql -U postgres jika Anda memerlukan shell.

Penyimpanan history dipindahkan dari bind mount ./history ke named volume. Bind mount mengikat data ke satu path dan satu uid pada host ini, sedangkan named volume merupakan objek yang dapat dibuat snapshot dan dipindahkan oleh Docker. Named volume dibandingkan bind mount membahas kapan masing-masing pilihan tepat digunakan.

Perintah tersebut menghapus --reload dan mempertahankan alembic upgrade head. Pertahankan langkah migrasi itu. Tanpanya, aplikasi melakukan boot dengan database yang tidak memiliki tabel, sehingga setiap request gagal pada query pertama.

NEXT_PUBLIC_API_URL adalah URL yang dipanggil browser Anda, sehingga harus berupa alamat HTTPS publik, bukan http://mem0:8000. Next.js menyertakan setiap nilai NEXT_PUBLIC_ ke dalam kode saat build, sehingga perubahan nilai tersebut memerlukan docker compose up -d --build mem0-dashboard. Restart biasa tetap menggunakan nilai lama yang sudah tertanam dalam JavaScript, sehingga dashboard memanggil host yang salah.

Rahasia disimpan dalam .env, dan .env tidak boleh terekspos ke Internet

cd server
cp .env.example .env
openssl rand -hex 32    # paste into JWT_SECRET
openssl rand -hex 32    # paste into ADMIN_API_KEY
chmod 600 .env

Atur POSTGRES_PASSWORD, JWT_SECRET, dan ADMIN_API_KEY. Biarkan AUTH_DISABLED=false. Namanya menjelaskan fungsi flag tersebut: jika diaktifkan, server menyerahkan seluruh memori yang dimilikinya kepada siapa pun yang dapat menjangkau port tersebut. Atur MEM0_TELEMETRY=false jika Anda tidak ingin event onboarding dikirim ke upstream.

ADMIN_API_KEY dibandingkan dengan header X-API-Key menggunakan secrets.compare_digest, dan kecocokan akan melewati semua pencarian database. Ini adalah kredensial root untuk seluruh API. Perlakukan kredensial ini dengan semestinya: jangan menyimpannya dalam riwayat shell, git, atau menempelkannya ke prompt. File environment Compose dan tempat rahasia dapat bocor darinya serta menjauhkan kunci API dari konteks agent berlaku langsung karena pemanggil server ini adalah agent.

Nilai yang dimuat dari env_file berada di environment container, dan docker inspect menampilkannya secara lengkap. Siapa pun dalam grup docker dapat membacanya, dan siapa pun dalam grup docker secara efektif memiliki akses root pada host.

Pasang TLS di depan API, bukan membuka port 8888

API merespons pada 127.0.0.1:8888, sedangkan dashboard berjalan pada 127.0.0.1:3000. nginx mengakhiri TLS (transport layer security) pada port 443, lalu meneruskan trafik ke keduanya.

server {
    listen 443 ssl;
    server_name mem0.example.com;

    ssl_certificate     /etc/letsencrypt/live/mem0.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mem0.example.com/privkey.pem;

    location ~ ^/(memories|search|configure|auth|api-keys|docs|openapi.json) {
        proxy_pass http://127.0.0.1:8888;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_read_timeout 180s;
    }

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

proxy_read_timeout lebih penting daripada yang terlihat. Panggilan add akan terblokir saat language model membaca percakapan dan mengekstrak fakta. Model lokal 8B pada CPU sering memerlukan waktu lebih lama daripada batas waktu default nginx, yaitu 60 detik. Akibatnya, pemanggil menerima 504 Gateway Time-out saat model masih bekerja dan memori tetap ditulis. Hasilnya, Anda memiliki memori yang dilaporkan gagal, padahal sebenarnya berhasil ditulis.

Tutup akses lainnya dengan kebijakan ufw default deny, dan biarkan 22 serta 443 tetap terbuka. Terbitkan sertifikat menggunakan certbot di Ubuntu 24.04 di belakang nginx. Jika server tersebut sudah meneruskan aplikasi lain menggunakan Traefik untuk merutekan beberapa aplikasi Compose, tambahkan mem0 ke router itu, bukan memasang proxy kedua.

Uji asap: tambahkan satu memori lalu baca kembali

export MEM0_KEY='<the ADMIN_API_KEY from .env>'

curl -sS -X POST http://127.0.0.1:8888/memories \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"messages":[{"role":"user","content":"I deploy with Docker Compose and I run Postgres 17."}],"user_id":"smoke"}'

Respons yang sehat adalah objek JSON dengan daftar results, dan setiap entri berisi id, teks memory yang diekstrak, serta "event": "ADD". Algoritma saat ini hanya mengembalikan event ADD. Event UPDATE dan DELETE telah dihapus, sehingga ketidakhadirannya bukan bug.

curl -sS -X POST http://127.0.0.1:8888/search \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d '{"query":"which database do I run?","filters":{"user_id":"smoke"},"top_k":5}'

Fakta tentang Postgres 17 seharusnya dikembalikan bersama skor. Masukkan identifier di dalam filters, seperti ditunjukkan. Field tingkat atas user_id masih berfungsi, dan server mencatat Top-level user_id in /search is deprecated. Use filters={...} instead. setiap kali Anda menggunakannya.

Bersihkan data setelah pengujian agar data uji tidak mencemari pencarian nyata:

curl -sS -X DELETE "http://127.0.0.1:8888/memories?user_id=smoke" \
  -H "X-API-Key: $MEM0_KEY"

Jika pencarian mengembalikan lebih sedikit baris daripada yang diharapkan, periksa nilai default sebelum menyalahkan retrieval. Pada rilis saat ini, top_k secara default bernilai 20, turun dari 100, dan threshold secara default bernilai 0.1, bukan none, sehingga kecocokan yang lemah kini difilter secara otomatis. Setelah ini berfungsi melalui curl, endpoint yang sama dapat dihubungkan ke agent, baik secara langsung maupun melalui MCP server yang berjalan pada VPS yang sama.

Jalankan mem0 tanpa OpenAI key sama sekali

Mulai dari penghalangnya, karena Anda akan menemukannya dalam lima menit pertama. Server image menyertakan kumpulan provider library yang tetap, dan /configure menolak apa pun di luar kumpulan tersebut:

LLM provider 'ollama' is not bundled in this image. Bundled providers: openai, anthropic, gemini. To use another provider, install its Python package, rebuild the container, and extend BUNDLED_LLM_PROVIDERS in server/main.py.

Anda tidak perlu melakukan rebuild. Ollama menyediakan API yang kompatibel dengan OpenAI pada /v1, yang mencakup /v1/chat/completions dan /v1/embeddings, dan provider openai milik mem0 menerima sebuah openai_base_url. Arahkan key tersebut ke Ollama dan pemeriksaan bawaan akan berhasil karena provider tersebut memang openai. Hanya alamatnya yang berubah.

Tambahkan Ollama ke Compose project yang sama:

  ollama:
    image: ollama/ollama
    restart: unless-stopped
    networks: [mem0_network]
    ports:
      - "127.0.0.1:11434:11434"
    volumes:
      - ollama_models:/root/.ollama

Tambahkan ollama_models: di bawah key tingkat teratas volumes:, lalu pull satu chat model dan satu embedding model:

docker compose up -d ollama
docker compose exec ollama ollama pull llama3.1:8b
docker compose exec ollama ollama pull nomic-embed-text

Jika Ollama sudah berjalan pada host sebagai systemd unit, seperti pada menjalankan Ollama langsung pada VPS, jangan arahkan container ke 127.0.0.1:11434. Di dalam container mem0, 127.0.0.1 adalah container mem0. Berikan extra_hosts: ["host.docker.internal:host-gateway"] kepada service mem0, tetapkan Environment="OLLAMA_HOST=0.0.0.0:11434" dalam systemd drop-in agar Ollama mendengarkan pada alamat yang dapat dijangkau bridge, dan tetap tutup port 11434 pada firewall.

Tanyakan dimensi embedding model sebelum mengonfigurasi apa pun

Langkah ini menentukan apakah retrieval dapat berfungsi sama sekali.

pgvector store milik mem0 membuat tabel dengan lebar vector tetap, vector vector(1536), karena embedding_model_dims secara default bernilai 1536, yaitu lebar text-embedding-3-small milik OpenAI. nomic-embed-text mengembalikan 768 nilai. Tidak ada bagian di dalam mem0 yang membandingkan kedua angka tersebut, sehingga ketidakcocokan muncul dari Postgres pada insert pertama:

expected 1536 dimensions, not 768

Jangan memercayai angka dalam paragraf ini. Tanyakan kepada model:

curl -sS http://127.0.0.1:11434/v1/embeddings \
  -H "Content-Type: application/json" \
  -d '{"model":"nomic-embed-text","input":"dimension check"}' \
  | python3 -c "import json,sys; print(len(json.load(sys.stdin)['data'][0]['embedding']))"

Perintah tersebut menampilkan lebar yang harus digunakan collection Anda. Tulis konfigurasi ke dalam file karena menempelkan password Postgres melalui shell quoting dapat memasukkan typo ke production.

{
  "vector_store": {
    "provider": "pgvector",
    "config": {
      "host": "postgres",
      "port": 5432,
      "dbname": "postgres",
      "user": "postgres",
      "password": "<POSTGRES_PASSWORD from .env>",
      "collection_name": "memories_local_768",
      "embedding_model_dims": 768
    }
  },
  "llm": {
    "provider": "openai",
    "config": {
      "model": "llama3.1:8b",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1",
      "temperature": 0.2
    }
  },
  "embedder": {
    "provider": "openai",
    "config": {
      "model": "nomic-embed-text",
      "api_key": "ollama",
      "openai_base_url": "http://ollama:11434/v1"
    }
  }
}
curl -sS -X POST http://127.0.0.1:8888/configure \
  -H "Content-Type: application/json" \
  -H "X-API-Key: $MEM0_KEY" \
  -d @config.json

curl -sS http://127.0.0.1:8888/configure -H "X-API-Key: $MEM0_KEY"

Pemanggilan kedua membaca kembali konfigurasi tersebut. Ini adalah pemeriksaan bahwa penulisan berhasil. Setelah itu, ulangi smoke test di atas.

Ada empat detail dalam JSON tersebut yang tidak terlihat jelas. Masing-masing akan menyebabkan sesuatu gagal jika salah.

api_key adalah string ollama, dan Ollama mengabaikan nilainya. Nilai tersebut tidak boleh kosong karena OpenAI client library memunculkan error sebelum request apa pun meninggalkan process jika tidak ada key yang ditetapkan. String tidak kosong apa pun dapat digunakan.

embedding_model_dims ditempatkan pada vector store, dan memang tidak ada embedding_dims pada embedder. mem0 hanya mengirim parameter OpenAI dimensions jika Anda menetapkan embedding_dims, dan backend yang tidak menerapkan Matryoshka truncation akan langsung menolak parameter tersebut. Tetapkan lebar saat tabel dibuat dan biarkan embedder tanpa konfigurasi itu.

collection_name adalah konfigurasi baru. mem0 membuat tabel dengan CREATE TABLE IF NOT EXISTS, sehingga mengarahkan width yang berbeda ke collection yang sudah ada tidak mengubah apa pun: kolom vector(1536) lama tetap ada dan setiap insert gagal. Perubahan width memerlukan nama collection baru, atau Anda harus menghapus tabel lama secara manual.

Host dalam openai_base_url adalah Compose service name ollama, bukan localhost. Container saling menemukan berdasarkan service name pada shared network.

Biaya yang ditimbulkan oleh jalur yang sepenuhnya lokal

Bersikaplah realistis mengenai kualitas. Skor benchmark yang dipublikasikan untuk mem0 diukur menggunakan frontier model untuk melakukan ekstraksi. Karena itu, anggap skor tersebut sebagai batas atas, bukan perkiraan untuk model 8B pada VPS Anda. Model kecil menghasilkan fakta yang lebih samar dan terkadang mengembalikan prose ketika JSON diminta. Hal ini terlihat ketika add call mengembalikan list results kosong tanpa error.

Kecepatan adalah biaya lainnya. Ekstraksi yang hanya menggunakan CPU memerlukan beberapa detik untuk setiap add call, dan setiap pesan yang Anda simpan menanggung biaya tersebut. Jika latensi itu penting, VPS dengan GPU terpasang adalah solusi yang tepat. Menambahkan lebih banyak CPU core pada model 8B membantu jauh lebih sedikit daripada yang diperkirakan banyak orang.

Satu aturan berlaku apa pun pilihan Anda: jangan pernah mencampur embedding model dalam satu collection. Dua model berbeda yang kebetulan memiliki width sama akan menghasilkan vector yang tidak dapat dibandingkan. Insert berhasil, search mengembalikan rows, dan rows tersebut salah tanpa ada bagian yang melaporkan error.

Cadangan: terdapat dua database, bukan satu

Kesalahan backup mem0 yang paling umum adalah membuang satu database saja. init-db.sh membuat mem0_app selain database default postgres, dan keduanya menyimpan data yang berbeda. Database postgres menyimpan koleksi pgvector, yaitu memori. mem0_app menyimpan pengguna, sesi, API key, dan log permintaan.

Jika hanya postgres yang dipulihkan, memori akan kembali, tetapi semua akun dan API key hilang sehingga tidak ada yang dapat melakukan autentikasi untuk membacanya. Buat dump keduanya, termasuk role, dalam satu perintah:

docker compose exec -T postgres pg_dumpall -U postgres --clean \
  | gzip > "mem0-$(date +%F).sql.gz"

Volume history terpisah dari Postgres dan memerlukan salinan tersendiri:

docker run --rm -v mem0_mem0_history:/data -v "$PWD:/backup" \
  alpine tar czf /backup/mem0-history.tgz -C /data .

Docker menambahkan nama project ke nama volume. Karena itu, pastikan nama volume Anda dengan docker volume ls sebelum mengasumsikan mem0_mem0_history.

Pulihkan ke dalam container scratch, lalu periksa jumlah baris sebelum menganggap backup tersebut valid:

gunzip -c mem0-2026-08-03.sql.gz \
  | docker compose exec -T postgres psql -U postgres -d postgres

Backup yang belum pernah Anda pulihkan hanyalah dugaan. Setelah dump dipastikan benar, kirim ke luar server dengan snapshot restic ke penyimpanan di luar lokasi, karena backup yang berada di server yang dilindunginya tidak melindungi apa pun.

Mode kegagalan dan string persis yang akan Anda lihat

{"detail":"Authentication required. Provide a Bearer token or X-API-Key header."} berarti header tidak ada atau salah eja. Namanya adalah X-API-Key, dan curl mengirim nama header secara literal.

{"detail":"At least one identifier (user_id, agent_id, run_id) is required."} pada operasi add berarti request tidak memiliki satu pun dari header tersebut. Memory harus dikaitkan dengan sesuatu karena filter pencarian menggunakan kolom tersebut secara persis.

LLM provider 'ollama' is not bundled in this image dengan HTTP 400 berarti Anda mengirim "provider": "ollama". Gunakan "provider": "openai" dengan openai_base_url yang diarahkan ke Ollama.

expected 1536 dimensions, not 768 dari Postgres berarti collection dibuat dengan satu ukuran, sedangkan embedder mengembalikan ukuran lain. Tetapkan embedding_model_dims pada vector store dan gunakan collection_name baru.

Search returns rows that make no sense setelah perubahan model, tanpa error apa pun. Ukurannya masih cocok sehingga database tidak bermasalah, tetapi dua model menempatkan kalimat yang sama pada posisi yang berbeda. Buat collection baru, lalu tambahkan kembali datanya.

Connection refused dalam log mem0 saat mengakses Ollama biasanya berarti 127.0.0.1 dalam openai_base_url. Di dalam container, alamat tersebut merujuk ke container itu sendiri. Gunakan nama service, atau host gateway jika Ollama berjalan pada host.

504 Gateway Time-out dari nginx pada operasi add berarti model memerlukan waktu lebih lama daripada proxy_read_timeout. Naikkan nilainya, lalu periksa apakah memory tetap berhasil ditulis sebelum mengulangi request.

exit code 137 selama docker compose up --build adalah out-of-memory killer yang menghentikan proses build dashboard. Tambahkan swap, atau build image pada mesin yang lebih besar lalu push ke registry.

error: port 3000 is already in use berasal dari target make up pada repo, yang menolak start jika port 3000 atau 8888 sedang digunakan. Cari proses pemiliknya dengan lsof -iTCP:3000 -sTCP:LISTEN.

FAQ

Apakah saya masih memerlukan Neo4j untuk menjalankan mem0 dengan memori graf?

Tidak. Algoritme memori baru yang dirilis pada April 2026 menghapus kunci konfigurasi graph_store dan enable_graph dari SDK open source. Ekstraksi entitas kini berjalan selama operasi add biasa dan menulis ke koleksi pgvector kedua bernama <collection_name>_entities, sehingga tidak ada database graf eksternal, container tambahan, atau langkah migrasi. Konsekuensinya, field relations tidak lagi tersedia pada hasil pencarian. Entitas kini meningkatkan peringkat memori, bukan memberi Anda edge untuk ditelusuri. Jadi, aplikasi yang menelusuri relasi tersebut memerlukan penyimpanan graf sendiri di luar mem0.

Apa VPS paling kecil yang dapat menjalankan server mem0 yang di-host sendiri?

Jika model bahasa di-host di tempat lain, RAM 2 GB dan sekitar 4 GB disk kosong sudah cukup untuk container API, Postgres, dan dashboard. Beban tertinggi terjadi saat build pertama, karena kompilasi dashboard Next.js menggunakan lebih banyak memori daripada saat menjalankannya. Pada mesin dengan RAM 1 GB, proses build dihentikan dengan exit code 137. Jika Ollama berjalan pada server yang sama, tentukan kapasitas berdasarkan modelnya. Model 8B dengan kuantisasi 4-bit memerlukan sekitar 6 GB RAM, sehingga siapkan RAM 8 GB.

Apakah saya dapat menjalankan mem0 tanpa API key OpenAI?

Ya, melalui endpoint yang kompatibel dengan OpenAI milik Ollama. Menetapkan "provider": "ollama" akan gagal karena image server hanya menyertakan library openai, anthropic, dan gemini, lalu mengembalikan HTTP 400. Sebagai gantinya, pertahankan "provider": "openai" dan tetapkan "openai_base_url": "http://ollama:11434/v1" dengan api_key tidak kosong apa pun, baik untuk llm maupun embedder. Ollama mengabaikan key tersebut, dan pemeriksaan provider yang disertakan berhasil karena provider yang digunakan memang openai.

Mengapa mem0 tidak mengembalikan hasil setelah saya beralih ke model embedding lokal?

Karena tabel pgvector dibuat dengan lebar yang tetap. embedding_model_dims secara default bernilai 1536, sedangkan nomic-embed-text mengembalikan 768. Postgres kemudian menolak insert dengan expected 1536 dimensions, not 768. mem0 membuat tabel menggunakan CREATE TABLE IF NOT EXISTS, sehingga mengubah angkanya saja tidak berdampak pada koleksi yang sudah ada. Tetapkan embedding_model_dims ke lebar sebenarnya dari model Anda, pastikan lebar tersebut dengan memanggil /v1/embeddings dan menghitung nilai yang dikembalikannya, lalu berikan collection_name baru ke vector store pada saat yang sama.