MrOtherGuy / fx-autoconfig

Load custom javascript in browser context
Mozilla Public License 2.0
164 stars 10 forks source link

Workaround for Nix(OS) #45

Closed codenyte closed 4 months ago

codenyte commented 6 months ago

Please consider creating a package for the Nix package manager/NixOS. Although NixOS is a Linux distribution, it handles many things very differently and unfortunately it's not possible to install fx-autoconfig the traditional way on Nix. This guide explains how to create a Nix package: https://nixos.wiki/wiki/Packaging/Tutorial

MrOtherGuy commented 6 months ago

Note that this is not a installable package and I purposefully don't provide any kind of "install-script" for it.

The way you you would set up fx-autoconfig is to just copy the files in program directory to wherever your firefox binary is, and the files in profile to wherever your Firefox profile directory is located. Follow the steps in readme for more detailed information, or if there is particular bit that you can't get past of then tell me what it is and maybe we can figure it out.

codenyte commented 6 months ago

All packages installed through Nix are located in a read-only directory. When using the Nix package manager on a "normal" distro, you might be able to bypass this with root, but on NixOS there is no real way around it. Packages (like Firefox) can't be modified. I thought packaging fx-autoconfig for Nix would solve that, but then I reallized that a package can't overwrite another package's files either. I'll figure out a solution and let you know. But it would be great if there was some workaround for installing fx-autoconfig on Nix or other immutable distributions.

MrOtherGuy commented 6 months ago

Right, I doubt I can do anything about that. Firefox' autoconfig feature requires that you can write default pref files to program folder because that's the only place it knows to look for them.

So, I suppose you have to compile Firefox in a way where it looks somewhere else for them. This is probably a long shot, but maybe the package manager already compiles Firefox to make it look for default pref/autoconfiguration files in some different folder?

codenyte commented 6 months ago

There actually is a way in Nix to modify system/package files: https://discourse.nixos.org/t/how-to-edit-file-in-nix-store/19261

It's complicated (at least for me) and I'm not very familiar with the Nix language. (I only know how to set up basic stuff). But I will try to figure it out.

If this works and I manage to create a Nix config snippet that installs fx-autoconfig, you could maybe put that in the README.

MrOtherGuy commented 6 months ago

Sure. It seems quite a task though, that sounds like you would have to compile or at least re-package the whole Firefox with your added patch.

SoSeDiK commented 6 months ago

I was wondering the same thing and came up with this workaround for now by using an overlay to symlink the files from my home dir into the nix store:

final: prev: {
  firefox = (prev.firefox).overrideAttrs (oldAttrs: {
    buildCommand = (oldAttrs.buildCommand or "") + ''
      ln -sf /home/${username}/.dotfiles/${path_to_userChromeJS}/config.js $out/lib/firefox/config.js
      ln -sf /home/${username}/.dotfiles/${path_to_userChromeJS}/config-prefs.js $out/lib/firefox/browser/defaults/preferences/config-prefs.js
    '';
  });
}

If using this, replace the config paths with yours (postInstall isn't called in firefox's case, so I had to append to buildCommand instead)

chrome can be managed manually just fine, I personally symlink it too to my dotfiles:

# Symlink chrome dir
home.file."/home/${username}/.mozilla/firefox/${profile}/chrome".source = config.lib.file.mkOutOfStoreSymlink "/home/${username}/.dotfiles/user/apps/browser/firefox_profile/chrome";
# Symlink user.js
xdg.configFile."/home/${username}/.mozilla/firefox/${profile}/user.js".source = config.lib.file.mkOutOfStoreSymlink "/home/${username}/.dotfiles/user/apps/browser/firefox_profile/user.js";

I don't know if there's a better solution, but for now this seems to work

MrOtherGuy commented 6 months ago

Okay, so essentially what you are saying is that if you don't have write access to the program directory then you can instead create symlink for <firefox-bin>/defaults/preferences/config-prefs.js and <firefox-bin>/config.js - or did I misunderstand something? (The actual path names and structure can vary between systems).

Sidenote, honestly that feels kinda nonsensical since then you kinda do have write access to that directory after all.

SoSeDiK commented 6 months ago

Yes, you understood correctly. I instruct nix to create a symlink during the firefox's package build phase. There's probably a way to write the files instead, but I'm very new to NixOS and haven't found a way yet.

From what I understand, you have write access only during the package build phase and only within the isolated build environment. You lose write access once the package is built and moved into the nix store. The package's isolated build environment has no access to the system (hence symlink instead of a copy) or Internet (so no fetch from github & move files).

My workaround works as a temporary solution, but I'm positive there should be a proper way to resolve this.

DADA30000 commented 4 months ago

I was wondering the same thing and came up with this workaround for now by using an overlay to symlink the files from my home dir into the nix store:

final: prev: {
  firefox = (prev.firefox).overrideAttrs (oldAttrs: {
    buildCommand = (oldAttrs.buildCommand or "") + ''
      ln -sf /home/${username}/.dotfiles/${path_to_userChromeJS}/config.js $out/lib/firefox/config.js
      ln -sf /home/${username}/.dotfiles/${path_to_userChromeJS}/config-prefs.js $out/lib/firefox/browser/defaults/preferences/config-prefs.js
    '';
  });
}

If using this, replace the config paths with yours (postInstall isn't called in firefox's case, so I had to append to buildCommand instead)

chrome can be managed manually just fine, I personally symlink it too to my dotfiles:

# Symlink chrome dir
home.file."/home/${username}/.mozilla/firefox/${profile}/chrome".source = config.lib.file.mkOutOfStoreSymlink "/home/${username}/.dotfiles/user/apps/browser/firefox_profile/chrome";
# Symlink user.js
xdg.configFile."/home/${username}/.mozilla/firefox/${profile}/user.js".source = config.lib.file.mkOutOfStoreSymlink "/home/${username}/.dotfiles/user/apps/browser/firefox_profile/user.js";

I don't know if there's a better solution, but for now this seems to work

where do I put this stuff?

SoSeDiK commented 4 months ago

where do I put this stuff?

I was later told in NixOS Discord that it's better to use it as package directly instead of overlay. You can put this in your configuration.nix/home.nix, or as a separate module if you use flakes:

Minimal flake example ```nix { pkgs, config, ... }: let userChromeJSPath = "/path/to/user_chrome_js_files"; # (!) Replace with your path firefox = (pkgs.firefox).overrideAttrs (oldAttrs: { # Add support for https://github.com/MrOtherGuy/fx-autoconfig buildCommand = (oldAttrs.buildCommand or "") + '' ln -sf ${userChromeJSPath}/config.js $out/lib/firefox/config.js ln -sf ${userChromeJSPath}/defaults/pref/config-prefs.js $out/lib/firefox/browser/defaults/preferences/config-prefs.js ''; }); in { programs.firefox = { enable = true; package = firefox; }; } ``` Note: `$out` path to `config-prefs.js` might be different if you are not on Firefox stable.

Sadly, I'm unable to find a way to do this with Firefox Nightly.

DADA30000 commented 4 months ago
{ pkgs, config, ... }:

let
  userChromeJSPath = "/path/to/user_chrome_js_files"; # (!) Replace with your path
  firefox = (pkgs.firefox).overrideAttrs (oldAttrs: {
    # Add support for https://github.com/MrOtherGuy/fx-autoconfig
    buildCommand = (oldAttrs.buildCommand or "") + ''
      ln -sf ${userChromeJSPath}/config.js $out/lib/firefox/config.js
      ln -sf ${userChromeJSPath}/defaults/pref/config-prefs.js $out/lib/firefox/browser/defaults/preferences/config-prefs.js
    '';
  });
in
{
  programs.firefox = {
    enable = true;
    package = firefox;
  };
}

I tried adding this to configuration.nix, but I get unexpected LET error

SoSeDiK commented 4 months ago

I tried adding this to configuration.nix, but I get unexpected LET error

Are you sure you added it in the right places? It builds for me, so I believe the syntax is correct Can you show your configuration.nix?

rohanssrao commented 4 months ago

All I had to do to get this working was

programs.firefox = {
  enable = true;
  autoConfig = builtins.readFile(builtins.fetchurl {  
    url = "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js";
    sha256 = "1mx679fbc4d9x4bnqajqx5a95y1lfasvf90pbqkh9sm3ch945p40";
  });
};
codenyte commented 4 months ago

@rohanssrao Your solution is probably the best one, thanks for sharing it

@MrOtherGuy Consider putting this in the README as the official way of installing on Nix(OS)

SoSeDiK commented 4 months ago

@rohanssrao Oh, that's neat! I can confirm it works with the base firefox package. Sadly, it doesn't with firefox-nightly-bin from nix-community, but I guess that's package's fault. Might also be worth noting that the programs.firefox.autoConfig option does not exist in home-manager.

One other thing I'm curious about, is it okay to completely ignore defaults/pref/config-prefs.js?

rohanssrao commented 4 months ago

@SoSeDiK

One other thing I'm curious about, is it okay to completely ignore defaults/pref/config-prefs.js?

Yes, this is configured by default in the firefox package definition.

Might also be worth noting that the programs.firefox.autoConfig option does not exist in home-manager.

Nix on non-NixOS systems doesn't support modules (i.e. programs.<name>.<option>) so that is expected.

Looking at the definition, there is an extraPrefsFiles attribute that defines files which get appended to mozilla.cfg so I believe you can put the following in your home.nix to achieve the equivalent:

home.packages = with pkgs; [
  # hello
  # cowsay
  # ...
  (firefox.overrideAttrs {
    extraPrefsFiles = [(builtins.fetchurl {  
      url = "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js";
      sha256 = "1mx679fbc4d9x4bnqajqx5a95y1lfasvf90pbqkh9sm3ch945p40";
    })];
  })
];

I don't use home-manager anymore though so I can't test it. Let me know if it works. If it does, I'll add it to my PR.

Sadly, it doesn't with firefox-nightly-bin from nix-community, but I guess that's package's fault.

You could possibly try something like this to make a new derivation, inheriting the original, that manually puts the files in the correct spot afterward:

environment.systemPackages = with pkgs; [
  # hello
  # cowsay
  # ...
  (stdenv.mkDerivation {
    name = "firefoxWithAutoconfig";
    src = inputs.firefox.packages.${system}.firefox-nightly-bin; # if you specified the package a different way, replace it here
    buildPhase = ''
      mkdir $out
      cp -r * $out/
      echo 'pref("general.config.filename", "mozilla.cfg");' > "$out/lib/firefox/defaults/pref/autoconfig.js"
      echo 'pref("general.config.obscure_value", 0);' >> "$out/lib/firefox/defaults/pref/autoconfig.js"
      cp ${builtins.fetchurl {  
        url = "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js";
        sha256 = "1mx679fbc4d9x4bnqajqx5a95y1lfasvf90pbqkh9sm3ch945p40";
      }} $out/lib/firefox/mozilla.cfg;
    '';
  })
];

This probably won't work as written since I just wrote it in the text editor and haven't tested it, but feel free to mess around with it.

SoSeDiK commented 4 months ago

home-manager has some programs.firefox options, but autoConfig is not implemented (yet?). I've tried using extraPrefsFiles as suggested (only had to wrap builtins.fetchurl in (parentheses)), but while it compiles without errors, there's no fx-autoconfig support.

The issue with firefox-nightly-bin is that it fully consists of symlinks to firefox-nightly-bin-unwrapped, including the launching binary, so any changes to firefox-nightly-bin's nix store are ignored.

rohanssrao commented 4 months ago

I've tried using extraPrefsFiles as suggested (only had to wrap builtins.fetchurl in (parentheses)), but while it compiles without errors, there's no fx-autoconfig support.

Thanks, updated to include parentheses.

This is weird because all that programs.firefox.autoConfig does in the background is override extraPrefsFiles.

If you go to the build output in the /nix/store, does it have the correct file layout and contents needed for fx-autoconfig?

Have you also tried adding pref("general.config.sandbox_enabled", false);, both through Nix and manually through about:config?

SoSeDiK commented 4 months ago

If you go to the build output in the /nix/store, does it have the correct file layout and contents needed for fx-autoconfig?

From what I can see, building with nixos (autoConfig) appends fx-autoconfig's config.js contents into mozilla.cfg. For some reason, it doesn't when built with home-manager (extraPrefsFiles).

This is weird because all that programs.firefox.autoConfig does in the background is override extraPrefsFiles.

I've tried using extraPrefsFiles with nixos:

```nix environment.systemPackages = with pkgs; [ (firefox.overrideAttrs { extraPrefsFiles = [ (builtins.fetchurl { url = "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js"; sha256 = "1mx679fbc4d9x4bnqajqx5a95y1lfasvf90pbqkh9sm3ch945p40"; }) ]; }) ]; ```

But it also doesn't append to mozilla.cfg for some reason?

rohanssrao commented 4 months ago

Try changing overrideAttrs to override.

SoSeDiK commented 4 months ago

Using override did the trick, works with home-manager now!

rohanssrao commented 4 months ago

Great, I added it to the PR.

SoSeDiK commented 4 months ago

Not sure why I haven't thought of this earlier, but I was finally able to add fx-autoconfig to nightly. I just replaced symlinks to binaries with actual binaries upon building it. If anyone's interested, I've used nix-community/flake-firefox-nightly with this home-manager flake:

firefox.nix ```nix { pkgs, config, inputs, ... }: let # Firefox Nightly with https://github.com/MrOtherGuy/fx-autoconfig firefox-nightly = ( (inputs.firefox-nightly.packages.${pkgs.system}.firefox-nightly-bin).override { extraPrefsFiles = [ (builtins.fetchurl { url = "https://raw.githubusercontent.com/MrOtherGuy/fx-autoconfig/master/program/config.js"; sha256 = "1mx679fbc4d9x4bnqajqx5a95y1lfasvf90pbqkh9sm3ch945p40"; }) ]; } ).overrideAttrs (oldAttrs: { buildCommand = (oldAttrs.buildCommand or "") + '' # Find firefox dir firefoxDir=$(find "$out/lib/" -type d -name 'firefox*' -print -quit) # Function to replace symlink with destination file replaceSymlink() { local symlink_path="$firefoxDir/$1" local target_path=$(readlink -f "$symlink_path") rm "$symlink_path" cp "$target_path" "$symlink_path" } # Copy firefox binaries replaceSymlink "firefox" replaceSymlink "firefox-bin" ''; }); in { programs.firefox = { enable = true; package = firefox-nightly; }; } ```

For NixOS, just replace that override block with programs.firefox.autoConfig option.