feat: cleanup the houdini image setup
This commit is contained in:
66
README.md
66
README.md
@@ -1,35 +1,40 @@
|
|||||||
# distrobox-images
|
# distrobox-images
|
||||||
|
|
||||||
Dockerfiles pour les softs lourds (Houdini, ...) lancés via [distrobox](https://github.com/89luca89/distrobox),
|
Dockerfiles for heavy software (Houdini, ...) run via
|
||||||
buildés une fois et poussés sur un registry privé plutôt que rebuild à chaque
|
[distrobox](https://github.com/89luca89/distrobox), built once and pushed to
|
||||||
`distrobox create`.
|
a private registry instead of rebuilding on every `distrobox create`.
|
||||||
|
|
||||||
## Convention
|
## Convention
|
||||||
|
|
||||||
Un dossier par soft, autonome :
|
One self-contained folder per app:
|
||||||
|
|
||||||
```
|
```
|
||||||
<soft>/
|
<soft>/
|
||||||
Dockerfile # souvent multi-stage: base commune + variante amd / nvidia
|
Dockerfile # often multi-stage: shared base + amd / nvidia variant
|
||||||
build-and-push.sh # build + push vers le registry
|
build-and-push.sh # build + push to the registry
|
||||||
<soft>-run # launcher installé dans l'image (entrypoint applicatif)
|
<soft>-run # launcher installed in the image (app entrypoint)
|
||||||
README.md # specifics: prérequis, licence, distrobox create, gotchas
|
README.md # specifics: prerequisites, licensing, distrobox create, gotchas
|
||||||
```
|
```
|
||||||
|
|
||||||
Pas de base image partagée entre softs différents — chacun a ses propres
|
No shared base image across different apps — each has its own system
|
||||||
dépendances système, ça n'apporte rien de mutualiser au-delà du dossier.
|
dependencies, sharing more than the folder structure doesn't buy anything.
|
||||||
|
|
||||||
Deux variantes GPU par soft quand le rendu OpenGL/Vulkan compte (viewport,
|
Two GPU variants per app when OpenGL/Vulkan rendering matters (viewport,
|
||||||
préview) :
|
preview):
|
||||||
- `<soft>-amd` — Mesa embarqué dans l'image (radeonsi / RADV), marche aussi
|
- `<soft>-amd` — Mesa baked into the image (radeonsi / RADV), also works for
|
||||||
pour Intel.
|
Intel.
|
||||||
- `<soft>-nvidia` — rien embarqué; le driver NVIDIA de l'hôte est monté au
|
- `<soft>-nvidia` — nothing baked in; the host's NVIDIA driver is mounted at
|
||||||
runtime par `distrobox --nvidia`.
|
runtime by `distrobox --nvidia`.
|
||||||
|
|
||||||
Si le rendu GPU n'a pas d'importance pour un soft donné, une seule image
|
If GPU rendering doesn't matter for a given app, one image is enough — don't
|
||||||
suffit — ne pas dupliquer par principe.
|
duplicate on principle.
|
||||||
|
|
||||||
## Registry privé
|
## Private registry
|
||||||
|
|
||||||
|
Registry: `docker.slambin.fr`. If it's a real domain with TLS (reverse proxy
|
||||||
|
+ cert) in front, nothing to configure on the container engine side —
|
||||||
|
`push`/`pull` just work. Only if the registry runs plain HTTP (e.g. a local
|
||||||
|
test without TLS) does it need to be declared "insecure":
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
podman run -d --name registry --restart=always \
|
podman run -d --name registry --restart=always \
|
||||||
@@ -37,32 +42,27 @@ podman run -d --name registry --restart=always \
|
|||||||
registry:2
|
registry:2
|
||||||
```
|
```
|
||||||
|
|
||||||
HTTP en clair, donc à déclarer en "insecure" côté moteur de conteneurs.
|
|
||||||
|
|
||||||
**podman** — `/etc/containers/registries.conf.d/local.conf`:
|
**podman** — `/etc/containers/registries.conf.d/local.conf`:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[[registry]]
|
[[registry]]
|
||||||
location = "registry.lan:5000"
|
location = "docker.slambin.fr"
|
||||||
insecure = true
|
insecure = true
|
||||||
```
|
```
|
||||||
|
|
||||||
**docker** — `/etc/docker/daemon.json`, puis restart docker :
|
**docker** — `/etc/docker/daemon.json`, then restart docker:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{ "insecure-registries": ["registry.lan:5000"] }
|
{ "insecure-registries": ["docker.slambin.fr"] }
|
||||||
```
|
```
|
||||||
|
|
||||||
Au-delà d'un LAN de confiance, mettre TLS + auth devant plutôt que
|
## Licensing / EULA
|
||||||
`insecure`.
|
|
||||||
|
|
||||||
## Licences / EULA
|
Several of these apps (Houdini included) are installed from a proprietary
|
||||||
|
binary downloaded with a personal account, and the EULA generally forbids
|
||||||
|
redistribution. The registry must stay **private** — never push an image
|
||||||
|
containing one of these binaries to a public registry.
|
||||||
|
|
||||||
Plusieurs de ces softs (Houdini compris) sont installés depuis un binaire
|
## Apps
|
||||||
propriétaire téléchargé avec un compte perso, et l'EULA interdit en général
|
|
||||||
la redistribution. Le registry doit rester **privé** — jamais de push d'une
|
|
||||||
image contenant un de ces binaires vers un registry public.
|
|
||||||
|
|
||||||
## Softs
|
|
||||||
|
|
||||||
- [`houdini/`](houdini/README.md) — Houdini Apprentice
|
- [`houdini/`](houdini/README.md) — Houdini Apprentice
|
||||||
|
|||||||
164
houdini/CLAUDE.md
Normal file
164
houdini/CLAUDE.md
Normal file
@@ -0,0 +1,164 @@
|
|||||||
|
# Houdini image — design notes and debugging history
|
||||||
|
|
||||||
|
Context for whoever (Claude) touches this Dockerfile next. Simon doesn't need
|
||||||
|
to read this — it's implementation reasoning, not usage docs (those are in
|
||||||
|
`README.md`).
|
||||||
|
|
||||||
|
## Why these choices
|
||||||
|
|
||||||
|
- **Base image + install command copy SideFX's own `docker/Ubuntu/Dockerfile`**
|
||||||
|
(shipped inside the Houdini tarball under `docker/Ubuntu/`), not guessed.
|
||||||
|
That reference folder has been deleted from this repo once its contents
|
||||||
|
were folded in here — it only ever served as a source to copy from, and
|
||||||
|
keeping it around invited drift between two copies of the same info.
|
||||||
|
- **Ubuntu 22.04, not Rocky/RHEL.** The tarball is `gccXX.X`-tagged (here
|
||||||
|
`gcc14.2`), meaning the runtime needs a `libstdc++` new enough for that
|
||||||
|
build. Ubuntu's base image keeps `libstdc++6` updated via regular package
|
||||||
|
updates; RHEL-family distros pin their system toolchain for the whole OS
|
||||||
|
lifetime, so a Rocky 9 base risks a `GLIBCXX_x` version mismatch depending
|
||||||
|
on which Houdini build you're on. This was a real, not hypothetical,
|
||||||
|
concern with the 22.0.429/gcc14.2 build tested here.
|
||||||
|
- **`--auto-install --accept-EULA <date>`, no `--make-dir`, no
|
||||||
|
`--install-license`.** An earlier draft of this Dockerfile invented an
|
||||||
|
`--install-license <path>` flag that doesn't exist, based on scripted-
|
||||||
|
install docs that actually describe a *different* tool
|
||||||
|
(`houdini_installer`, the newer credential-based launcher — irrelevant
|
||||||
|
here, since it needs network + stored SideFX credentials at build time,
|
||||||
|
which is worse for a private-registry-baked-tarball workflow). The
|
||||||
|
flags actually used are copy-pasted from SideFX's own Dockerfile.
|
||||||
|
- **EULA date is a plain `YYYY-MM-DD`, no `SideFX-` prefix.** The
|
||||||
|
`SideFX-YYYY-MM-DD` form belongs to `houdini_installer`'s config file, not
|
||||||
|
to `houdini.install`. Mixing the two up silently breaks `--accept-EULA`
|
||||||
|
matching. Value as of writing: `2021-10-13` (from
|
||||||
|
https://www.sidefx.com/legal/license-agreement/ — SideFX can update this
|
||||||
|
without notice, it's not pinned/checked anywhere).
|
||||||
|
- **`/opt/hfs` symlink is created explicitly.** `houdini.install`'s default
|
||||||
|
behavior only creates a major.minor symlink (`/opt/hfs22.0` here), not a
|
||||||
|
generic `/opt/hfs`. The Dockerfile globs for the installed `hfs[0-9]*` dir
|
||||||
|
and symlinks it to `/opt/hfs` itself, so `houdini-run` and the
|
||||||
|
`/etc/profile.d` snippet don't need to know the exact version.
|
||||||
|
|
||||||
|
## Runtime library list
|
||||||
|
|
||||||
|
SideFX's own package list in `docker/Ubuntu/Dockerfile` is built for headless
|
||||||
|
`hython`/`sesinetd` use (their `docker-compose.yml` only ever runs `hython`
|
||||||
|
or `sesinetd` as separate services, never the GUI). Running the actual
|
||||||
|
`houdinifx` GUI needed 4 more libs, each found by `ldd`-checking the real
|
||||||
|
binaries/plugins in a test build and confirmed missing before adding:
|
||||||
|
|
||||||
|
- `libegl1` — EGL dispatch, `houdinifx-bin` linked against it directly.
|
||||||
|
- `libatomic1` — `houdinifx-bin`/`hython-bin` both needed it.
|
||||||
|
- `libxkbfile1` — same.
|
||||||
|
- `libxcb-cursor0` — this one took the longest to find. Qt6's `xcb` platform
|
||||||
|
plugin (`libqxcb.so`, under
|
||||||
|
`/opt/hfs<ver>/dsolib/Qt_plugins/platforms/`) hard-depends on it (a known
|
||||||
|
Qt6 change from Qt5, where cursor theming moved from Xcursor to
|
||||||
|
xcb-cursor). Without it, Houdini fails at Qt platform-plugin init with a
|
||||||
|
generic "no Qt platform plugin could be initialized" — nothing points at
|
||||||
|
the actual missing symbol unless you `ldd` the plugin directly.
|
||||||
|
|
||||||
|
If a future Houdini/Qt version adds new failures here, the fastest diagnosis
|
||||||
|
path is: `ldd` every `.so` under `dsolib/Qt_plugins/` recursively (see git
|
||||||
|
history of this file / session transcript for the exact one-liner), not
|
||||||
|
guessing from the vague top-level Qt error message.
|
||||||
|
|
||||||
|
## `houdini-run` strict-mode compatibility
|
||||||
|
|
||||||
|
`houdini_setup_bash` (sourced by `houdini-run` to set up `$HFS`/`PATH`/etc.)
|
||||||
|
is not written for `set -euo pipefail`:
|
||||||
|
- It references variables that are legitimately unset in some code paths
|
||||||
|
(`set -u` would abort).
|
||||||
|
- It does things like `d=$(which java)` expecting a silent empty result on
|
||||||
|
failure (`set -e` would abort on the failed `which`).
|
||||||
|
|
||||||
|
Fix: wrap the `source ./houdini_setup` call with `set +euo pipefail` /
|
||||||
|
`set -euo pipefail` around it, rather than trying to patch the vendor
|
||||||
|
script.
|
||||||
|
|
||||||
|
## NixOS / distrobox host environment leakage
|
||||||
|
|
||||||
|
Distrobox forwards the *host* shell's environment into the container by
|
||||||
|
design (needed for `DISPLAY`, `WAYLAND_DISPLAY`, `XDG_*`, D-Bus, etc. to
|
||||||
|
work at all for GUI apps). On a NixOS host that also sets its own
|
||||||
|
`LD_LIBRARY_PATH` (observed here pointing at a Nix-store `alsa-lib` built
|
||||||
|
against a much newer glibc than Ubuntu 22.04 ships), that leaks into the
|
||||||
|
container and crashes Houdini's binaries at dynamic-link time
|
||||||
|
(`GLIBC_ABI_GNU2_TLS not found`, etc.) — a library meant for the host's
|
||||||
|
libc, loaded into a binary linked against the container's older libc.
|
||||||
|
|
||||||
|
`houdini_setup_bash` only ever *prepends* to `LD_LIBRARY_PATH` if it's
|
||||||
|
already set — it never resets it. So `houdini-run` explicitly
|
||||||
|
`unset LD_LIBRARY_PATH` before sourcing it, discarding whatever leaked in
|
||||||
|
from the host and letting Houdini build its own from scratch. This is safe
|
||||||
|
on any host, not just NixOS — it just happens to matter there.
|
||||||
|
|
||||||
|
This class of problem (host env leaking into the container and colliding
|
||||||
|
with container-local binaries) is worth checking first if a *new*,
|
||||||
|
unexplained crash shows up after this image has otherwise worked before.
|
||||||
|
|
||||||
|
## sesinetd / Apprentice licensing — the two real bugs
|
||||||
|
|
||||||
|
Both now handled automatically inside `houdini-run` (not just documented as
|
||||||
|
manual steps), found via `/var/log/sidefx/sesinetd.log` after a genuinely
|
||||||
|
confusing symptom in the GUI:
|
||||||
|
|
||||||
|
1. **License file permissions.** `sesinetd` drops privileges to `www-data`
|
||||||
|
after being started as root via `sudo`. The license file bind-mounted
|
||||||
|
from the host (`~/.houdini-apprentice/licenses:/usr/lib/sesi/licenses`)
|
||||||
|
is created with `touch` as the host user, so it's not writable by
|
||||||
|
`www-data` inside the container. Result: activation's network round-trip
|
||||||
|
to SideFX succeeds fine (curl-level success), but writing the resulting
|
||||||
|
license locally fails — surfaced in the GUI as the deeply misleading
|
||||||
|
**"Success (curl error 0)"** error dialog that just loops back to the
|
||||||
|
install-license prompt with no indication anything is actually wrong.
|
||||||
|
The real error only shows up in `/var/log/sidefx/sesinetd.log`:
|
||||||
|
`[FATAL - Licensing] [Manager] - Failed to open license file.`
|
||||||
|
Fix: `houdini-run` now `chmod 666`s the license file before starting
|
||||||
|
`sesinetd`, every time, unconditionally.
|
||||||
|
2. **Stuck self-signed TLS cert.** If cert generation for `sesinetd`'s HTTPS
|
||||||
|
listener gets interrupted (observed here across our own repeated
|
||||||
|
container kill/restart cycles during testing), it leaves 0-byte
|
||||||
|
`/usr/lib/sesi/ssl/auth.cert` / `auth.priv` behind. On next start,
|
||||||
|
`sesinetd` tries to read those, fails (`Bad certificate chain: 'PEM
|
||||||
|
lib'`), and — rather than regenerating — spins retrying at ~100% CPU
|
||||||
|
forever, never actually finishing startup or opening port 1715.
|
||||||
|
No error surfaces in the GUI for this one at all; the only symptom is a
|
||||||
|
pegged CPU core and a license dialog that never succeeds. Fix:
|
||||||
|
`houdini-run` deletes those two files first if either is 0 bytes.
|
||||||
|
|
||||||
|
Also confirmed, contra a plausible-sounding but wrong worry: SideFX's own
|
||||||
|
docker README warns that regular (non-floating) licenses need special
|
||||||
|
"container enabled" entitlements to run `sesinetd` in Docker, working around
|
||||||
|
it with `network_mode: host` in their own `docker-compose.yml`. 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`), which is the same situation as SideFX's own
|
||||||
|
workaround — so this doesn't apply here, and was confirmed by an actual
|
||||||
|
successful Apprentice activation.
|
||||||
|
|
||||||
|
## Confidence table (as of the last real end-to-end test)
|
||||||
|
|
||||||
|
Everything below was confirmed with an actual build + an actual
|
||||||
|
`distrobox create` + `houdini-run` launch on a real AMD iGPU (Vega,
|
||||||
|
`raven`) host, not just read from docs.
|
||||||
|
|
||||||
|
| Area | Confidence | Note |
|
||||||
|
|---|---|---|
|
||||||
|
| Base image + install command | High | Matches SideFX's own Dockerfile; built end to end against the real 22.0.429/gcc14.2 tarball. |
|
||||||
|
| `/opt/hfs` symlink | High | Confirmed by test build. |
|
||||||
|
| EULA date value | Medium | `2021-10-13` as of writing; unpinned, SideFX can change it. |
|
||||||
|
| Licensing works under distrobox's shared netns | High | Confirmed with a real Apprentice activation. |
|
||||||
|
| Runtime library list | High | Vendor's list + 4 libs added, all confirmed via `ldd` and an actual successful launch. |
|
||||||
|
| `houdini-run` strict-mode compatibility | High | Confirmed end to end. |
|
||||||
|
| `sesinetd` license-file-permission and stuck-cert fixes | High | Both bugs actually hit during testing, root-caused via `/var/log/sidefx/sesinetd.log`, fixed in `houdini-run`, confirmed working after the fix. |
|
||||||
|
| distrobox default hostname | Medium | Pinned explicitly (`houdini-apprentice`) rather than trusting the default, since Apprentice node-locks to hostname too. |
|
||||||
|
| GUI rendering via XWayland (Hyprland host) | High | Confirmed real AMD hardware acceleration (`glxinfo`: direct rendering, AMD Radeon Vega renderer, not llvmpipe). First launch was slow (container's first-run package install + cold start); later launches fluid. |
|
||||||
|
| AMD OpenCL (sims) | Low | Not set up; needs ROCm/rusticl. GL/Vulkan viewport is unaffected. |
|
||||||
|
| NVIDIA variant | Untested | Builds fine (same base, no extra packages), but never run against real NVIDIA hardware — only the `amd` target has been used end to end. |
|
||||||
|
|
||||||
|
## Repo-wide conventions
|
||||||
|
|
||||||
|
See the top-level `../README.md` for the multi-software repo convention
|
||||||
|
(one self-contained folder per app, shared registry setup notes) — that
|
||||||
|
file is meant for Simon to read; this one and the top-level `../CLAUDE.md`
|
||||||
|
(if one exists) are for future-Claude context.
|
||||||
@@ -1,95 +1,62 @@
|
|||||||
# Houdini Apprentice in distrobox, from a private registry
|
# Houdini Apprentice in distrobox
|
||||||
|
|
||||||
Two images built from one shared base:
|
Two images built from the same `Dockerfile`, pushed to a private registry,
|
||||||
|
used via distrobox:
|
||||||
|
|
||||||
- `houdini-amd` — Houdini + Mesa (radeonsi / RADV) for AMD/Intel GPUs
|
- `houdini-amd` — Houdini + Mesa, for AMD/Intel GPUs
|
||||||
- `houdini-nvidia` — Houdini; the NVIDIA driver is injected at runtime by `distrobox --nvidia`
|
- `houdini-nvidia` — Houdini only; the NVIDIA driver is injected at runtime
|
||||||
|
by `distrobox --nvidia`
|
||||||
|
|
||||||
Files: `Dockerfile` (multi-stage), `houdini-run` (in-image launcher), `build-and-push.sh`.
|
Registry: `docker.slambin.fr`. Files: `Dockerfile`, `houdini-run` (in-image
|
||||||
|
launcher), `build-and-push.sh`.
|
||||||
|
|
||||||
> **Single-image alternative (honest note):** because `distrobox --nvidia`
|
> Houdini binaries are baked into these images under a personal SideFX
|
||||||
> mounts the host driver at runtime, a *single* image (base + Mesa) usually
|
> account. Keep the registry **private** — never push these images publicly.
|
||||||
> 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
|
## Prerequisites
|
||||||
|
|
||||||
- `podman` (or `docker`) and `distrobox` on the host.
|
- Your Houdini Linux tarball from your SideFX account (e.g.
|
||||||
- A private registry — see the [repo-level README](../README.md) for setup.
|
`houdini-22.0.429-linux_x86_64_gcc14.2.tar.gz`), placed next to the
|
||||||
- Your Houdini Linux tarball from your SideFX account, e.g.
|
`Dockerfile`.
|
||||||
`houdini-22.0.429-linux_x86_64_gcc14.2.tar.gz`, placed next to the `Dockerfile`.
|
- A SideFX account (Apprentice is free) to activate the license on first
|
||||||
The `gccXX.X` suffix means the runtime needs a `libstdc++` new enough for
|
launch.
|
||||||
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
|
## Build & push
|
||||||
> (`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
|
Edit the variables at the top of `build-and-push.sh` (version, tarball name,
|
||||||
> the registry **private**. Do not push Houdini images to a public registry.
|
EULA date if it changed), then:
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 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
|
```bash
|
||||||
./build-and-push.sh
|
./build-and-push.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
> **EULA date format:** plain `YYYY-MM-DD`, no `SideFX-` prefix (that prefix
|
Builds both variants and pushes all tags to `docker.slambin.fr`.
|
||||||
> 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.
|
|
||||||
|
|
||||||
---
|
## Install / run
|
||||||
|
|
||||||
## 2. Use it via distrobox
|
One-time, on the host — persists the Apprentice license across container
|
||||||
|
recreation:
|
||||||
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
|
```bash
|
||||||
# One-time: create the persisted license file on the host.
|
mkdir -p ~/.houdini-apprentice && touch ~/.houdini-apprentice/licenses
|
||||||
mkdir -p ~/.houdini-apprentice
|
|
||||||
touch ~/.houdini-apprentice/licenses
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**NVIDIA:**
|
Create the box (pick the image matching your GPU):
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
# AMD / Intel
|
||||||
distrobox create \
|
distrobox create \
|
||||||
--name houdini \
|
--name houdini \
|
||||||
--image registry.lan:5000/houdini-nvidia:latest \
|
--image docker.slambin.fr/houdini-amd:latest \
|
||||||
--nvidia \
|
|
||||||
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
|
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
|
||||||
```
|
|
||||||
|
|
||||||
**AMD / Intel** (drop `--nvidia`; distrobox exposes `/dev/dri` automatically):
|
# NVIDIA
|
||||||
|
|
||||||
```bash
|
|
||||||
distrobox create \
|
distrobox create \
|
||||||
--name houdini \
|
--name houdini \
|
||||||
--image registry.lan:5000/houdini-amd:latest \
|
--image docker.slambin.fr/houdini-nvidia:latest \
|
||||||
|
--nvidia \
|
||||||
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
|
--additional-flags "--hostname houdini-apprentice -v $HOME/.houdini-apprentice/licenses:/usr/lib/sesi/licenses"
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -97,16 +64,24 @@ Then:
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
distrobox enter houdini
|
distrobox enter houdini
|
||||||
houdini-run # starts sesinetd, then launches Houdini FX
|
houdini-run
|
||||||
```
|
```
|
||||||
|
|
||||||
On **first launch** Houdini prompts to install the free Apprentice license: log
|
First launch prompts to install the free Apprentice license — log in with
|
||||||
in with your SideFX account.
|
your SideFX account. Two things worth knowing:
|
||||||
|
|
||||||
To add a real app-menu entry (icon, no terminal window) instead of a plain
|
- The `--hostname houdini-apprentice` flag must stay the same every time you
|
||||||
binary shortcut, export a `.desktop` file from inside the box — the icon path
|
recreate the box — Apprentice licenses node-lock to hostname as well as
|
||||||
must point at Houdini's own bundled icon (there's no separate `.desktop` file
|
hardware.
|
||||||
shipped, so this one is written by hand):
|
- Apprentice licenses expire after 30 days; re-activate the same way (a
|
||||||
|
quick re-login in the same dialog).
|
||||||
|
|
||||||
|
## App menu entry (icon, no terminal)
|
||||||
|
|
||||||
|
Houdini doesn't ship its own `.desktop` file, and distrobox doesn't have a
|
||||||
|
built-in way to generate a proper GUI-app entry from a binary —
|
||||||
|
`distrobox-generate-entry` only makes the generic "Terminal entering X"
|
||||||
|
shortcut. So write one by hand and export it:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
distrobox enter houdini
|
distrobox enter houdini
|
||||||
@@ -124,80 +99,8 @@ EOF
|
|||||||
distrobox-export --app /tmp/houdini.desktop
|
distrobox-export --app /tmp/houdini.desktop
|
||||||
```
|
```
|
||||||
|
|
||||||
`distrobox-export` copies the icon out to `~/.local/share/icons/` on the host
|
This copies the icon to `~/.local/share/icons/` on the host and writes
|
||||||
and writes `~/.local/share/applications/houdini-houdini.desktop`. Distrobox
|
`~/.local/share/applications/houdini-houdini.desktop`. Distrobox also
|
||||||
also auto-creates a generic `houdini.desktop` ("Terminal entering Houdini")
|
auto-creates a generic `houdini.desktop` ("Terminal entering Houdini") when
|
||||||
for every box at creation time — set `NoDisplay=true` in that file (or delete
|
the box is created — set `NoDisplay=true` in that file, or delete it, if you
|
||||||
it) if you don't want both showing up in the app menu.
|
don't want both entries 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. |
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
# Build both variants (shared base) and push. Heavy: run when ready.
|
# Build both variants (shared base) and push. Heavy: run when ready.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
REGISTRY="${REGISTRY:-registry.lan:5000}"
|
REGISTRY="${REGISTRY:-docker.slambin.fr}"
|
||||||
VERSION="${VERSION:-22.0.429}"
|
VERSION="${VERSION:-22.0.429}"
|
||||||
TARBALL="${TARBALL:-houdini-22.0.429-linux_x86_64_gcc14.2.tar.gz}"
|
TARBALL="${TARBALL:-houdini-22.0.429-linux_x86_64_gcc14.2.tar.gz}"
|
||||||
# Date the EULA at https://www.sidefx.com/legal/license-agreement/ was last
|
# Date the EULA at https://www.sidefx.com/legal/license-agreement/ was last
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
There are two versions of the Dockerfiles, one for Ubuntu Linux and one for
|
|
||||||
Windows. Note that the Ubuntu image size is much smaller.
|
|
||||||
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
1. You need Docker and Docker-compose installed if you're on Linux.
|
|
||||||
2. You need Docker Desktop installed if you're on a Windows or Mac host.
|
|
||||||
3. You need to modify "EULA_DATE" in the Dockerfile to specify the date for the
|
|
||||||
installer's `accept-EULA` argument. For example, if the EULA at
|
|
||||||
https://www.sidefx.com/legal/license-agreement/ was last updated on
|
|
||||||
April 10, 2020, you would set "EULA_DATE" in the Dockerfile to 2020-04-10.
|
|
||||||
4. To run sesinetd within docker you must have container enabled licenses.
|
|
||||||
Regular licenses will not work within containers.
|
|
||||||
|
|
||||||
To create a Houdini Docker image:
|
|
||||||
1. Download a build of Houdini from www.sidefx.com for the container's platform.
|
|
||||||
4. Navigate to one of the "Ubuntu" or "Windows" folders.
|
|
||||||
3. Ensure you have set "EULA_DATE" in the Dockerfile.
|
|
||||||
4. Run `docker-compose build`
|
|
||||||
|
|
||||||
|
|
||||||
Some handy docker-compose commands:
|
|
||||||
1. `docker-compose run -d -p 1715:1715 sesinetd` will create a container
|
|
||||||
running the license server (sesinetd).
|
|
||||||
2. `docker-compose run hython` will start up hython in the interactive terminal
|
|
||||||
running the container. In the Linux container hython is in
|
|
||||||
/opt/hfs[VERSION].
|
|
||||||
In the Windows container, hython is in
|
|
||||||
C:/Program Files/Side Effects Software/Houdini[VERSION].
|
|
||||||
3. `docker-compose build` will build/rebuild the Houdini Docker images.
|
|
||||||
|
|
||||||
|
|
||||||
Some notes about Docker:
|
|
||||||
1. Docker requires that the Windows image version matches your host's Windows
|
|
||||||
version. The current Windows Houdini image is based on windows:1903; you
|
|
||||||
might need to update the Dockerfile accordingly.
|
|
||||||
2. The Mac and Windows versions do not support the "host" network, but host is
|
|
||||||
reachable on the special DNS name "host.docker.internal". If you have a
|
|
||||||
running sesinetd license server on host and would like to connect to it for
|
|
||||||
license checkout, you could switch point hserver to it.
|
|
||||||
3. All platforms (Mac/Linux/Windows) support the Linux version image. Only
|
|
||||||
Windows hosts support the Windows image.
|
|
||||||
4. Don't forget to toggle which daemon (Linux or Windows) the Docker CLI talks
|
|
||||||
to if you are using Windows Docker Desktop. You can switch it from the
|
|
||||||
Docker Desktop menu by selecting:
|
|
||||||
"Switch to Windows containers to use Windows containers" and
|
|
||||||
"Switch to Linux containers to use Linux containers"
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
FROM ubuntu:22.04
|
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends bc fontconfig wget libasound2 libgl1 libglu1 libglu1-mesa libglx0 libice6 libnss3 libopengl0 libpci3 libsm6 libx11-6 libx11-xcb1 libxcb-icccm4 libxcb-image0 libxcb-keysyms1 libxcb-randr0 libxcb-render-util0 libxcb-render0 libxcb-shape0 libxcb-shm0 libxcb-sync1 libxcb-util1 libxcb-xfixes0 libxcb-xinerama0 libxcb-xkb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxi6 libxkbcommon-x11-0 libxkbcommon0 libxrandr2 libxrender1 libxss1 libxt6 libxtst6 && rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
RUN mkdir houdiniInstaller
|
|
||||||
COPY houdini* /houdiniInstaller/
|
|
||||||
|
|
||||||
# Please update the following EULA_DATE to match the latest updated
|
|
||||||
# date of EULA in yyyy-mm-dd format. E.g. "2020-05-05"
|
|
||||||
# For Houdini 18.0 and previous version, EULA_DATE should be left empty
|
|
||||||
ARG EULA_DATE=""
|
|
||||||
RUN tar -xf /houdiniInstaller/houdini* -C /houdiniInstaller \
|
|
||||||
&& ./houdiniInstaller/houdini*/houdini.install --auto-install --accept-EULA ${EULA_DATE} \
|
|
||||||
&& rm -r /houdiniInstaller
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
|
||||||
hython:
|
|
||||||
container_name: hython
|
|
||||||
hostname: hython
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
network_mode: host
|
|
||||||
image: houdini:22.0
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
FROM mcr.microsoft.com/windows:1903
|
|
||||||
|
|
||||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
|
||||||
|
|
||||||
COPY "houdini-*-win64-vc141.exe" "C:\\"
|
|
||||||
|
|
||||||
# Please update the following EULA_DATE to match the latest updated
|
|
||||||
# date of EULA in yyyy-mm-dd format. E.g. "2020-05-05"
|
|
||||||
# For Houdini 18.0 and previous versions, EULA_DATE should be left empty
|
|
||||||
ARG EULA_DATE=""
|
|
||||||
|
|
||||||
RUN Start-Process "C:\\houdini-*-win64-vc141.exe" '/S /AcceptEULA=${EULA_DATE} /DesktopIcon=No /FileAssociations=No /StartMenu=No' -Wait;
|
|
||||||
|
|
||||||
RUN Remove-Item -Force "C:\\houdini-*-win64-vc141.exe"
|
|
||||||
|
|
||||||
RUN $vtokens = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Side Effects Software').ActiveVersion.Split('.'); \
|
|
||||||
$helppath = (Get-ItemProperty -Path 'HKLM:\SOFTWARE\Side Effects Software\Houdini').psobject.properties[$vtokens[0] + '.' + $vtokens[1] + '.0.' + $vtokens[2]].Value + 'houdini\help'; \
|
|
||||||
Remove-Item -Force $helppath -Recurse;
|
|
||||||
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
version: '3'
|
|
||||||
|
|
||||||
services:
|
|
||||||
hython:
|
|
||||||
container_name: hython
|
|
||||||
hostname: hython
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: houdini:22.0
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user