Files
vh a2b5b58eee feat(waterland-studio): containerise the GPU render service on irv-ml1
Replaces a bare nohup on irv-ml1:8410 that would not have survived a reboot,
handed over by waterland-dev. Tracks vh/waterland @ main (PR #4 merged; main
HEAD is exactly the pinned 8025366).

Build context is a checkout at /opt/waterland-studio/src, deliberately OUTSIDE
the compose dir — deploy-stack.sh rsyncs stacks/<stack>/ with --delete and
would otherwise eat it. The Dockerfile is passed out-of-context.

Three landmines, all measured:

1. Both uv extras are load-bearing at build AND run. jobs.py shells the
   renderer out as a literal  with no --extra flags, so uv
   would re-sync at runtime and prune cupy — silently dropping to the numpy
   path at ~21x wall time. UV_NO_SYNC pins it; UV_OFFLINE makes any failure
   loud instead of quietly slow.

2. cupy needs CUDA HEADERS for its NVRTC compile, not just the driver and the
   wheel's runtime libs. The host has a system CUDA toolkit so the nohup
   process found them by accident; a slim image does not, and every render
   died 1.7s in with 'Failed to find CUDA headers' printed through argparse's
   usage banner — which reads like a CLI bug, not a missing toolkit. Fixed
   with cupy-cuda12x[ctk] (hundreds of MB, vs ~6 GB for a -devel base).

3. The A6000 is host device 1 but container device 0, since compose exposes
   exactly one GPU. CUDA_VISIBLE_DEVICES_TARGET=0 inside; copying the host's
   value selects a device that does not exist.

/root/.cupy is a volume because the NVRTC compile costs ~17s: verified at
23.3s cold vs 6.1s warm, and re-verified across a restart (23.2s on a fresh
cache volume, 6.0s once populated). Warm 256^2+anim beats the 7.4s recorded
against bare metal, so containerising cost nothing.

Job store seeded with the 4 jobs from the displaced instance. Serial by design
(one replica, one card) and unauthenticated, so it stays LAN/WireGuard-only.
2026-08-19 00:42:12 -07:00

12 lines
510 B
Bash

# waterland-studio on irv-ml1. Real .env lives on the host; every value below
# is the compose default, so an absent .env is a working configuration.
WLS_PORT=8410
WLS_CONTAINER=waterland-studio
WLS_BACKEND=cupy
# Docker's device index for the A6000 on this host. Device 0 is the 3090 and
# hosts the TTS zoo — do not point this at it.
WLS_GPU_ID=1
# The A6000's index INSIDE the container. Exactly one GPU is exposed, so it is
# 0 here even though it is 1 on the host. See the Dockerfile.
WLS_CUDA_TARGET=0