From 104d8a7c3f526511bc243c16bb8a7cecb7187958 Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Thu, 17 Sep 2026 22:45:54 -0500 Subject: [PATCH 1/4] citrix-workspace: expose HDX MediaStream plugin Install the bundled flatstm plugin in a wrapper-managed search path, matching the registration performed by Citrix's installer. Verify that multimedia remains enabled after the installer configuration rewrite. --- pkgs/by-name/ci/citrix-workspace/package.nix | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pkgs/by-name/ci/citrix-workspace/package.nix b/pkgs/by-name/ci/citrix-workspace/package.nix index 14a4860b6662..6c46828b7f32 100644 --- a/pkgs/by-name/ci/citrix-workspace/package.nix +++ b/pkgs/by-name/ci/citrix-workspace/package.nix @@ -263,7 +263,7 @@ stdenv.mkDerivation (finalAttrs: { ++ [ ''--set ICAROOT "$ICAInstDir"'' ''--prefix GIO_EXTRA_MODULES : "${glib-networking}/lib/gio/modules"'' - ''--prefix GST_PLUGIN_SYSTEM_PATH_1_0 : "${gstPluginPath}"'' + ''--prefix GST_PLUGIN_SYSTEM_PATH_1_0 : "$ICAInstDir/gst-plugins:${gstPluginPath}"'' ''--prefix LD_LIBRARY_PATH : "${ldLibraryPath program}"'' ''--set LD_PRELOAD "${libredirect}/lib/libredirect.so ${lib.getLib pcsclite}/lib/libpcsclite.so"'' ''--set NIX_REDIRECTS "/usr/share/zoneinfo=${tzdata}/share/zoneinfo:/etc/zoneinfo=${tzdata}/share/zoneinfo:/etc/timezone=$ICAInstDir/timezone"'' @@ -362,9 +362,16 @@ stdenv.mkDerivation (finalAttrs: { rm $ICAInstDir/util/{gst_aud_{play,read},gst_*0.10,libgstflatstm0.10.so} || true ln -sf $ICAInstDir/util/gst_play1.0 $ICAInstDir/util/gst_play ln -sf $ICAInstDir/util/gst_read1.0 $ICAInstDir/util/gst_read + + # hinst links this plugin into FHS directories; expose it through the wrapper instead. + mkdir -p "$ICAInstDir/gst-plugins" + ln -s "$ICAInstDir/util/libgstflatstm1.0.so" \ + "$ICAInstDir/gst-plugins/libgstflatstm.so" + # `hinst` disables multimedia when it cannot link into FHS plugin # directories. In Nix we provide the plugin path via wrappers instead. sed -i 's/^MultiMedia=Off$/MultiMedia=On/' "$ICAInstDir/config/module.ini" + grep -Fxq 'MultiMedia=On' "$ICAInstDir/config/module.ini" echo "We arbitrarily set the timezone to UTC. No known consequences at this point." echo UTC > "$ICAInstDir/timezone" From 4184cacac6f2cb98e9989efbf633a98598aa037f Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Thu, 17 Sep 2026 22:51:11 -0500 Subject: [PATCH 2/4] citrix-workspace: wrap command-line helpers Supply ICAROOT and the runtime library environment to storebrowse and diagnostic helpers without injecting unsupported -icaroot arguments. Keep new_store's explicit-root contract unchanged; it calls wrapped storebrowse and selfservice entry points. --- pkgs/by-name/ci/citrix-workspace/package.nix | 25 ++++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/pkgs/by-name/ci/citrix-workspace/package.nix b/pkgs/by-name/ci/citrix-workspace/package.nix index 6c46828b7f32..c374ac1264b7 100644 --- a/pkgs/by-name/ci/citrix-workspace/package.nix +++ b/pkgs/by-name/ci/citrix-workspace/package.nix @@ -230,11 +230,22 @@ stdenv.mkDerivation (finalAttrs: { isSelfservice = program: (builtins.match "selfservice(.*)" program) != null; isWfica = program: (builtins.match "wfica(.*)" program) != null; + # These helpers read ICAROOT without accepting the generic -icaroot flag. + isEnvOnly = + program: + builtins.elem program [ + "util/logmgr" + "util/nfcui" + "util/sendfeedback" + "util/setlog" + "util/storebrowse" + ]; + icaFlag = program: if isSelfservice program then "--icaroot" - else if isWfica program then + else if isWfica program || isEnvOnly program then null else "-icaroot"; @@ -307,6 +318,7 @@ stdenv.mkDerivation (finalAttrs: { "util/conncenter" "util/ctx_rehash" "util/ctxwebhelper" + "util/storebrowse" ]; in '' @@ -335,20 +347,19 @@ stdenv.mkDerivation (finalAttrs: { # FHS launcher hinst generates even for non-root installs; it hardcodes # store paths without any of the wrapper environment. rm -f "$ICAInstDir/wfica.sh" - if [ -f "$ICAInstDir/util/setlog" ]; then - chmod +x "$ICAInstDir/util/setlog" - ln -sf "$ICAInstDir/util/setlog" "$out/bin/citrix-setlog" - fi + chmod +x "$ICAInstDir/util/setlog" ${mkWrappers wrapLink toWrap} ${makeBinWrapper "wfica" "wfica"} + ${makeBinWrapper "util/setlog" "citrix-setlog"} ${mkWrappers wrap [ "PrimaryAuthManager" "ServiceRecord" "AuthManagerDaemon" + "util/logmgr" + "util/nfcui" + "util/sendfeedback" ]} - ln -sf $ICAInstDir/util/storebrowse $out/bin/storebrowse - # As explained in https://wiki.archlinux.org/index.php/Citrix#Security_Certificates echo "Expanding certificates..." pushd "$ICAInstDir/keystore/cacerts" From 53c42c584002c2d491e2faea22374091d82a12d0 Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Thu, 17 Sep 2026 22:53:59 -0500 Subject: [PATCH 3/4] citrix-workspace: ship the logging user service Retain the vendor ctxcwalogd user unit that the non-root installer writes outside the package output. Document opt-in NixOS registration so logging tools can connect to the daemon without introducing a system service. --- doc/packages/citrix.section.md | 10 ++++++++++ pkgs/by-name/ci/citrix-workspace/package.nix | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/doc/packages/citrix.section.md b/doc/packages/citrix.section.md index fe59f083a0b1..ff3589e3f1b8 100644 --- a/doc/packages/citrix.section.md +++ b/doc/packages/citrix.section.md @@ -6,6 +6,16 @@ The [Citrix Workspace App](https://www.citrix.com/products/workspace-app/) is a The tarball archive needs to be downloaded manually, as the license agreements of the vendor for [Citrix Workspace](https://www.citrix.com/downloads/workspace-app/linux/workspace-app-for-linux-latest.html) needs to be accepted first. Then run `nix-prefetch-url file://$PWD/linuxx64-$version.tar.gz`. With the archive available in the store, the package can be built and installed with Nix. +The package includes the `ctxcwalogd.service` user unit required by Citrix's logging tools. +To enable it on NixOS: + +```nix +{ + systemd.packages = [ pkgs.citrix-workspace ]; + systemd.user.services.ctxcwalogd.wantedBy = [ "default.target" ]; +} +``` + ## Citrix Self-service {#sec-citrix-selfservice} The [self-service](https://support.citrix.com/article/CTX200337) is an application for managing Citrix desktops and applications. Please note that this feature only works with at least `citrix_workspace_20_06_0` and later versions. diff --git a/pkgs/by-name/ci/citrix-workspace/package.nix b/pkgs/by-name/ci/citrix-workspace/package.nix index c374ac1264b7..b89568f99f2d 100644 --- a/pkgs/by-name/ci/citrix-workspace/package.nix +++ b/pkgs/by-name/ci/citrix-workspace/package.nix @@ -344,6 +344,14 @@ stdenv.mkDerivation (finalAttrs: { # the tarball still contains the legacy WebKitGTK 4.0 bundle. rm -rf "$ICAInstDir/Webkit2gtk4.0" + # hinst installs this user unit outside the package for non-root installs. + mkdir -p $out/lib/systemd/user + sed \ + -e '/^#/d' \ + -e "s,###ICAROOT###,$ICAInstDir,g" \ + -e 's,###USER###,default,' \ + linuxx64/linuxx64.cor/ctxcwalogd.service > $out/lib/systemd/user/ctxcwalogd.service + # FHS launcher hinst generates even for non-root installs; it hardcodes # store paths without any of the wrapper environment. rm -f "$ICAInstDir/wfica.sh" From 6a105ae81ea29f44488c6d117f8682caa7af56bd Mon Sep 17 00:00:00 2001 From: Austin Horstman Date: Thu, 17 Sep 2026 23:00:49 -0500 Subject: [PATCH 4/4] citrix-workspace: find the privileged FUSE helper Redirect Citrix's /usr/bin/fusermount3 calls to the NixOS security wrapper when it is executable. Preserve the original path on other systems and document programs.fuse.enable for FUSE-based file transfer. --- doc/packages/citrix.section.md | 10 ++++++++++ pkgs/by-name/ci/citrix-workspace/package.nix | 15 ++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/doc/packages/citrix.section.md b/doc/packages/citrix.section.md index ff3589e3f1b8..fc78ccbdc11d 100644 --- a/doc/packages/citrix.section.md +++ b/doc/packages/citrix.section.md @@ -16,6 +16,16 @@ To enable it on NixOS: } ``` +For FUSE-based file transfer, enable the privileged helper on NixOS: + +```nix +{ + programs.fuse.enable = true; +} +``` + +The package uses `/run/wrappers/bin/fusermount3` when it is available. + ## Citrix Self-service {#sec-citrix-selfservice} The [self-service](https://support.citrix.com/article/CTX200337) is an application for managing Citrix desktops and applications. Please note that this feature only works with at least `citrix_workspace_20_06_0` and later versions. diff --git a/pkgs/by-name/ci/citrix-workspace/package.nix b/pkgs/by-name/ci/citrix-workspace/package.nix index b89568f99f2d..5a6b2acb1c68 100644 --- a/pkgs/by-name/ci/citrix-workspace/package.nix +++ b/pkgs/by-name/ci/citrix-workspace/package.nix @@ -263,6 +263,15 @@ stdenv.mkDerivation (finalAttrs: { ] ); + runtimeSetup = '' + export NIX_REDIRECTS="/usr/share/zoneinfo=${tzdata}/share/zoneinfo:/etc/zoneinfo=${tzdata}/share/zoneinfo:/etc/timezone=$ICAROOT/timezone" + + # Citrix invokes the FHS helper path; NixOS supplies the privileged wrapper here. + if [ -x /run/wrappers/bin/fusermount3 ]; then + NIX_REDIRECTS="$NIX_REDIRECTS:/usr/bin/fusermount3=/run/wrappers/bin/fusermount3" + fi + ''; + # Only the ICA engine needs the top-level client directory on the library # path. Leaving it enabled for UI helpers exposes Citrix's session-only # libproxy.so to the embedded web stack, which then fails to resolve CGP @@ -277,7 +286,7 @@ stdenv.mkDerivation (finalAttrs: { ''--prefix GST_PLUGIN_SYSTEM_PATH_1_0 : "$ICAInstDir/gst-plugins:${gstPluginPath}"'' ''--prefix LD_LIBRARY_PATH : "${ldLibraryPath program}"'' ''--set LD_PRELOAD "${libredirect}/lib/libredirect.so ${lib.getLib pcsclite}/lib/libpcsclite.so"'' - ''--set NIX_REDIRECTS "/usr/share/zoneinfo=${tzdata}/share/zoneinfo:/etc/zoneinfo=${tzdata}/share/zoneinfo:/etc/timezone=$ICAInstDir/timezone"'' + "--run ${lib.escapeShellArg runtimeSetup}" ] ++ lib.optionals (isWfica program) [ # wfica is an X11 client (it runs under XWayland). On a Wayland @@ -291,7 +300,7 @@ stdenv.mkDerivation (finalAttrs: { ); wrap = program: '' - wrapProgram $out/opt/citrix-icaclient/${program} \ + wrapProgramShell $out/opt/citrix-icaclient/${program} \ ${wrapperArgs program} ''; @@ -301,7 +310,7 @@ stdenv.mkDerivation (finalAttrs: { ''; makeBinWrapper = program: wrapperName: '' - makeWrapper $out/opt/citrix-icaclient/${program} $out/bin/${wrapperName} \ + makeShellWrapper $out/opt/citrix-icaclient/${program} $out/bin/${wrapperName} \ ${wrapperArgs program} '';