Atv0.3.0Repositorytessera

docs/guix-and-nix.md

Release v0.3.0 · Default-branch version

Document

Running Tessera on Guix and NixOS

The downloaded Linux amd64 binary asks for the loader at /lib64/ld-linux-x86-64.so.2 and libraries in the usual Linux directories. Guix System and NixOS keep these files in their package stores instead. That can make an executable which exists and has execute permission fail with "No such file or directory". The steps below give Tessera a loader and the libraries it needs without changing your system's library paths.

Use the examples from the same Tessera version as your download. Commands below start in the root of an extracted Tessera source archive or checkout, with the verified tessera-0.3.0-linux-amd64 download beside it. You do not need to compile Tessera or install Sigil.

Keep the original download. Verify its SHA256SUMS before patching. A patched copy has a different checksum. Tessera contains an application archive after its executable code; running patchelf directly on the complete file can make that archive unreadable. The included patch-tessera helper patches only the executable prefix and reattaches the unchanged application with an updated offset. It takes an input, a new output, a loader and a library path, and refuses to overwrite an existing output. It requires Bash, GNU coreutils and patchelf.

Guix

The pinned shell and patching steps were checked on x86_64 Guix on 2026-10-24 with a Tessera 0.1 candidate: all libraries resolved, --help and theme list ran, and a headless Pixman session answered expression IPC. The embedded application archive was unchanged by patching.

The runtime manifest includes the loader, Wayland, Mesa, DRM, input and seat libraries, keyboard data, text libraries and fonts. It also supplies Xwayland and the standard companion programs: foot, fuzzel, swaybg, swaylock, swayidle, mako, grim and slurp, plus notification and session helpers. wlroots and the Sigil runtime are already in the binary.

Enter the environment using the repository's channel pin:

guix time-machine -C channels.scm -- \
  shell --no-grafts -m docs/examples/guix/manifest.scm

Inside that shell, make and check your copy:

bash docs/examples/patch-tessera \
  ./tessera-0.3.0-linux-amd64 ./tessera-guix \
  "$GUIX_ENVIRONMENT/lib/ld-linux-x86-64.so.2" \
  "$GUIX_ENVIRONMENT/lib"

ldd ./tessera-guix
ls "$GUIX_ENVIRONMENT"/lib/libcairo.so "$GUIX_ENVIRONMENT"/lib/libfreetype.so \
  "$GUIX_ENVIRONMENT"/lib/libharfbuzz.so "$GUIX_ENVIRONMENT"/lib/libfontconfig.so \
  "$GUIX_ENVIRONMENT"/lib/librsvg-2.so "$GUIX_ENVIRONMENT"/lib/libgobject-2.0.so
./tessera-guix --help

ldd must have no not found entries, and ls must list all six files. ldd only sees the libraries the executable links directly. Tessera's text bindings open Cairo, FreeType, HarfBuzz and Fontconfig by these unversioned names when a session starts. The bundled SVG binding additionally opens librsvg and GObject when imported. A missing binding library can pass ldd and --help and then stops tessera start with c-library: cannot load "libcairo" (or the matching name). Build your environment or profile from the runtime manifest, not from the ldd output. The helper runs this operation on the separated ELF prefix:

patchelf --set-interpreter "$GUIX_ENVIRONMENT/lib/ld-linux-x86-64.so.2" \
  --set-rpath "$GUIX_ENVIRONMENT/lib" ELF_PREFIX

When WLR_XWAYLAND is unset and /usr/bin/Xwayland is absent, Tessera finds Xwayland on PATH automatically. An explicit WLR_XWAYLAND still overrides it. Use the same Guix environment whenever you start this copy, so helpers, fonts and keyboard data remain available. An unpinned guix shell -m docs/examples/guix/manifest.scm uses your current channels; it may select different library ABIs. libdisplay-info and libliftoff are linked into the executable and need no runtime package.

From an existing Wayland desktop, try it in a window first:

WLR_BACKENDS=wayland WLR_RENDERER=pixman TESSERA_MODIFIER=Alt \
  ./tessera-guix start

Alt+Shift+Return opens a terminal; Alt+Shift+x exits. Pixman uses software rendering for this first check.

Keep a runtime profile

For regular use, create a profile that keeps the dependencies reachable by Guix's garbage collector. From the same source directory:

mkdir -p "$HOME/.local/share/tessera" "$HOME/.local/bin"
guix time-machine -C channels.scm -- package --no-grafts \
  --profile="$HOME/.local/share/tessera/runtime" \
  --manifest=docs/examples/guix/manifest.scm

guix shell --profile="$HOME/.local/share/tessera/runtime"

Inside this shell, patch a fresh copy against the persistent profile:

bash docs/examples/patch-tessera \
  ./tessera-0.3.0-linux-amd64 "$HOME/.local/bin/tessera" \
  "$HOME/.local/share/tessera/runtime/lib/ld-linux-x86-64.so.2" \
  "$HOME/.local/share/tessera/runtime/lib"
lib="$HOME/.local/share/tessera/runtime/lib"
ls "$lib/libcairo.so" "$lib/libfreetype.so" "$lib/libharfbuzz.so" "$lib/libfontconfig.so" "$lib/librsvg-2.so" "$lib/libgobject-2.0.so"

Enter that profile shell again in future sessions. Keep the profile installed while using this binary. After changing its library versions, create a new patched copy from the original download and check it again.

Start from a TTY

Log into an unused local TTY as your normal user, enter the runtime shell, then run ~/.local/bin/tessera. Leave WLR_BACKENDS and WLR_RENDERER unset so Tessera can select your real GPU and input devices. The login must provide a user-owned, mode-0700 XDG_RUNTIME_DIR and a user D-Bus session. If your login does not already start the latter, use dbus-run-session -- ~/.local/bin/tessera.

On Guix System, an active local elogind session can provide seat access; desktop configurations commonly include elogind-service-type. No extra video or input group is needed for that route. If you use seatd instead, enable seatd-service-type in the operating-system configuration and add your user to the group owning its socket. Guix's default seatd group is seat; follow your actual service configuration, then log out and back in. Installing libseat in a shell does not start either system service. See the Guix service reference. Run Tessera as your user, without sudo.

The loader, CLI and software-rendered startup checks do not qualify hardware DRM/input, VT switching or screen unlocking. Keep a spare TTY available. The pinned environment includes Mesa; GPU drivers and their kernel support must also work on your host. Do not export a global LD_LIBRARY_PATH to mix graphics libraries from other profiles.

Build from source instead

The source build instructions use the repository's channels.scm with the build and nested-runtime manifests. Those launchers arrange their own library environment, so they do not need this download-patching step.

Nix / NixOS (untested)

These Nix instructions have not been run. The shell.nix example supplies the corresponding runtime libraries, fonts, keyboard data, patching tools and companion programs. It uses your <nixpkgs> package set. libdisplay-info and libliftoff are linked into the executable.

Enter the shell and patch a new copy with the same archive-preserving helper:

nix-shell docs/examples/nix/shell.nix

bash docs/examples/patch-tessera \
  ./tessera-0.3.0-linux-amd64 ./tessera-nix \
  "$(cat "$NIX_CC/nix-support/dynamic-linker")" \
  "$TESSERA_LIBRARY_PATH"

ldd ./tessera-nix
./tessera-nix --help

The underlying patchelf operation is --set-interpreter with the loader from $NIX_CC/nix-support/dynamic-linker, and --set-rpath with $TESSERA_LIBRARY_PATH, applied to the separated prefix. The example sets XKB_CONFIG_ROOT and Fontconfig configuration for you. Tessera finds Xwayland on PATH. Start inside this shell, using the nested command above with ./tessera-nix, or from a local TTY with ./tessera-nix and no backend overrides. Re-enter the same shell for later launches; a permanent Nix package/wrapper should retain these dependencies as store references before garbage collection.

For a NixOS TTY session, enable hardware.graphics.enable = true; in your system configuration and use your configured GPU drivers. The shell searches /run/opengl-driver/lib before its fallback graphics libraries, following NixOS's graphics driver setup. On another distribution with Nix installed, host-driver integration needs separate setup; this example does not establish that it works there.

An active local systemd-logind session normally grants seat access without adding video or input groups. If you choose seatd instead, enable its service and add your user to the group configured for its socket, then log out and back in. Keep PAM support for the chosen locker: for swaylock on NixOS, configure security.pam.services.swaylock = {};. A shell dependency does not install a PAM service. The same runtime-directory and D-Bus requirements as the Guix TTY instructions apply.

nix-ld: keep the download unchanged

On NixOS, nix-ld can provide the conventional loader path without editing Tessera. Enable programs.nix-ld.enable = true; in your NixOS configuration, rebuild your system, and log in again. Then enter the example shell and run the original:

nix-shell docs/examples/nix/shell.nix
chmod +x ./tessera-0.3.0-linux-amd64
./tessera-0.3.0-linux-amd64 --help

The shell sets NIX_LD and NIX_LD_LIBRARY_PATH for nix-ld. It still supplies the helpers and data files needed for a compositor session. If you configure programs.nix-ld.libraries system-wide instead, include the complete library list from shell.nix. Enabling nix-ld alone does not provide Tessera's libraries, seat access or GPU drivers. See the NixOS nix-ld module.