CipherStashDocs
CipherStash CLI

Install and upgrade EQL

Install or upgrade EQL extensions in Postgres with the stash CLI, covering Supabase and Drizzle migrations, auto-detection, and permission fallbacks.

install

Install the CipherStash EQL extensions into your database. Uses bundled SQL by default for offline, deterministic installs.

npx stash db install [options]

db install scaffolds stash.config.ts if it is missing. The command:

  1. Scaffolds stash.config.ts with the database URL and client path (if the file does not already exist).
  2. Scaffolds the encryption client file at the path referenced in stash.config.ts if the file does not exist. Uses the same auto-detected integration template as init (Drizzle, Supabase, or generic Postgres). Silent, no prompt.
  3. Checks permissions and auto-selects the right SQL variant based on your database role.
  4. Installs EQL extensions in your database.

After a successful install, the CLI prints a summary of what was installed. If you reached this step via stash init, EQL was already installed as part of init. Manual invocation is useful when you need specific flags (for example, --supabase --migration to write a Supabase migration file) or when you skipped the database connection during init.

OptionDescription
--dry-runShow what would happen without making changes
--forceReinstall even if EQL is already installed
--supabaseUse Supabase-compatible install (excludes operator families and grants Supabase roles)
--migrationWrite EQL into a Supabase migration file instead of pushing directly. Requires --supabase.
--directPush EQL directly to the database, skipping the migration-file prompt. Requires --supabase.
--migrations-dir <path>Override the Supabase migrations directory (default: supabase/migrations/). Requires --supabase.
--exclude-operator-familySkip operator family creation (for non-superuser database roles)
--drizzleGenerate a Drizzle migration instead of direct install
--latestFetch the latest EQL from GitHub instead of using the bundled version
--name <value>Migration name when using --drizzle (default: install-eql)
--out <value>Drizzle output directory when using --drizzle (default: drizzle)

Standard install:

npx stash db install

Dry run to preview changes:

npx stash db install --dry-run

Fetch the latest EQL from GitHub:

npx stash db install --latest

Auto-detection

db install auto-detects two things before prompting you:

  • Supabase: If DATABASE_URL contains a *.supabase.co, *.supabase.com, or *.pooler.supabase.com host, the CLI uses the Supabase-compatible install automatically. You can still pass --supabase explicitly to override.
  • Drizzle: If a drizzle.config.* file exists or drizzle-orm/drizzle-kit appears in package.json, the CLI generates a Drizzle migration automatically. You can still pass --drizzle explicitly.

Automatic OPE fallback

On managed databases (Supabase, Neon, RDS), the connected role is often not a superuser. db install detects this and automatically uses the no-operator-family (OPE) install variant, logging a line to inform you. You do not need to pass --exclude-operator-family manually on these hosts.

Supabase install

npx stash db install --supabase

The --supabase flag uses the Supabase-specific SQL variant. It omits CREATE OPERATOR FAMILY and grants USAGE, table, routine, and sequence permissions on the eql_v2 schema to anon, authenticated, and service_role.

When --supabase is passed and a supabase/migrations/ directory is detected, the CLI prompts:

How should EQL be installed?
  > Create a Supabase migration file (recommended)
    Push directly to the database

The migration-file path writes EQL SQL into supabase/migrations/00000000000000_cipherstash_eql.sql. The all-zero timestamp prefix ensures it runs before any user migrations that reference eql_v2_encrypted. Use --migration to skip the prompt and always create the file, or --direct to skip the prompt and always push directly.

# Write EQL as a migration file
npx stash db install --supabase --migration

# Push EQL directly to the database
npx stash db install --supabase --direct

# Override the migrations directory
npx stash db install --supabase --migration --migrations-dir ./db/migrations

--migration, --direct, and --migrations-dir all require --supabase to be passed explicitly. Passing them without --supabase will error. --latest is not compatible with --migration.

EQL installed via direct push does not survive supabase db reset. The reset command drops the database and reruns only files in supabase/migrations/. If you use supabase db reset, install EQL as a migration file instead. See Supabase db reset removes EQL.

Without operator families, ORDER BY on encrypted columns is not supported, regardless of the client or ORM used. Sort application-side after decrypting results as a workaround. This limitation also applies when using --exclude-operator-family on any database.

Drizzle migrations

If you use Drizzle ORM and want EQL installation as part of your migration history, use --drizzle:

npx stash db install --drizzle
npx drizzle-kit migrate

This process:

  1. Runs drizzle-kit generate --custom --name=<name> to create an empty migration.
  2. Loads the bundled EQL install SQL (or downloads from GitHub with --latest).
  3. Writes the EQL SQL into the generated migration file.

To customize the migration name and output directory:

npx stash db install --drizzle --name setup-eql --out ./migrations

drizzle-kit must be installed. The --out value must match your Drizzle config.

You can combine --drizzle and --supabase:

npx stash db install --drizzle --supabase

This generates a Supabase-compatible EQL migration file.

Encrypting existing columns

When you add encryptedType to a Drizzle column that already has data, drizzle-kit generate emits an ALTER TABLE ... ALTER COLUMN ... SET DATA TYPE eql_v2_encrypted statement. Postgres cannot cast existing data to eql_v2_encrypted implicitly, so this migration would fail.

db install --drizzle automatically rewrites those statements into a safe ADD COLUMN / DROP COLUMN / RENAME COLUMN sequence. The rewrite adds a comment in the migration to remind you to backfill the new column with encryptModel before dropping the old one. You are responsible for writing and running that backfill in your application code before applying the DROP step.

Permission pre-checks

Before installing, the CLI verifies you have the following permissions:

  • CREATE on the database (for CREATE SCHEMA and CREATE EXTENSION)
  • CREATE on the public schema (for CREATE TYPE "public"."eql_v2_encrypted")
  • SUPERUSER or extension owner (for CREATE EXTENSION pgcrypto, if not already installed)

If the role is not a superuser, the CLI falls back automatically to the OPE (no-operator-family) variant instead of exiting with an error.


upgrade

Upgrade an existing EQL installation to the version bundled with the package, or to the latest version from GitHub.

npx stash db upgrade [options]
OptionDescription
--dry-runShow what would happen without making changes
--supabaseUse Supabase-compatible upgrade
--exclude-operator-familySkip operator family creation
--latestFetch the latest EQL from GitHub instead of using the bundled version

The EQL install SQL is idempotent and safe to re-run. The CLI checks the current version, re-runs the install SQL, and reports the new version. If EQL is not installed, the CLI suggests running npx stash db install instead.

Bundled EQL SQL

The EQL install SQL is bundled with the package for offline, deterministic installs. The bundled version is pinned to the package version. Use --latest to fetch the newest version from GitHub.

Three SQL variants are included:

FileUsed when
cipherstash-encrypt.sqlDefault install
cipherstash-encrypt-supabase.sql--supabase flag
cipherstash-encrypt-no-operator-family.sql--exclude-operator-family flag or automatic OPE fallback

On this page