second-brain/deploy/tower/second-brain-transcribe.service
Travis Herbranson 24055ad686 Merge branch 'claude/laughing-shirley-52f4a6': queue-page add form + tower CUDA-12 pin
Two commits since the last merge:

- web: add-to-queue form on /queue too, with per-page HTMX dispatch.
  Shared form partial reused by /dashboard and /queue; the POST
  /sources/add endpoint dispatches the response partial by inspecting
  HX-Current-URL so each page's own list/counts refresh inline. Same
  service call, same flash behavior.

- tower: pin CUDA-12 wheels + LD_LIBRARY_PATH wrapper for the systemd
  service. ctranslate2 4.7.2 needs CUDA 12 + cuDNN 9 but Arch ships
  CUDA 13, so we pin nvidia-cublas-cu12 + nvidia-cudnn-cu12>=9,<10 in
  the `tower` extra and add deploy/tower/run-transcribe-worker.sh,
  which resolves the venv's lib dirs at runtime and prepends them to
  LD_LIBRARY_PATH before exec-ing the worker. systemd doesn't inherit
  shell exports, so this is what makes the service survive reboots
  and Python upgrades. ExecStart= now points at the wrapper, and the
  StartLimit* directives moved into [Unit] where modern systemd
  expects them.

Travis's tower-side corrections on main (`User=trucktrav`,
`gitea-pbs-trucktrav` clone alias, tower WG IP 10.99.0.3) auto-merge
cleanly against these branch edits — different lines in the same files.
2026-05-25 15:43:47 -04:00

51 lines
1.9 KiB
Desktop File

[Unit]
Description=second-brain transcribe worker (tower-side, faster-whisper on GPU)
Documentation=https://gitea.plantbasedsoutherner.com/petal-power/second-brain
# The worker reaches petalbrain over WireGuard, so the tunnel must be up first.
# `Wants=` is the soft form — if the tunnel disappears later the worker logs
# DB-unreachable warnings and retries, it doesn't crash-loop.
After=network-online.target wg-quick@wg-lan.service
Wants=network-online.target wg-quick@wg-lan.service
# Crash loop guard — systemd will give up after this if the unit keeps
# dying. The worker itself logs+backs-off on DB outages so this only
# trips on genuine failure. (StartLimit* directives live in [Unit] on
# modern systemd; placing them in [Service] is a silent no-op.)
StartLimitIntervalSec=300
StartLimitBurst=5
[Service]
Type=simple
User=trucktrav
Group=trucktrav
# Adjust to wherever you `git clone`d the repo on the tower.
WorkingDirectory=/opt/projects/homelab/second-brain
# Env (SECOND_BRAIN_DATABASE_URL, optional knobs). 0600, owned by herbyadmin.
EnvironmentFile=/etc/default/second-brain-transcribe
# The wrapper resolves the venv's CUDA-12 lib dirs (nvidia-cublas-cu12 /
# nvidia-cudnn-cu12 pulled in by `uv sync --extra tower`), prepends them
# to LD_LIBRARY_PATH, then execs the worker via `uv run`. systemd does
# NOT inherit a shell's LD_LIBRARY_PATH, so doing this inline in the
# unit would require a brittle hard-coded `python3.XX` path and break
# on Python upgrades.
ExecStart=/opt/projects/homelab/second-brain/deploy/tower/run-transcribe-worker.sh
Restart=always
RestartSec=10
# A few sandboxing nice-to-haves. Loose on purpose — the worker needs
# /dev/nvidia* for CUDA and writes to user-owned media/subtitles dirs.
ProtectSystem=full
ProtectHome=no
NoNewPrivileges=true
# Stdout/stderr → journald.
StandardOutput=journal
StandardError=journal
[Install]
WantedBy=multi-user.target