hikyo
Documentation

Self-hosting baseline

Replace evaluation defaults with explicit production boundaries.

Production startup is fail-closed. Hikyo refuses to serve without an explicit datastore and root-key source. A non-loopback public listener requires native TLS or an explicit trusted-proxy boundary.

This page is the production checklist. Use the linked pages for the full configuration and recovery procedures.

For Kubernetes, use the complete Helm installation example.

Required decisions

BoundaryConfigureRule
DatastoreHIKYO_DBUse sqlite:PATH or an explicit PostgreSQL DSN.
Root key--root-key-file or a systemd credentialUse exactly one source; keep it outside the database backup.
Public originHIKYO_EXTERNAL_ORIGINSet the canonical HTTPS origin seen by browsers.
Networknative TLS pair, or reverse proxy plus HIKYO_TRUSTED_PROXY_CIDRSTerminate TLS natively by default; keep operational listener private.
BackupsHIKYO_BACKUP_RECIPIENTS and HIKYO_BACKUP_DIRConfigure recipients and destination together.

Build the production binary

Until Hikyo publishes a stable release, build from a reviewed commit:

npm install --global --ignore-scripts corepack@0.35.0
corepack enable
corepack install --global pnpm@11.24.0
pnpm --dir clients/ts install --frozen-lockfile
pnpm --dir web install --frozen-lockfile
pnpm --dir web build
go build -trimpath -tags ui -o ./hikyo ./cmd/hikyo
./hikyo version

Record the commit beside the deployed binary. Do not describe an unversioned development build as a supported release.

SQLite baseline

install -d -m 0700 /var/lib/hikyo /etc/hikyo
openssl rand -hex 32 | install -m 0600 /dev/stdin /etc/hikyo/root.key

HIKYO_DB=sqlite:/var/lib/hikyo/hikyo.db \
HIKYO_EXTERNAL_ORIGIN=https://hikyo.example.com \
./hikyo server \
  --listen 0.0.0.0:8443 \
  --operational-listen 127.0.0.1:8081 \
  --tls-cert-file /etc/hikyo/tls.crt \
  --tls-key-file /etc/hikyo/tls.key \
  --root-key-file /etc/hikyo/root.key

Install the TLS private key as mode 0400 or 0600. Renewals are detected by a 10-second file poll; SIGHUP reloads immediately. Failed reloads retain the last known-good certificate.

For reverse-proxy mode, omit the TLS flags, bind the public listener privately, set HIKYO_TRUSTED_PROXY_CIDRS to the exact proxy networks, and set HIKYO_EXTERNAL_ORIGIN explicitly. Do not expose that plaintext listener.

Setting an https external origin is also what turns HSTS on: Hikyo emits Strict-Transport-Security: max-age=31536000 whenever the configured public origin is https and its browser-visible host is not loopback, whether TLS is terminated natively or at a proxy whose Hikyo backend binds to loopback. Configure the proxy to pass that header through rather than adding its own. A proxy that appends a second Strict-Transport-Security, or overwrites it with a shorter max-age, gives browsers a policy nobody chose. If you want includeSubDomains or preload, own the header at the proxy and strip Hikyo’s; Hikyo does not send those directives because they commit hostnames it does not serve. See security response headers for the full carried set.

Check both probes through the private listener:

curl --fail http://127.0.0.1:8081/healthz
curl --fail http://127.0.0.1:8081/readyz

The same private listener serves /metrics in Prometheus text format — RED-style request counters and latency per surface class, in-flight and admission-pressure gauges, plus the retention and TLS gauges — with no external service dependency. It is unauthenticated; scrape it only from the host or a trusted network and never expose the operational bind. See metrics for the full list.

Then check the public HTTPS origin from outside the host. A local probe does not prove DNS, TLS, or reverse-proxy routing.

Back up two independent things

A database backup without the root key cannot decrypt Hikyo data. A root key without the database cannot reconstruct it. Store and test them through separate recovery paths.

PostgreSQL boundary

Remote PostgreSQL DSNs must name the host explicitly and use sslmode=verify-full or sslmode=verify-ca. Plaintext connections to a non-loopback database host are refused.

Use a dedicated database and role. Back up the Hikyo archive through hikyo backup export; a generic PostgreSQL dump does not replace Hikyo’s encrypted export and restore reconciliation workflow.

Root-key custody

The root key is exactly 32 random bytes encoded as 64 hexadecimal characters. Hikyo refuses a file readable by group or other.

Prefer a service-manager credential mounted for the process. A fixed protected file is the next tier. HIKYO_ROOT_KEY is the weakest tier because the value remains in the process environment.

Before real secret material

  1. Terminate TLS natively or name exact proxy CIDRs; keep the operational listener private. Set HIKYO_EXTERNAL_ORIGIN to the public https origin and do not double-set Strict-Transport-Security at the proxy.
  2. Store the root key through your service manager’s credential mechanism.
  3. Configure encrypted backups and perform a restore test.
  4. Create the first administrator on the server host.
  5. Review the security and support policies.

Continue with server configuration and backup and restore.