Skip to content

Quickstart (Docker)

This is the fastest path from nothing to your first search. You will run HeliosLogs in a container, log in, send a few events, and query them.

For a from-source build, see Install from source.

1. Run the container

HeliosLogs ships as a single container image. Build it from the repo and run it with two persistent volumes — one for data, one for the secret keys:

bash
# Build the image (first time only).
make build
# Equivalent to: docker build -t helios:latest .

# Run it.
make run

make run is a thin wrapper around:

bash
docker run -p 7300:7300 \
  -v helios-data:/app/data \
  -v helios-secret:/app/secret \
  -e [email protected] \
  -e HELIOS_ADMIN_PASSWORD=changeme \
  helios:latest
  • -p 7300:7300 publishes the HTTP API and UI.
  • helios-data holds the log partitions and (single-node) control plane.
  • helios-secret holds the encryption and JWT keys — keep this volume.
  • HELIOS_ADMIN_EMAIL / HELIOS_ADMIN_PASSWORD bootstrap the first admin user.

Build dependencies

The default image is a FIPS build and compiles the AWS-LC validated module, so the first make build needs Go, Perl, and CMake in the build environment (already present in the rust:1-bookworm build stage). Subsequent builds are cached. See FIPS 140-3.

Open http://localhost:7300.

2. Log in

Because you set HELIOS_ADMIN_PASSWORD, an admin user already exists — log in with the email and password you passed.

No admin password?

If you start HeliosLogs without HELIOS_ADMIN_PASSWORD and no users exist yet, the browser shows a one-time setup wizard instead: the first visitor claims the instance by creating the admin account. Either path works — see First steps.

3. Send your first events

HeliosLogs accepts newline-delimited JSON (NDJSON) — one event per line — on POST /api/ingest. Each event routes to a (env, index, day) partition by its timestamp:

bash
curl -X POST 'http://localhost:7300/api/ingest?env=default&index=adhoc' \
  --data-binary @- <<'JSON'
{"timestamp":"2026-06-14T18:00:00Z","level":"INFO","service":"web","message":"hello from curl"}
{"timestamp":"2026-06-14T18:00:01Z","level":"ERROR","service":"web","message":"goodbye","error_type":"DeadlineExceeded","status":504}
JSON
# {"ingested":2,"errors":0}

You don't have to declare any of those fields first — level, service, error_type, and status are all immediately queryable. That's schema-on-read.

4. Or load sample data

Prefer to explore with a realistic dataset? On a fresh install the search page offers a Load sample data button (an admin action that ingests a generated set of events). Click it and HeliosLogs will poll until the data appears.

5. Run your first searches

Go to Search and try these, picking a time range (top-right) that covers your events:

QueryFinds
errorevents containing "error" anywhere in the message
level:ERRORevents whose level field is ERROR
service:web status:504implicit AND across two fields
level:ERROR | stats count by serviceerror counts per service (table mode)

Click a field value in the left field panel to filter by it; drag across the histogram to zoom into a time window.

Where to go next