Skip to content
BasaltDBBasaltDB
Star

Install

View as Markdown

Use this page to put BasaltDB on a Postgres you own and choose the tables your agent may touch. To try it first on a sample database, use the Quickstart.

You need:

  • macOS or Linux, with sudo.
  • Go 1.26 or newer, and git.
  • A Postgres you own: Supabase, RDS, or one you host yourself. You need its admin connection string, the one for the postgres user.
  • A browser on the same machine, with a passkey (Touch ID, a security key, or a password manager that stores passkeys).
  • An agent that supports MCP. See Connect an agent.

The admin connection string is used once, by basalt init, typed into its hidden prompt. It is never stored. Do not export it or put it on a command line.

There is no release download yet. You build basalt from source. You need Go 1.26 or newer and git.

git clone https://github.com/BasaltDBHq/BasaltDB.git
cd BasaltDB
go build -o basalt ./cmd/basalt
sudo install -d -o root -m 0755 /usr/local/libexec
sudo install -o root -m 0755 basalt /usr/local/libexec/basalt
sudo mkdir -p /usr/local/bin
sudo ln -sf /usr/local/libexec/basalt /usr/local/bin/basalt
basalt version

basalt version prints the version.

The engine runs as its own OS user from the real file behind the link, /usr/local/libexec/basalt. Whoever can change that file can run code with the agent’s credential. So basalt init and basalt service install check that the file and every directory above it belong to root and are not writable by group or others. If they do not, they stop before changing anything:

basalt: /usr/local/bin is owned by uid 501, not root: the engine service runs /usr/local/bin/basalt as the engine's OS user, so only root may be able to change it or any directory above it. Install basalt in a root-owned directory and run that copy: ... (or run basalt init with --no-service)

That is why the commands above put the binary in /usr/local/libexec and only link it from /usr/local/bin. Do not install it in your home directory.

Supabase. In the dashboard press Connect and copy the string that matches your network.

String Use it
Session pooler, port 5432 (postgres.<ref>@aws-0-<region>.pooler.supabase.com) If unsure. Works on IPv4 and IPv6.
Direct connection (db.<ref>.supabase.co) Only if your network has IPv6.

Fill in [PASSWORD] with your database password. URL-encode characters such as @, /, : and #. Add ?sslmode=require at the end.

Other Postgres. Use postgresql://postgres:PASSWORD@HOST:5432/DBNAME?sslmode=require. See Hosts for RDS and self-hosted notes.

Name the tables the agent may use. --write lists tables it may read and change. --read lists tables it may only read. Both take a comma-separated list of schema.table.

basalt init --agent my_bot \
  --write public.leads --read public.lead_notes

my_bot is the agent’s name. Pick any name. Init asks, in order:

  1. Admin connection string (used once, never stored): Paste the string from step 2. Nothing is echoed.
  2. Only if a table has row-level security on and no policy for the agent: ... hides its rows with row-level security. Let my_bot see all <n> rows of this table? [y/N]. Answer y to add a policy for the agent role only. With n the agent reads zero rows. Supabase can turn row-level security on for every new table. Init asks before it shows the SQL.
  3. It prints the setup SQL, then Run this SQL as postgres? [y/N]. Type y.
  4. basalt: guard installed; agent role basalt_agent_my_bot
  5. It prints a http://localhost:8787/passkeys/register#... link. Open it, press the button, confirm with your passkey, copy the basalt-passkey.1.... code the page shows, and paste it at Paste the code the page shows:. Then basalt: passkey registered for localhost.
  6. Install the engine as a background service? ... [Y/n] Press Enter. Init runs one sudo, installs and starts the service, and checks that the engine answers.

Port 8787 must be free while init waits for the passkey, and afterwards for the engine. lsof -nP -iTCP:8787 -sTCP:LISTEN shows what holds it.

basalt status --agent my_bot
curl -s http://localhost:8787/healthz

basalt status reports the engine, the guard version and the passkey, and lists any problem with what to do about it. curl prints ok.

Next: Connect an agent. The agent starts basalt mcp --agent my_bot.

  • tables ... not found in database: the tables in --write or --read do not exist in the database this connection string points at. Init checks first and changes nothing.
  • The agent reads zero rows from a table that has rows: row-level security is on with no policy for the agent. Run step 3 again and answer y to the row-level security question, or add --agent-rls=all-rows.
  • /mcp shows the server failed, or the connection closes at once: the engine admits only the OS user that ran init. Start the agent as that user.
  • guard schema vN is older than this build's vM: run basalt upgrade --agent my_bot. See Upgrade.
  • No sudo, or you do not want a service: add --no-service to basalt init. It prints the one basalt engine --config ... command to run in the foreground as you. Writes are still guarded in Postgres, but your user can read the agent’s credential file.
basalt uninstall
sudo basalt service uninstall

basalt uninstall asks for the admin connection string, then drops the basalt_meta schema, the guard’s triggers and policies, and the basalt_* roles. service uninstall stops and removes the engine service. See Remove BasaltDB.

BasaltDB · Apache-2.0