Skip to Content
Self-host Quard

Self-host Quard

You can run Quard in your own cloud instead of using the hosted service, from one Docker Compose file. It starts Postgres and four services:

  • web: the dashboard, on port 3000.
  • webhook: receives events from your agents, on port 4100.
  • control: the live link your agents keep open for counters and approvals, on port 4200.
  • worker: finds the cause of incidents in the background. It has no port.

A one-off migrate step sets up the database before the services start.

What you need

  • A machine with Docker and Docker Compose v2, and at least 4 GB of memory to build the images.
  • Git, to get the code, and openssl, to make keys.
  • A free Privy  account. The dashboard signs people in through Privy, with an email code or GitHub.

1. Get the code

git clone https://github.com/oynozan/quard.git cd quard

2. Set up sign-in

  1. Create an app in the Privy dashboard .
  2. Under login methods, turn on Email and GitHub.
  3. Under allowed domains, add the address you will open the dashboard at, such as http://localhost:3000. Privy works on localhost and on HTTPS addresses only.
  4. Copy the App ID and the App secret from App settings.

Anyone who signs in with a verified email or a GitHub account can use the dashboard. To keep it private, run it inside your network or behind your VPN.

3. Fill in the settings

Copy the example settings file:

cp .env.example .env

Then fill in these lines in .env:

SettingWhat to put there
POSTGRES_PASSWORDA password for the database. Make one with openssl rand -hex 24.
QUARD_HASH_KEY64 hex characters. Make it with openssl rand -hex 32.
NEXT_PUBLIC_PRIVY_APP_IDThe Privy App ID, 25 characters.
PRIVY_APP_SECRETThe Privy App secret.
QUARD_SESSION_SECRETSigns the dashboard’s session cookie. Make it with openssl rand -hex 32.

The hash key turns IBANs and emails into hashes, so they are never stored in clear. It stays on your server. Each project hashes with its own key, made from this one, and the SDK gets its project’s key from Quard with the agent key. So your agents never need QUARD_HASH_KEY. Keep it with your other secrets. If it changes, hashes made before no longer match.

These are optional:

SettingWhat it does
OPENAI_API_KEYYour own OpenAI key. The worker uses it for the AI reviewer and replay. Without it, both are off.
OPENAI_BASE_URLAnother address for the OpenAI API. The default is https://api.openai.com/v1.
PRIVY_VERIFICATION_KEYPrivy’s verification key, with \n for line breaks. Saves a key fetch on each sign-in.
QUARD_PROJECT_IDThe project the dashboard shows. Empty means the first project.
QUARD_WEB_PORT, QUARD_WEBHOOK_PORT, QUARD_CONTROL_PORTOther ports on the machine, when 3000, 4100 or 4200 are taken.
POSTGRES_USER, POSTGRES_DBThe database user and name. Both default to quard.

4. Start Quard

docker compose up -d --build

The first build takes a few minutes. Then check that everything is up:

docker compose ps

postgres, webhook, control and web show healthy, and worker is up. migrate is not listed, because it ran once and exited. If a service keeps restarting, docker compose logs <service> says why.

5. Create a project and an agent key

docker compose run --rm migrate node db/cli/setup-main.ts --project "Acme"

It prints the project id and an agent key that starts with qk_live_:

Project: 7f0c2a52-… Agent key: qk_live_… The agent key is shown once. Only its hash is stored.

Copy the key now and keep it as a secret. Your agents send their runs with it, and it is the only Quard secret they need.

You can also make keys in the dashboard, under Settings. On a new install, the first key there sets up the project.

6. Open the dashboard

Go to http://localhost:3000  and sign in. The pages stay empty until your first run arrives. Your first guarded run sends one.

Run it on a server

  • Put HTTPS in front of web, with a reverse proxy such as Caddy or nginx, and add that address to the allowed domains in Privy.
  • Agents need to reach webhook and control. Give them their own HTTPS addresses, or keep them inside your network. control uses a WebSocket, so the proxy must pass WebSocket upgrades through.
  • Postgres keeps its data in the postgres-data volume and is not open to the outside. Back it up with docker compose exec postgres pg_dump -U quard quard.

Update Quard

git pull docker compose up -d --build

The migrate step brings the database up to date before the services start again.

If your agents set hashKey

Agents used to set hashKey in quard.configure(), with the same QUARD_HASH_KEY as the server. Now each project hashes with its own key, and the SDK gets it from Quard.

  1. Update Quard as above. Keep QUARD_HASH_KEY in your .env.
  2. Update the quard package in your agents. Remove hashKey from quard.configure(), and QUARD_HASH_KEY from their settings.

Moving to project keys changes every hash once, as a new hash key would.

When the hash key changes

Hashes made before the change don’t match the new ones:

  • Search no longer finds IBANs and emails from older runs.
  • Shared memory items written before the change read back as untrusted.
  • Calls that an “always approve” grant covered ask again.
  • The fleet check sees every IBAN and email as new. Those in quarantine are no longer blocked, and those marked as known can be quarantined again.

So change QUARD_HASH_KEY only if it leaked.

Last updated on