Accounts on your server

Run accounts and sync on your own server, with your own domain.

Accounts and sync currently need a Cloudflare server with a D1 database. A native server reports accounts: false and the app hides the account page.

Turn them on

Accounts switch on when the Worker has the GLYPH_DB database binding and PUBLIC_ORIGIN set. glyph setup cloudflare does both. Check with:

curl https://api.example.com/v1/health   # "accounts": true

Domain and passkeys

SettingExampleMeaning
PUBLIC_ORIGINhttps://api.example.comwhere the sign-in page is served
ACCOUNT_RP_IDexample.comthe domain passkeys belong to
ACCOUNT_EXTRA_ORIGINSandroid:apk-key-hash:...extra WebAuthn origins for mobile apps

Use a subdomain for the API so the bare domain stays free for a website. Set ACCOUNT_RP_ID to the bare domain: passkeys then work on every subdomain.

A passkey only works for the domain it was created on. Changing ACCOUNT_RP_ID later invalidates every passkey. Users still get in with their password, a pairing code or the recovery code, then add a new passkey. Pick the final domain before real users sign up.

Admin access

The admin API is off until you set a password hash:

glyph hash-password                       # prints a hash; the password is stored nowhere
glyph cloudflare secret ADMIN_PASSWORD_HASH
glyph remote login https://api.example.com
glyph remote status

Admin logins are locked for 15 minutes after five wrong passwords and only work over HTTPS. The admin login checks Argon2id on the Worker; if the free plan's CPU limit stops it, it needs the Workers Paid plan.

Device limit

The limit is a server setting; the app only shows it.

CommandEffect
glyph remote accounts default-limitshow the default (5)
glyph remote accounts default-limit 5default for every account, 1–100
glyph remote accounts limit alice 10own limit for @alice
glyph remote accounts limit alice defaultback to the default
glyph remote accounts show alicelimit in force and devices

Changes apply at once. Lowering a limit keeps existing devices signed in; new ones must wait until the account is below it. At the limit the sign-in page lets the user remove a device first.

Only signed-in users

glyph remote limits --require-account true

Every /v1/* route then needs a valid account token; guests get HTTP 401 account_required. Sign-in, health and public share pages stay reachable.

How sign-in works

  • Handle: @name, 3–20 characters a-z 0-9 _, unique, changeable once per 30 days. A released handle stays blocked for 30 days.
  • Password: the device computes Argon2id(password, salt); the server only stores the salt and a hash of that key. The password never reaches the server.
  • Passkeys: WebAuthn ES256/RS256 with user verification; only the public key is stored.
  • Pairing code: a new device shows a code, a signed-in device approves it.
  • Recovery code: shown once at sign-up, stored as a hash.
  • Tokens: per device an access token (1 hour) and a refresh token (90 days, rotated on every use). Only hashes are stored.
  • Sync: last writer wins per item; deletions are kept for 180 days.

Backups

npx wrangler d1 export glyph --remote --output backup.sql

If other people use your server, you hold their personal data. Depending on your country you may need a privacy notice and an imprint. See Privacy for what is stored.

edit this page on github · markdown

up down choose · enter open · esc closellms.txt