{ config, pkgs, lib, inputs, ... }: let cfg = config.local.programs.browsers.tor-browser; policiesJson = pkgs.callPackage ./policies.nix { firefoxAddons = inputs.firefox-addons.packages."${pkgs.system}"; }; torBrowser = (pkgs.tor-browser-bundle-bin.override { mediaSupport = true; pulseaudioSupport = true; }).overrideAttrs (attrs: { postInstall = '' rm $out/share/tor-browser/distribution/policies.json install -Dvm644 ${policiesJson} $out/share/tor-browser/distribution/policies.json ''; }); in { options.local.programs.browsers.tor-browser = with lib; { enable = mkEnableOption "tor-browser"; container = { enable = mkEnableOption "tor-browser inside a container"; externalInterface = mkOption { type = types.str; default = ""; }; sshAuthorizedKeys = mkOption { type = types.listOf types.str; default = [ ]; }; }; }; config = lib.mkIf cfg.enable (lib.mkMerge [ (lib.mkIf (!cfg.container.enable) { environment.systemPackages = [ torBrowser ]; }) (lib.mkIf cfg.container.enable ( let hostRunTorBrowser = pkgs.writeScriptBin "tor-browser" '' ${pkgs.socat}/bin/socat -d TCP-LISTEN:6000,fork,bind=192.168.7.10 UNIX-CONNECT:/tmp/.X11-unix/X0 & ${pkgs.xorg.xhost}/bin/xhost + ssh -X browser@192.168.7.11 tor-browser ${pkgs.xorg.xhost}/bin/xhost - ''; clientRunTorBrowser = pkgs.writeScriptBin "tor-browser" '' PULSE_SERVER=tcp:192.168.7.10:4713 \ XAUTHORITY="/home/browser/.Xauthority" \ DBUS_SESSION_BUS_ADDRESS="" \ DISPLAY=192.168.7.10:0.0 \ ${pkgs.apulse}/bin/apulse ${torBrowser}/bin/tor-browser $@ ''; in { assertions = [ { assertion = cfg.container.externalInterface != ""; message = "The `tor-browser` module with the `isContainer` option enabled requires a non-empty `externalInterface` with Internet access"; } { assertion = cfg.container.sshAuthorizedKeys != [ ]; message = "The `tor-browser` module with the `isContainer` option enabled requires a non-empty `sshAuthorizedKeys` to connect to the container"; } ]; environment.systemPackages = [ hostRunTorBrowser ]; hardware.pulseaudio = { systemWide = true; support32Bit = true; tcp = { enable = true; anonymousClients.allowedIpRanges = [ "127.0.0.1" "192.168.7.0/24" ]; }; }; networking = { firewall.allowedTCPPorts = [ 4713 6000 ]; nat = { enable = true; internalInterfaces = [ "ve-browser" ]; externalInterface = cfg.container.externalInterface; }; }; containers.browser = { autoStart = true; privateNetwork = true; hostAddress = "192.168.7.10"; localAddress = "192.168.7.11"; config = { ... }: { system.stateVersion = "23.11"; services.openssh = { enable = true; settings.X11Forwarding = true; }; users.extraUsers.browser = { isNormalUser = true; home = "/home/browser"; openssh.authorizedKeys.keys = cfg.container.sshAuthorizedKeys; extraGroups = [ "pulse-access" ]; packages = [ clientRunTorBrowser ]; }; }; }; } )) ]); }