repovec-appliance ships Qdrant as an appliance-internal Podman Quadlet. Operators should treat it as a local dependency of the appliance rather than a general-purpose network service.
The checked-in Quadlet is installed to
/etc/containers/systemd/qdrant.container. It tracks the official Qdrant
docker.io/qdrant/qdrant:v1 image stream and enables AutoUpdate=registry so
the systemd-managed container can participate in Podman's registry-based
auto-update flow within the current major version.
Qdrant's REST and gRPC ports are published only on loopback:
- REST:
127.0.0.1:6333 - gRPC:
127.0.0.1:6334
Persistent vector storage lives at /var/lib/repovec/qdrant-storage on the
host and is mounted into the container at /qdrant/storage. The mount uses an
explicit :Z SELinux relabel so the rootful Podman service can write to the
directory on enforcing hosts.
Qdrant requires an API key. On first boot, repovec-qdrant-api-key.service
generates a random raw key at /etc/repovec/qdrant-api-key, restricts the file
to repovec:repovec with mode 0400, and refreshes the rootful Podman secret
repovec-qdrant-api-key. The Qdrant Quadlet injects that Podman secret as
QDRANT__SERVICE__API_KEY inside the container.
Operators can inspect service state without printing the key:
systemctl status repovec-qdrant-api-key.service qdrant.service
journalctl -u repovec-qdrant-api-key.service
stat -c '%U:%G %a %n' /etc/repovec/qdrant-api-key
podman secret inspect repovec-qdrant-api-key
Local clients authenticate by reading the key as the repovec user and sending
it in Qdrant's api-key header:
sudo -u repovec sh -c \
'api_key="$(cat /etc/repovec/qdrant-api-key)"
curl --config - http://127.0.0.1:6333/collections <<EOF
header = "api-key: ${api_key}"
EOF'
Requests to Qdrant without the api-key header are rejected.
Qdrant liveness at daemon startup
repovecd and repovec-mcpd validate Qdrant before they continue startup.
Each daemon reads /etc/repovec/qdrant-api-key, connects to Qdrant gRPC at
http://127.0.0.1:6334, checks the gRPC health service, and performs a
read-only authenticated collection-list request. This proves both process
readiness and API-key validity.
If the liveness check fails, the daemon exits immediately with status 1.
Inspect service state and journals without printing the key:
systemctl status qdrant.service repovecd.service repovec-mcpd.service
journalctl -u qdrant.service --no-pager | tail -40
journalctl -u repovecd.service --no-pager | tail -40
journalctl -u repovec-mcpd.service --no-pager | tail -40
stat -c '%U:%G %a %n' /etc/repovec/qdrant-api-key
Common failure classes are missing or unreadable API-key file, empty or invalid
key material, Qdrant not listening on 127.0.0.1:6334, Qdrant taking longer
than the configured probe timeout, and authentication failure. Regenerate or
repair the key file and Podman secret only when the journal points to an
API-key problem; connection failures normally require inspecting
qdrant.service.
Qdrant API-key provisioning behaviour
REPOVEC_DEBUG environment variable
Setting REPOVEC_DEBUG=1 enables debug-level log lines emitted to stderr by the
repovec-qdrant-api-key helper. When enabled, the helper logs lock
acquisition and release events alongside other diagnostic output. This
variable is intended for troubleshooting only. It must not be set in
production systemd service units, and the default behaviour (no debug output)
is safe for production.
Flock-based serialization
The repovec-qdrant-api-key helper serializes all mutable operations behind an
exclusive flock on /etc/repovec/repovec-qdrant-api-key.lock. Concurrent
invocations block until the lock is available, preventing races between user
creation, directory creation, secret inspection, key generation, and secret
creation. The lock file is owned by root:root and resides in /etc/repovec,
a root-owned directory with mode 0750 that is not world-writable. This
ensures that an unprivileged process cannot substitute the lock file to
interfere with serialization.
Fail-closed secret-removal behaviour
If podman secret rm fails for any reason other than the secret being in use,
the helper exits non-zero. The caller (systemd) sees a unit failure rather
than silently continuing with stale credentials. When the removal fails
because the secret is in use (podman secret rm reports "in use"), the helper
exits zero because the existing secret remains valid and does not need to be
replaced. This fail-closed invariant ensures that an unexpected removal error
never results in the Qdrant Quadlet running with an outdated or missing API key.
Qdrant Quadlet validation diagnostics
repovec_core::appliance::qdrant_quadlet exposes validate_qdrant_quadlet and
the public QdrantQuadletError type for checking the packaged Quadlet
contract. The validator reports the first contract violation it finds. Display
strings are stable operator diagnostics and use these formats:
The validator is a static contract check. It does not emit tracing spans, logs,
or metrics itself; callers should log or count the returned
QdrantQuadletError when they need runtime observability.
InvalidLine:invalid quadlet line {line_number}: {line}.PropertyBeforeSection:quadlet property before section on line {line_number}: {line}.MissingImage:missing Image= entry in [Container].ImageNotFullyQualified:image reference must be fully qualified and tagged: {image}.UnexpectedImage:image reference must remain docker.io/qdrant/qdrant:v1: {image}.MissingRestPort:missing PublishPort=6333 in [Container].MissingGrpcPort:missing PublishPort=6334 in [Container].PortNotBoundToLoopback:port {port} must be published on 127.0.0.1 only: {publish_port}.MissingStorageMount:missing persistent Qdrant storage mount.IncorrectStorageSource:storage source must be /var/lib/repovec/qdrant-storage: {source}.IncorrectStorageTarget:storage target must be /qdrant/storage: {target}.MissingSelinuxRelabel:storage mount must include SELinux relabel :Z: {volume}.MissingAutoUpdate:missing AutoUpdate= entry in [Container].IncorrectAutoUpdate:AutoUpdate must remain registry: {auto_update}.MissingApiKeyProvisioningDependency:
missing {directive}=repovec-qdrant-api-key.service dependency for Qdrant API-key provisioning
IncorrectApiKeyProvisioningDependency:
{directive} must include repovec-qdrant-api-key.service for Qdrant API-key provisioning: {dependency}
MissingApiKeySecret:missing Secret=repovec-qdrant-api-key,type=env,target=QDRANT__SERVICE__API_KEY.IncorrectApiKeySecret:
Qdrant API-key secret must be repovec-qdrant-api-key,type=env,target=QDRANT__SERVICE__API_KEY: {secret}
InlineApiKeyEnvironmentDisallowed:Qdrant API keys must use a Podman secret, not inline Environment=<redacted>.