Skip to content

Quickstart

This page is dual-purpose. Read it top-to-bottom yourself, or select the whole page, copy it, and paste it into your AI assistant (Claude Code, Claude Desktop, ChatGPT, Cursor, Gemini CLI). The steps are written as imperatives it can execute in order.

Prereqs: Docker Engine 24+, ~4 GB RAM free, a domain pointing at the host (only if you want TLS at the end; localhost trials skip this).

Terminal window
git clone https://github.com/engram-app/Engram.git
cd Engram

2. Copy the env example and generate the three secrets

Section titled “2. Copy the env example and generate the three secrets”
Terminal window
cp .env.example .env

Open .env and fill in these three values, each generated with the command shown. Don’t skip this step. The app will fail to boot without them.

Terminal window
# Generate, then paste into .env:
openssl rand -base64 48 # → SECRET_KEY_BASE
openssl rand -base64 48 # → JWT_SECRET
openssl rand -base64 32 # → ENCRYPTION_MASTER_KEY

If you’re trialing on localhost (no domain, no TLS yet), also append these two lines to .env so the app’s advertised URLs match where it actually listens:

Terminal window
PHX_SCHEME=http
PHX_PORT=4000

For a production install with a domain, leave the two lines above unset (the release defaults to https / 443, which is correct when you put a TLS-terminating reverse proxy in front, see step 4) and instead set:

Terminal window
PHX_HOST=engram.example.com
Terminal window
docker compose up -d --build

First build compiles the Engram release (a few minutes). On first boot the bundled Ollama service also pulls the nomic-embed-text model, which can take a few minutes depending on bandwidth. Subsequent boots are instant.

The default stack starts five containers: Engram, Postgres, Qdrant (vector store), Ollama (local embeddings), and a one-shot ollama-init job that pulls the model. Only port 4000 is exposed to the host; everything else stays on the private Docker network.

Verify it’s healthy:

Terminal window
docker compose ps
curl -sf http://localhost:4000/api/health && echo OK

You should see engram healthy, postgres healthy, qdrant running, ollama healthy, ollama-init exited(0), and the health endpoint returns a JSON OK. If any service is unhealthy or the curl returns non-200, stop here and triage. docker compose logs engram shows boot output. Common issues: port 4000 already in use, Docker daemon not running, or the OS didn’t allocate enough memory.

Optional: enable MinIO/S3 for large vaults

Section titled “Optional: enable MinIO/S3 for large vaults”

The default stack stores attachments as Postgres bytea. Use that unless any of:

  • A single attachment will exceed ~50 MB (videos, big PDFs)
  • Total attachment storage will exceed ~10 GB
  • You want to point Engram at an existing S3 bucket (AWS / R2 / etc.)

To switch: in .env set STORAGE_BACKEND=s3 and uncomment the four STORAGE_* rows, then bring the stack up with the s3 profile so the bundled MinIO container runs:

Terminal window
docker compose --profile s3 up -d

See Storage for the detail.

Optional: switch to Voyage AI for better embedding quality

Section titled “Optional: switch to Voyage AI for better embedding quality”

The default uses local Ollama (no API key, runs in-stack). To swap to Voyage AI (managed, paid, sign up at voyageai.com): in .env set EMBED_BACKEND=voyage plus EMBED_MODEL=voyage-4-large, EMBED_DIMS=1024, and VOYAGE_API_KEY=.... No compose profile change needed. See Embeddings.

4. Reverse proxy + TLS (skip on localhost)

Section titled “4. Reverse proxy + TLS (skip on localhost)”

Engram doesn’t terminate TLS. For a production install put Caddy, Nginx, nginx-proxy-manager, or any reverse proxy you already run in front of port 4000.

Caddy example (/etc/caddy/Caddyfile):

engram.example.com {
reverse_proxy localhost:4000
}

Reload Caddy. TLS provisions automatically from Let’s Encrypt.

When PADDLE_API_KEY is unset (self-host mode), Engram’s onboarding wizard short-circuits and signup works in-app:

  1. Visit https://engram.example.com (or http://localhost:4000 for the localhost trial) in a browser.
  2. Use the Sign up form. POST /api/auth/register (email + password) creates the user via the local auth provider.
  3. The first user to sign up becomes admin and can mint invites for additional users from the admin settings.
  4. Log in; the vault opens directly without the billing/onboarding gate.

The default registration mode is open in .env.example so you can sign yourself up. Tighten later via ENGRAM_DEFAULT_REGISTRATION_MODE=invite_only (or closed) once you’ve created the accounts you want.

If you’d rather create users out-of-band, an IEx shell also works:

Terminal window
docker compose exec engram bin/engram remote
{:ok, user} = Engram.Accounts.create_user_with_password(
"you@example.com",
"a strong passphrase"
)

Install Engram Vault Sync in Obsidian (via BRAT), then:

SettingsEngram Vault SyncServer URLhttps://engram.example.com (or http://localhost:4000). Sign in with the account you just created. Push your vault. Done.

Verify the install is fully working by creating a note in Obsidian and waiting ~10 seconds for it to appear in the web UI at /notes. That round-trip exercises the sync, the embedding queue, and the vector store.

Then:

If anything above failed and you’re stuck, see Troubleshooting.