tts-voice-creator-clone-and.../docker-compose.nuc.yml
mARTin-B78 4249382ac6
Some checks are pending
Test and SonarQube / quality (push) Waiting to run
feat(deploy): stand up correspondence-nuc as a second instance
The NFS blocker from TODO.md's deployment entry is resolved (export
set up by the user on the DGX); picks up from there and completes the
deployment end to end.

- Mounted the DGX's TTS_Voices export read-write on the NUC at
  /mnt/dgx-tts-voices, persisted in /etc/fstab -- confirmed writable
  and confirmed the NUC instance sees the DGX's real voice library
  (344 voices), not a separate copy.
- Deployed by rsyncing the working tree from the DGX (excluding .git,
  config/, logs/ and other local-only paths) and building the image
  directly on the NUC, rather than pulling ghcr.io/martin-b78/... --
  that registry copy turned out to be both several versions stale and
  private with no credentials configured on the NUC, and the source
  was already right there to build from.
- Found and fixed a real gap while wiring it up: vision_ocr_url and
  vision_ocr_fallback_url default to host.docker.internal, which
  resolves to whichever host the container is running on -- correct
  on the DGX itself, silently wrong on the NUC (would have pointed at
  the NUC's own nonexistent OCR engine). Pinned both explicitly to the
  DGX's LAN IP via environment overrides.
- The container crash-looped on first start (sqlite3.OperationalError:
  unable to open database file) because docker compose had created
  config/ and logs/ root-owned under this session's root SSH access to
  the NUC, while the image's app user is uid 1000 -- chown -R 1000:1000
  fixed it.
- New docker-compose.nuc.yml, tracked here as the reviewable reference
  for that host (docker-compose.yml stays the DGX's own -- different
  build/network/socket-proxy shape). Deployed to the NUC as its own
  docker-compose.yml, since that host has no .git checkout to diff
  against, only the rsynced tree.

Verified: container stable (no restart loop), HTTP 200, settings
confirm all four engine URLs correctly resolve to the DGX, voice count
matches the DGX exactly, restart policy is unless-stopped.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-14 10:06:55 +02:00

69 lines
2.9 KiB
YAML

services:
tts-voice-creator-clone-and-design-2:
# Built locally rather than pulled: the ghcr.io image is private (this
# host has no registry credentials) and, checked on the DGX, several
# versions stale besides. The full source is already deployed here
# (see the deploy step that rsyncs it from the DGX) -- build directly
# from it instead of standing up registry auth for a copy that would
# need pushing to stay current anyway.
build:
context: .
dockerfile: Dockerfile
container_name: tts-voice-creator-clone-and-design-2
restart: unless-stopped
# Same hardening as the DGX deployment: image filesystem stays
# immutable, the app writes only to the explicit mounts below.
read_only: true
cap_drop:
- ALL
security_opt:
- no-new-privileges:true
tmpfs:
- /tmp:size=1g,mode=1777
mem_limit: "${APP_MEM_LIMIT:-4g}"
mem_reservation: "${APP_MEM_RESERVATION:-1g}"
ports:
- "7890:7890"
volumes:
# NFS-exported from the DGX (see /etc/exports there) so this instance
# shares exactly the voice library the DGX's TTS engine has on disk --
# never a separate copy that could drift.
- ${VOICE_HOST_DIR:-/mnt/dgx-tts-voices}:/voices:rw
- ./config:/home/app/.config/tts-voice-creator:rw # settings, presets, routes
- ./logs:/logs:rw # application logs
# Live-editable without a rebuild -- same pattern as the DGX compose.
- ./static:/app/static:ro
- ./server.py:/app/server.py:ro
- ./core:/app/core:ro
- ./routes:/app/routes:ro
- ./workflows:/app/workflows:ro
- ./VERSION:/app/VERSION:ro
- ./CHANGELOG.md:/app/CHANGELOG.md:ro
environment:
- PYTHONUNBUFFERED=1
- VOICES_DIR=/voices
- OUTPUT_DIR=/voices/active_voices
# Most engine defaults already point at the DGX's real LAN IP and work
# unmodified from any host. Vision OCR is the one exception: its
# default is host.docker.internal, which resolves to whichever HOST
# the container happens to run on -- correct from the DGX itself, but
# on the NUC that would mean the NUC's own (nonexistent) OCR engine
# rather than the DGX's. Pin both explicitly to the DGX.
- VISION_OCR_URL=http://192.168.178.8:8098/v1
- VISION_OCR_FALLBACK_URL=http://192.168.178.8:8099/v1
#
# No docker-socket-proxy / DOCKER_HOST here on purpose: this instance
# has no local Docker socket to control, and the DGX's TTS containers
# can't be restarted cross-host through it either way. Voice-change
# auto-restart is an accepted manual step on the DGX after a change --
# same as documented for the DGX deployment itself. Docker-dependent
# diagnostics on this instance report unavailable rather than failing.
extra_hosts:
- "host.docker.internal:host-gateway"