# Blindspark by HiveRelay — Umbrel App Store packaging.
#
# Conformance notes for Umbrel reviewers:
# - Multi-arch image (linux/amd64, linux/arm64), pinned by sha256 digest
# per Umbrel's reproducibility requirement. The `image:` ref below is
# name:tag@sha256:<digest>; the digest is authoritative and is rewritten
# to the freshly-built manifest digest at release time by
# `npm run release:prepare -- <version> --image-digest ...`. CI
# (.github/workflows/umbrel-app-validate.yml) fails the build if this ref
# ever regresses to a tag-only reference (audit HR-DIS-002).
# - The relay process runs non-root (uid/gid 999). The image entrypoint
# starts as root only to chown the bind-mounted /data, then drops to 999
# via gosu before exec'ing node — so no `user:` pin is set here (pinning
# one would block the chown and crash on first start with EACCES).
# - Persistent state lives under ${APP_DATA_DIR}/data and survives
# reinstalls. The relay's identity + management token are derived from
# Umbrel's $APP_SEED, so a reinstall restores the same relay.
# - Only the dashboard port (9100) is fronted by app_proxy. No host ports
# are published — the management UI is reachable solely through the
# authenticated proxy, which is the security boundary that makes
# HIVERELAY_UI_EXPOSE_TOKEN safe (see below).
services:
app_proxy:
environment:
APP_HOST: blindspark_web_1
APP_PORT: 9100
web:
# Pinned by immutable digest (name:tag@sha256:...). The digest is
# authoritative — Docker resolves and verifies it, so a moved or
# re-pushed tag can never change what runs here. `release:prepare`
# rewrites this line to the freshly-built multi-arch manifest digest at
# release time (--image-digest). Do NOT hand-edit down to a bare `:tag`:
# that reintroduces the audited supply-chain gap (HR-DIS-002) and CI
# will reject it. This baseline pin is the published v0.24.3 multi-arch
# index; the next `release:prepare` replaces both tag and digest together.
image: ghcr.io/bigdestiny2/p2p-hiverelay:0.24.3@sha256:cb104aa65d7e8f57766ea7d60d64dbb6b081a0b9fc5b318c0fa75cb22c0d31c8
init: true
restart: on-failure
stop_grace_period: 1m
# No user: pin — the image entrypoint starts as root, fixes the
# bind-mounted /data ownership, then drops to uid 999 (gosu). Pinning a
# user here would prevent that chown and reintroduce an EACCES crash on
# first start.
volumes:
- ${APP_DATA_DIR}/data:/data
environment:
# Home for config + storage — everything persists on the data volume
# (config.json, the corestore, the relay keypair).
HOME: /data
HIVERELAY_LOG_LEVEL: info
# Serve the single-page Blindspark appliance dashboard instead of the
# full multi-tab operator UI. No Docs/GitHub, no payments/calculator/
# leaderboard tabs — just identity + live status. The full dashboard
# ships in the same image for PC node operators (flag off). See
# packages/core/config/default.js -> ui.simple.
HIVERELAY_UI_SIMPLE: "true"
# Authenticate the dashboard/wizard behind Umbrel's app_proxy. The
# relay embeds a management token (derived from $APP_SEED) into the
# HTML it serves; the bundled UI sends it back as a bearer credential.
# This is safe ONLY because the API port is reachable solely through
# the authenticated app_proxy and is never published to the host/LAN.
# See packages/core/config/default.js -> ui.exposeToken.
HIVERELAY_UI_EXPOSE_TOKEN: "true"
# Home-server sovereignty default: queue incoming seed requests for
# operator review until the owner explicitly switches modes in setup or
# from the dashboard. This avoids a fresh Umbrel install silently filling
# disk by auto-accepting the public network.
HIVERELAY_ACCEPT_MODE: review
# Conservative home-server storage cap. PC/VPS operators keep the core
# 50 GB default or set --max-storage, but Umbrel installs start smaller
# to avoid surprising typical home boxes.
HIVERELAY_MAX_STORAGE: 10GB
# Deterministic, reinstall-safe identity + management token. Umbrel
# injects $APP_SEED (derived from the user's Umbrel seed and this app
# id); the relay reads it from the container environment.
APP_SEED: ${APP_SEED}