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
| Boundary | Configure | Rule |
|---|---|---|
| Datastore | HIKYO_DB | Use sqlite:PATH or an explicit PostgreSQL DSN. |
| Root key | --root-key-file or a systemd credential | Use exactly one source; keep it outside the database backup. |
| Public origin | HIKYO_EXTERNAL_ORIGIN | Set the canonical HTTPS origin seen by browsers. |
| Network | native TLS pair, or reverse proxy plus HIKYO_TRUSTED_PROXY_CIDRS | Terminate TLS natively by default; keep operational listener private. |
| Backups | HIKYO_BACKUP_RECIPIENTS and HIKYO_BACKUP_DIR | Configure 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 versionRecord 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.keyInstall 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/readyzThe 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
- Terminate TLS natively or name exact proxy CIDRs; keep the operational listener private.
Set
HIKYO_EXTERNAL_ORIGINto the public https origin and do not double-setStrict-Transport-Securityat the proxy. - Store the root key through your service manager’s credential mechanism.
- Configure encrypted backups and perform a restore test.
- Create the first administrator on the server host.
- Review the security and support policies.
Continue with server configuration and backup and restore.