Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .github/workflows/nix-release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Update Nix flake

# Checks whether flake.nix lags behind the latest stable GitHub release. If it
# does, prefetches the new release's per-platform SRI hashes, rewrites flake.nix,
# and opens a PR.
#
# Runs on a schedule instead of release: published because:
# 1. brave-browser releases are created by an external release pipeline (not
# this repo's GITHUB_TOKEN), and
# 2. a daily lag-check is fully decoupled from how releases are created and
# needs no PAT.
# The guard `github.repository == 'brave/brave-browser'` prevents the scheduled
# job from running on forks.

on:
schedule:
- cron: "17 6 * * *"
workflow_dispatch:

permissions:
contents: write
pull-requests: write

concurrency:
group: nix-flake-release
cancel-in-progress: true

jobs:
update-flake:
name: Bump flake version + hashes if lagging
runs-on: ubuntu-latest
if: github.repository == 'brave/brave-browser'
steps:
- name: Checkout
uses: actions/checkout@v6
with:
persist-credentials: false

- name: Install Nix
uses: cachix/install-nix-action@v31

- name: Check for lag and rewrite flake.nix
env:
# system|asset-filename-template — one per line. The template uses
# {VERSION} as a placeholder for the version (without the leading v).
# Brave's asset naming differs between Linux (.deb) and Darwin (.zip).
ASSET_MAP: |
x86_64-linux|brave-browser_{VERSION}_amd64.deb
aarch64-linux|brave-browser_{VERSION}_arm64.deb
x86_64-darwin|brave-v{VERSION}-darwin-x64.zip
aarch64-darwin|brave-v{VERSION}-darwin-arm64.zip
run: |
set -euo pipefail
tag=$(curl -fsSL -H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${GITHUB_REPOSITORY}/releases/latest" \
| python3 -c 'import json,sys; print(json.load(sys.stdin)["tag_name"])')
latest="${tag#v}"
current=$(python3 -c 'import re; s=open("flake.nix").read(); m=re.search(r"version = \"([^\"]*)\";", s); print(m.group(1))')
echo "flake.nix version: $current | latest release: $latest (tag $tag)"
if [ "$current" = "$latest" ]; then
echo "flake.nix is up to date; nothing to do."
echo "LAGGING=no" >> "$GITHUB_ENV"
exit 0
fi
echo "LAGGING=yes" >> "$GITHUB_ENV"
echo "VERSION=$latest" >> "$GITHUB_ENV"
export TAG="$tag"
python3 <<'PYEOF'
import os, re, subprocess
tag = os.environ["TAG"]
version = tag.lstrip("v")
repo = os.environ["GITHUB_REPOSITORY"]
asset_map = {}
for line in os.environ["ASSET_MAP"].splitlines():
line = line.strip()
if not line or line.startswith("#"):
continue
sys_, tmpl = line.split("|", 1)
asset_map[sys_.strip()] = tmpl.strip()
src = open("flake.nix").read()
src, n = re.subn(r'version = "[^"]*";', f'version = "{version}";', src, count=1)
if n != 1:
raise SystemExit('could not find version = "..." in flake.nix')
for sys_, tmpl in asset_map.items():
filename = tmpl.replace("{VERSION}", version)
url = f"https://github.com/{repo}/releases/download/{tag}/{filename}"
out = subprocess.check_output(
["nix", "store", "prefetch-file", "--json", "--hash-type", "sha256", url])
import json
sri = json.loads(out)["hash"]
# Replace the hash line within this system's asset block.
# Match up to the closing "};" — URLs contain ${version} so
# [^}]* would stop at the first } inside the interpolation.
pat = re.compile(r'("' + re.escape(sys_) + r'" = \{.*?\};)', re.S)
def repl(m):
b = m.group(1)
b = re.sub(r'hash = "[^"]*";', f'hash = "{sri}";', b, count=1)
return b
src, n = pat.subn(repl, src, count=1)
if n != 1:
raise SystemExit(f"could not find assets block for {sys_} in flake.nix")
open("flake.nix", "w").write(src)
print(f"bumped flake.nix to {version}: {list(asset_map)}")
PYEOF

- name: Open PR
if: env.LAGGING == 'yes'
uses: peter-evans/create-pull-request@v7
with:
commit-message: "chore(nix): bump flake to v${{ env.VERSION }}"
title: "chore(nix): bump flake to v${{ env.VERSION }}"
branch: chore/nix-flake-v${{ env.VERSION }}
base: master
body: |
Auto-generated by the `Update Nix flake` workflow (daily lag-check).
The latest stable GitHub release is v${{ env.VERSION }} but `flake.nix` was
pinned to an older version. This PR bumps `version` and refreshes the per-platform SRI
hashes by prefetching the new release assets.

Note: PRs opened by `GITHUB_TOKEN` do not trigger downstream workflow runs (e.g. CI),
so this PR will show no checks. The diff is a 5-line hash bump with no source changes —
safe to merge as-is.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
.Trashes
._*

# nix
/result
/result-*

# editors
CMakeLists.txt
cmake-build-debug
Expand Down
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,31 @@ This repository is not needed for building the browser and only holds issues, re

You can [visit our website](https://brave.com/download) to get the latest stable release.

### Nix

The repository provides a Nix flake that wraps the prebuilt release binary (the
same prebuilt `.deb`/`.zip` artifacts that
[nixpkgs `brave`](https://github.com/NixOS/nixpkgs/blob/nixos-26.05/pkgs/by-name/br/brave/make-brave.nix)
uses). It is not built from source.

```bash
# Run without installing
nix run github:brave/brave-browser

# Install into your profile
nix profile install github:brave/brave-browser
```

The flake tracks the default branch and is auto-bumped to the latest stable
release by a daily [workflow](.github/workflows/nix-release.yml), so
`github:brave/brave-browser` always serves the current release. (Release tags
are cut before the bump lands, so `github:brave/brave-browser/vX.Y.Z` is not a
valid pin — use the nixpkgs package or a specific commit SHA if you need
reproducibility.)

Supported platforms: `x86_64-linux`, `aarch64-linux`, `x86_64-darwin`,
`aarch64-darwin`.

## Contributing

Please see the [contributing guidelines](https://github.com/brave/brave-core/blob/master/CONTRIBUTING.md).
Expand Down
16 changes: 16 additions & 0 deletions devbox.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.12.0/.schema/devbox.schema.json",
"packages": [
"nix"
],
"shell": {
"init_hook": [
"echo 'Welcome to the brave-browser devbox. Use nix run .#brave to test the flake.'"
],
"scripts": {
"check": "nix flake check --no-build",
"build": "nix build .#brave --no-link",
"run": "nix run .#brave -- --version"
}
}
}
27 changes: 27 additions & 0 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

71 changes: 71 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
description = "Brave browser — privacy-oriented browser (prebuilt binaries from upstream releases)";

inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";

outputs = { self, nixpkgs }:
let
# Bumped by .github/workflows/update-brave-hashes.yml (daily lag-check).
# Tag-pinning does NOT work for this flake: the hash bump lands AFTER the
# upstream release tag is cut, so github:brave/brave-browser/vX.Y.Z may
# predate the flake.nix update. Pin the flake ref or commit instead.
version = "1.92.134";

assets = {
"x86_64-linux" = {
url = "https://github.com/brave/brave-browser/releases/download/v${version}/brave-browser_${version}_amd64.deb";
hash = "sha256-T3A/ejmLkIRYGWc8GXQmvIAZvQFwYEyhQJxssNDalhQ=";
};
"aarch64-linux" = {
url = "https://github.com/brave/brave-browser/releases/download/v${version}/brave-browser_${version}_arm64.deb";
hash = "sha256-qo40t+PGl1RO2ajJ2Hev4G1FWvzTx7Ak5CVxjdxabLI=";
};
"x86_64-darwin" = {
url = "https://github.com/brave/brave-browser/releases/download/v${version}/brave-v${version}-darwin-x64.zip";
hash = "sha256-IrhvRVFZGLoGSVNy10ppFL9rEy7MRTb/HIhzspDsrs8=";
};
"aarch64-darwin" = {
url = "https://github.com/brave/brave-browser/releases/download/v${version}/brave-v${version}-darwin-arm64.zip";
hash = "sha256-K1p5mAYfEDJNZFSmoOQV7kHNsA5RQuyUl3T2KVsNcbw=";
};
};

systems = builtins.attrNames assets;
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);

# Reuse nixpkgs' brave packaging (patchelf, wrapGAppsHook3, desktop-file
# fixup, icon symlinks, OutdatedBuildDetector disable, darwin .app install)
# by overriding only version + src to track upstream releases. Vendoring
# make-brave.nix would duplicate ~150 lines that upstream already maintains.
braveFor = system:
let
pkgs = nixpkgs.legacyPackages.${system};
asset = assets.${system};
in
pkgs.brave.overrideAttrs (old: {
inherit version;
src = pkgs.fetchurl { inherit (asset) url hash; };
meta = old.meta // {
changelog = "https://github.com/brave/brave-browser/blob/master/CHANGELOG_DESKTOP.md#"
+ nixpkgs.lib.replaceStrings [ "." ] [ "" ] version;
};
});
in
{
packages = forAllSystems (system: rec {
brave = braveFor system;
default = brave;
});

apps = forAllSystems (system: {
brave = {
type = "app";
program = nixpkgs.lib.getExe (braveFor system);
};
default = {
type = "app";
program = nixpkgs.lib.getExe (braveFor system);
};
});
};
}