feat: setup houdini image build

This commit is contained in:
Simon Lambin
2026-09-09 08:31:28 +02:00
commit 105bb36b29
11 changed files with 485 additions and 0 deletions

203
houdini/README.md Normal file
View File

@@ -0,0 +1,203 @@
# Houdini Apprentice in distrobox, from a private registry
Two images built from one shared base:
- `houdini-amd` — Houdini + Mesa (radeonsi / RADV) for AMD/Intel GPUs
- `houdini-nvidia` — Houdini; the NVIDIA driver is injected at runtime by `distrobox --nvidia`
Files: `Dockerfile` (multi-stage), `houdini-run` (in-image launcher), `build-and-push.sh`.
> **Single-image alternative (honest note):** because `distrobox --nvidia`
> mounts the host driver at runtime, a *single* image (base + Mesa) usually
> works for both vendors, with the GPU chosen at `distrobox create` time. Two
> images are cleaner and leaner per vendor, which is what this setup does — but
> if you'd rather maintain one, build only the `amd` target and use it with or
> without `--nvidia`.
---
## 0. Prerequisites
- `podman` (or `docker`) and `distrobox` on the host.
- A private registry — see the [repo-level README](../README.md) for setup.
- Your Houdini Linux tarball from your SideFX account, e.g.
`houdini-22.0.429-linux_x86_64_gcc14.2.tar.gz`, placed next to the `Dockerfile`.
The `gccXX.X` suffix means the runtime needs a `libstdc++` new enough for
that build; that's why the base image is Ubuntu 22.04, not Rocky/RHEL —
Ubuntu's base image keeps `libstdc++6` updated, while RHEL-family distros
pin their system toolchain for the OS's lifetime.
- A SideFX account (Apprentice is free) to activate the license on first launch.
> This Dockerfile mirrors the one SideFX ships inside the tarball itself
> (`docker/Ubuntu/Dockerfile`) for the base image, package list, and install
> command — verified against the vendor's own recipe rather than guessed. Their
> package list is for headless `hython`/`sesinetd` use, though; running the
> actual `houdinifx` GUI needed 3 more runtime libs (`libegl1`, `libatomic1`,
> `libxkbfile1`), found by test-building and `ldd`-checking the binaries —
> already folded into the `Dockerfile`.
> **EULA / redistribution:** Houdini binaries are baked into these images. Keep
> the registry **private**. Do not push Houdini images to a public registry.
---
## 1. Build & push
Edit the variables at the top of `build-and-push.sh` (registry, version,
tarball name, EULA date), then run it. It builds the shared base once, then the
two variants, and pushes all tags. The base layers are stored only once in the
registry.
```bash
./build-and-push.sh
```
> **EULA date format:** plain `YYYY-MM-DD`, no `SideFX-` prefix (that prefix
> belongs to a different, unrelated tool — the newer credential-based
> `houdini_installer` launcher, not the `houdini.install` script used here).
> Current EULA date is `2021-10-13`; double check against
> https://www.sidefx.com/legal/license-agreement/ since SideFX can update it.
---
## 2. Use it via distrobox
Pick the image matching your GPU. The two `--additional-flags` bits below are
what make Apprentice licensing survive (see section 3):
- `--hostname houdini-apprentice` — stable machine name for the node-lock
- a bind mount of the `licenses` file so the activation persists
```bash
# One-time: create the persisted license file on the host.
mkdir -p ~/.houdini-apprentice
touch ~/.houdini-apprentice/licenses
```
**NVIDIA:**
```bash
distrobox create \
--name houdini \
--image registry.lan:5000/houdini-nvidia:latest \
--nvidia \
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
```
**AMD / Intel** (drop `--nvidia`; distrobox exposes `/dev/dri` automatically):
```bash
distrobox create \
--name houdini \
--image registry.lan:5000/houdini-amd:latest \
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
```
Then:
```bash
distrobox enter houdini
houdini-run # starts sesinetd, then launches Houdini FX
```
On **first launch** Houdini prompts to install the free Apprentice license: log
in with your SideFX account.
To add a real app-menu entry (icon, no terminal window) instead of a plain
binary shortcut, export a `.desktop` file from inside the box — the icon path
must point at Houdini's own bundled icon (there's no separate `.desktop` file
shipped, so this one is written by hand):
```bash
distrobox enter houdini
cat > /tmp/houdini.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=Houdini FX
Comment=Houdini Apprentice (distrobox)
Exec=houdini-run
Icon=/opt/hfs/houdini/cloudsubmit/houdini_icon.png
Terminal=false
Categories=Graphics;3DGraphics;Education;
StartupWMClass=houdinifx-bin
EOF
distrobox-export --app /tmp/houdini.desktop
```
`distrobox-export` copies the icon out to `~/.local/share/icons/` on the host
and writes `~/.local/share/applications/houdini-houdini.desktop`. Distrobox
also auto-creates a generic `houdini.desktop` ("Terminal entering Houdini")
for every box at creation time — set `NoDisplay=true` in that file (or delete
it) if you don't want both showing up in the app menu.
---
## 3. Apprentice licensing — read this
Apprentice is the fragile part, by design. Confirmed SideFX behaviour:
- **No Login Licensing** for Apprentice — only node-locked (workstation)
licenses served by a **local** `sesinetd`, which must be running for Houdini
to start at all.
- The license is **node-locked to the machine hardware _and_ the machine name**.
Change the hostname and the license is invalidated — hence the fixed
`--hostname houdini-apprentice`. Always create the box with the same hostname.
- Apprentice licenses are **valid 30 days**, then you reinstall a fresh free set
(a quick re-login in the same dialog).
- On Linux the keys live in `/usr/lib/sesi/licenses`. The bind mount in section
2 persists just that file into `~/.houdini-apprentice/`, so recreating or
re-pulling the container keeps the activation (within the 30 days, same host).
Confirmed by an actual Apprentice activation. Two gotchas that took a while
to track down, both now handled automatically by `houdini-run`:
- **File permissions.** `sesinetd` runs as `www-data`, not as your
distrobox user. A bind-mounted file created on the host with `touch`
belongs to your host user and isn't writable by `www-data`, so activation
fails with `Failed to open license file` in
`/var/log/sidefx/sesinetd.log` — surfaced in the GUI as an unrelated-
looking **"Success (curl error 0)"** error that just loops back to the
install-license prompt. `houdini-run` now `chmod 666`s the file before
starting `sesinetd` every time, so this self-heals.
- **Stuck self-signed cert.** If `sesinetd`'s self-signed TLS cert
generation is interrupted (it was, once, across our own container
restarts), it leaves 0-byte `auth.cert`/`auth.priv` files behind, and the
daemon then spins at ~100% CPU retrying against them forever instead of
regenerating — silently breaking activation with no obvious error.
`houdini-run` now deletes those files first if they're empty.
Practical consequences:
- **Same physical machine, stable hostname:** activate once; survives container
recreation and image updates until the 30-day expiry.
- **A different physical machine:** the hardware differs, so you re-activate
there (still free). The image is portable; the *license state* is per-machine.
Inspect or manage licenses from inside the box with `houdini-run hkey`
(graphical) or `sesictrl` (CLI).
> **"Container-enabled licenses" — why this doesn't apply here:** SideFX's own
> docker README warns that regular (non-floating) licenses need special
> "container enabled" entitlements to run `sesinetd` in Docker, and their own
> `docker-compose.yml` works around it with `network_mode: host`. That warning
> is about Docker's default *isolated* network namespace confusing the
> node-lock check. Distrobox shares the host's network namespace by default
> (no `--unshare-netns`), so the container sees the real host network identity
> — same situation as SideFX's own host-network workaround. Regular Apprentice
> licensing is expected to work unmodified.
---
## 4. Known-fragile / to verify (honest status)
| Area | Confidence | Note |
|---|---|---|
| Overall Dockerfile + distrobox shape | High | Standard distrobox GUI/GPU pattern. |
| Base image + install command (`--auto-install --accept-EULA <date>`) | High | Copied from SideFX's own `docker/Ubuntu/Dockerfile`; test-built end to end against the real 22.0.429 tarball. |
| `/opt/hfs` symlink | High | The installer only creates a major.minor symlink (`/opt/hfs22.0`); the Dockerfile adds the generic `/opt/hfs` one itself — confirmed by test build. |
| EULA date value | Medium | `2021-10-13` as of writing; SideFX can update the EULA without notice, check the legal page. |
| Licensing works under distrobox's shared netns | High | Confirmed with a real Apprentice activation via the GUI, over the host's shared network namespace. |
| Runtime library list | High | Vendor's list plus 4 libs it was missing for the GUI (`libegl1`, `libatomic1`, `libxkbfile1`, `libxcb-cursor0`), all confirmed by `ldd`-checking `houdinifx-bin`/Qt plugins and by an actual successful launch. |
| `houdini-run` strict-mode compatibility | High | `houdini_setup` isn't written for `set -euo pipefail` (unset vars, `which java` expected to fail silently) — fixed by relaxing those flags just around the `source`; confirmed end to end. |
| `sesinetd` auto-start via the launcher | High | Confirmed under distrobox's real non-root user + sudo setup, including the license-file-permission and stuck-cert fixes described in section 3. |
| distrobox default hostname | Medium | We pin it explicitly rather than trust the default. |
| Actual GUI rendering (X11/Wayland via XWayland) | High | Confirmed: real AMD hardware acceleration (`glxinfo` reports direct rendering, AMD Radeon Vega renderer, not a software fallback), Houdini FX runs and renders normally through XWayland on a Hyprland session. First launch was noticeably slow; subsequent launches were fluid. |
| AMD OpenCL (sims) | Low | Not set up here; needs ROCm/rusticl. GL/Vulkan viewport is fine. |