Agent-readable docs index: /llms.txt. Full docs in one file: /llms-full.txt. Download /docs.zip to grep all markdown files locally.

Self-host Sigillo on your own Cloudflare account

Run Sigillo on your own Cloudflare account with a single command. No git clone, no build step, no wrangler config:
npx @kldzj/sigillo self-host
The command provisions two Workers and their D1 databases on your account: the Sigillo app and its own login provider. It applies the database migrations, uploads the release, and prints your instance URL. The whole thing runs on Cloudflare's free plan, and depends on no one else's servers.

What it does

npx @kldzj/sigillo self-host │ ├──> 1. Unlock ~/.sigillo/selfhost.json with your passphrase ├──> 2. Log in to Cloudflare (reuses wrangler login when present) ├──> 3. Download this version's release bundle from github.com/kldzj/sigillo, and check its SHA-256 ├──> 4. Create the app's D1 database and apply its migrations ├──> 5. Deploy the login provider (<name>-auth): D1, migrations, Worker ├──> 6. Deploy the app (<name>): Worker, static assets ├──> 7. Enable both workers.dev URLs └──> 8. Optionally attach a custom domain to the app

Google sign-in

People sign in with Google through your login provider. A new deployment needs a Google OAuth client for it, and the command shows you exactly what to register:
  1. Open Google Cloud credentials and choose Create credentials → OAuth client ID → Web application.
  2. Add the redirect URI the command prints, for example https://sigillo-auth.<your-subdomain>.workers.dev/api/auth/callback/google.
  3. Paste the client ID and secret when the command asks for them, or pass --google-client-id and --google-client-secret.
The first time someone signs in to your instance, the login provider asks them to allow it once.

Cloudflare credentials

The command finds credentials in this order:
  1. CLOUDFLARE_API_TOKEN environment variable (or --api-token)
  2. A login saved by a previous self-host run
  3. Your existing wrangler login (refreshed automatically if expired)
  4. Interactive: an OAuth browser login, or a pre-filled API token creation link you can open from any device
Deploying over SSH? Pick the API token option: the pre-filled link opens on your phone or laptop and you paste the token back into the terminal.

Updating

Re-run the same command anytime to update to the latest release:
npx @kldzj/sigillo self-host
Re-runs are idempotent: only new database migrations are applied, unchanged assets are skipped, and no secret is ever rotated, so your stored secrets stay decryptable and your users stay signed in.
Each version of @kldzj/sigillo deploys its own release, which is why npx @kldzj/sigillo without a version updates to the latest one. The bundle holds the code that runs with your secrets, so the CLI checks it against the SHA-256 that CI recorded in the npm package when it built both, and deploys nothing that doesn't match. It also refuses to deploy a version older than the one your instance runs, unless you pass --allow-downgrade.
A deployment that already signs in through another provider, such as one made with upstream Sigillo's self-host against auth.sigillo.dev, keeps that provider on update: switching would give every user a new login.
New deployments get their own ENCRYPTION_KEY, separate from the BETTER_AUTH_SECRET that signs sessions. Deployments made before there was an ENCRYPTION_KEY keep deriving their key from BETTER_AUTH_SECRET.

Your deploy file

self-host saves both keys in ~/.sigillo/selfhost.json on the machine that ran it, together with the login provider's secret, the Google client and a Cloudflare login from the browser. The file is encrypted with a passphrase of at least 12 characters, chosen on the first run, and each run asks for it once. Keep the passphrase in your password manager; the file can then stay where it is.
Back up the file, and don't lose the passphrase. A database backup cannot be decrypted without the keys, and if the worker and the file are both lost, self-host refuses to reuse that database.
Runs without a terminal, such as CI, read the passphrase from SIGILLO_SELFHOST_PASSPHRASE. A file from before encryption is encrypted on the next run in a terminal, if you agree, or right away when the variable is set. To change the passphrase:
npx @kldzj/sigillo self-host --change-passphrase

Your own encryption key

Optional. To choose the key yourself instead of getting a random one, set SIGILLO_ENCRYPTION_KEY on the first deploy:
SIGILLO_ENCRYPTION_KEY="$(openssl rand -base64 32)" npx @kldzj/sigillo self-host
It must be 32 bytes, base64-encoded. It is bound as the worker's ENCRYPTION_KEY secret and saved in ~/.sigillo/selfhost.json. It cannot be set on an existing deployment, because a new key would make its stored secrets unreadable.

Limit who can sign in

By default, anyone who can sign in with Google gets an account. To let in only certain people, pass a comma-separated list of email addresses and domains:
npx @kldzj/sigillo self-host --allowed-users acme.com,ops@partner.io
A new deployment run in a terminal asks for the list. With --yes or without a terminal, pass --allowed-users, or anyone with a Google account can sign in. Only verified emails match: an address matches itself, a domain matches exactly that domain, not its subdomains. Nobody else can sign up or sign in, in the browser or with the CLI, and a signed-in user taken off the list is signed out on their next request. The app and its login provider both check it.
Updates keep the list saved in ~/.sigillo/selfhost.json. Pass --allowed-users again to change it, or --allowed-users '' to let anyone in.

Options

OptionDescription
--name <name>Worker name (default: sigillo); the login provider is <name>-auth
--account <id>Cloudflare account id (skips the account prompt)
--api-token <token>Cloudflare API token
--google-client-id <id>Google OAuth client ID for a new login provider
--google-client-secret <secret>Google OAuth client secret for a new login provider
--allowed-users <list>Email addresses and domains that may sign in, comma-separated; '' lets anyone in
--domain <hostname>Attach a custom domain to the app (the zone must be on your account)
--skip-domainSkip the custom domain prompt
--bundle <path>Deploy a local copy of this version's bundle, checked like a download
--release-url <url>Download this version's bundle from a custom URL, checked like a download
--allow-downgradeDeploy even if the instance runs a newer version
--change-passphraseEncrypt ~/.sigillo/selfhost.json with a new passphrase, then stop
--reset-passkeys <email>Remove every passkey of this user and sign them out, for a sole admin who lost theirs, then stop. See Hardening
--yesAccept all defaults, non-interactive
Non-interactive example for CI or agents:
CLOUDFLARE_API_TOKEN=xxx SIGILLO_SELFHOST_PASSPHRASE=xxx npx @kldzj/sigillo self-host --yes \ --google-client-id xxx.apps.googleusercontent.com --google-client-secret xxx \ --allowed-users acme.com

Using your instance

Point the CLI at your deployment with --api-url:
sigillo login --api-url https://sigillo.<your-subdomain>.workers.dev
Then everything works exactly like before:
sigillo setup sigillo run -- next dev