# 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 `) | 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. |