Get started
Run it with Docker
TessariDB Vault 0.0.1 runs as two containers: the server, with the web application inside it, and the TessariDB node that keeps everything it holds. One compose file starts both, declares the server's own database account and writes its key.
Docker
Two containers and one command
Set the two passwords and the platform admin in .env, then start it. The first start builds the server's image from the repository and takes a few minutes; later starts take seconds.
git clone https://github.com/tessaridb/tessaridb-vault && cd tessaridb-vault
cp .env.example .env # set TESSARIDB_PASSWORD, VAULT_STORE_PASSWORD and the platform admin
docker compose up -d --waitWhat runs
What the compose file starts
- tessaridb: the TessariDB node,
tessaridb/tessaridb:0.39.6, reachable only from the server over the compose network. Its first start declares the store's owner from.env. - vault-account: signs in as that owner once, declares the
vaultnamespace and an account that may edit that namespace and nothing else, then exits. The server never signs in as the owner. - service-key: writes 32 random bytes as the service key into a volume of its own, readable by the server alone, and leaves an existing key untouched.
- vault: the server, on
http://localhost:8080, published on127.0.0.1only. Put a TLS-terminating proxy in front and setVAULT_PUBLIC_URLto the https address before anyone else reaches it.
The first person
A single-use link for the platform admin
While the platform admin has no credential, enrolment-link prints a single-use enrolment token, valid for 24 hours, to the terminal that ran it and to nowhere else. Open http://localhost:8080/#/join, paste the token, and set a sign-in password and an authenticator.
docker compose run --rm vault enrolment-link
# enrolment token for ops@example.com, valid for one use within 24 hours:
# 3f9c...The first company
A company and its owner
The platform admin creates a company and names its owner; the answer carries the owner's enrolment token, which you send to them. The platform admin's session comes from the two sign-in steps the pages use: the password, then a code from the authenticator. The owner joins the same way, sets an unlock password the first time they open the company, and from then on adds members, departments and teams in the browser.
VAULT=http://localhost:8080; JSON="content-type: application/json"
CHALLENGE=$(curl -s $VAULT/api/sign-in -H "$JSON" \
-d '{"email":"ops@example.com","password":"..."}' | jq -r .challenge)
SESSION=$(curl -s $VAULT/api/sign-in/code -H "$JSON" \
-d "{\"challenge\":\"$CHALLENGE\",\"code\":\"123456\"}" | jq -r .session)
curl -s $VAULT/api/companies -H "authorization: Bearer $SESSION" -H "$JSON" \
-d '{"name":"Northwind","owner_email":"dana@example.com","owner_name":"Dana Owner"}'Keeping it
Two volumes, backed up apart
Everything the server keeps is in the tessaridb volume; the service key is in vault-keys. Back them up separately: the key derives every company's vault key, so a database restored without it cannot be opened, and a key kept with the database's backups gives whoever holds them one fewer lock to pick.
Without Docker
The binary beside a node
The server needs a TessariDB node, 0.39.3 or later (0.39.6 is current; 0.39.4 is withdrawn), an account on it that may edit one namespace, and the key file, which its group and others may not read. It refuses to start, naming the variable, when anything is missing.
docker/vault-account.sh in the repository holds the statements the store's owner runs once to declare that account.
| Variable | Default | What it is |
|---|---|---|
TESSARIDB_VAULT_STORE | required | the node's wire address, host:port |
TESSARIDB_VAULT_STORE_USER | required | the server's account on the node |
TESSARIDB_VAULT_STORE_PASSWORD | required | that account's password |
TESSARIDB_VAULT_STORE_AUTHORITY | none | a PEM file, for a node reached over TLS |
TESSARIDB_VAULT_SERVICE_KEY_FILE | required | the service key file |
TESSARIDB_VAULT_NAMESPACE | vault | the namespace it keeps everything in |
TESSARIDB_VAULT_DATABASE | main | the database inside it |
TESSARIDB_VAULT_LISTEN | 127.0.0.1:8080 | where it serves the pages and the API |
TESSARIDB_VAULT_PUBLIC_URL | none | the address people reach it at; needed for passkeys |
TESSARIDB_VAULT_PLATFORM_ADMIN_EMAIL, _NAME | none | the platform admin to ensure at start, both or neither |
TESSARIDB_VAULT_OIDC_ISSUER, _CLIENT_ID, _REDIRECT | none | an OpenID Connect issuer to sign in through, all three or none |
openssl rand -hex 32 > service-key && chmod 600 service-key
export TESSARIDB_VAULT_STORE=127.0.0.1:9080 TESSARIDB_VAULT_STORE_USER=vault
export TESSARIDB_VAULT_STORE_PASSWORD="$VAULT_STORE_PASSWORD" TESSARIDB_VAULT_SERVICE_KEY_FILE="$PWD/service-key"
export TESSARIDB_VAULT_PLATFORM_ADMIN_EMAIL=ops@example.com TESSARIDB_VAULT_PLATFORM_ADMIN_NAME="Platform Ops"
tessaridb-vaultFrom source
Building the binary
A Cargo workspace on Rust 1.98. The web application's built output is committed, so building the server never needs Node.
cargo build --release
./target/release/tessaridb-vault