Skip to content

Latest commit

 

History

128 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Trove

Read-only service catalogue for Docker, Kubernetes, Proxmox, and Linux.
Know what's running without giving it the keys.

CI Release Trove Wiki License: MIT

Trove is an automatically discovered, read-only inventory of everything running in your homelab. Small agents sit next to your workloads — Docker hosts, Kubernetes clusters, Proxmox nodes, plain Linux boxes — and push what they see to one Trove service catalogue: what's running, where it lives, whether it's healthy, whether its image is outdated, and whether it is still reporting.

Trove is the place to start an investigation, not the place to make a change. It links the facts across your homelab without becoming a homepage, Grafana, Portainer, or an infrastructure management interface.

Built by Techdox.

Trove dashboard: needs attention, infrastructure summary, service catalogue, and recent history

Dashboard shown with public fixture data. It contains example services only, never a real homelab.

Read-only by design. Trove can never deploy, restart, exec into, or edit anything. There is no code path that mutates a workload — agents only ever issue read/list calls to their platforms. This is an architectural constraint, not a feature toggle, and it's the project's one hard rule.

Features

  • Service catalog across platforms — containers, K8s workloads (with pods nested under their Deployments), Proxmox VMs/LXCs, and systemd units, all in one normalized view grouped by host.
  • Health + heartbeats — platform health where it exists (Docker healthchecks, K8s readiness), plus server-side staleness: an agent that goes quiet flags itself and all its services within ~90 seconds.
  • Host condition + resources — reporting health stays separate from the platform's host condition. Proxmox and Linux hosts surface CPU, load, memory, disk, and uptime; local Docker agents report the kernel metrics they can observe truthfully; Kubernetes rolls up node readiness plus CPU/memory when Metrics API is available. Open the dedicated host-stats drawer from each host.
  • Image freshness — the server checks registries (batched, cached, rate-limit-aware) and badges services whose running image is behind its tag.
  • Alerts & digest — instant notifications via webhook / Discord / ntfy when a host stops reporting, a service goes unhealthy or dies, or an image falls behind — with recovery notices, flap suppression, and a scheduled email digest. See docs/alerts.md.
  • Operational dashboard — a calm needs-attention queue first, then infrastructure and the full catalogue; recent changes stay available as history rather than competing with current problems.
  • Fast, keyboard-friendly UI — no framework, auto-refreshing; use / to filter, j/k to move, and enter to open details.
  • Trivial to operate — one static binary (or container) per role, SQLite storage, automatic schema migrations, push-model agents that work from behind NAT.

Documentation

Use this README for installation, quickstarts, and the configuration reference. Versioned operational guidance lives in the repository:

The wiki is for discoverable walkthroughs, screenshots, and community-oriented guides. It links back to the repository for version-specific commands, configuration, authentication, upgrades, and security details.

Quickstart (5 minutes)

Trove is a server (the dashboard + API) plus one agent per platform you want to watch. The server is the same everywhere; only the agent differs. Start with the compose file that matches what you're watching — each one stands up the server and the right agent together. Requires Docker with Compose on the machine that will host the dashboard, and a user account that can run Docker without sudo. Check that first with docker ps; if it reports permission denied, follow Docker's post-install steps for your distribution and open a new shell before continuing.

Docker host — server + an agent watching this box's containers:

mkdir trove && cd trove
curl -fsSLO https://raw.githubusercontent.com/techdox/trove/main/examples/docker-compose.yml

# Save the agent's token to .env — Compose loads it automatically and it
# survives restarts and upgrades. (Don't just `export` it: a new shell would
# lose it, and re-running with a fresh token silently breaks the agent.)
umask 077
echo "TROVE_TOKEN=trove_$(openssl rand -hex 24)" > .env
docker compose up -d

Proxmox VE — server + an agent watching your cluster's VMs and LXCs. First create a read-only API token (the Proxmox guide has the exact pveum commands), then:

mkdir trove && cd trove
curl -fsSLO https://raw.githubusercontent.com/techdox/trove/main/examples/docker-compose.proxmox.yml

# Save settings to .env (Compose loads it automatically; it persists across
# restarts). TROVE_TOKEN is Trove's own agent token; TROVE_PROXMOX_TOKEN is
# your Proxmox API token — two different credentials.
umask 077
{
  echo "TROVE_TOKEN=trove_$(openssl rand -hex 24)"
  echo "TROVE_PROXMOX_URL=https://YOUR-PVE-HOST:8006"
  echo "TROVE_PROXMOX_TOKEN=trove@pve!trove-agent=YOUR-TOKEN-SECRET"
} > .env
chmod 600 .env
# If PVE uses its default private CA, copy /etc/pve/pve-root-ca.pem from a node
# to ./pve-root-ca.pem and uncomment the CA lines in the Compose file.
# now edit .env to fill in your real PVE host and API token, then:
docker compose -f docker-compose.proxmox.yml up -d

Kubernetes or bare-metal Linux — the agent doesn't run in Compose (the K8s agent runs in-cluster as a Deployment; the bare-metal agent runs as a systemd unit). Stand up just the server — docker-compose.server.yml runs the server with no bundled agent — then deploy the agent from the Kubernetes or bare-metal guide.

The compose files auto-register this first agent from TROVE_TOKEN (via TROVE_BOOTSTRAP_*), so you don't run agent create for it — every additional host gets its own token (below).

Open http://localhost:8080. Your services appear within ~30 seconds. First, check Needs attention: a healthy first report shows a calm all-clear state; an agent that stops reporting becomes stale and then offline. A newly registered agent whose token has never been accepted remains unknown; its logs show the server's 401 response.

If an agent does not show up, watch it connect with docker compose logs -f agent (add -f docker-compose.proxmox.yml if you used the Proxmox file).

⚠️ By default, the dashboard and read APIs are open. Keep Trove on a trusted network (LAN/VPN/tailnet), put it behind an authenticating reverse proxy, or enable native OIDC. See Dashboard authentication.

Adding more hosts and platforms

Each host or platform you watch runs its own agent — a separate process or container, with its own image and its own token. You don't repoint an existing agent at a new platform; you run another one. (Setting TROVE_PROXMOX_* on the Docker agent, for example, does nothing — it's a different agent image; it will connect, look healthy, and never report your Proxmox guests.)

Mint a token per agent, on the server:

# server running via Docker Compose (the quickstart):
docker compose exec server trove-server agent create <name>

# server running as a bare-metal binary — point at the SAME database the server
# uses, or the token lands in a throwaway ./trove.db and the agent can't auth
# (the systemd unit sets TROVE_DB=/var/lib/trove/trove.db):
sudo TROVE_DB=/var/lib/trove/trove.db trove-server agent create <name>
# e.g. <name> = docker-nas, k8s-homelab, proxmox

If an agent token is exposed or the host changes hands, rotate it with trove-server agent rotate <name>. Rotation immediately invalidates the old token, without deleting the agent or its history. Follow the platform-specific maintenance-window rotation guide before running the command.

Then follow the guide for the platform:

Platform Agent Guide
Docker host trove-agent-docker docs/agents/docker.md
Kubernetes cluster trove-agent-k8s docs/agents/kubernetes.md
Proxmox VE cluster trove-agent-proxmox docs/agents/proxmox.md
Bare-metal Linux (systemd) trove-agent-local docs/agents/local.md

Container images (multi-arch amd64/arm64) live on GHCR: ghcr.io/techdox/trove-server, ghcr.io/techdox/trove-agent-docker, ghcr.io/techdox/trove-agent-k8s, ghcr.io/techdox/trove-agent-proxmox. Static binaries for everything (including the bare-metal agent) are on the releases page.

How it works

  docker host          k8s cluster         proxmox            nas (systemd)
 ┌────────────┐      ┌────────────┐      ┌────────────┐      ┌────────────┐
 │ agent      │      │ agent      │      │ agent      │      │ agent      │
 └─────┬──────┘      └─────┬──────┘      └─────┬──────┘      └─────┬──────┘
       │    POST /api/v1/report (Bearer token, every 30s)          │
       └───────────────┬───┴──────────────┬────────────────────────┘
                       ▼                  ▼
                  ┌─────────────────────────────┐
                  │ trove-server                │
                  │  SQLite · REST · dashboard  │
                  └─────────────────────────────┘
  • Agents, hosts, services: an agent is one connection to the server (one token). It reports one or more hosts — a Docker host, each Proxmox node, a whole cluster — and each host has services (containers, VMs/LXCs, pods, systemd units). A Docker agent reports one host; one Proxmox agent reports every node in its cluster. On the dashboard, services are grouped by host.
  • Push model: agents POST full-state snapshots on an interval. The server never reaches into your infrastructure — homelab/NAT friendly.
  • Heartbeats: agents and hosts are tracked independently. Miss 3 intervals → stale; miss 10 → offline. Services follow their host's status, so one healthy host cannot hide another missing host from the same agent. Thresholds scale with each agent's own interval.
  • Full-state reports are idempotent and tolerate lost pushes. Services that disappear are soft-removed and pruned after 24h (configurable, TROVE_REMOVED_RETENTION).

Server install options

Docker Compose — the quickstart above; data lives in the trove-data volume.

Bare metal — download the trove-server archive for your arch from the latest release (the trove-server.service unit is bundled inside it):

# pick the URL for your arch off the releases page, e.g.:
VERSION=0.17.1       # x-release-please-version; check https://github.com/techdox/trove/releases/latest for newer releases
curl -fLO "https://github.com/techdox/trove/releases/download/v${VERSION}/trove-server_${VERSION}_linux_amd64.tar.gz"
tar xzf trove-server_${VERSION}_linux_amd64.tar.gz

sudo install -m 0755 trove-server /usr/local/bin/
sudo cp deploy/systemd/trove-server.service /etc/systemd/system/
sudo systemctl enable --now trove-server

The server listens on :8080 and stores its database at /var/lib/trove/trove.db (the unit creates that directory via StateDirectory). Mint agent tokens against that same DB — see Adding more hosts.

Go install (needs Go 1.26+):

go install github.com/techdox/trove/cmd/trove-server@latest

Configuration reference

trove-server

Variable Default Purpose
TROVE_ADDR :8080 Listen address.
TROVE_DB trove.db SQLite file path (containers default to /data/trove.db).
TROVE_FRESHNESS_ENABLED true false disables image-freshness checking.
TROVE_FRESHNESS_INTERVAL 5m How often to scan for images due a check.
TROVE_FRESHNESS_TTL 6h How long a resolved digest counts as fresh before rechecking.
TROVE_REGISTRY_AUTHS (unset) Credentials for private registries — see below.
TROVE_REGISTRY_PRIVATE_HOSTS (unset) Comma-separated private registry host[:port] allowlist. Hosts in TROVE_REGISTRY_AUTHS are allowed automatically.
TROVE_HEALTH_DETAILS_ENABLED false Explicitly retain and display bounded, redacted platform health messages.
TROVE_EVENT_RETENTION 720h (30d) How long events (activity feed / alert stream) are kept.
TROVE_REMOVED_RETENTION 24h How long removed services linger before being purged.
TROVE_HOST_RETENTION 720h (30d) How long a silent host and its remaining inventory are retained.
TROVE_ALERT_* / TROVE_SMTP_* (unset) Notification channels & SMTP — see docs/alerts.md.
TROVE_DIGEST daily@08:00* Digest schedule; *only takes effect once TROVE_SMTP_* is set — see docs/alerts.md.
TROVE_BOOTSTRAP_AGENT / TROVE_BOOTSTRAP_TOKEN (unset) Seed one agent at startup (used by the quickstart compose).

Dashboard authentication (OIDC)

By default the dashboard and read APIs are open — bind to a trusted network or front with a reverse proxy. For native authentication, configure any OIDC-compatible provider (Authentik, Keycloak, Auth0, Google, Dex, etc.):

Variable Purpose
TROVE_OIDC_ISSUER OIDC discovery URL, e.g. https://auth.example/application/o/trove/
TROVE_OIDC_CLIENT_ID OAuth2 client ID registered with your IdP
TROVE_OIDC_CLIENT_SECRET OAuth2 client secret
TROVE_OIDC_REDIRECT_URL Callback URL, e.g. https://trove.example/oauth2/callback
TROVE_API_TOKEN (optional) Random bearer token of at least 32 characters for programmatic API access (bypasses OIDC)
TROVE_OIDC_SESSION_MAX_AGE (optional) Session duration (default 8h)

OIDC is enabled only when all four required TROVE_OIDC_* settings are present. If any required setting is present while another is missing, the server fails startup and names the missing variables instead of leaving the dashboard open. TROVE_API_TOKEN is valid only alongside a complete OIDC configuration.

Generate the optional API token with openssl rand -hex 32; Trove rejects short tokens and known documentation placeholders at startup. Provider setup, login/logout behaviour, API-token examples, verification, and troubleshooting are owned by docs/authentication.md. Agent ingest (POST /api/v1/report) and /healthz remain outside OIDC.

Private registry / Docker Hub credentials for freshness checks:

TROVE_REGISTRY_AUTHS='{"docker.io":{"username":"me","password":"dckr_pat_..."},"gitea.example.com":{"username":"me","password":"...","auth_realm_hosts":["sso.example.com"]}}'

Private IP ranges are denied by default. A host configured in TROVE_REGISTRY_AUTHS is an explicit private-network allowlist entry. For an anonymous private registry, set its exact endpoint separately, for example TROVE_REGISTRY_PRIVATE_HOSTS=registry.lan:5000. Loopback, link-local/cloud metadata, unspecified, and multicast destinations remain blocked even when listed. Registry credentials are sent to a separate bearer-token realm only when that realm is the registry itself, Docker Hub's standard auth service, or an exact auth_realm_hosts entry. Those explicitly trusted realm hosts are also eligible to resolve to a private address.

Docker Hub's anonymous rate limits are generous for Trove's batched, cached checks at homelab scale, but if you run many distinct Hub images, adding a (free) Hub account raises the ceiling.

Agents — common to all

Variable Default Purpose
TROVE_SERVER_URL (required) Base URL of the server.
TROVE_TOKEN (required) Bearer token from trove-server agent create.
TROVE_INTERVAL 30s Push interval (30s, 1m, or bare seconds 30).
TROVE_AGENT_NAME hostname Informational; not used for the dashboard display name (see below). For the bare-metal agent specifically, it (or the OS hostname) becomes the reported host name.

The name an agent appears under on the dashboard is the one you chose in trove-server agent create <name> — not TROVE_AGENT_NAME. Platform-specific settings are covered in each agent guide.

Managing agents

Deleting an agent is an intentional server-side catalogue cleanup. It does not stop or change anything on the infrastructure the agent used to observe.

trove-server agent create <name>    # mint a token (shown once, stored hashed)
trove-server agent list             # names, platform, status, last seen
trove-server agent delete <name>    # remove an agent and all its data
trove-server alert test             # test every configured channel + send a sample digest

On a Docker Compose server, run these inside the container, e.g. docker compose exec server trove-server agent create <name>. On a bare-metal server, set TROVE_DB to the server's database path (see Adding more hosts).

API

Method & path Auth Purpose
POST /api/v1/report Bearer Agent pushes a full-state report.
GET /api/v1/services OIDC or optional API token Services grouped by host (dashboard data).
GET /api/v1/agents OIDC or optional API token Agents with derived heartbeat status.
GET /api/v1/events OIDC or optional API token Recent state-change events (?limit=&offset=&kind=&since=).
GET /api/v1/me OIDC or optional API token Current dashboard/API auth state.
GET /metrics OIDC or optional API token Prometheus text metrics.
GET /healthz none Database and enabled-worker health.

Pagination, filtering, and metrics details are in docs/api.md.

The wire contract lives in pkg/model — the one package agents import. Building an agent for a new platform means implementing one interface; see CONTRIBUTING.md.

Security model

  • Agent ingest is authenticated with per-agent bearer tokens (256-bit random, stored only as SHA-256 hashes). Revoke by deleting the agent.
  • The dashboard and read APIs support optional OIDC authentication. When all four required OIDC settings are set, the dashboard and all read APIs require a valid OIDC session. Partial configuration fails startup. When all authentication settings are unset, the dashboard is open — bind to a trusted network or front it with an authenticating reverse proxy. See Dashboard authentication.
  • Agents cannot change anything on the platforms they watch — read-only is enforced in code, not convention. Details in SECURITY.md.
  • Tagged binaries and container images ship with checksums, SPDX SBOMs, provenance, and keyless GitHub attestations. See Release integrity and provenance for the policy and verification commands.

Upgrades & backup

Schema migrations are automatic and additive, but the SQLite database is durable state and a verified backup is the rollback path. Upgrade the server before its agents.

The canonical procedure is docs/upgrades.md: it owns the Compose, systemd, and go install commands; trove-server doctor; backup creation and read-only verification; retention examples; restore rehearsal; and rollback.

Building from source

git clone https://github.com/techdox/trove.git && cd trove
make native   # all binaries for your host platform → bin/
make build    # cross-compile linux amd64+arm64
make test     # go test ./...
docker compose up --build   # contributor dev stack

Pure Go, no CGO, no frontend build step — the dashboard is vanilla JS embedded into the server binary.

Roadmap & contributing

Current focus: operator confidence and the stability contract on the path to v1.0.0. Helm packaging and certificate-expiry monitoring remain post-1.0 — see ROADMAP.md for the gates and sequencing. Contributions welcome: start with CONTRIBUTING.md.

License

MIT © Techdox

About

Automatically discovered, read-only service catalogue for Docker, Kubernetes, Proxmox, and Linux.

Resources

Contributing

Security policy

Stars

57 stars

Watchers

0 watching

Forks

Releases

Sponsor this project

Packages

Contributors

Languages