group conversations with models and local files
0

Configure Feed

Select the types of activity you want to include in your feed.

hezo / DEPLOY.md
4.0 kB

Deploying Hezo#

The repo ships a working Dockerfile. Two paths covered here: Railway (simplest) and any host that runs containers + mounts a volume.

Current production deployment#

This repo is already linked to a Railway project. From the repo root:

railway status   # → Project: hezo  /  Service: centrosome  /  Env: production
railway up       # uploads the local tree, builds the Dockerfile, deploys

Live at https://hezo.app. The service is named centrosome (v1 codename — the rename never happened, the URL did). Volume is mounted at /data. HEZO_EMAIL_HMAC_KEY is set on Railway; back it up to your password manager so you can re-set the same value if the volume is ever lost. Releases are manual — no CI, no GitHub Actions.

Watch a deploy:

railway logs --build    # build output
railway logs            # runtime / migrations / startup

Setting up a fresh instance#

The rest of this doc covers an instance that isn't already linked.

Required environment#

Var Default Notes
PORT 3001 HTTP listen port. Railway sets this automatically.
HOST 127.0.0.1 The Dockerfile overrides to 0.0.0.0.
HEZO_DATA ./data (dev), /data (Docker) Where global.sqlite + per-project DBs + blob dirs live. Must be on a persistent volume.
HEZO_EMAIL_HMAC_KEY (auto) Optional. Base64url-encoded ≥32 bytes used to HMAC user emails into a blind index. If unset, the server generates one on first boot and persists it to <HEZO_DATA>/email_hmac.key. Back this file up alongside the SQLite DB — losing it orphans every account.

No other config required. The access model is invite-only by construction (see below).

Railway#

railway init                  # interactive — pick a project name
railway add --service hezo
railway volume add --mount-path /data
railway up                    # builds the Dockerfile, deploys
railway domain                # generates a public URL

The VOLUME Dockerfile directive isn't supported by Railway — use railway volume add instead.

Access model#

Hezo is invite-only by default. There's no global allow-list to configure; the gates are:

  1. Bootstrap login. The very first /api/auth/login request (when the users table is empty) is always allowed. That email becomes the founding user. Sign in once after deploy to claim ownership of the instance.
  2. Existing-user login. After bootstrap, direct login only works for emails already in the users table. Returning users can sign in normally from any browser.
  3. Invite-grant login. Anyone with a valid invite URL can sign in, regardless of allow-list status. The invite URL is the access grant — sharing it grants both the right to register on the instance and membership in a project. Tokens are one-shot.

So the flow is:

  • Bootstrap user (you) deploys, opens the URL, signs in (any email), creates a project, generates an invite, copies the URL, sends it to a collaborator out of band.
  • Collaborator opens the URL, sees "You've been invited," signs in with their email + API key. The same call accepts the invite and mints their session. They're in.

Trust model in prototype mode#

Still no email verification — anyone with an invite URL can claim any email on the instance. Fine for a small trusted group where invite URLs are shared privately; not safe if invite URLs ever leak (chat history, forwarded mail, etc.). Future hardening: magic-link email proof, expiring invite tokens.

Bringing your existing key#

After deploy, sign in once via the web UI to bind your email to the instance. Then use npm run import-keychain -- you@example.com locally to push your macOS Keychain API key into the local browser's IndexedDB. The key is never sent to the server — the import URL is a client-only fragment.

If you're signing in on a fresh machine without that Keychain entry, just paste the key into the login form directly.