Skip to content

Deploy to production

The local profile is wide open by design — no auth on the dashboard or the API. Before you expose merido to anything but your own machine, do the security checklist first.

1. Security checklist (do this first)

Gate the dashboard and /api/*

Set a dashboard password hash. Generate it with the built-in helper (argon2):

bash
merido hash-password --password 'a-strong-password'

It prints the env var to set:

bash
MERIDO_DASHBOARD_PASSWORD_HASH='$argon2id$...'

With this set, the dashboard and the control-plane /api/* endpoints require a login session.

Require an API key on /v1/*

bash
MERIDO_REQUIRE_API_KEY=true

Now anonymous data-plane requests are rejected — callers must present a valid client (gateway) key.

Keep your master key stable

Encryption-at-rest (provider credentials, OAuth tokens) is sealed with the master key. Set MERIDO_MASTER_KEY to a stable base64 32-byte value and never rotate it casually — changing it orphans every stored secret. (Locally it lives at data_dir/master.key if you don't set the env var.)

2. Docker

The repo ships a multi-stage Dockerfile that builds the dashboard with bun, then the release binary:

bash
docker build -t merido .
docker run -p 8788:8788 \
  -e MERIDO_DASHBOARD_PASSWORD_HASH='$argon2id$...' \
  -e MERIDO_REQUIRE_API_KEY=true \
  -e MERIDO_MASTER_KEY='...' \
  merido

For a shared deployment, run the cloud profile with Postgres:

bash
-e MERIDO_PROFILE=cloud \
-e DATABASE_URL='postgres://user:pass@host/merido'

A bare DATABASE_URL (Postgres' own convention) is accepted. For high availability, also set REDIS_URL — see High availability.

3. Fly.io

merido includes a Fly.io setup: fly.toml, scripts/deploy-fly.sh, and a smoke test (scripts/smoke-fly.sh).

  1. Copy the secrets template and fill it in:

    bash
    cp .env.fly.example .env.fly
    # edit .env.fly — it's gitignored; never commit secrets

    It carries DATABASE_URL, MERIDO_MASTER_KEY, MERIDO_DASHBOARD_PASSWORD_HASH, MERIDO_REQUIRE_API_KEY, and (optionally) REDIS_URL / MERIDO_RESEND_API_KEY.

  2. Deploy — the script pushes secrets and ships the app:

    bash
    ./scripts/deploy-fly.sh
  3. Verify hardening:

    bash
    ./scripts/smoke-fly.sh

4. Verify it's locked down

After deploy, confirm the gates are live:

bash
curl https://your-app.example/healthz                 # 200, reports profile + db/redis status
curl https://your-app.example/v1/models               # 401 without a client key
curl https://your-app.example/api/usage               # 401 without a session/mgmt token

5. Backup & restore

merido can export a portable configuration document (POST /api/backup/export) and re-apply it on another instance (POST /api/backup/import).

Restore is additive and non-destructive — it is not a wipe-and-replace. Importing a backup creates only entries that don't already exist and upserts allow-listed settings; anything that already exists on the target is left unchanged (the response reports how many entries were skipped because they already existed). Restoring into a populated instance therefore merges the backup in rather than overwriting the current state.

Secrets are never in the backup, so a few things can't be recreated by a restore: gateway-key material is not exported (keys are reported but not restored), restored provider connections come back without credentials (re-add each API key), and proxy-pool URLs are not restored. Treat a restore as "re-create the shape of the config, then re-enter the secrets," not as a full clone.

See Backup & restore for the full export contents and the restore flow.

Next

© merido. All rights reserved.