Running the sidecar producer
A local walkthrough of RUNTIME_MODE=pgconsole-sidecar: the filesystem profile
is the hard part, so this tutorial builds it explicitly before starting the
producer.
This is an integration-development exercise. No pgConsole/ObjectStoreViewer runtime pair is qualified or advertised as supported — see the sidecar profile.
1. Create the socket directory
The producer refuses to create its socket unless the directory is a real
directory, setgid, at least 02770, and group-owned by a group the process
belongs to.
sudo mkdir -p /var/run/objectstoreviewer
sudo chgrp "$(id -g)" /var/run/objectstoreviewer
sudo chmod 2770 /var/run/objectstoreviewer
In Kubernetes this is an emptyDir with fsGroup set; a conformant kubelet
delivers an effective 02777, which the gate accepts. The surplus world bits are
inert because confinement comes from which containers mount the volume, never
from the mode.
2. Create the token file
Exactly 32 random bytes, unpadded base64url — 43 characters — in a regular
non-symlink file with mode exactly 0440:
mkdir -p /tmp/osv-secrets
head -c 32 /dev/urandom | basenc --base64url | tr -d '=\n' > /tmp/osv-secrets/token
chmod 0440 /tmp/osv-secrets/token
wc -c < /tmp/osv-secrets/token # must print 43
0400 is rejected on purpose: the console container reads the same file under a
different UID sharing only the supplementary group.
3. Credentials
Sidecar mode has no ambient credential fallback — STORE_CREDENTIAL_MODE is
required and exact. Using the static-file mode:
printf '%s' 'local-access' > /tmp/osv-secrets/aws-access-key-id
printf '%s' 'local-secret-value' > /tmp/osv-secrets/aws-secret-access-key
chmod 0400 /tmp/osv-secrets/aws-*
4. Start the producer
RUNTIME_MODE=pgconsole-sidecar \
REPOSITORY_FORMAT=barman-cloud \
PROVIDER=s3 \
DESTINATION_PATH=s3://backups/repository \
ENDPOINT_URL=http://127.0.0.1:9000 \
BARMAN_SERVER_NAMES=orders \
EVIDENCE_TOKEN_FILE=/tmp/osv-secrets/token \
CNPG_CLUSTER_NAMESPACE=database-team \
CNPG_CLUSTER_UID=2f12b7d1-7e8d-4c37-a68f-233efc5f3191 \
CNPG_CLUSTER_NAME=orders \
STORE_CREDENTIAL_MODE=static-files \
AWS_ACCESS_KEY_ID_FILE=/tmp/osv-secrets/aws-access-key-id \
AWS_SECRET_ACCESS_KEY_FILE=/tmp/osv-secrets/aws-secret-access-key \
AWS_REGION=us-east-1 \
./bin/objectstoreviewer
Reuse the MinIO from getting started. Note that
BARMAN_SERVER_NAMES takes exactly one name here, and the scanner is
confined to orders/ beneath the destination even if the credential can read
more.
Confirm there is no TCP listener at all:
ss -ltnp | grep objectstoreviewer # expect no output
5. Call the API
TOKEN=$(cat /tmp/osv-secrets/token)
SOCK=/var/run/objectstoreviewer/evidence.sock
curl -s --unix-socket "$SOCK" -H "Authorization: Bearer $TOKEN" \
http://localhost/healthz
curl -s --unix-socket "$SOCK" -H "Authorization: Bearer $TOKEN" \
http://localhost/api/v1alpha1/snapshot | jq .
Without the header you get 401 unauthenticated and nothing else:
curl -s -o /dev/null -w '%{http_code}\n' --unix-socket "$SOCK" \
http://localhost/api/v1alpha1/snapshot # 401
6. Page a collection consistently
Collections are bound to the publication identity. Read revision from the
snapshot and pass it:
REV=$(curl -s --unix-socket "$SOCK" -H "Authorization: Bearer $TOKEN" \
http://localhost/api/v1alpha1/snapshot | jq -r .revision)
curl -s --unix-socket "$SOCK" -H "Authorization: Bearer $TOKEN" \
"http://localhost/api/v1alpha1/backups?revision=$REV&limit=100" | jq .
Wait for a refresh and reuse the stale revision: you get 409 publication-changed, which is the contract telling you to discard the partial
assembly and restart from /snapshot. A cursor from one route is never valid on
another, and a restart invalidates every cursor with invalid-request.
7. The liveness probe
EVIDENCE_TOKEN_FILE=/tmp/osv-secrets/token ./bin/objectstoreviewer probe
echo $? # 0 when the authenticated /healthz answered within two seconds
It prints no token, no response body, and no raw transport error — by design. Use it as the kubelet liveness command, never as a readiness gate.
8. Clean up
# stop the producer with SIGTERM; the socket is removed on graceful shutdown
ls /var/run/objectstoreviewer/ # expect the socket to be gone
sudo rmdir /var/run/objectstoreviewer
rm -rf /tmp/osv-secrets
Testing the denials
The container test exercises the failure modes this tutorial only touches:
make test-container
It runs the real image under ordinary and OpenShift-style distinct arbitrary
UIDs sharing only a supplementary fsGroup, pins the 02770 directory floor
with 0660/0440 socket and token modes, and asserts authorized access plus
unmounted, socket-only, and token-only denials, the absence of a TCP listener,
and graceful socket cleanup.