diff --git a/home/browsers/mullvad-browser.nix b/home/browsers/mullvad-browser.nix index 17b6154..e0fbcc8 100644 --- a/home/browsers/mullvad-browser.nix +++ b/home/browsers/mullvad-browser.nix @@ -39,12 +39,6 @@ let # Use native file picker instead of GTK file picker "widget.use-xdg-desktop-portal.file-picker" = 1; - - # enable WebAuthn - "security.webauth.webauthn" = true; - - # video acceleration - "media.ffmpeg.vaapi.enabled" = true; }; commonExtensions = with firefox-addons; [ diff --git a/home/modules/firefox/common.nix b/home/modules/firefox/common.nix index 449cc0f..8fda3fe 100644 --- a/home/modules/firefox/common.nix +++ b/home/modules/firefox/common.nix @@ -1,18 +1,751 @@ -{ lib, ... }: +{ + config, + lib, + pkgs, + ... +}: + +with lib; let + jsonFormat = pkgs.formats.json { }; + + # The extensions path shared by all profiles; will not be supported + # by future Firefox versions. + extensionPath = "extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"; + userPrefValue = pref: - builtins.toJSON ( - if lib.isBool pref || lib.isInt pref || lib.isString pref then pref else builtins.toJSON pref - ); -in -{ + builtins.toJSON (if isBool pref || isInt pref || isString pref then pref else builtins.toJSON pref); + mkConfig = prefs: - lib.concatStrings ( - lib.mapAttrsToList (name: value: '' + concatStrings ( + mapAttrsToList (name: value: '' user_pref("${name}", ${userPrefValue value}); '') prefs ); + + mkUserJs = + prefs: extraPrefs: bookmarks: + let + prefs' = + lib.optionalAttrs ([ ] != bookmarks) { + "browser.bookmarks.file" = toString (firefoxBookmarksFile bookmarks); + "browser.places.importBookmarksHTML" = true; + } + // prefs; + in + '' + // Generated by Home Manager. + + ${mkConfig prefs'} + + ${extraPrefs} + ''; + + firefoxBookmarksFile = + bookmarks: + let + indent = level: lib.concatStringsSep "" (map (lib.const " ") (lib.range 1 level)); + + bookmarkToHTML = + indentLevel: bookmark: + ''${indent indentLevel}
${escapeXML bookmark.name}''; + + directoryToHTML = indentLevel: directory: '' + ${indent indentLevel}
${ + if directory.toolbar then + ''

Bookmarks Toolbar'' + else + "

${escapeXML directory.name}" + }

+ ${indent indentLevel}

+ ${allItemsToHTML (indentLevel + 1) directory.bookmarks} + ${indent indentLevel}

''; + + itemToHTMLOrRecurse = + indentLevel: item: + if item ? "url" then bookmarkToHTML indentLevel item else directoryToHTML indentLevel item; + + allItemsToHTML = + indentLevel: bookmarks: lib.concatStringsSep "\n" (map (itemToHTMLOrRecurse indentLevel) bookmarks); + + bookmarkEntries = allItemsToHTML 1 bookmarks; + in + pkgs.writeText "firefox-bookmarks.html" '' + + + + Bookmarks +

Bookmarks Menu

+

+ ${bookmarkEntries} +

+ ''; +in +{ + inherit mkConfig; + + mkModule = + browser: + let + cfg = config.programs.${browser.name}; + inherit (browser) + displayName + dataConfigPath + defaultPackage + defaultPackageName + isSecure + ; + + profilesPath = dataConfigPath; + + profiles = + flip mapAttrs' cfg.profiles ( + _: profile: + nameValuePair "Profile${toString profile.id}" { + Name = profile.name; + Path = profile.path; + IsRelative = 1; + Default = if profile.isDefault then 1 else 0; + } + ) + // { + General = { + StartWithLastProfile = 1; + }; + }; + + profilesIni = generators.toINI { } profiles; + + mkProfileBin = + profile: + let + name = "${browser.name}-${profile}"; + scriptBin = pkgs.writeScriptBin name '' + ${browser.name} -P "${profile}" --name="${name}" $@ + ''; + desktopFile = pkgs.makeDesktopItem { + inherit name; + exec = "${scriptBin}/bin/${name} %U"; + icon = browser.name; + extraConfig.StartupWMClass = name; + desktopName = "${displayName} (${profile})"; + genericName = "Web Browser"; + categories = [ + "Network" + "WebBrowser" + ] ++ optional isSecure "Security"; + }; + in + pkgs.runCommand name { } '' + mkdir -p $out/{bin,share} + cp -r ${scriptBin}/bin/${name} $out/bin/${name} + cp -r ${desktopFile}/share/applications $out/share/applications + ''; + in + { + options = { + programs.${browser.name} = { + enable = mkEnableOption displayName; + + createProfileBins = mkOption { + type = types.bool; + default = false; + description = '' + When enabled installs a binary for all non-default profiles named `${browser.name}-''${profile}`. + This also includes a `.desktop` file that is configured to show separate icons (on GNOME at least). + ''; + }; + + package = mkOption { + type = types.package; + default = defaultPackage; + defaultText = literalExpression defaultPackageName; + example = literalExpression '' + ${defaultPackageName}.override { + # See nixpkgs' ${defaultPackageName} to check which options you can use + pulseaudioSupport = true; + } + ''; + description = "The ${displayName} package to use."; + }; + + profiles = mkOption { + type = types.attrsOf ( + types.submodule ( + { config, name, ... }: + { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Profile name."; + }; + + id = mkOption { + type = types.ints.unsigned; + default = 0; + description = '' + Profile ID. This should be set to a unique number per profile. + ''; + }; + + settings = mkOption { + type = types.attrsOf ( + jsonFormat.type + // { + description = "Firefox preference (int, bool, string, and also attrs, list, float as a JSON string)"; + } + ); + default = { }; + example = literalExpression '' + { + "browser.startup.homepage" = "https://nixos.org"; + "browser.search.region" = "GB"; + "browser.search.isUS" = false; + "distribution.searchplugins.defaultLocale" = "en-GB"; + "general.useragent.locale" = "en-GB"; + "browser.bookmarks.showMobileBookmarks" = true; + "browser.newtabpage.pinned" = [{ + title = "NixOS"; + url = "https://nixos.org"; + }]; + } + ''; + description = '' + Attribute set of Firefox preferences. + + Firefox only supports int, bool, and string types for + preferences, but home-manager will automatically + convert all other JSON-compatible values into strings. + ''; + }; + + extraConfig = mkOption { + type = types.lines; + default = ""; + description = '' + Extra preferences to add to user.js. + ''; + }; + + userChrome = mkOption { + type = types.lines; + default = ""; + description = "Custom Firefox user chrome CSS."; + example = '' + /* Hide tab bar in FF Quantum */ + @-moz-document url("chrome://browser/content/browser.xul") { + #TabsToolbar { + visibility: collapse !important; + margin-bottom: 21px !important; + } + + #sidebar-box[sidebarcommand="treestyletab_piro_sakura_ne_jp-sidebar-action"] #sidebar-header { + visibility: collapse !important; + } + } + ''; + }; + + userContent = mkOption { + type = types.lines; + default = ""; + description = "Custom Firefox user content CSS."; + example = '' + /* Hide scrollbar in FF Quantum */ + *{scrollbar-width:none !important} + ''; + }; + + bookmarks = mkOption { + type = + let + bookmarkSubmodule = + types.submodule ( + { config, name, ... }: + { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Bookmark name."; + }; + + keyword = mkOption { + type = types.nullOr types.str; + default = null; + description = "Bookmark search keyword."; + }; + + url = mkOption { + type = types.str; + description = "Bookmark url, use %s for search terms."; + }; + }; + } + ) + // { + description = "bookmark submodule"; + }; + + bookmarkType = types.addCheck bookmarkSubmodule (x: x ? "url"); + + directoryType = + types.submodule ( + { config, name, ... }: + { + options = { + name = mkOption { + type = types.str; + default = name; + description = "Directory name."; + }; + + bookmarks = mkOption { + type = types.listOf nodeType; + default = [ ]; + description = "Bookmarks within directory."; + }; + + toolbar = mkOption { + type = types.bool; + default = false; + description = "If directory should be shown in toolbar."; + }; + }; + } + ) + // { + description = "directory submodule"; + }; + + nodeType = types.either bookmarkType directoryType; + in + with types; + coercedTo (attrsOf nodeType) attrValues (listOf nodeType); + default = [ ]; + example = literalExpression '' + [ + { + name = "wikipedia"; + keyword = "wiki"; + url = "https://en.wikipedia.org/wiki/Special:Search?search=%s&go=Go"; + } + { + name = "kernel.org"; + url = "https://www.kernel.org"; + } + { + name = "Nix sites"; + bookmarks = [ + { + name = "homepage"; + url = "https://nixos.org/"; + } + { + name = "wiki"; + url = "https://nixos.wiki/"; + } + ]; + } + ] + ''; + description = '' + Preloaded bookmarks. Note, this may silently overwrite any + previously existing bookmarks! + ''; + }; + + path = mkOption { + type = types.str; + default = name; + description = "Profile path."; + }; + + isDefault = mkOption { + type = types.bool; + default = config.id == 0; + defaultText = "true if profile ID is 0"; + description = "Whether this is a default profile."; + }; + + search = { + force = mkOption { + type = with types; bool; + default = false; + description = '' + Whether to force replace the existing search + configuration. This is recommended since Firefox will + replace the symlink for the search configuration on every + launch, but note that you'll lose any existing + configuration by enabling this. + ''; + }; + + default = mkOption { + type = with types; nullOr str; + default = null; + example = "DuckDuckGo"; + description = '' + The default search engine used in the address bar and search bar. + ''; + }; + + order = mkOption { + type = with types; uniq (listOf str); + default = [ ]; + example = [ + "DuckDuckGo" + "Google" + ]; + description = '' + The order the search engines are listed in. Any engines + that aren't included in this list will be listed after + these in an unspecified order. + ''; + }; + + engines = mkOption { + type = with types; attrsOf (attrsOf jsonFormat.type); + default = { }; + example = literalExpression '' + { + "Nix Packages" = { + urls = [{ + template = "https://search.nixos.org/packages"; + params = [ + { name = "type"; value = "packages"; } + { name = "query"; value = "{searchTerms}"; } + ]; + }]; + + icon = "''${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = [ "@np" ]; + }; + + "NixOS Wiki" = { + urls = [{ template = "https://nixos.wiki/index.php?search={searchTerms}"; }]; + iconUpdateURL = "https://nixos.wiki/favicon.png"; + updateInterval = 24 * 60 * 60 * 1000; # every day + definedAliases = [ "@nw" ]; + }; + + "Bing".metaData.hidden = true; + "Google".metaData.alias = "@g"; # builtin engines only support specifying one additional alias + } + ''; + description = '' + Attribute set of search engine configurations. Engines + that only have metaData specified will + be treated as builtin to Firefox. + + See SearchEngine.jsm + in Firefox's source for available options. We maintain a + mapping to let you specify all options in the referenced + link without underscores, but it may fall out of date with + future options. + + Note, icon is also a special option + added by Home Manager to make it convenient to specify + absolute icon paths. + ''; + }; + }; + + extensions = mkOption { + type = types.listOf types.package; + default = [ ]; + example = literalExpression '' + with firefox-addons; [ + privacy-badger + ] + ''; + description = '' + List of Firefox add-on packages to install for this profile. + Some pre-packaged add-ons are accessible from NUR, + . + Once you have NUR installed run + + + $ nix-env -f '<nixpkgs>' -qaP -A firefox-addons + + + to list the available Firefox add-ons. + + + + Note that it is necessary to manually enable these extensions + inside Firefox after the first installation. + ''; + }; + }; + } + ) + ); + default = { }; + description = "Attribute set of Firefox profiles."; + }; + }; + }; + + config = mkIf cfg.enable { + assertions = [ + ( + let + defaults = catAttrs "name" (filter (a: a.isDefault) (attrValues cfg.profiles)); + in + { + assertion = cfg.profiles == { } || length defaults == 1; + message = + "Must have exactly one default Firefox profile but found " + + toString (length defaults) + + optionalString (length defaults > 1) (", namely " + concatStringsSep ", " defaults); + } + ) + + ( + let + duplicates = filterAttrs (_: v: length v != 1) ( + zipAttrs (mapAttrsToList (n: v: { "${toString v.id}" = n; }) (cfg.profiles)) + ); + + mkMsg = n: v: " - ID ${n} is used by ${concatStringsSep ", " v}"; + in + { + assertion = duplicates == { }; + message = + '' + Must not have Firefox profiles with duplicate IDs but + '' + + concatStringsSep "\n" (mapAttrsToList mkMsg duplicates); + } + ) + ]; + + warnings = optional (cfg.enableGnomeExtensions or false) '' + Using 'programs.${browser.name}.enableGnomeExtensions' has been deprecated and + will be removed in the future. Please change to overriding the package + configuration using 'programs.${browser.name}.package' instead. You can refer to + its example for how to do this. + ''; + + home.packages = + [ cfg.package ] + ++ ( + if cfg.createProfileBins then + (mapAttrsToList (name: profile: (mkProfileBin name)) ( + filterAttrs (_: p: !p.isDefault) cfg.profiles + )) + else + [ ] + ); + + home.file = mkMerge ( + [ { "${dataConfigPath}/profiles.ini" = mkIf (cfg.profiles != { }) { text = profilesIni; }; } ] + ++ flip mapAttrsToList cfg.profiles ( + _: profile: { + "${profilesPath}/${profile.path}/.keep".text = ""; + + "${profilesPath}/${profile.path}/chrome/userChrome.css" = mkIf (profile.userChrome != "") { + text = profile.userChrome; + }; + + "${profilesPath}/${profile.path}/chrome/userContent.css" = mkIf (profile.userContent != "") { + text = profile.userContent; + }; + + "${profilesPath}/${profile.path}/user.js" = mkIf ( + profile.settings != { } || profile.extraConfig != "" || profile.bookmarks != [ ] + ) { text = mkUserJs profile.settings profile.extraConfig profile.bookmarks; }; + + "${profilesPath}/${profile.path}/search.json.mozlz4" = + mkIf + (profile.search.default != null || profile.search.order != [ ] || profile.search.engines != { }) + { + force = profile.search.force; + source = + let + settings = { + version = 6; + engines = + let + # Map of nice field names to internal field names. + # This is intended to be exhaustive and should be + # updated at every version bump. + internalFieldNames = + (genAttrs [ + "name" + "isAppProvided" + "loadPath" + "hasPreferredIcon" + "updateInterval" + "updateURL" + "iconUpdateURL" + "iconURL" + "iconMapObj" + "metaData" + "orderHint" + "definedAliases" + "urls" + ] (name: "_${name}")) + // { + searchForm = "__searchForm"; + }; + + processCustomEngineInput = + input: + (removeAttrs input [ "icon" ]) + // optionalAttrs (input ? icon) { + # Convenience to specify absolute path to icon + iconURL = "file://${input.icon}"; + } + // ( + optionalAttrs (input ? iconUpdateURL) { + # Convenience to default iconURL to iconUpdateURL so + # the icon is immediately downloaded from the URL + iconURL = input.iconURL or input.iconUpdateURL; + } + // { + # Required for custom engine configurations, loadPaths + # are unique identifiers that are generally formatted + # like: [source]/path/to/engine.xml + loadPath = ''[home-manager]/programs.${browser.name}.profiles.${profile.name}.search.engines."${ + replaceStrings [ "\\" ] [ "\\\\" ] input.name + }"''; + } + ); + + processEngineInput = + name: input: + let + requiredInput = { + inherit name; + isAppProvided = input.isAppProvided or removeAttrs input [ "metaData" ] == { }; + metaData = input.metaData or { }; + }; + in + if requiredInput.isAppProvided then + requiredInput + else + processCustomEngineInput (input // requiredInput); + + buildEngineConfig = + name: input: + mapAttrs' (name: value: { + name = internalFieldNames.${name} or name; + inherit value; + }) (processEngineInput name input); + + sortEngineConfigs = + configs: + let + buildEngineConfigWithOrder = + order: name: + let + config = + configs.${name} or { + _name = name; + _isAppProvided = true; + _metaData = { }; + }; + in + config + // { + _metaData = config._metaData // { + inherit order; + }; + }; + + engineConfigsWithoutOrder = attrValues (removeAttrs configs profile.search.order); + + sortedEngineConfigs = + (imap buildEngineConfigWithOrder profile.search.order) ++ engineConfigsWithoutOrder; + in + sortedEngineConfigs; + + engineInput = profile.search.engines // { + # Infer profile.search.default as an app provided + # engine if it's not in profile.search.engines + ${profile.search.default} = profile.search.engines.${profile.search.default} or { }; + }; + in + sortEngineConfigs (mapAttrs buildEngineConfig engineInput); + + metaData = + optionalAttrs (profile.search.default != null) { + current = profile.search.default; + hash = "@hash@"; + } + // { + useSavedOrder = profile.search.order != [ ]; + }; + }; + + # Home Manager doesn't circumvent user consent and isn't acting + # maliciously. We're modifying the search outside of Firefox, but + # a claim by Mozilla to remove this would be very anti-user, and + # is unlikely to be an issue for our use case. + disclaimer = + appName: + "By modifying this file, I agree that I am doing so " + + "only within ${appName} itself, using official, user-driven search " + + "engine selection processes, and in a way which does not circumvent " + + "user consent. I acknowledge that any attempt to change this file " + + "from outside of ${appName} is a malicious act, and will be responded " + + "to accordingly."; + + salt = + if profile.search.default != null then + profile.path + profile.search.default + disclaimer "Firefox" + else + null; + in + pkgs.runCommand "search.json.mozlz4" + { + nativeBuildInputs = with pkgs; [ + mozlz4a + openssl + ]; + json = builtins.toJSON settings; + inherit salt; + } + '' + if [[ -n $salt ]]; then + export hash=$(echo -n "$salt" | openssl dgst -sha256 -binary | base64) + mozlz4a <(substituteStream json search.json.in --subst-var hash) "$out" + else + mozlz4a <(echo "$json") "$out" + fi + ''; + }; + + "${profilesPath}/${profile.path}/extensions" = mkIf (profile.extensions != [ ]) { + source = + let + extensionsEnvPkg = pkgs.buildEnv { + name = "hm-${browser.name}-extensions"; + paths = profile.extensions; + }; + in + "${extensionsEnvPkg}/share/mozilla/${extensionPath}"; + recursive = true; + force = true; + onChange = '' + # Includes references to old versions that are shown in UI. + rm -f "${profilesPath}/${profile.path}/extensions.json" + ''; + }; + } + ) + ); + }; + }; } diff --git a/home/modules/firefox/firefox.nix b/home/modules/firefox/firefox.nix index 0aad241..4e2ab4c 100644 --- a/home/modules/firefox/firefox.nix +++ b/home/modules/firefox/firefox.nix @@ -1,20 +1,18 @@ -_: +{ + config, + lib, + pkgs, + ... +}: let - mkFirefoxProfileBinModule = import ./mkFirefoxProfileBinModule.nix; - - modulePath = [ - "programs" - "firefox" - ]; - name = "Firefox"; - packageName = "firefox"; + common = import ./common.nix { inherit config lib pkgs; }; in -{ - imports = [ - (mkFirefoxProfileBinModule { - inherit modulePath name packageName; - isSecure = true; - }) - ]; +common.mkModule { + name = "firefox"; + displayName = "Firefox"; + dataConfigPath = ".mozilla/firefox"; + defaultPackage = pkgs.firefox; + defaultPackageName = "pkgs.firefox"; + isSecure = false; } diff --git a/home/modules/firefox/mkFirefoxModuleCompat.nix b/home/modules/firefox/mkFirefoxModuleCompat.nix deleted file mode 100644 index dabeac4..0000000 --- a/home/modules/firefox/mkFirefoxModuleCompat.nix +++ /dev/null @@ -1,67 +0,0 @@ -{ modulePath, ... }@moduleArgs: - -{ - inputs, - config, - lib, - ... -}: - -let - mkFirefoxModule = import "${inputs.home-manager.outPath}/modules/programs/firefox/mkFirefoxModule.nix"; - - cfg = lib.getAttrFromPath modulePath config; - - # HINT home-manager's Firefox module uses a read-only `finalPackage` option - # that creates a wrapper around `package`. However, this wrapper is not - # compatible with all Firefox-based browser packages. Thus, we adjust the module - # to always set `finalPackage` to `package` & remove unsupported options. - fixFirefoxModuleCompat = - module: - { - config, - lib, - pkgs, - ... - }: - let - optionsPath = [ "options" ] ++ modulePath; - configPath = [ - "config" - "content" # due to mkIf - ] ++ modulePath; - in - lib.updateManyAttrsByPath - [ - { - path = optionsPath ++ [ "languagePacks" ]; - update = old: { }; - } - { - path = configPath ++ [ "finalPackage" ]; - update = old: cfg.package; - } - { - path = configPath ++ [ "policies" ]; - update = old: { }; - } - ] - (module { - inherit config lib pkgs; - }); -in -{ - imports = [ - (fixFirefoxModuleCompat (mkFirefoxModule moduleArgs)) - ]; - - options = lib.setAttrByPath modulePath { }; - - config = lib.mkIf cfg.enable ( - { } - // lib.setAttrByPath modulePath { - # Tor & Mullvad Browser don't support profile version 2 yet - profileVersion = null; - } - ); -} diff --git a/home/modules/firefox/mkFirefoxProfileBinModule.nix b/home/modules/firefox/mkFirefoxProfileBinModule.nix deleted file mode 100644 index ebae797..0000000 --- a/home/modules/firefox/mkFirefoxProfileBinModule.nix +++ /dev/null @@ -1,67 +0,0 @@ -{ - modulePath, - name, - packageName, - isSecure ? false, -}: - -{ - config, - lib, - pkgs, - ... -}: - -let - appName = name; - cfg = lib.getAttrFromPath modulePath config; - - mkProfileBin = - profileName: profile: - let - pname = "${packageName}-${profileName}"; - scriptBin = pkgs.writeScriptBin pname '' - ${packageName} -P "${profileName}" --name="${pname}" $@ - ''; - desktopFile = pkgs.makeDesktopItem { - name = pname; - exec = "${scriptBin}/bin/${pname} %U"; - icon = packageName; - extraConfig.StartupWMClass = pname; - desktopName = "${appName} (${profileName})"; - genericName = "Web Browser"; - categories = [ - "Network" - "WebBrowser" - ] ++ lib.optional isSecure "Security"; - }; - in - pkgs.runCommand pname { } '' - mkdir -p $out/{bin,share} - cp -r ${scriptBin}/bin/${pname} $out/bin/${pname} - cp -r ${desktopFile}/share/applications $out/share/applications - ''; -in -{ - options = lib.setAttrByPath modulePath { - createProfileBins = lib.mkOption { - type = lib.types.bool; - default = false; - description = '' - When enabled installs a binary for all non-default profiles named `${packageName}-''${profile}`. - This also includes a `.desktop` file that is configured to show separate icons (on GNOME at least). - ''; - }; - }; - - config = lib.mkIf cfg.enable ( - { - home.packages = - if cfg.createProfileBins then - (lib.mapAttrsToList mkProfileBin) (lib.filterAttrs (_: p: !p.isDefault) cfg.profiles) - else - [ ]; - } - // lib.setAttrByPath modulePath { } - ); -} diff --git a/home/modules/firefox/mullvad-browser.nix b/home/modules/firefox/mullvad-browser.nix index 8542da4..7ad5f77 100644 --- a/home/modules/firefox/mullvad-browser.nix +++ b/home/modules/firefox/mullvad-browser.nix @@ -1,31 +1,18 @@ -_: +{ + config, + lib, + pkgs, + ... +}: let - mkFirefoxModuleCompat = import ./mkFirefoxModuleCompat.nix; - mkFirefoxProfileBinModule = import ./mkFirefoxProfileBinModule.nix; - - modulePath = [ - "programs" - "mullvad-browser" - ]; - name = "Mullvad Browser"; - packageName = "mullvad-browser"; + common = import ./common.nix { inherit config lib pkgs; }; in -{ - imports = [ - (mkFirefoxModuleCompat { - inherit modulePath name; - description = "Privacy-focused browser made in a collaboration between The Tor Project and Mullvad"; - unwrappedPackageName = packageName; - visible = true; - platforms.linux = rec { - vendorPath = ".mullvad"; - configPath = "${vendorPath}/mullvadbrowser"; - }; - }) - (mkFirefoxProfileBinModule { - inherit modulePath name packageName; - isSecure = true; - }) - ]; +common.mkModule { + name = "mullvad-browser"; + displayName = "Mullvad Browser"; + dataConfigPath = ".mullvad/mullvadbrowser"; + defaultPackage = pkgs.mullvad-browser; + defaultPackageName = "pkgs.mullvad-browser"; + isSecure = true; } diff --git a/home/modules/firefox/tor-browser.nix b/home/modules/firefox/tor-browser.nix index ee9ec23..9626100 100644 --- a/home/modules/firefox/tor-browser.nix +++ b/home/modules/firefox/tor-browser.nix @@ -1,31 +1,18 @@ -_: +{ + config, + lib, + pkgs, + ... +}: let - mkFirefoxModuleCompat = import ./mkFirefoxModuleCompat.nix; - mkFirefoxProfileBinModule = import ./mkFirefoxProfileBinModule.nix; - - modulePath = [ - "programs" - "tor-browser" - ]; - name = "Tor Browser"; - packageName = "tor-browser"; + common = import ./common.nix { inherit config lib pkgs; }; in -{ - imports = [ - (mkFirefoxModuleCompat { - inherit modulePath name; - description = "Privacy-focused browser routing traffic through the Tor network"; - unwrappedPackageName = packageName; - visible = true; - platforms.linux = rec { - vendorPath = ".tor project"; - configPath = "${vendorPath}/firefox"; - }; - }) - (mkFirefoxProfileBinModule { - inherit modulePath name packageName; - isSecure = true; - }) - ]; +common.mkModule { + name = "tor-browser"; + displayName = "Tor Browser"; + dataConfigPath = ".tor project/firefox"; + defaultPackage = pkgs.tor-browser; + defaultPackageName = "pkgs.tor-browser"; + isSecure = true; } diff --git a/hosts/home-server.nix b/hosts/home-server.nix index db971ed..760e49c 100644 --- a/hosts/home-server.nix +++ b/hosts/home-server.nix @@ -81,8 +81,8 @@ in ''}"; services.inadyn.ipv6.enable = true; services.inadyn.ipv6.command = "${pkgs.writeScript "get-ipv6" '' - ${pkgs.iproute2}/bin/ip -6 addr show scope global \ - | ${pkgs.grepcidr}/bin/grepcidr '2000::/3' \ + ${pkgs.tailscale}/bin/tailscale status --json \ + | ${pkgs.jq}/bin/jq -r '.Self.Addrs' \ | grep -o '[0-9a-f:]*::102' ''}"; services.inadyn.domains = [