{ lib , stdenv , fetchurl , makeDesktopItem , copyDesktopItems , makeWrapper , writeText , autoPatchelfHook , wrapGAppsHook , callPackage , atk , cairo , dbus , dbus-glib , fontconfig , freetype , gdk-pixbuf , glib , gtk3 , libxcb , libX11 , libXext , libXrender , libXt , libXtst , mesa , pango , pciutils , zlib , libnotifySupport ? stdenv.isLinux , libnotify , waylandSupport ? stdenv.isLinux , libxkbcommon , libdrm , libGL , mediaSupport ? true , ffmpeg , audioSupport ? mediaSupport , pipewireSupport ? audioSupport , pipewire , pulseaudioSupport ? audioSupport , libpulseaudio , apulse , alsa-lib , libvaSupport ? mediaSupport , libva # Hardening , graphene-hardened-malloc # Whether to use graphene-hardened-malloc , useHardenedMalloc ? null # Whether to disable multiprocess support , disableContentSandbox ? false # Extra preferences , extraPrefs ? "" }: lib.warnIf (useHardenedMalloc != null) "tor-browser: useHardenedMalloc is deprecated and enabling it can cause issues" (let libPath = lib.makeLibraryPath ( [ alsa-lib atk cairo dbus dbus-glib fontconfig freetype gdk-pixbuf glib gtk3 libxcb libX11 libXext libXrender libXt libXtst mesa # for libgbm pango pciutils stdenv.cc.cc stdenv.cc.libc zlib ] ++ lib.optionals libnotifySupport [ libnotify ] ++ lib.optionals waylandSupport [ libxkbcommon libdrm libGL ] ++ lib.optionals pipewireSupport [ pipewire ] ++ lib.optionals pulseaudioSupport [ libpulseaudio ] ++ lib.optionals libvaSupport [ libva ] ++ lib.optionals mediaSupport [ ffmpeg ] ); version = "13.0.12"; sources = { x86_64-linux = fetchurl { urls = [ "https://archive.torproject.org/tor-package-archive/torbrowser/${version}/tor-browser-linux-x86_64-${version}.tar.xz" "https://dist.torproject.org/torbrowser/${version}/tor-browser-linux-x86_64-${version}.tar.xz" "https://tor.eff.org/dist/torbrowser/${version}/tor-browser-linux-x86_64-${version}.tar.xz" "https://tor.calyxinstitute.org/dist/torbrowser/${version}/tor-browser-linux-x86_64-${version}.tar.xz" ]; hash = "sha256-2AzcDYngLr+J+s12tAMdB9SjDzOWPnQY9WL7/3+N0FA="; }; i686-linux = fetchurl { urls = [ "https://archive.torproject.org/tor-package-archive/torbrowser/${version}/tor-browser-linux-i686-${version}.tar.xz" "https://dist.torproject.org/torbrowser/${version}/tor-browser-linux-i686-${version}.tar.xz" "https://tor.eff.org/dist/torbrowser/${version}/tor-browser-linux-i686-${version}.tar.xz" "https://tor.calyxinstitute.org/dist/torbrowser/${version}/tor-browser-linux-i686-${version}.tar.xz" ]; hash = "sha256-ect++2xZe00Hlikz6eMNMiiHnVoETSvjD0Cf1oBgj9E="; }; }; distributionIni = writeText "distribution.ini" (lib.generators.toINI {} { # Some light branding indicating this build uses our distro preferences Global = { id = "nixos"; version = "1.0"; about = "Tor Browser for NixOS"; }; }); policiesJson = writeText "policies.json" (builtins.toJSON { policies.DisableAppUpdate = true; }); in stdenv.mkDerivation rec { pname = "tor-browser"; inherit version; src = sources.${stdenv.hostPlatform.system} or (throw "unsupported system: ${stdenv.hostPlatform.system}"); nativeBuildInputs = [ autoPatchelfHook copyDesktopItems makeWrapper wrapGAppsHook ]; buildInputs = [ gtk3 alsa-lib dbus-glib libXtst ]; preferLocalBuild = true; allowSubstitutes = false; desktopItems = [(makeDesktopItem { name = "torbrowser"; exec = "tor-browser %U"; icon = "tor-browser"; desktopName = "Tor Browser"; genericName = "Web Browser"; comment = meta.description; categories = [ "Network" "WebBrowser" "Security" ]; })]; buildPhase = '' runHook preBuild # For convenience ... TBB_IN_STORE=$out/share/tor-browser interp=$(< $NIX_CC/nix-support/dynamic-linker) # Unpack & enter mkdir -p "$TBB_IN_STORE" tar xf "$src" -C "$TBB_IN_STORE" --strip-components=2 pushd "$TBB_IN_STORE" # Set ELF interpreter for exe in firefox.real TorBrowser/Tor/tor ; do echo "Setting ELF interpreter on $exe ..." >&2 patchelf --set-interpreter "$interp" "$exe" done # firefox is a wrapper that checks for a more recent libstdc++ & appends it to the ld path mv firefox.real firefox # store state at `~/.tor browser` instead of relative to executable touch "$TBB_IN_STORE/system-install" # The final libPath. Note, we could split this into firefoxLibPath # and torLibPath for accuracy, but this is more convenient ... libPath=${libPath}:$TBB_IN_STORE:$TBB_IN_STORE/TorBrowser/Tor # apulse uses a non-standard library path. For now special-case it. ${lib.optionalString (audioSupport && !pulseaudioSupport) '' libPath=${apulse}/lib/apulse:$libPath ''} # Fixup paths to pluggable transports. sed -i TorBrowser/Data/Tor/torrc-defaults \ -e "s,./TorBrowser,$TBB_IN_STORE/TorBrowser,g" # Fixup obfs transport. Work around patchelf failing to set # interpreter for pre-compiled Go binaries by invoking the interpreter # directly. sed -i TorBrowser/Data/Tor/torrc-defaults \ -e "s|\(ClientTransportPlugin meek_lite,obfs2,obfs3,obfs4,scramblesuit\) exec|\1 exec $interp|" # Similarly fixup snowflake sed -i TorBrowser/Data/Tor/torrc-defaults \ -e "s|\(ClientTransportPlugin snowflake\) exec|\1 exec $interp|" # Prepare for autoconfig. # # See https://developer.mozilla.org/en-US/Firefox/Enterprise_deployment cat >defaults/pref/autoconfig.js <mozilla.cfg <fonts,$TBB_IN_STORE/fonts," # Hard-code paths to geoip data files. TBB resolves the geoip files # relative to torrc-defaults_path but if we do not hard-code them # here, these paths end up being written to the torrc in the user's # state dir. cat >>TorBrowser/Data/Tor/torrc-defaults </dev/null echo "Checking tor-browser wrapper ..." $out/bin/tor-browser --version >/dev/null runHook postBuild ''; installPhase = '' runHook preInstall # Install distribution customizations install -Dvm644 ${distributionIni} $out/share/tor-browser/distribution/distribution.ini install -Dvm644 ${policiesJson} $out/share/tor-browser/distribution/policies.json runHook postInstall ''; passthru = { inherit sources; updateScript = callPackage ./update.nix { inherit pname version meta; }; }; meta = with lib; { description = "Privacy-focused browser routing traffic through the Tor network"; mainProgram = "tor-browser"; homepage = "https://www.torproject.org/"; changelog = "https://gitweb.torproject.org/builders/tor-browser-build.git/plain/projects/tor-browser/Bundle-Data/Docs/ChangeLog.txt?h=maint-${version}"; platforms = attrNames sources; maintainers = with maintainers; [ felschr panicgh joachifm hax404 ]; # MPL2.0+, GPL+, &c. While it's not entirely clear whether # the compound is "libre" in a strict sense (some components place certain # restrictions on redistribution), it's free enough for our purposes. license = with licenses; [ mpl20 lgpl21Plus lgpl3Plus free ]; sourceProvenance = with sourceTypes; [ binaryNativeCode ]; }; })