Brave preferences are located at ~/.config/BraveSoftware/Brave-Browser/Default/Preferences in JSON format. So I use an script that let me make a deep merge using existing prefs as base, and my external JSON overrides/adds keys. But, there are still some settings can’t be change it 'cause are MAC-protected values and are impossible to change (Brave will revert it if you try to set a value to them, and. Here are the relevant parts of my solution:
(tree-wide)
modules/
├── system/
│ ├── app/
│ │ │ ├── brave/
│ │ │ ├── default.nix
│ │ │ ├── GroupPolicy.json
│ │ │ └── user-agent-switcher.json
│ │ └── ...
│ └── ...
├── home/
│ ├── app/
│ │ ├── brave/
│ │ │ ├── default.nix
│ │ │ ├── merge-prefs.sh
│ │ │ └── Preferences.json
│ │ └── ...
│ └── ...
└── ...
Preferences declaration throw Home-Manager
You can check all available options in brave://prefs-internals/ page.
(modules/user/app/brave/default.nix)
let
mergeScript = pkgs.runCommand "brave-merge-prefs.sh" { } ''
cp ${./merge-prefs.sh} $out
chmod +x $out
'';
in
{
programs.brave = {
enable = true;
extensions = [ { id = "bhchdcejhohfmigjafbampogmaanbfkg"; } # User-Agent Switcher and Manager ];
};
home.activation.mergeBraveSettings = lib.hm.dag.entryAfter [ "writeBoundary" ] ''
${mergeScript} ${pkgs.jq}/bin/jq '${./Preferences.json}' '${config.home.homeDirectory}/.config/BraveSoftware/Brave-Browser/Default/Preferences'
'';
}
(modules/user/app/brave/merge-prefs.sh)
#!/usr/bin/env bash
set -euo pipefail
JQ_BIN="$1"
PREFS_JSON="$2"
PREFS_FILE="$3"
if [ ! -f "$PREFS_FILE" ]; then
echo "[Brave] SKIP: Preferences not found"
exit 0
fi
# Deep merge: existing prefs as base, external JSON overrides/adds keys.
"$JQ_BIN" --slurpfile new "$PREFS_JSON" '. * $new[0]' "$PREFS_FILE" > "$PREFS_FILE.tmp"
if ! diff -q <("$JQ_BIN" -S '.' "$PREFS_FILE") <("$JQ_BIN" -S '.' "$PREFS_FILE.tmp") >/dev/null 2>&1; then
cp "$PREFS_FILE" "$PREFS_FILE.bak.$(date +%s)"
mv "$PREFS_FILE.tmp" "$PREFS_FILE"
echo "[Brave] APPLIED"
else
rm "$PREFS_FILE.tmp"
echo "[Brave] UNCHANGED"
fi
(modules/user/app/brave/Preferences.json)
{
"brave": {
"tabs": {
"vertical_tabs_collapsed": true,
...
},
...
}
For check if specific setting was apply it use:
jq '.brave.new_tab_page.show_stats' ~/.config/BraveSoftware/Brave-Browser/Default/Preferences
NixOS system-wide configs
Like in the above response, you can manage browser policies. Additionally to that, third-party extensions policies can be manage too. In this case, my intend was setup User-Agent Switcher and Manager extension for it randomly selects and apply one UA from the array per browsing session.
(modules/system/app/brave/GroupPolicy.json)
{
"BraveAIChatEnabled": false,
"BraveRewardsDisabled": true,
...
}
(modules/system/app/brave/user-agent-switcher.json)
{
"3rdparty": {
"extensions": {
"bhchdcejhohfmigjafbampogmaanbfkg": {
"json": "{\"mode\":\"custom\",\"custom\":\"{\\\"*\\\":[\\\"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36\\\",\\\"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36\\\",\\\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36\\\"]}\"}",
"json-forced": true
}
}
}
}
Note: Brave merges all .json files in the managed directory automatically. That’s why I split the files.
Finally, setting the files:
(modules/system/app/brave/default.nix)
{
# Brave policies
environment.etc."/brave/policies/managed/GroupPolicy.json".source = ./GroupPolicy.json;
# User-Agent Switcher extension
environment.etc."brave/policies/managed/extension-user-agent-switcher.json".source =
./user-agent-switcher.json;
}
You can check all policies set in brave://policy page.