The appliance provisions a private on-disk tree owned by the repovec service
account. repovec-provision.service creates and enforces these directories at
target start, and both daemons verify them again at startup:
| Path | Owner | Mode |
|---|---|---|
/var/lib/repovec |
repovec:repovec |
0700 |
/var/lib/repovec/git-mirrors |
repovec:repovec |
0700 |
/var/lib/repovec/worktrees |
repovec:repovec |
0700 |
/var/lib/repovec/.grepai |
repovec:repovec |
0700 |
/var/lib/repovec/qdrant-storage |
root:root |
0700 |
/etc/repovec |
root:repovec |
0750 |
The data tree holds private repository mirrors, worktrees, and derived indexes.
These directories are intentionally not world- or group-readable: only the
repovec service account (via owner access), root, and — for
qdrant-storage — the rootful Podman Qdrant container may touch them.
qdrant-storage stays root:root because Qdrant runs as uid 0 under rootful
Podman and is the only filesystem accessor; the daemons reach Qdrant over
loopback gRPC only.
/etc/repovec holds secrets. It is 0750 root:repovec: root owns the
directory so the repovec user can read but cannot change directory
permissions or replace secret files; the files themselves are
0400 repovec:repovec. The directory is provisioned by the
repovec-qdrant-api-key helper, not by the tmpfiles.d asset — /etc/repovec
has exactly one provisioning authority.
Operators must not loosen these modes or change the ownership or group. A loosened mode or a re-owned directory is a confidentiality violation, and the daemons refuse to start when the live ownership, group, or confidentiality check on any of these directories fails. Restore the documented mode and owner/group (or recreate the directory) and restart the target; see the startup logging section below for the diagnostic shape.
The repovec system user itself is declared by the sysusers asset with home
/var/lib/repovec and shell /usr/sbin/nologin (a locked, non-interactive
shell). No numeric uid/gid is pinned; systemd-sysusers allocates the account.
Startup validation logging
Both repovecd and repovec-mcpd validate their checked-in systemd unit
contracts, then the live directory-layout contract, then Qdrant liveness at
startup before starting any async work. The outcomes are observable in the
systemd journal:
Success — a TRACE-level event followed by a DEBUG-level confirmation:
TRACE systemd unit contract validated
DEBUG systemd unit contract validated at daemon startup
Failure — an ERROR-level event with structured fields identifying the
violating unit and the nature of the failure, followed by a non-zero process
exit:
ERROR systemd unit contract violation — aborting startup
unit=repovecd.service
error=repovecd.service is missing [Service]
The unit field contains the logical systemd unit name (e.g.
repovecd.service) and the error field contains the human-readable
description of the contract violation. The Qdrant Quadlet validator emits
INFO, WARN, and ERROR events; use a target-scoped filter such as
RUST_LOG=repovec_core::qdrant_quadlet=info to inspect those validation
events. The systemd unit validator emits TRACE, DEBUG, and ERROR events;
use RUST_LOG=repovec_core::systemd_units=trace when startup ordering or
unit-contract diagnostics require the lower-level trace.
Directory-layout failure — an ERROR-level event with the violating path,
followed by a non-zero process exit:
ERROR live directory layout violation - aborting startup
path=/var/lib/repovec/worktrees
error=/var/lib/repovec/worktrees must be owned by repovec (uid 998): uid 0
The path field names the directory whose ownership, group, mode, type, or
presence violates the contract; the error field states the expected value and
the account or mode that is actually present. The live pre-flight runs after
the static unit-contract validation and before the Qdrant liveness wait, so a
misprovisioned host is rejected before any daemon-side network work begins.
Concrete grepai indexer instances also start after and require both Qdrant and
repovecd.