Skip to main content
The Vexlo server is one Go binary, vexlo. It ingests records from relay daemons, owns storage, and serves the /v1 API and the UI from one address. This page builds it, starts it, and explains every flag vexlo serve and vexlo check take. Tokens are on Authentication and tokens; the daemon that feeds the server is on The relay daemon. Flags are spelled with a single dash throughout, as the binary’s own -h output prints them. The binary accepts the double-dash spelling too.

Requirements

The server repository is not yet public, so the build starts from a checkout rather than a download. It needs:
  • Go 1.27
  • Node.js 22.12 or later, for the UI that the binary embeds
  • A C toolchain. The SQLite driver is cgo, and the Makefile exports CGO_ENABLED=1 for every target that needs it.

Build

make build has to run before a bare go build ./... works: the server embeds the built UI with //go:embed, so web/dist must exist before the Go build that embeds it can compile. Running the binary with no arguments lists its commands and exits 1:
Every command below is written vexlo. From a checkout that is bin/vexlo, unless bin/ is on your PATH.

The six commands

Each leaf command prints its own flags: vexlo serve -h, vexlo check -h, vexlo relay run -h, vexlo relay status -h, vexlo token create -h (and list, revoke), vexlo policy set -h (and show). Each exits 1 after printing, and its last line reads vexlo: flag: help requested. vexlo token -h, vexlo policy -h, vexlo relay -h, and vexlo -h print no flags: each reads -h as a command name it does not recognize, prints the names it does accept, and exits 1.

Run the server

With no flags the server binds 127.0.0.1:8080, applies its database migrations on startup (a fresh, empty database file needs no separate migration step), and stores everything under ~/.vexlo/data: the SQLite file vexlo.db and the value store directory values/. That directory is the server storage directory. vexlo serve resolves it from -db-path and -value-store-dir, each falling back to its own environment variable, then to VEXLO_DATA_DIR, then to ~/.vexlo/data. It never reads the -data-dir flag vexlo token takes, so a token minted under an explicit -data-dir is found on the first start only when the server names the same directory. The first log line records the eight settings it names and no others: the bind address, whether TLS is required, -no-auth and -header-trust, the two storage paths, and the two retention settings. -team, -tls-cert, -tls-key, and -allow-insecure-http never appear in it. The request log lines that follow are omitted here. The run below bound a non-default port and named a scratch server storage directory with -db-path and -value-store-dir:
Every request is logged with its method, path, status, duration, and request id; the Authorization header is never logged. Ctrl-C (SIGINT) or SIGTERM stops the server: new requests are refused and in-flight ones get 30 seconds to finish. On a clean drain the last line is msg="serve: shutting down" and the exit code is 0. A request still running after those 30 seconds is abandoned, and the process exits 1 with an error on its last line instead.

Loopback or TLS

The server refuses to bind a non-loopback address without a TLS certificate. Loopback means a host of 127.0.0.1, ::1, or localhost, matched as a string once it is lowercased and a trailing dot is dropped, never resolved through DNS. vexlo check applies the same rule as vexlo serve and reports it without opening a port:
The refusal names the three ways forward.
Pass -tls-cert and -tls-key (or VEXLO_TLS_CERT_FILE and VEXLO_TLS_KEY_FILE). Both files are loaded at startup, so a missing or malformed pair fails vexlo check and vexlo serve alike rather than a first request. A supplied certificate is always used, even on a loopback bind. The certificate below is self-signed, on a loopback address:
A plain http:// request to that port is answered 400 Bad Request with the body Client sent an HTTP request to an HTTPS server.

Check the configuration

vexlo check resolves the identical configuration vexlo serve would run with, validates it, reports free disk on the value store’s filesystem, and prints the retention arithmetic. It never opens the database or the value store. Run it with the same flags and environment you will start the server with. On the default retention settings it exits 1. A 20 GiB value budget at the default expected write rate of 2 traces per second holds about 104 hours of values, and the default shape retention is 168 hours, so every trace would lose its values before it ages out of search. The run below names a scratch server storage directory; the defaults are ~/.vexlo/data/vexlo.db and ~/.vexlo/data/values:
For a first run on one machine, -allow-overcommit is the lever to pick. The check then exits 0 and prints the same arithmetic with one extra line:
vexlo serve has no -allow-overcommit flag and applies no overcommit check of its own: it starts on the configuration vexlo check rejects. The check is where the arithmetic is read. -expected-write-rate changes the figure the arithmetic is computed at. vexlo check has no live traffic to measure it from, so a production estimate has to be passed in.

Flag reference

Both commands share one flag set; check adds two of its own. The serve -h output as printed:
-db-path and -value-store-dir render their placeholder as vexlo token; both take a path. The phrase is the help text’s reference to vexlo token’s own storage, picked up as the value name.
vexlo check -h prints the same flags plus -allow-overcommit and -expected-write-rate:
Four flags have no environment-variable form: -shape-retention-days, -value-budget-bytes, -allow-overcommit, and -expected-write-rate. The rest resolve flag first, then environment variable, then default; -db-path and -value-store-dir take one step more, VEXLO_DATA_DIR, before that default. The three boolean environment variables (VEXLO_ALLOW_INSECURE_HTTP, VEXLO_NO_AUTH, VEXLO_HEADER_TRUST) count as set for any value other than empty, 0, or false, case-insensitive. -no-auth, -team, -header-trust, and -header-trust-secret are explained on Authentication and tokens.

Retention

Shape (traces, steps, attempts, tags) is kept by day count, -shape-retention-days, default 7. Values are kept against the byte budget, -value-budget-bytes, default 20 GiB: when the budget is full the oldest values go first, and the trace keeps its shape. The function index (observed callers and callees per function) is kept for 90 days and has no flag. vexlo check’s “effective value retention” line is how long values last at the expected write rate, which is the number to compare against the shape retention.