Run it
Updates, backups and recovery
On this page
This page is for whoever looks after a HappyToHelp installation. It shows how to keep a running installation safe: update it, back up and restore its data, build its release package yourself and share its source.
It also sums up where an installation can run and how HappyToHelp is licensed.
Each installation stands alone
Every HappyToHelp installation is independent. It does not need:
- a HappyToHelp company account
- a shared database
- a checkout of the original HappyToHelp application's source (this open-source project is a new edition of that application)
The company's own service at happytohelp.com is separate from your installation, and you don't need an account there.
Never copy another installation's secrets, resource names or customer data into yours.
Update your installation
Keep these, so you can always rebuild or roll back:
- your fork of the source
- the exact commit and release package (the build artifact) you accepted
- your own customizations
- your migration receipts (the record of which database migrations you applied)
For a checkout cloned from the public repository, stop dev or preview and back up its state and private settings before updating. Keep your own commits and merge public main into them:
git fetch origin main
git merge origin/main
pnpm install --frozen-lockfile
pnpm exec rer build
pnpm exec rer deploy --dry-run
These commands use Node 22.20.0 and pnpm 10.12.4. If origin is your own
fork, fetch the public repository through your upstream remote and merge that
remote's main instead. Resolve conflicts while retaining your customizations.
The current package-mode instructions require current public source; the
older v0.4.1 tag does not contain this command-package conversion.
The build and deployment dry run preserve local data and private settings and
make no deployment. Rer 0.2.22's dry-run preflight requires the same private mail
inputs as real deployment; see deployment prerequisites. Do not reset or replace .wrangler/state during an update.
Run setup with your existing owner and private answers to apply local migrations,
then start pnpm exec rer dev --foreground. For a hosted installation, apply the
reviewed update only through the owner-authorized deployment path.
Upgrade an existing installation
covers backup and rollback; Upgrading from 0.3.x
covers retained owners and settings from the older local installer.
Important
Never overwrite SQL migrations that have already been applied, and never silently change the identities of the Cloudflare resources your installation is bound to (its D1 database, R2 bucket and queues).
Back up your data
Your data lives in two places: the D1 database (named <prefix>-db, where
<prefix> is your resource name) and the R2 file bucket (<prefix>-files). To
take a consistent backup:
-
Stop application writes and background jobs. HappyToHelp has no built-in pause switch, so choose a quiet time and make sure nothing is writing to the installation while you export.
-
Export the D1 database. Wrangler, Cloudflare's command-line tool, can do this from your checkout:
pnpm exec wrangler d1 export <prefix>-db --remote --output private-backup.sql -
Export every R2 object, with both its metadata and its bytes. HappyToHelp doesn't include a command for this, so use a tool that copies each object's metadata as well as its contents.
-
Write down any call to an outside service whose outcome you're unsure of, such as an email or AI reply that may or may not have gone out (HappyToHelp marks these as uncertain). Before you let HappyToHelp try one again, check with the provider what actually happened: restoring an old database must not repeat effects that already happened outside HappyToHelp.
Warning
A raw D1 export contains credentials. Keep it private: it is not safe to pass around as is. Before you give a D1 export to anyone, run the cleaning script in Restore from a backup on it first.
What a D1 and R2 backup covers
Live conversations use a Cloudflare Durable Object called ConversationSocket.
It keeps no application data in Durable Object storage:
- transcripts and the queue of messages waiting to be replayed (the replay outbox) live in D1
- each open connection holds only a temporary position marker, so a new connection re-checks its access and replays what it missed from D1
A backup of D1 and R2 therefore holds all of your HappyToHelp data. It is not a complete export of your Cloudflare account.
Restore from a backup
-
Clean the export. Before importing any backup, run this script (it needs Python 3):
python3 scripts/independent/delegation-backup.py private-backup.sql restore.sqlImport only the resulting
restore.sql. It keeps your application records, migration history and content-free receipts. It removes the dedicated delegation grants, code hashes and consent replay material that let a connected application act for a member. -
Restore into fresh resources that you control. Preserve:
- the migration history
- the IDs in D1
- roles and history
- the bytes of every object
- the
INTEGRATION_ENCRYPTION_KEY, which stored integrations need
-
Export the restored data again and compare its records and object hashes with your backup before you let traffic in.
-
Test that:
- revoked access, and access from another workspace (foreign access), are still refused
- the owner can sign in
- conversations reload
- knowledge articles can be published
- the widget's website origin check still works
- website preview refuses access it should refuse
-
Keep the old resources until you have accepted the restore.
After a restore, every member who had connected Slate (an outside application that members can connect under Settings → Connected applications) must give consent again. Otherwise, normal sign-in sessions work as before.
Where an installation can run
On your computer
You need Node.js 22 or later (with npm) and Git. Check with node --version;
if it is older or missing, install Node 22 from nodejs.org,
or with a version manager (nvm install 22, fnm install 22, or brew install node@22
on macOS). The global rer command itself needs that Node. It then provisions the
checkout's own pinned Node and pnpm. Install dependencies, then start local setup:
npm install -g @runeditrun/rer@0.2.22
git clone https://github.com/just-every/run-happytohelp
cd run-happytohelp
rer install
rer dev
Dev uses its local address for the chat widget and generates a private owner
password. Wait for RER_READY, then open the RER_OPEN address to enter as the
real local owner and reach Setup. No private answers, email service or AI
account are needed. Use rer dev --stop from the checkout to stop the managed app.
See Install for scripted private answers and contributor setup for pnpm commands.
You do not need an email or AI account to set up the owner, hold conversations, let visitors in through the widget, or answer from knowledge content you supply yourself. Before you use any feature that needs an outside provider, configure that provider explicitly (see Operations). A feature whose provider is missing returns an error, and the repository's provider tests do not prove that a real provider works.
To hand support work to your own computer, use the local agent's pairing steps (Local agent).
On your own Cloudflare account
Use pnpm exec rer deploy --environment production with the real
deploy.json declaration and private owner-account credentials.
Deploy to your Cloudflare account
covers prerequisites, secret custody and health boundaries. Local
pnpm exec rer deploy --dry-run requires the same private mail inputs as real
deployment with rer 0.2.22. It validates their shape and builds locally without
provider requests or sending mail.
Website preview lets owners and admins see their website with the chat
widget on it. It needs its own custom-domain origin (PREVIEW_ORIGIN), pointed
at the same Worker but separate from the origin where owners sign in
(APP_ORIGIN). Keep the two origins separate, keep the existing access checks
on each preview link (its scoped grant), and never serve previews on the owner
origin.
Hosted by Run Edit Run
Run Edit Run, a separate service, offers hosted Assisted and Managed installations of HappyToHelp. If you host HappyToHelp yourself, you can skip this section. These files describe HappyToHelp to that service:
rer-project.jsonis the project descriptor: the source repository, licence, deployment target, and the setup, build, verify and artifact commands. It deliberately records no revision; the service registers an exact 40-character source commit separately..github/workflows/rer-managed.ymlcalls the service's trusted build workflow at a pinned commit. HappyToHelp's own commands that this build runs receive no deployment credentials; the delivery service does the publishing itself.node scripts/independent/setup-build.mjsprepares that build: it installs pnpm into.rer-tools, then the frozen application dependencies and Chromium. The trusted build provides Node but no global pnpm, so the build and verify commands put.rer-tools/node_modules/.binfirst onPATHbefore running the package scripts.management/holds the integration profile the service adopts (management/README.md).
A hosted installation needs a fresh, private H2H_SETUP_TOKEN. rer deploy uses it
once to claim the owner named by OWNER_EMAIL, then removes it; entering it at
/setup is recovery only. Creating the first owner closes setup permanently.
Build the release package yourself
The artifact is the deployable package of your installation. You only need
it if you deliver builds yourself or want to check a published build. To build
it, run pnpm exec rer build or pnpm exec rer verify. Both run the pinned Base producer
(the packaging step, fixed to an exact upstream version) after Vite.
- The producer writes
delivery-artifact/happytohelp-worker-artifact.json. - A normal build first cleans only its own generated
delivery-artifact/output. Run directly (node scripts/delivery/build.mjs), the producer refuses to overwrite an existing artifact. - The manifest (schema 2) points to raw sidecar files in
payload/, each with its SHA-256 and byte size. Keep and upload the whole directory. - Private credential files and symlinks make packaging fail.
- Building an artifact does not deploy it.
The artifact carries:
- the exact SQL migrations and their digests
- the Worker modules
- the public assets
- the D1, R2 and queue bindings
- the
ConversationSocketclass and its migration - the once-a-minute schedule
- the secret declarations
- the health contract
The artifact is byte-reproducible with the Node and pnpm versions declared in
package.json. Anyone can build the same commit and compare their SHA-256 with
a published artifact.
To run the artifact locally and check backup and restore, run
node tests/independent-runtime.mjs (see
tests/helpers/INDEPENDENT-RECOVERY.md).
Share the source without Git history
To give someone a clean copy of the source:
-
Commit the reviewed tree.
-
Run:
node scripts/independent/source-snapshot.mjs /new/output-directoryIt writes a tar of the committed tree and a SHA-256 receipt, without
.git. -
Unpack the tar into a new directory, initialize a new repository there and commit the snapshot.
The maintainer command pnpm run source:release keeps history. It is meant for
the maintainers' own trusted release records, not for a clean public snapshot.
Licence
The root LICENSE (MIT) covers the whole repository, including
the homepage drawings and setup artwork. Keep docs/licenses/ and third-party
package notices with any copy you redistribute; see
SOURCE-PROVENANCE.md.