resticprofile schedule copies env-file values into the generated units, which
are 0644, so RESTIC_REPOSITORY (the rest-server basic-auth password included)
was readable by every local user on every restic host.
New playbooks/restic-repository-file.yaml:
- derives /etc/restic/repository (root 0400) from restic.env;
- uploads the profile switched to repository-file, but only when the live
profile's sha matches the repo copy it was edited from (drift guard);
- checks the repository is reachable through the new profile (cat config);
- regenerates the units and verifies they exist and contain no rest:http.
Applied to ana-docker, fv-ml1 (configs/restic/ana-ml2), esh-docker-vm,
esh-vm-db, irv-ml1, nh3-dev and nh3-docker. An independent check across all
eight restic hosts (these seven plus esh-ml1) found 0 leaking units. nh3-docker's
scheduled unit ran a real backup afterwards (snapshot a29b889d). Each host's
URL and passphrase are vaulted as <host>/etc/restic/{repository,password}.
restic.env is kept (root 0600) because the per-host READMEs and the freshness
probe source it. A rotation must update the vault, restic.env and repository.
vm-esh-nas has no infra-ops account. Its in-place migration script is staged
for Prime to run with sudo, and its repo profile is pre-edited to match.
Also mirrors augaman-dev's 401df2d (compose header only). The config hash on
esh-ml1 is unchanged.
71 lines
3.3 KiB
YAML
71 lines
3.3 KiB
YAML
# augaman: the fleet's face-recognition service for Cicada (gitea pfi/augaman). It runs on
|
|
# esh-ml1 (CT 110 on esh-pve, RTX 2000E Ada 16 GB), with the gallery and the backup. Enroll,
|
|
# recognize, verify; buffalo_l (SCRFD + ArcFace w600k_r50) on ONNX Runtime CUDA. Canonical copy:
|
|
# this file in pfi/augaman; the eshpfi stack mirrors it as stacks/augaman.
|
|
#
|
|
# ⚠ BIOMETRIC DATA. The gallery volume holds face embeddings and crops of household members.
|
|
# - The live SQLite stays on the local named volume. Never NFS (the service refuses it).
|
|
# - esh-ml1 is OUTSIDE vzdump. The gallery reaches backup only through the backup CLI,
|
|
# writing to BACKUP_DIR, a restic-covered host path. Wire the schedule and VERIFY A
|
|
# RESTORE before real people are enrolled (operator ruling):
|
|
# docker exec augaman python -m augaman.gallery.backup --db /data/gallery.db --dest /backup/gallery.db
|
|
# It prints one JSON line and exits 0, or "backup failed: ..." and exits 1.
|
|
# - BACKUP_DIR must be writable by uid 10001, the container user. Backups are mode 0600.
|
|
#
|
|
# Startup refuses to serve unless CUDA really runs every convolution: a profiled warmup plus
|
|
# ORT's CPU fallbacks turned off. /health reports backend "cuda" only then. Confirm once by the
|
|
# process in `nvidia-smi` on the host. Warmup, including the first CUDA inference, is covered
|
|
# by the healthcheck's start_period.
|
|
#
|
|
# Only AUGAMAN_* variables reach the app, and it refuses any it does not know, so compose's own
|
|
# variables below carry no AUGAMAN_ prefix and are never passed through wholesale (no env_file).
|
|
#
|
|
# .env (tunables): IMAGE, PORT (8040), BACKUP_DIR, HOST_IP (10.0.50.80), AUGAMAN_API_TOKEN
|
|
# (>= 32 visible-ASCII characters; the source of truth is the vault), GPU_ID (the host's card
|
|
# index, default 0), CARD_SUFFIX (appended to the Homepage name, e.g. " (fv-ml1)").
|
|
# AUGAMAN_CUDA_DEVICE_ID stays "0" on every host: the reservation shows the container only the
|
|
# card GPU_ID names, and it sees that card as index 0.
|
|
|
|
name: augaman
|
|
|
|
services:
|
|
augaman:
|
|
image: ${IMAGE:?set IMAGE}
|
|
container_name: augaman
|
|
restart: unless-stopped
|
|
ports:
|
|
- "${PORT:-8040}:8040"
|
|
environment:
|
|
AUGAMAN_API_TOKEN: ${AUGAMAN_API_TOKEN:?set AUGAMAN_API_TOKEN}
|
|
AUGAMAN_DEVICE: cuda
|
|
AUGAMAN_CUDA_DEVICE_ID: "0"
|
|
volumes:
|
|
- gallery:/data
|
|
- ${BACKUP_DIR:?set BACKUP_DIR}:/backup
|
|
# Multipart spools of large uploads land here: RAM only, never persistent disk (api INV-A07).
|
|
tmpfs:
|
|
- /tmp:size=512m
|
|
deploy:
|
|
resources:
|
|
reservations:
|
|
devices:
|
|
- driver: nvidia
|
|
device_ids: ["${GPU_ID:-0}"]
|
|
capabilities: [gpu]
|
|
healthcheck:
|
|
# 200 only when ready and not degraded; a 503 (degraded) fails the check.
|
|
test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8040/health', timeout=5)"]
|
|
interval: 30s
|
|
timeout: 10s
|
|
retries: 3
|
|
start_period: 180s
|
|
labels:
|
|
- homepage.group=AI - Eval & Retrieval
|
|
- homepage.name=augaman — face recognition${CARD_SUFFIX:-}
|
|
- homepage.icon=mdi-face-recognition
|
|
- homepage.description=Enroll, recognize, verify (buffalo_l on CUDA) for Cicada
|
|
- homepage.href=http://${HOST_IP:-10.0.50.80}:${PORT:-8040}/health
|
|
|
|
volumes:
|
|
gallery:
|