(Re)Packaging Linux/Mac Kontur Talk Application with Nix
Our company recently decided to transition from Zoom to Kontur Talk (ktalk) for voice and video communications. Kontur provides official application packages as Linux AppImage and macOS DMG files, but to ensure consistency across developer workstations running both Linux and macOS, I set out to create unified packaging using Nix. Surprisingly, at the time of writing, no existing Nix derivation for ktalk was available, motivating this packaging initiative.
Packaging for Linux
Step 1: Defining Source AppImage via fetchurl
To begin, we first define the source AppImage from Kontur’s official servers. Using Nix’s built-in fetchurl utility simplifies fetching the binary while ensuring reproducibility through a verified hash.
src = builtins.fetchurl {
url = "https://st.ktalk.host/ktalk-app/linux/${pname}${version}x86_64.AppImage";
sha256 = "0sb7n49kv0kwjby7sbp959jg0hhb6k0dygz7i2wv5rh58q01cy2a";
};
Step 2: Using pkgs.appimageTools.wrapType2
We then utilize pkgs.appimageTools.wrapType2, a convenient NixOS helper to automate extraction and wrapping of AppImages, enabling the binary to integrate seamlessly with the system.
pkgs.appimageTools.wrapType2 rec {
inherit pname version src desktopItem;
extraInstallCommands = ''
source "${pkgs.makeWrapper}/nix-support/setup-hook"
wrapProgram $out/bin/${pname} \
--run "setsid $out/bin/.${pname}-wrapped \"$@\" >/dev/null 2>&1 </dev/null &" \
--run "exit 0"
mkdir -p $out/share/applications/
cp ${desktopItem}/share/applications/*.desktop $out/share/applications/
cp -r ${appimageContents}/usr/share/icons/ $out/share/icons/
runHook postInstall
'';
}
Step 3: Creating a Wrapper to Run the App in the Background
To prevent terminal clutter and allow seamless background operation, I created a wrapper script that invokes the actual ktalk binary in a detached session (setsid), ensuring a smooth user experience.
Step 4: Making the Application Easily Launchable with Rofi
By generating a desktop item using makeDesktopItem, ktalk appears in application launchers like Rofi, further enhancing ease of use.
desktopItem = pkgs.makeDesktopItem {
name = "ktalk";
desktopName = "ktalk";
comment = "Kontur.Talk";
icon = "ktalk";
exec = "ktalk %U";
categories = ["VideoConference"];
mimeTypes = ["x-scheme-handler/ktalk"];
};
Packaging for macOS
The macOS packaging posed an interesting challenge:
Step 1: Handling Cyrillic Name in DMG
The original DMG from Kontur uses the Cyrillic name “Толк”, causing issues with the standard undmg extraction tool. It renamed ‘Толк.app’ into ‘”>;:.app’, resulting in being unable in install it.
Step 2: Using hdiutil to Unpack the Archive
Instead, I utilized the native hdiutil utility to properly mount and extract the DMG during the unpackPhase.
unpackPhase = ''
tmp=$(mktemp -d)
/usr/bin/hdiutil attach "${src}" -mountpoint "$tmp" -nobrowse -quiet
cp -R "$tmp"/* ./
/usr/bin/hdiutil detach "$tmp" -quiet
rm -rf "$tmp"
'';
Step 3: Simplifying installPhase
After extracting the DMG correctly, the installation simply involves copying the Contents directory to the designated location:
installPhase = ''
mkdir -p $out/Applications/Толк.app
cp -R "Contents" $out/Applications/Толк.app/
'';
Defining Meta for Both Systems
To complete our derivation, we defined consistent metadata across both Linux and macOS:
meta = with lib; {
description = ''Kontur talk, communication platform'';
longDescription = ''
A space for communication and teamwork.
Combines hangouts, chat rooms, webinars, online whiteboards, and a
dedicated application for meeting rooms. Allows capturing and saving
communication outcomes.
'';
homepage = "https://kontur.ru/talk";
license = licenses.unfree;
maintainers = with maintainers; [sbulav];
platforms = ["x86_64-linux" "x86_64-darwin" "aarch64-darwin"];
};
Full Module Code
Here’s the complete Nix derivation integrating both platforms:
{
pkgs,
lib,
...
}: let
pname = "ktalk";
version = "3.0.0";
# Platform-specific sources
src =
if pkgs.stdenv.isLinux
then
builtins.fetchurl {
url = "https://st.ktalk.host/ktalk-app/linux/${pname}${version}x86_64.AppImage";
sha256 = "0sb7n49kv0kwjby7sbp959jg0hhb6k0dygz7i2wv5rh58q01cy2a";
}
else
builtins.fetchurl {
url = "https://st.ktalk.host/ktalk-app/mac/ktalk.${version}-mac.dmg";
sha256 = "17dg51017byd3idmk477aqgp2b748xizj4jgw2h0xdw33bz5pvl7";
};
meta = with lib; {
description = ''
Kontur talk, communication platform
'';
longDescription = ''
A space for communication and teamwork
It combines hangouts, chat rooms, webinars, online whiteboards and an
application for meeting rooms. Allows you to capture and save the result of
communications.
'';
homepage = "https://kontur.ru/talk";
license = licenses.unfree;
maintainers = with maintainers; [sbulav];
platforms = ["x86_64-linux" "x86_64-darwin" "aarch64-darwin"];
};
# Linux-specific: Desktop item for AppImage
desktopItem = pkgs.makeDesktopItem {
name = "ktalk";
desktopName = "ktalk";
comment = "Kontur.Talk";
icon = "ktalk";
exec = "ktalk %U";
categories = ["VideoConference"];
mimeTypes = ["x-scheme-handler/ktalk"];
};
# Linux-specific: Extract AppImage contents
appimageContents = pkgs.appimageTools.extractType2 {
inherit pname version src meta;
};
in
if pkgs.stdenv.isLinux
then
pkgs.appimageTools.wrapType2 rec {
inherit pname version src desktopItem;
extraInstallCommands = ''
source "${pkgs.makeWrapper}/nix-support/setup-hook"
# Create a wrapper that runs the binary in a detached session
wrapProgram $out/bin/${pname} \
--run "setsid $out/bin/.${pname}-wrapped \"\$@\" >/dev/null 2>&1 </dev/null &" \
--run "exit 0"
mkdir -p $out/share/applications/
cp ${desktopItem}/share/applications/*.desktop $out/share/applications/
cp -r ${appimageContents}/usr/share/icons/ $out/share/icons/
runHook postInstall
'';
}
else
pkgs.stdenv.mkDerivation rec {
inherit pname version meta src;
sourceRoot = "Толк.app"; # Matches the .dmg volume name
unpackPhase = ''
tmp=$(mktemp -d)
/usr/bin/hdiutil attach "${src}" -mountpoint "$tmp" -nobrowse -quiet
cp -R "$tmp"/* ./
/usr/bin/hdiutil detach "$tmp" -quiet
rm -rf "$tmp"
'';
installPhase = ''
mkdir -p $out/Applications/Толк.app
cp -R "Contents" $out/Applications/Толк.app/
'';
}
Conclusion
Packaging Kontur Talk with Nix turned out to be simultaneously simpler and more challenging than expected. While Linux integration was straightforward due to excellent tooling, macOS required deeper exploration due to specific quirks. Documentation was another pain, even finding simple function description can be a challenge.
Overall, the outcome is a seamless, reproducible setup benefiting all our developers.
Comments