Self-hosting

Deploy the Mnemoid API

You deploy the Mnemoid API on your infrastructure. Each deployment is a single instance for one organization, with its own users and data. The Mnemoid UI (web or APK) connects directly to your API instance. Users join through secure invitation links or reconnect with login-only connect links—no manual API URL configuration. Your data stays on your servers; we do not host project data.

Quick start

  1. Start the API with Docker (see below).
  2. Configure environment variables in your .env file.
  3. Let startup run migrations and bootstrap automatically (no manual commands).
  4. Copy the connect link printed in the API logs.
  5. Open the Mnemoid client (web or APK) and sign in.

Prerequisites

  • Docker
  • PostgreSQL 14+

Docker image

Use the API container image from Docker Hub (placeholder name shown below).

igin/mnemoid-api:latest

Environment variables

Define the required variables in a .env file. Use DATABASE_URL or the DB_* set.

PORT
Optional: port the API container listens on (defaults to 3000).
API_URL
Required: public API base URL (include /api). Used for links and metadata.
AUTH_SECRET
Required: secret used to sign auth tokens. Use a strong random value.
ALLOW_OPEN_SIGNUP
Optional: allow open signup without invitation (default false).
BOOTSTRAP_ADMIN_EMAIL
Required: email for the bootstrap admin account created on startup.
BOOTSTRAP_ADMIN_PASSWORD
Required: password for the bootstrap admin account (min 8 chars).
MNEMOID_INSTANCE_PATH
Optional: identity file path (defaults to /etc/mnemoid-api/.mnemoid.instance.json).
FIREBASE_CREDENTIALS_JSON
Required: absolute path to the Firebase service account JSON file.
DB_HOSTNAME
Required (unless DATABASE_URL): PostgreSQL host.
DB_PORT
Required (unless DATABASE_URL): PostgreSQL port (default 5432).
DB_SCHEMA
Required (unless DATABASE_URL): database name.
DB_USERNAME
Required (unless DATABASE_URL): database user.
DB_PASSWORD
Required (unless DATABASE_URL): database password.
DATABASE_URL
Optional: full connection string used instead of DB_* variables.
ASSETS_UPLOAD_DIR
Required: absolute path where uploads are stored (mount a volume).

Minimal docker run

docker run -d \
  --name mnemoid-api \
  --env-file .env \
  -p 3000:3000 \
  -v /srv/mnemoid/assets:/var/lib/mnemoid-api/assets \
  -v /srv/mnemoid/identity:/data \
  -v /srv/mnemoid/firebase.json:/run/secrets/firebase.json:ro \
  igin/mnemoid-api:latest

Recommended docker-compose.yml

services:
  api:
    image: igin/mnemoid-api:latest
    env_file: .env
    ports:
      - "3000:3000"
    volumes:
      - /srv/mnemoid/assets:/var/lib/mnemoid-api/assets
      - /srv/mnemoid/identity:/data
      - /srv/mnemoid/firebase.json:/run/secrets/firebase.json:ro
    depends_on:
      - postgres

  postgres:
    image: postgres:16
    environment:
      POSTGRES_DB: mnemoid
      POSTGRES_USER: mnemoid
      POSTGRES_PASSWORD: change-me
    volumes:
      - /srv/mnemoid/postgres:/var/lib/postgresql/data

Recommended Caddyfile

mnemoid.XXXXX.fr {
    reverse_proxy localhost:XXXX
}

Automatic bootstrap

On startup, the API applies migrations, creates or loads the instance identity file, and ensures the bootstrap admin account. There are no manual commands to run in production.

Mount a persistent volume at /etc/mnemoid-api/.mnemoid.instance.json so/etc/mnemoid-api/.mnemoid.instance.json remains stable across restarts.

Happy path logs

Migrations applied and bootstrap ensured before the API banner prints. Expect output similar to this:

▗▖  ▗▖▗▖  ▗▖▗▄▄▄▖▗▖  ▗▖ ▗▄▖ ▗▄▄▄▖▗▄▄▄ 
▐▛▚▞▜▌▐▛▚▖▐▌▐▌   ▐▛▚▞▜▌▐▌ ▐▌  █  ▐▌  █
▐▌  ▐▌▐▌ ▝▜▌▐▛▀▀▘▐▌  ▐▌▐▌ ▐▌  █  ▐▌  █
▐▌  ▐▌▐▌  ▐▌▐▙▄▄▖▐▌  ▐▌▝▚▄▞▘▗▄█▄▖▐▙▄▄▀

────────────────────────────────────────────────────────────
            MNEMOID • API ONLINE
────────────────────────────────────────────────────────────

Environment          : development
Local API            : http://localhost:XXXX/api
Health API           : http://localhost:XXXX/api/health
Documentation        : http://localhost:XXXX/api/docs
Public URL           : https://api.XXXX.test/api
Process PID          : XXXXX

────────────────────────────────────────────────────────────
Connect Link         : https://ui.mnemoid.test/connect?token=eyXXXXXXXXXXXXXXXXXXXXX
Expires At           : 202X-XX-XXTXX:XX:XX.XXXZ
────────────────────────────────────────────────────────────
📡 Server ready. Listening on port XXXX...

Join via the client UI

Open the Mnemoid web client at https://app-mnemoid.igin.fr and paste the connect or invitation link from your API.

Native app store releases are planned. We will announce availability once they are ready.

Inviting users to your instance

Admins generate secure invitation links for new users from the admin console or the API. The UI never asks for API URLs; users open the invitation link to connect and create a session.

Existing users reconnect with a login-only connect link. It is safe to share internally and never creates new users.

Invitation endpoints are protected and available only to admin/owner roles.

POST https://api.example.com/api/invitations
curl -X POST https://api.example.com/api/invitations \
  -H "Authorization: Bearer <admin-access-token>" \
  -H "Content-Type: application/json" \
  -d '{
    "email": "new.user@example.com",
    "role": "user",
    "expiresInHours": 72,
    "displayName": "New User",
    "identifier": "new_user"
  }'

The response includes a ready-to-share link:https://app-mnemoid.igin.fr/connect?token=...

Links are signed, time-limited, and revocable. To revoke a link, callPOST /api/invitations/<id>/revoke.

POST https://api.example.com/api/auth/connect-link

Connect links are login-only (no signup) and can be used by bootstrap admins before any invitations exist.

You can retrieve a connect link from the startup logs or by callingPOST /api/auth/connect-link.

Users open links in the web UI (or future native apps). The UI selects the correct API, then creates a session only after signup or login. A single user can keep multiple accounts across different client instances.

Production notes

  • Terminate HTTPS with your reverse proxy and set API_URL to the public HTTPS URL so the UI can connect.
  • Persist both /data and ASSETS_UPLOAD_DIR plus your PostgreSQL volume.
  • Upgrade by pulling the latest image tag and restarting the container.

License reminder

Personal, non-commercial use is free. Professional or commercial usage requires a paid license per API instance.