about summary refs log tree commit diff
path: root/third_party
diff options
context:
space:
mode:
Diffstat (limited to 'third_party')
-rw-r--r--third_party/cgit/default.nix25
-rw-r--r--third_party/chicago95/default.nix47
-rw-r--r--third_party/ddclient/default.nix12
-rw-r--r--third_party/ddclient/module.nix230
-rw-r--r--third_party/ddclient/pkg.nix45
-rw-r--r--third_party/gerrit/0001-Syntax-highlight-nix.patch16
-rw-r--r--third_party/gerrit/0002-Syntax-highlight-rules.pl.patch12
-rw-r--r--third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch35
-rw-r--r--third_party/gerrit/bazelrc11
-rw-r--r--third_party/gerrit/default.nix175
-rw-r--r--third_party/gerrit/detzip.go97
-rw-r--r--third_party/gerrit/workspace_overrides.bzl5
-rw-r--r--third_party/gerrit_plugins/builder.nix25
-rw-r--r--third_party/gerrit_plugins/code-owners/default.nix6
-rw-r--r--third_party/gerrit_plugins/oauth/default.nix11
-rw-r--r--third_party/git/default.nix2
-rw-r--r--third_party/gitignoreSource/default.nix12
-rw-r--r--third_party/nixpkgs/default.nix3
-rw-r--r--third_party/overlays/patches/cbtemulator-uds.patch140
-rw-r--r--third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch109
-rw-r--r--third_party/overlays/patches/crate2nix-drop-darwin-explicit-dontstrip.patch22
-rw-r--r--third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch69
-rw-r--r--third_party/overlays/patches/treefmt-fix-no-cache.patch43
-rw-r--r--third_party/overlays/tvl.nix66
-rw-r--r--third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch78
-rw-r--r--third_party/radicle-explorer/default.nix66
-rw-r--r--third_party/rust-crates/default.nix126
-rw-r--r--third_party/sources/sources.json66
28 files changed, 590 insertions, 964 deletions
diff --git a/third_party/cgit/default.nix b/third_party/cgit/default.nix
index c783bda16ed2..bac6a3264e6e 100644
--- a/third_party/cgit/default.nix
+++ b/third_party/cgit/default.nix
@@ -27,12 +27,25 @@ stdenv.mkDerivation rec {
   #
   # TODO(tazjin): Add an assert for this somewhere so we notice it on
   # channel bumps.
-  preBuild = ''
-    rm -rf git # remove submodule dir ...
-    cp -r --no-preserve=ownership,mode ${pkgs.srcOnly depot.third_party.git} git
-    makeFlagsArray+=(prefix="$out" CGIT_SCRIPT_PATH="$out/cgit/")
-    cat tvl-extra.css >> cgit.css
-  '';
+  preBuild =
+    let
+      # we have to give cgit a git with dottime support to build
+      git' = pkgs.git.overrideAttrs (old: {
+        src = pkgs.fetchurl {
+          url = "https://github.com/git/git/archive/refs/tags/v2.44.2.tar.gz";
+          hash = "sha256-3h0LBfAD4MXfZc0tjWQDO81UdbRo3w5C0W7j7rr9m9I=";
+        };
+        patches = (old.patches or [ ]) ++ [
+          ../git/0001-feat-third_party-git-date-add-dottime-format.patch
+        ];
+      });
+    in
+    ''
+      rm -rf git # remove submodule dir ...
+      cp -r --no-preserve=ownership,mode ${pkgs.srcOnly git'} git
+      makeFlagsArray+=(prefix="$out" CGIT_SCRIPT_PATH="$out/cgit/")
+      cat tvl-extra.css >> cgit.css
+    '';
 
   stripDebugList = [ "cgit" ];
 
diff --git a/third_party/chicago95/default.nix b/third_party/chicago95/default.nix
new file mode 100644
index 000000000000..8703ec3548ad
--- /dev/null
+++ b/third_party/chicago95/default.nix
@@ -0,0 +1,47 @@
+# A rendition of everyone's favourite computer theme.
+{ pkgs, ... }:
+
+let
+  # Chicago95 has no GTK-4 theme (because GTK-4 removed important features that
+  # it needs), but there is a project with an approximation.
+  #
+  # This is a bit of a hack, but I inject that project's GTK-4 theme as if it
+  # was a part of Chicago95.
+  #
+  # This other project is GPL-3.0, under which Chicago95 is also distributed.
+  gtk4ProjectSrc = pkgs.fetchFromGitHub {
+    owner = "B00merang-Project";
+    repo = "Windows-95";
+    rev = "055abd7a3608afdcb2ef021732e07020f2b416b2";
+    hash = "sha256:1li6wzyn3y09d188xki1h96pmn4xcx2lklfc4rkiq2y2r22wx7kz";
+  };
+in
+pkgs.stdenvNoCC.mkDerivation {
+  pname = "Chicago95";
+  version = "master";
+
+  src = pkgs.fetchFromGitHub {
+    owner = "grassmunk";
+    repo = "Chicago95";
+    rev = "bdf5cf36a16102aaac297f3de887c601c2b1146f";
+    hash = "sha256:11fsy3bam1rhp1292zflvzmf1432z1p0ncwy3601wl2f8rnvfdfm";
+  };
+
+  # The project has a Makefile, but it's broken in all sorts of ways, so we just
+  # copy the important stuff manually.
+  dontBuild = true;
+  installPhase = ''
+    mkdir -p $out/share/{icons,fonts,themes,sounds,qt5ct/colors}
+
+    cp -r Theme/Chicago95 $out/share/themes
+    cp -r Icons/* $out/share/icons
+    cp -r Cursors/* $out/share/icons
+    cp -r Fonts/* $out/share/fonts
+    cp Extras/Chicago95_qt.conf $out/share/qt5ct/colors
+
+    cp -r ${gtk4ProjectSrc}/gtk-4.0 $out/share/themes/Chicago95
+  '';
+
+  meta.license = pkgs.lib.licenses.gpl3;
+}
+
diff --git a/third_party/ddclient/default.nix b/third_party/ddclient/default.nix
deleted file mode 100644
index 28b036ea66fc..000000000000
--- a/third_party/ddclient/default.nix
+++ /dev/null
@@ -1,12 +0,0 @@
-# Users of this package & module should replace it with something like
-# inadyn, after https://github.com/NixOS/nixpkgs/issues/242330 is
-# landed.
-#
-# TODO(aspen): replace ddclient with inadyn or something else.
-{ pkgs, ... }:
-
-(pkgs.callPackage ./pkg.nix { }).overrideAttrs (old: {
-  passthru = old.passthru // {
-    module = ./module.nix;
-  };
-})
diff --git a/third_party/ddclient/module.nix b/third_party/ddclient/module.nix
deleted file mode 100644
index c8d68f9be932..000000000000
--- a/third_party/ddclient/module.nix
+++ /dev/null
@@ -1,230 +0,0 @@
-# SPDX-License-Identifier: MIT
-# SPDX-FileCopyrightText: Copyright (c) 2003-2023 The Nixpkgs/NixOS contributors
-{ config, pkgs, lib, ... }:
-
-let
-  cfg = config.services.deprecated-ddclient;
-  boolToStr = bool: if bool then "yes" else "no";
-  dataDir = "/var/lib/ddclient";
-  StateDirectory = builtins.baseNameOf dataDir;
-  RuntimeDirectory = StateDirectory;
-
-  configFile' = pkgs.writeText "ddclient.conf" ''
-    # This file can be used as a template for configFile or is automatically generated by Nix options.
-    cache=${dataDir}/ddclient.cache
-    foreground=YES
-    use=${cfg.use}
-    login=${cfg.username}
-    password=${if cfg.protocol == "nsupdate" then "/run/${RuntimeDirectory}/ddclient.key" else "@password_placeholder@"}
-    protocol=${cfg.protocol}
-    ${lib.optionalString (cfg.script != "") "script=${cfg.script}"}
-    ${lib.optionalString (cfg.server != "") "server=${cfg.server}"}
-    ${lib.optionalString (cfg.zone != "")   "zone=${cfg.zone}"}
-    ssl=${boolToStr cfg.ssl}
-    wildcard=YES
-    quiet=${boolToStr cfg.quiet}
-    verbose=${boolToStr cfg.verbose}
-    ${cfg.extraConfig}
-    ${lib.concatStringsSep "," cfg.domains}
-  '';
-  configFile = if (cfg.configFile != null) then cfg.configFile else configFile';
-
-  preStart = ''
-    install --mode=600 --owner=$USER ${configFile} /run/${RuntimeDirectory}/ddclient.conf
-    ${lib.optionalString (cfg.configFile == null) (if (cfg.protocol == "nsupdate") then ''
-      install --mode=600 --owner=$USER ${cfg.passwordFile} /run/${RuntimeDirectory}/ddclient.key
-    '' else if (cfg.passwordFile != null) then ''
-      "${pkgs.replace-secret}/bin/replace-secret" "@password_placeholder@" "${cfg.passwordFile}" "/run/${RuntimeDirectory}/ddclient.conf"
-    '' else ''
-      sed -i '/^password=@password_placeholder@$/d' /run/${RuntimeDirectory}/ddclient.conf
-    '')}
-  '';
-
-in
-
-with lib;
-
-{
-  ###### interface
-
-  options = {
-
-    services.deprecated-ddclient = with lib.types; {
-
-      enable = mkOption {
-        default = false;
-        type = bool;
-        description = lib.mdDoc ''
-          Whether to synchronise your machine's IP address with a dynamic DNS provider (e.g. dyndns.org).
-        '';
-      };
-
-      package = mkOption {
-        type = package;
-        default = pkgs.ddclient;
-        defaultText = lib.literalExpression "pkgs.ddclient";
-        description = lib.mdDoc ''
-          The ddclient executable package run by the service.
-        '';
-      };
-
-      domains = mkOption {
-        default = [ "" ];
-        type = listOf str;
-        description = lib.mdDoc ''
-          Domain name(s) to synchronize.
-        '';
-      };
-
-      username = mkOption {
-        # For `nsupdate` username contains the path to the nsupdate executable
-        default = lib.optionalString (cfg.protocol == "nsupdate") "${pkgs.bind.dnsutils}/bin/nsupdate";
-        defaultText = "";
-        type = str;
-        description = lib.mdDoc ''
-          User name.
-        '';
-      };
-
-      passwordFile = mkOption {
-        default = null;
-        type = nullOr str;
-        description = lib.mdDoc ''
-          A file containing the password or a TSIG key in named format when using the nsupdate protocol.
-        '';
-      };
-
-      interval = mkOption {
-        default = "10min";
-        type = str;
-        description = lib.mdDoc ''
-          The interval at which to run the check and update.
-          See {command}`man 7 systemd.time` for the format.
-        '';
-      };
-
-      configFile = mkOption {
-        default = null;
-        type = nullOr path;
-        description = lib.mdDoc ''
-          Path to configuration file.
-          When set this overrides the generated configuration from module options.
-        '';
-        example = "/root/nixos/secrets/ddclient.conf";
-      };
-
-      protocol = mkOption {
-        default = "dyndns2";
-        type = str;
-        description = lib.mdDoc ''
-          Protocol to use with dynamic DNS provider (see https://sourceforge.net/p/ddclient/wiki/protocols).
-        '';
-      };
-
-      server = mkOption {
-        default = "";
-        type = str;
-        description = lib.mdDoc ''
-          Server address.
-        '';
-      };
-
-      ssl = mkOption {
-        default = true;
-        type = bool;
-        description = lib.mdDoc ''
-          Whether to use SSL/TLS to connect to dynamic DNS provider.
-        '';
-      };
-
-      quiet = mkOption {
-        default = false;
-        type = bool;
-        description = lib.mdDoc ''
-          Print no messages for unnecessary updates.
-        '';
-      };
-
-      script = mkOption {
-        default = "";
-        type = str;
-        description = lib.mdDoc ''
-          script as required by some providers.
-        '';
-      };
-
-      use = mkOption {
-        default = "web, web=checkip.dyndns.com/, web-skip='Current IP Address: '";
-        type = str;
-        description = lib.mdDoc ''
-          Method to determine the IP address to send to the dynamic DNS provider.
-        '';
-      };
-
-      verbose = mkOption {
-        default = false;
-        type = bool;
-        description = lib.mdDoc ''
-          Print verbose information.
-        '';
-      };
-
-      zone = mkOption {
-        default = "";
-        type = str;
-        description = lib.mdDoc ''
-          zone as required by some providers.
-        '';
-      };
-
-      extraConfig = mkOption {
-        default = "";
-        type = lines;
-        description = lib.mdDoc ''
-          Extra configuration. Contents will be added verbatim to the configuration file.
-          ::: {.note}
-          `daemon` should not be added here because it does not work great with the systemd-timer approach the service uses.
-          :::
-        '';
-      };
-    };
-  };
-
-
-  ###### implementation
-
-  config = mkMerge [
-    (mkIf cfg.enable {
-      systemd.services.ddclient = {
-        description = "Dynamic DNS Client";
-        wantedBy = [ "multi-user.target" ];
-        after = [ "network.target" ];
-        restartTriggers = optional (cfg.configFile != null) cfg.configFile;
-        path = lib.optional (lib.hasPrefix "if," cfg.use) pkgs.iproute2;
-
-        serviceConfig = {
-          DynamicUser = true;
-          RuntimeDirectoryMode = "0700";
-          inherit RuntimeDirectory;
-          inherit StateDirectory;
-          Type = "oneshot";
-          ExecStartPre = "!${pkgs.writeShellScript "ddclient-prestart" preStart}";
-          ExecStart = "${lib.getBin cfg.package}/bin/ddclient -file /run/${RuntimeDirectory}/ddclient.conf";
-        };
-      };
-
-      systemd.timers.ddclient = {
-        description = "Run ddclient";
-        wantedBy = [ "timers.target" ];
-        timerConfig = {
-          OnBootSec = cfg.interval;
-          OnUnitInactiveSec = cfg.interval;
-        };
-      };
-    })
-    {
-      ids.uids.ddclient = 30;
-      ids.gids.ddclient = 30;
-    }
-  ];
-}
diff --git a/third_party/ddclient/pkg.nix b/third_party/ddclient/pkg.nix
deleted file mode 100644
index 586f3891ac96..000000000000
--- a/third_party/ddclient/pkg.nix
+++ /dev/null
@@ -1,45 +0,0 @@
-# SPDX-License-Identifier: MIT
-# SPDX-FileCopyrightText: Copyright (c) 2003-2023 The Nixpkgs/NixOS contributors
-{ lib, fetchFromGitHub, perlPackages, autoreconfHook, iproute2, perl }:
-
-perlPackages.buildPerlPackage rec {
-  pname = "ddclient";
-  version = "3.10.0";
-
-  outputs = [ "out" ];
-
-  src = fetchFromGitHub {
-    owner = "ddclient";
-    repo = "ddclient";
-    rev = "v${version}";
-    sha256 = "sha256-wWUkjXwVNZRJR1rXPn3IkDRi9is9vsRuNC/zq8RpB1E=";
-  };
-
-  postPatch = ''
-    touch Makefile.PL
-  '';
-
-  nativeBuildInputs = [ autoreconfHook ];
-
-  buildInputs = with perlPackages; [ IOSocketINET6 IOSocketSSL JSONPP ];
-
-  installPhase = ''
-    runHook preInstall
-    # patch sheebang ddclient script which only exists after buildPhase
-    preConfigure
-    install -Dm755 ddclient $out/bin/ddclient
-    install -Dm644 -t $out/share/doc/ddclient COP* README.* ChangeLog.md
-    runHook postInstall
-  '';
-
-  # TODO: run upstream tests
-  doCheck = false;
-
-  meta = with lib; {
-    description = "Client for updating dynamic DNS service entries";
-    homepage = "https://ddclient.net/";
-    license = licenses.gpl2Plus;
-    platforms = platforms.linux;
-    maintainers = with maintainers; [ SuperSandro2000 ];
-  };
-}
diff --git a/third_party/gerrit/0001-Syntax-highlight-nix.patch b/third_party/gerrit/0001-Syntax-highlight-nix.patch
index bdc3fd3b5510..d17dc27db094 100644
--- a/third_party/gerrit/0001-Syntax-highlight-nix.patch
+++ b/third_party/gerrit/0001-Syntax-highlight-nix.patch
@@ -1,4 +1,4 @@
-From 084e4f92fb58f7cd85303ba602fb3c40133c8fcc Mon Sep 17 00:00:00 2001
+From 216843cff4a8e41ad9887118751a412c1a22ce72 Mon Sep 17 00:00:00 2001
 From: Luke Granger-Brown <git@lukegb.com>
 Date: Thu, 2 Jul 2020 23:02:32 +0100
 Subject: [PATCH 1/3] Syntax highlight nix
@@ -9,23 +9,23 @@ Subject: [PATCH 1/3] Syntax highlight nix
  2 files changed, 2 insertions(+)
 
 diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
-index a9f88bdd81..385249f280 100644
+index 50742903de..d1e89920cc 100644
 --- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
 +++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
-@@ -93,6 +93,7 @@ const LANGUAGE_MAP = new Map<string, string>([
+@@ -98,6 +98,7 @@ const LANGUAGE_MAP = new Map<string, string>([
    ['text/x-vhdl', 'vhdl'],
    ['text/x-yaml', 'yaml'],
    ['text/vbscript', 'vbscript'],
 +  ['text/x-nix', 'nix'],
  ]);
  
- const CLASS_PREFIX = 'gr-diff gr-syntax gr-syntax-';
+ const CLASS_PREFIX = 'gr-syntax gr-syntax-';
 diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties
-index 2f9561ba2e..739818ec05 100644
+index 642ef474a5..97f1ff835b 100644
 --- a/resources/com/google/gerrit/server/mime/mime-types.properties
 +++ b/resources/com/google/gerrit/server/mime/mime-types.properties
-@@ -149,6 +149,7 @@ mscin = text/x-mscgen
- msgenny = text/x-msgenny
+@@ -154,6 +154,7 @@ msgenny = text/x-msgenny
+ mts = application/typescript
  nb = text/x-mathematica
  nginx.conf = text/x-nginx-conf
 +nix = text/x-nix
@@ -33,5 +33,5 @@ index 2f9561ba2e..739818ec05 100644
  nsi = text/x-nsis
  nt = text/n-triples
 -- 
-2.37.3
+2.45.1
 
diff --git a/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch b/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch
index 4b91e2c3541f..d0da61dd0f21 100644
--- a/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch
+++ b/third_party/gerrit/0002-Syntax-highlight-rules.pl.patch
@@ -1,4 +1,4 @@
-From aedf8ac8fa5113843bcd83ff85e2d9f3bffdb16c Mon Sep 17 00:00:00 2001
+From 63f1ff6ea749ae2af29a53463bca81bc3f4bf25b Mon Sep 17 00:00:00 2001
 From: Luke Granger-Brown <git@lukegb.com>
 Date: Thu, 2 Jul 2020 23:02:43 +0100
 Subject: [PATCH 2/3] Syntax highlight rules.pl
@@ -9,10 +9,10 @@ Subject: [PATCH 2/3] Syntax highlight rules.pl
  2 files changed, 2 insertions(+)
 
 diff --git a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
-index 385249f280..7cb3068494 100644
+index d1e89920cc..5d62af1c64 100644
 --- a/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
 +++ b/polygerrit-ui/app/embed/diff/gr-syntax-layer/gr-syntax-layer-worker.ts
-@@ -68,6 +68,7 @@ const LANGUAGE_MAP = new Map<string, string>([
+@@ -72,6 +72,7 @@ const LANGUAGE_MAP = new Map<string, string>([
    ['text/x-perl', 'perl'],
    ['text/x-pgsql', 'pgsql'], // postgresql
    ['text/x-php', 'php'],
@@ -21,10 +21,10 @@ index 385249f280..7cb3068494 100644
    ['text/x-protobuf', 'protobuf'],
    ['text/x-puppet', 'puppet'],
 diff --git a/resources/com/google/gerrit/server/mime/mime-types.properties b/resources/com/google/gerrit/server/mime/mime-types.properties
-index 739818ec05..58eb727bf9 100644
+index 97f1ff835b..85d630340f 100644
 --- a/resources/com/google/gerrit/server/mime/mime-types.properties
 +++ b/resources/com/google/gerrit/server/mime/mime-types.properties
-@@ -200,6 +200,7 @@ rq = application/sparql-query
+@@ -208,6 +208,7 @@ rq = application/sparql-query
  rs = text/x-rustsrc
  rss = application/xml
  rst = text/x-rst
@@ -33,5 +33,5 @@ index 739818ec05..58eb727bf9 100644
  s = text/x-gas
  sas = text/x-sas
 -- 
-2.37.3
+2.45.1
 
diff --git a/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch b/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch
index c4edee3a40c3..a5881e5a6c27 100644
--- a/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch
+++ b/third_party/gerrit/0003-Add-titles-to-CLs-over-HTTP.patch
@@ -1,19 +1,19 @@
-From f49c50ca9a84ca374b7bd91c171bbea0457f2c7a Mon Sep 17 00:00:00 2001
+From ca2df6d7f53441d443d42908e30bf60fbfc15392 Mon Sep 17 00:00:00 2001
 From: Luke Granger-Brown <git@lukegb.com>
 Date: Thu, 2 Jul 2020 23:03:02 +0100
 Subject: [PATCH 3/3] Add titles to CLs over HTTP
 
 ---
- .../gerrit/httpd/raw/IndexHtmlUtil.java       | 13 +++-
+ .../gerrit/httpd/raw/IndexHtmlUtil.java       | 12 +++-
  .../google/gerrit/httpd/raw/IndexServlet.java |  8 ++-
  .../google/gerrit/httpd/raw/StaticModule.java |  5 +-
  .../gerrit/httpd/raw/TitleComputer.java       | 67 +++++++++++++++++++
  .../gerrit/httpd/raw/PolyGerritIndexHtml.soy  |  4 +-
- 5 files changed, 89 insertions(+), 8 deletions(-)
+ 5 files changed, 88 insertions(+), 8 deletions(-)
  create mode 100644 java/com/google/gerrit/httpd/raw/TitleComputer.java
 
 diff --git a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
-index 72bfe40c3b..439bd73b44 100644
+index a92dd18f04..f87c46d321 100644
 --- a/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
 +++ b/java/com/google/gerrit/httpd/raw/IndexHtmlUtil.java
 @@ -41,6 +41,7 @@ import java.util.Collections;
@@ -24,7 +24,7 @@ index 72bfe40c3b..439bd73b44 100644
  import java.util.Set;
  import java.util.function.Function;
  
-@@ -62,13 +63,14 @@ public class IndexHtmlUtil {
+@@ -63,13 +64,14 @@ public class IndexHtmlUtil {
        String faviconPath,
        Map<String, String[]> urlParameterMap,
        Function<String, SanitizedContent> urlInScriptTagOrdainer,
@@ -36,22 +36,21 @@ index 72bfe40c3b..439bd73b44 100644
      data.putAll(
              staticTemplateData(
                  canonicalURL, cdnPath, faviconPath, urlParameterMap, urlInScriptTagOrdainer))
--        .putAll(dynamicTemplateData(gerritApi, requestedURL));
-+        .putAll(dynamicTemplateData(gerritApi, requestedURL, titleComputer));
+-        .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL));
++        .putAll(dynamicTemplateData(gerritApi, requestedURL, canonicalURL, titleComputer));
      Set<String> enabledExperiments = new HashSet<>();
      enabledExperiments.addAll(experimentFeatures.getEnabledExperimentFeatures());
      // Add all experiments enabled through url
-@@ -81,7 +83,8 @@ public class IndexHtmlUtil {
+@@ -82,7 +84,7 @@ public class IndexHtmlUtil {
  
    /** Returns dynamic parameters of {@code index.html}. */
    public static ImmutableMap<String, Object> dynamicTemplateData(
--      GerritApi gerritApi, String requestedURL) throws RestApiException, URISyntaxException {
-+      GerritApi gerritApi, String requestedURL, TitleComputer titleComputer)
-+                throws RestApiException, URISyntaxException {
+-      GerritApi gerritApi, String requestedURL, String canonicalURL)
++      GerritApi gerritApi, String requestedURL, String canonicalURL, TitleComputer titleComputer)
+       throws RestApiException, URISyntaxException {
      ImmutableMap.Builder<String, Object> data = ImmutableMap.builder();
      Map<String, SanitizedContent> initialData = new HashMap<>();
-     Server serverApi = gerritApi.config().server();
-@@ -129,6 +132,10 @@ public class IndexHtmlUtil {
+@@ -141,6 +143,10 @@ public class IndexHtmlUtil {
      }
  
      data.put("gerritInitialData", initialData);
@@ -102,17 +101,17 @@ index fcb821e5ae..e1464b992b 100644
      } catch (URISyntaxException | RestApiException e) {
        throw new IOException(e);
 diff --git a/java/com/google/gerrit/httpd/raw/StaticModule.java b/java/com/google/gerrit/httpd/raw/StaticModule.java
-index 15dcf42e0e..9f56bf33ce 100644
+index b00294f73e..f1c1aae12c 100644
 --- a/java/com/google/gerrit/httpd/raw/StaticModule.java
 +++ b/java/com/google/gerrit/httpd/raw/StaticModule.java
-@@ -241,10 +241,11 @@ public class StaticModule extends ServletModule {
+@@ -224,10 +224,11 @@ public class StaticModule extends ServletModule {
          @CanonicalWebUrl @Nullable String canonicalUrl,
          @GerritServerConfig Config cfg,
          GerritApi gerritApi,
 -        ExperimentFeatures experimentFeatures) {
 +        ExperimentFeatures experimentFeatures,
 +        TitleComputer titleComputer) {
-       String cdnPath = options.devCdn().orElse(cfg.getString("gerrit", null, "cdnPath"));
+       String cdnPath = options.devCdn().orElseGet(() -> cfg.getString("gerrit", null, "cdnPath"));
        String faviconPath = cfg.getString("gerrit", null, "faviconPath");
 -      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures);
 +      return new IndexServlet(canonicalUrl, cdnPath, faviconPath, gerritApi, experimentFeatures, titleComputer);
@@ -193,7 +192,7 @@ index 0000000000..8fd2053ad0
 +  }
 +}
 diff --git a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
-index dbfef44dfe..347ee75aab 100644
+index 5ff1822cd9..81c3cdf0e1 100644
 --- a/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
 +++ b/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy
 @@ -33,10 +33,12 @@
@@ -211,5 +210,5 @@ index dbfef44dfe..347ee75aab 100644
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">{\n}
  
 -- 
-2.37.3
+2.45.1
 
diff --git a/third_party/gerrit/bazelrc b/third_party/gerrit/bazelrc
new file mode 100644
index 000000000000..f77da77b46ee
--- /dev/null
+++ b/third_party/gerrit/bazelrc
@@ -0,0 +1,11 @@
+# Not using common --repository_cache because Gerrit's bazelrc overrides this...
+build --repository_cache=repository-cache
+build --action_env=SSL_CERT_FILE
+build --action_env=GERRIT_CACHE_HOME
+build --tool_java_runtime_version=local_jdk --java_runtime_version=local_jdk
+build --workspace_status_command="cat .version"
+
+# Disable errorprone
+build --javacopt="-XepDisableAllChecks"
+
+sync --repository_cache=repository-cache
diff --git a/third_party/gerrit/default.nix b/third_party/gerrit/default.nix
index a137946264ed..fdf4a8d9d460 100644
--- a/third_party/gerrit/default.nix
+++ b/third_party/gerrit/default.nix
@@ -1,41 +1,33 @@
 { depot, pkgs, ... }:
 
 let
-  bazelRunScript = pkgs.writeShellScriptBin "bazel-run" ''
-    yarn config set cache-folder "$bazelOut/external/yarn_cache"
-    export HOME="$bazelOut/external/home"
-    mkdir -p "$bazelOut/external/home"
-    exec /bin/bazel "$@"
-  '';
-  bazelTop = pkgs.buildFHSUserEnv {
-    name = "bazel";
-    targetPkgs = pkgs: [
-      (pkgs.bazel_5.override { enableNixHacks = true; })
-      pkgs.jdk17_headless
-      pkgs.zlib
-      pkgs.python3
-      pkgs.curl
-      pkgs.nodejs
-      pkgs.yarn
-      pkgs.git
-      bazelRunScript
-    ];
-    runScript = "/bin/bazel-run";
-  };
-  bazel = bazelTop // { override = x: bazelTop; };
-  version = "3.9.1";
+  inherit (depot.nix) buildBazelPackageNG;
+  inherit (buildBazelPackageNG) bazelRulesJavaHook bazelRulesNodeJS5Hook;
 in
-pkgs.lib.makeOverridable pkgs.buildBazelPackage {
+pkgs.lib.makeOverridable depot.nix.buildBazelPackageNG rec {
   pname = "gerrit";
-  inherit version;
+  version = "3.10.0";
 
-  src = pkgs.fetchgit {
+  bazel = pkgs.bazel_7;
+
+  src = (pkgs.fetchgit {
     url = "https://gerrit.googlesource.com/gerrit";
-    rev = "620a819cbf3c64fff7a66798822775ad42c91d8e";
-    branchName = "v${version}";
-    sha256 = "sha256:1mdxbgnx3mpxand4wq96ic38bb4yh45q271h40jrk7dk23sgmz02";
+    rev = "v${version}";
     fetchSubmodules = true;
-  };
+    deepClone = true;
+    hash = "sha256-FpKuzityHuHNYBIOL8YUjCLlkuVBfxjvHECb26NsZNE=";
+  }).overrideAttrs (_: {
+    env.NIX_PREFETCH_GIT_CHECKOUT_HOOK = ''
+      pushd "$dir" >/dev/null
+      ${pkgs.python3}/bin/python tools/workspace_status_release.py | sort > .version
+      popd >/dev/null
+
+      # delete all the .git; we can't do this using fetchgit if deepClone is on,
+      # but our mischief has already been achieved by the python command above :)
+      find "$dir" -name .git -print0 | xargs -0 rm -rf
+    '';
+  });
+  depsHash = "sha256-OS2kLXjtuWf+XRyQO2qGvEaAOvxqu20+gXR+fsCvpMc=";
 
   patches = [
     ./0001-Syntax-highlight-nix.patch
@@ -43,97 +35,52 @@ pkgs.lib.makeOverridable pkgs.buildBazelPackage {
     ./0003-Add-titles-to-CLs-over-HTTP.patch
   ];
 
-  bazelTargets = [ "release" "api-skip-javadoc" ];
-  inherit bazel;
+  nativeBuildInputs = with pkgs; [
+    bazelRulesJavaHook
+    bazelRulesNodeJS5Hook
 
-  bazelFlags = [
-    "--repository_cache="
-    "--disk_cache="
+    curl
+    jdk
+    python3
+    unzip
   ];
 
-  removeRulesCC = false;
-  fetchConfigured = true;
+  prePatch = ''
+    rm .bazelversion
 
-  fetchAttrs = {
-    sha256 = "sha256:119mqli75c9fy05ddrlh2brjxb354yvv1ijjkk1y1yqcaqppwwb8";
-    preBuild = ''
-      rm .bazelversion
-    '';
+    ln -sf ${./bazelrc} user.bazelrc
 
-    installPhase = ''
-      runHook preInstall
-
-      # Remove all built in external workspaces, Bazel will recreate them when building
-      rm -rf $bazelOut/external/{bazel_tools,\@bazel_tools.marker}
-      rm -rf $bazelOut/external/{embedded_jdk,\@embedded_jdk.marker}
-      rm -rf $bazelOut/external/{local_config_cc,\@local_config_cc.marker}
-      rm -rf $bazelOut/external/{local_*,\@local_*.marker}
-
-      # Clear markers
-      find $bazelOut/external -name '@*\.marker' -exec sh -c 'echo > {}' \;
-
-      # Remove all vcs files
-      rm -rf $(find $bazelOut/external -type d -name .git)
-      rm -rf $(find $bazelOut/external -type d -name .svn)
-      rm -rf $(find $bazelOut/external -type d -name .hg)
-
-      # Removing top-level symlinks along with their markers.
-      # This is needed because they sometimes point to temporary paths (?).
-      # For example, in Tensorflow-gpu build:
-      #sha256:06bmzbcb9717s4b016kcbn8nr9pgaz04i8bnzg7ybkbdwpl8vxvv"; platforms -> NIX_BUILD_TOP/tmp/install/35282f5123611afa742331368e9ae529/_embedded_binaries/platforms
-      find $bazelOut/external -maxdepth 1 -type l | while read symlink; do
-        name="$(basename "$symlink")"
-        rm -rf "$symlink" "$bazelOut/external/@$name.marker"
-      done
-
-      # Patching symlinks to remove build directory reference
-      find $bazelOut/external -type l | while read symlink; do
-        new_target="$(readlink "$symlink" | sed "s,$NIX_BUILD_TOP,NIX_BUILD_TOP,")"
-        rm "$symlink"
-        ln -sf "$new_target" "$symlink"
-      done
-
-      echo '${bazel.name}' > $bazelOut/external/.nix-bazel-version
-
-      # Gerrit fixups:
-      # Normalize permissions on .yarn-{tarball,metadata} files
-      test -d $bazelOut/external/yarn_cache && find $bazelOut/external/yarn_cache \( -name .yarn-tarball.tgz -or -name .yarn-metadata.json \) -exec chmod 644 {} +
-
-      mkdir $bazelOut/_bits/
-      find . -name node_modules -prune -print | while read d; do
-        echo "$d" "$(dirname $d)"
-        mkdir -p $bazelOut/_bits/$(dirname $d)
-        cp -R "$d" "$bazelOut/_bits/$(dirname $d)/node_modules"
-      done
-
-      (cd $bazelOut/ && tar czf $out --sort=name --mtime='@1' --owner=0 --group=0 --numeric-owner external/ _bits/)
-
-      runHook postInstall
-    '';
-  };
+    ln -sf ${./workspace_overrides.bzl} workspace_overrides.bzl
+    substituteInPlace WORKSPACE \
+      --replace-fail 'load("@io_bazel_rules_webtesting//web:repositories.bzl"' 'load("//:workspace_overrides.bzl"' \
+      --replace-fail 'load("@io_bazel_rules_webtesting//web/versioned:browsers-0.3.3.bzl"' 'load("//:workspace_overrides.bzl"'
 
-  buildAttrs = {
-    preConfigure = ''
-      rm .bazelversion
+    patchShebangs Documentation/replace_macros.py
+  '';
 
-      [ "$(ls -A $bazelOut/_bits)" ] && cp -R $bazelOut/_bits/* ./ || true
-    '';
-    postPatch = ''
-      # Disable all errorprone checks, since we might be using a different version.
-      sed -i \
-        -e '/-Xep:/d' \
-        -e '/-XepExcludedPaths:/a "-XepDisableAllChecks",' \
-        tools/BUILD
-    '';
-    installPhase = ''
-      mkdir -p "$out"/webapps/ "$out"/share/api/
-      cp bazel-bin/release.war "$out"/webapps/gerrit-${version}.war
-      unzip bazel-bin/api-skip-javadoc.zip -d "$out"/share/api
-    '';
+  postPatch = ''
+    sed -Ei 's,^(STABLE_BUILD_GERRIT_LABEL.*)$,\1-dirty-nix,' .version
+  '';
 
-    nativeBuildInputs = with pkgs; [
-      unzip
-    ];
+  preBuild = ''
+    export GERRIT_CACHE_HOME=$HOME/gerrit-cache
+  '';
+
+  extraCacheInstall = ''
+    cp -R $GERRIT_CACHE_HOME $out/gerrit-cache
+  '';
+
+  extraBuildSetup = ''
+    ln -sf $cache/gerrit-cache $GERRIT_CACHE_HOME
+  '';
+  extraBuildInstall = ''
+    mkdir -p "$out"/share/api/
+    unzip bazel-bin/api-skip-javadoc.zip -d "$out"/share/api
+  '';
+
+  bazelTargets = {
+    "//:release" = "$out/webapps/gerrit-${version}.war";
+    "//:api-skip-javadoc" = null;
   };
 
   passthru = {
@@ -154,5 +101,5 @@ pkgs.lib.makeOverridable pkgs.buildBazelPackage {
     ];
   };
 
-  meta.ci.targets = [ "deps" ];
+  meta.ci.targets = [ "cache" ];
 }
diff --git a/third_party/gerrit/detzip.go b/third_party/gerrit/detzip.go
deleted file mode 100644
index 511c18ecfe17..000000000000
--- a/third_party/gerrit/detzip.go
+++ /dev/null
@@ -1,97 +0,0 @@
-package main
-
-import (
-	"archive/zip"
-	"flag"
-	"fmt"
-	"io"
-	"log"
-	"os"
-	"path/filepath"
-	"sort"
-	"strings"
-)
-
-var (
-	exclude = flag.String("exclude", "", "comma-separated list of filenames to exclude (in any directory)")
-)
-
-func init() {
-	flag.Usage = func() {
-		fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s [zip file] [directory]:\n", os.Args[0])
-		flag.PrintDefaults()
-	}
-}
-
-func listToMap(ss []string) map[string]bool {
-	m := make(map[string]bool)
-	for _, s := range ss {
-		m[s] = true
-	}
-	return m
-}
-
-func main() {
-	flag.Parse()
-	if flag.NArg() != 2 {
-		flag.Usage()
-		os.Exit(1)
-	}
-
-	outPath := flag.Arg(0)
-	dirPath := flag.Arg(1)
-
-	excludeFiles := listToMap(strings.Split(*exclude, ","))
-
-	// Aggregate all files first.
-	var files []string
-	filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
-		if err != nil {
-			return err
-		}
-		if info.IsDir() {
-			return nil
-		}
-		if excludeFiles[info.Name()] {
-			return nil
-		}
-		files = append(files, path)
-		return nil
-	})
-
-	// Create zip
-	outW, err := os.Create(outPath)
-	if err != nil {
-		log.Fatalf("Create(%q): %v", outPath, err)
-	}
-
-	zipW := zip.NewWriter(outW)
-
-	// Output files in alphabetical order
-	sort.Strings(files)
-	for _, f := range files {
-		fw, err := zipW.CreateHeader(&zip.FileHeader{
-			Name:   f,
-			Method: zip.Store,
-		})
-		if err != nil {
-			log.Fatalf("creating %q in zip: %v", f, err)
-		}
-
-		ff, err := os.Open(f)
-		if err != nil {
-			log.Fatalf("opening %q: %v", f, err)
-		}
-		if _, err := io.Copy(fw, ff); err != nil {
-			log.Fatalf("copying %q to zip: %v", f, err)
-		}
-		ff.Close()
-	}
-
-	if err := zipW.Close(); err != nil {
-		log.Fatalf("writing ZIP central directory: %v", err)
-	}
-	if err := outW.Close(); err != nil {
-		log.Fatalf("closing ZIP file: %v", err)
-	}
-}
diff --git a/third_party/gerrit/workspace_overrides.bzl b/third_party/gerrit/workspace_overrides.bzl
new file mode 100644
index 000000000000..839368606557
--- /dev/null
+++ b/third_party/gerrit/workspace_overrides.bzl
@@ -0,0 +1,5 @@
+def web_test_repositories():
+    pass
+
+def browser_repositories(*args, **kwargs):
+    pass
diff --git a/third_party/gerrit_plugins/builder.nix b/third_party/gerrit_plugins/builder.nix
index 50a4e78ae7cf..a478dfe5d71d 100644
--- a/third_party/gerrit_plugins/builder.nix
+++ b/third_party/gerrit_plugins/builder.nix
@@ -2,30 +2,33 @@
 {
   buildGerritBazelPlugin =
     { name
+    , version
     , src
-    , depsOutputHash
+    , depsHash ? null
     , overlayPluginCmd ? ''
         cp -R "${src}" "$out/plugins/${name}"
+        echo "STABLE_BUILD_${lib.toUpper name}_LABEL v${version}-nix${if patches != [] then "-dirty" else ""}" >> $out/.version
       ''
+    , postOverlayPlugin ? ""
     , postPatch ? ""
     , patches ? [ ]
-    }: ((depot.third_party.gerrit.override {
+    }: ((depot.third_party.gerrit.override (old: {
       name = "${name}.jar";
 
       src = pkgs.runCommandLocal "${name}-src" { } ''
         cp -R "${depot.third_party.gerrit.src}" "$out"
-        chmod +w "$out/plugins"
+        chmod -R +w "$out"
         ${overlayPluginCmd}
+        ${postOverlayPlugin}
       '';
+      depsHash = (if depsHash != null then depsHash else old.depsHash);
 
-      bazelTargets = [ "//plugins/${name}" ];
-    }).overrideAttrs (super: {
-      deps = super.deps.overrideAttrs (superDeps: {
-        outputHash = depsOutputHash;
-      });
-      installPhase = ''
-        cp "bazel-bin/plugins/${name}/${name}.jar" "$out"
-      '';
+      bazelTargets = {
+        "//plugins/${name}" = "$out";
+      };
+
+      extraBuildInstall = "";
+    })).overrideAttrs (super: {
       postPatch = ''
         ${super.postPatch or ""}
         pushd "plugins/${name}"
diff --git a/third_party/gerrit_plugins/code-owners/default.nix b/third_party/gerrit_plugins/code-owners/default.nix
index 0dc3ef83ae7f..c849bfb52d41 100644
--- a/third_party/gerrit_plugins/code-owners/default.nix
+++ b/third_party/gerrit_plugins/code-owners/default.nix
@@ -5,11 +5,11 @@ let
 in
 buildGerritBazelPlugin rec {
   name = "code-owners";
-  depsOutputHash = "sha256:0jv62cc1kpgsmwk119i9njmqn6w6k8frlbgcw87y8nfbpprmcf01";
+  version = "7de40d8";
   src = pkgs.fetchgit {
     url = "https://gerrit.googlesource.com/plugins/code-owners";
-    rev = "e654ae5bda2085bce9a99942bec440e004a114f3";
-    sha256 = "sha256:14d3x3iqskgw16pvyaa0swh252agj84p9pzlf24l8lgx9d7y4biz";
+    rev = "7de40d8b30e55eb64316b6fc3d0d00da9caddade";
+    hash = "sha256-0sLwUcG9RN1o9vZGW8ErwL7UgJapgYoo8XMGsWLO25Q=";
   };
   patches = [
     ./using-usernames.patch
diff --git a/third_party/gerrit_plugins/oauth/default.nix b/third_party/gerrit_plugins/oauth/default.nix
index e7626fa88c38..811614d66a18 100644
--- a/third_party/gerrit_plugins/oauth/default.nix
+++ b/third_party/gerrit_plugins/oauth/default.nix
@@ -5,15 +5,14 @@ let
 in
 buildGerritBazelPlugin rec {
   name = "oauth";
-  depsOutputHash = "sha256:01z7rn8hnms3cp7mq27yk063lpy4pmqwpfrcc3cfl0r43k889zz3";
+  version = "982316";
   src = pkgs.fetchgit {
     url = "https://gerrit.googlesource.com/plugins/oauth";
-    rev = "b27cf3ea820eec2ddd22d217fc839261692ccdb0";
-    sha256 = "1m654ibgzprrhcl0wpzqrmq8drpgx6rzlw0ha16l1fi2zv5idkk2";
+    rev = "98231604d60788bb43490f1a301d792817ac8008";
+    hash = "sha256-AuVO1Yys8BYqGHZI/adszCUg0JM2v4Td4fe26LdOPLM=";
   };
-  overlayPluginCmd = ''
-    chmod +w "$out" "$out/plugins/external_plugin_deps.bzl"
-    cp -R "${src}" "$out/plugins/${name}"
+  depsHash = "sha256-7SC4NXm4zGeJrYBqtEvcrLmsZmXEX8P21J0kwHBDBZ4=";
+  postOverlayPlugin = ''
     cp "${src}/external_plugin_deps.bzl" "$out/plugins/external_plugin_deps.bzl"
   '';
 }
diff --git a/third_party/git/default.nix b/third_party/git/default.nix
index eed07b5616c6..19613fd69555 100644
--- a/third_party/git/default.nix
+++ b/third_party/git/default.nix
@@ -4,6 +4,6 @@
 
 pkgs.git.overrideAttrs (old: {
   patches = (old.patches or [ ]) ++ [
-    ./0001-feat-third_party-git-date-add-dottime-format.patch
+    # ./0001-feat-third_party-git-date-add-dottime-format.patch
   ];
 })
diff --git a/third_party/gitignoreSource/default.nix b/third_party/gitignoreSource/default.nix
index 150de7c990e4..78a7414ed3ad 100644
--- a/third_party/gitignoreSource/default.nix
+++ b/third_party/gitignoreSource/default.nix
@@ -1,15 +1,7 @@
-{ pkgs, ... }:
+{ depot, lib, ... }:
 
 let
-  gitignoreNix = import
-    (pkgs.fetchFromGitHub {
-      owner = "hercules-ci";
-      repo = "gitignore";
-      rev = "f9e996052b5af4032fe6150bba4a6fe4f7b9d698";
-      sha256 = "0jrh5ghisaqdd0vldbywags20m2cxpkbbk5jjjmwaw0gr8nhsafv";
-    })
-    { inherit (pkgs) lib; };
-
+  gitignoreNix = import depot.third_party.sources."gitignore.nix" { inherit lib; };
 in
 {
   __functor = _: gitignoreNix.gitignoreSource;
diff --git a/third_party/nixpkgs/default.nix b/third_party/nixpkgs/default.nix
index 03dc7b267c98..3ec49ea084d8 100644
--- a/third_party/nixpkgs/default.nix
+++ b/third_party/nixpkgs/default.nix
@@ -58,6 +58,9 @@ let
 
     # the big lis package change breaks everything in //3p/lisp, undo it for now.
     lispPackages = stableNixpkgs.lispPackages;
+
+    # mypaint is broken on stable (2024-09-05)
+    mypaint = stableNixpkgs.mypaint;
   };
 
   # Overlay to expose the nixpkgs commits we are using to other Nix code.
diff --git a/third_party/overlays/patches/cbtemulator-uds.patch b/third_party/overlays/patches/cbtemulator-uds.patch
deleted file mode 100644
index a19255306f88..000000000000
--- a/third_party/overlays/patches/cbtemulator-uds.patch
+++ /dev/null
@@ -1,140 +0,0 @@
-commit 1397e10225d8c6fd079a86fccd58fb5d0f4200bc
-Author: Florian Klink <flokli@flokli.de>
-Date:   Fri Mar 29 10:06:34 2024 +0100
-
-    feat(bigtable/emulator): allow listening on Unix Domain Sockets
-    
-    cbtemulator listening on unix domain sockets is much easier than trying
-    to allocate free TCP ports, especially if many cbtemulators are run at
-    the same time in integration tests.
-    
-    This adds an additional flag, address, which has priority if it's set,
-    rather than host:port.
-    
-    `NewServer` already takes a `laddr string`, so we simply check for it to
-    contain slashes, and if so, listen on unix, rather than TCP.
-
-diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go
-index 556abc2a85..33e4bf2667 100644
---- a/bttest/inmem.go
-+++ b/bttest/inmem.go
-@@ -40,6 +40,7 @@ import (
- 	"math"
- 	"math/rand"
- 	"net"
-+	"os"
- 	"regexp"
- 	"sort"
- 	"strings"
-@@ -106,7 +107,15 @@ type server struct {
- // The Server will be listening for gRPC connections, without TLS,
- // on the provided address. The resolved address is named by the Addr field.
- func NewServer(laddr string, opt ...grpc.ServerOption) (*Server, error) {
--	l, err := net.Listen("tcp", laddr)
-+	var l net.Listener
-+	var err error
-+
-+	// If the address contains slashes, listen on a unix domain socket instead.
-+	if strings.Contains(laddr, "/") {
-+		l, err = net.Listen("unix", laddr)
-+	} else {
-+		l, err = net.Listen("tcp", laddr)
-+	}
- 	if err != nil {
- 		return nil, err
- 	}
-diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go
-index 144c09ffb1..deaf69b717 100644
---- a/cmd/emulator/cbtemulator.go
-+++ b/cmd/emulator/cbtemulator.go
-@@ -27,8 +27,9 @@ import (
- )
- 
- var (
--	host = flag.String("host", "localhost", "the address to bind to on the local machine")
--	port = flag.Int("port", 9000, "the port number to bind to on the local machine")
-+	host    = flag.String("host", "localhost", "the address to bind to on the local machine")
-+	port    = flag.Int("port", 9000, "the port number to bind to on the local machine")
-+	address = flag.String("address", "", "address:port number or unix socket path to listen on. Has priority over host/port")
- )
- 
- const (
-@@ -42,7 +43,15 @@ func main() {
- 		grpc.MaxRecvMsgSize(maxMsgSize),
- 		grpc.MaxSendMsgSize(maxMsgSize),
- 	}
--	srv, err := bttest.NewServer(fmt.Sprintf("%s:%d", *host, *port), opts...)
-+
-+	var laddr string
-+	if *address != "" {
-+		laddr = *address
-+	} else {
-+		laddr = fmt.Sprintf("%s:%d", *host, *port)
-+	}
-+
-+	srv, err := bttest.NewServer(laddr, opts...)
- 	if err != nil {
- 		log.Fatalf("failed to start emulator: %v", err)
- 	}
-commit ce16f843d6c93159d86b3807c6d9ff66e43aac67
-Author: Florian Klink <flokli@flokli.de>
-Date:   Fri Mar 29 11:53:15 2024 +0100
-
-    feat(bigtable): clean up unix socket on close
-    
-    Call srv.Close when receiving an interrupt, and delete the unix domain
-    socket in that function.
-
-diff --git a/bigtable/bttest/inmem.go b/bigtable/bttest/inmem.go
-index 33e4bf2667..0dc96024b1 100644
---- a/bttest/inmem.go
-+++ b/bttest/inmem.go
-@@ -148,6 +148,11 @@ func (s *Server) Close() {
- 
- 	s.srv.Stop()
- 	s.l.Close()
-+
-+	// clean up unix socket
-+	if strings.Contains(s.Addr, "/") {
-+		_ = os.Remove(s.Addr)
-+	}
- }
- 
- func (s *server) CreateTable(ctx context.Context, req *btapb.CreateTableRequest) (*btapb.Table, error) {
-diff --git a/bigtable/cmd/emulator/cbtemulator.go b/bigtable/cmd/emulator/cbtemulator.go
-index deaf69b717..5a9e8f7a8c 100644
---- a/cmd/emulator/cbtemulator.go
-+++ b/cmd/emulator/cbtemulator.go
-@@ -18,9 +18,12 @@ cbtemulator launches the in-memory Cloud Bigtable server on the given address.
- package main
- 
- import (
-+	"context"
- 	"flag"
- 	"fmt"
- 	"log"
-+	"os"
-+	"os/signal"
- 
- 	"cloud.google.com/go/bigtable/bttest"
- 	"google.golang.org/grpc"
-@@ -51,11 +54,18 @@ func main() {
- 		laddr = fmt.Sprintf("%s:%d", *host, *port)
- 	}
- 
-+	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt)
-+	defer stop()
-+
- 	srv, err := bttest.NewServer(laddr, opts...)
- 	if err != nil {
- 		log.Fatalf("failed to start emulator: %v", err)
- 	}
- 
- 	fmt.Printf("Cloud Bigtable emulator running on %s\n", srv.Addr)
--	select {}
-+	select {
-+	case <-ctx.Done():
-+		srv.Close()
-+		stop()
-+	}
- }
diff --git a/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch b/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch
new file mode 100644
index 000000000000..fbc18860ac81
--- /dev/null
+++ b/third_party/overlays/patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch
@@ -0,0 +1,109 @@
+From 96f66ec32e003c6c215aa2a644281289a71dae7d Mon Sep 17 00:00:00 2001
+From: Ilan Joselevich <personal@ilanjoselevich.com>
+Date: Sun, 4 Aug 2024 02:35:27 +0300
+Subject: [PATCH] Fix: Use mkDerivation with src instead of runCommand for test
+ derivation
+
+The problem with using runCommand and recreating the src directory with
+lndir is that it changes the file types of individual files, they will
+now be a symlink instead of a regular file. If you have a crate that tests
+that a file is of regular type then it will fail inside the crate2nix derivation.
+---
+ templates/nix/crate2nix/default.nix | 81 ++++++++-----------
+ 1 file changed, 35 insertions(+), 46 deletions(-)
+
+diff --git a/templates/nix/crate2nix/default.nix b/templates/nix/crate2nix/default.nix
+index c53925e..90e10c6 100644
+--- a/templates/nix/crate2nix/default.nix
++++ b/templates/nix/crate2nix/default.nix
+@@ -120,52 +120,41 @@ rec {
+               testPostRun
+             ]);
+         in
+-        pkgs.runCommand "run-tests-${testCrate.name}"
+-          {
+-            inherit testCrateFlags;
+-            buildInputs = testInputs;
+-          } ''
+-          set -e
+-
+-          export RUST_BACKTRACE=1
+-
+-          # recreate a file hierarchy as when running tests with cargo
+-
+-          # the source for test data
+-          # It's necessary to locate the source in $NIX_BUILD_TOP/source/
+-          # instead of $NIX_BUILD_TOP/
+-          # because we compiled those test binaries in the former and not the latter.
+-          # So all paths will expect source tree to be there and not in the build top directly.
+-          # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself.
+-          # NOTE: There could be edge cases if `crate.sourceRoot` does exist but
+-          # it's very hard to reason about them.
+-          # Open a bug if you run into this!
+-          mkdir -p source/
+-          cd source/
+-
+-          ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src}
+-
+-          # build outputs
+-          testRoot=target/debug
+-          mkdir -p $testRoot
+-
+-          # executables of the crate
+-          # we copy to prevent std::env::current_exe() to resolve to a store location
+-          for i in ${crate}/bin/*; do
+-            cp "$i" "$testRoot"
+-          done
+-          chmod +w -R .
+-
+-          # test harness executables are suffixed with a hash, like cargo does
+-          # this allows to prevent name collision with the main
+-          # executables of the crate
+-          hash=$(basename $out)
+-          for file in ${drv}/tests/*; do
+-            f=$testRoot/$(basename $file)-$hash
+-            cp $file $f
+-            ${testCommand}
+-          done
+-        '';
++        pkgs.stdenvNoCC.mkDerivation {
++          name = "run-tests-${testCrate.name}";
++
++          inherit (crate) src;
++
++          inherit testCrateFlags;
++
++          buildInputs = testInputs;
++
++          buildPhase = ''
++            set -e
++            export RUST_BACKTRACE=1
++
++            # build outputs
++            testRoot=target/debug
++            mkdir -p $testRoot
++
++            # executables of the crate
++            # we copy to prevent std::env::current_exe() to resolve to a store location
++            for i in ${crate}/bin/*; do
++              cp "$i" "$testRoot"
++            done
++            chmod +w -R .
++
++            # test harness executables are suffixed with a hash, like cargo does
++            # this allows to prevent name collision with the main
++            # executables of the crate
++            hash=$(basename $out)
++            for file in ${drv}/tests/*; do
++              f=$testRoot/$(basename $file)-$hash
++              cp $file $f
++              ${testCommand}
++            done
++          '';
++        };
+     in
+     pkgs.runCommand "${crate.name}-linked"
+       {
+-- 
+2.44.0
+
diff --git a/third_party/overlays/patches/crate2nix-drop-darwin-explicit-dontstrip.patch b/third_party/overlays/patches/crate2nix-drop-darwin-explicit-dontstrip.patch
deleted file mode 100644
index ba64e660c0e3..000000000000
--- a/third_party/overlays/patches/crate2nix-drop-darwin-explicit-dontstrip.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-From 0209f258cda8a9972a785e26d92fb477ce4d1b0e Mon Sep 17 00:00:00 2001
-From: Ilan Joselevich <personal@ilanjoselevich.com>
-Date: Tue, 11 Jun 2024 18:14:06 +0300
-Subject: [PATCH] Get rid of dontStrip for Darwin as it's no longer needed
-
-Fixed in https://github.com/NixOS/nixpkgs/pull/255900
----
- templates/nix/crate2nix/default.nix                  | 2 --
-
-diff --git a/templates/nix/crate2nix/default.nix b/templates/nix/crate2nix/default.nix
-index 95d3730f..c53925e7 100644
---- a/templates/nix/crate2nix/default.nix
-+++ b/templates/nix/crate2nix/default.nix
-@@ -349,8 +349,6 @@ rec {
-           buildRustCrateForPkgsFunc pkgs
-             (
-               crateConfig // {
--                # https://github.com/NixOS/nixpkgs/issues/218712
--                dontStrip = stdenv.hostPlatform.isDarwin;
-                 src = crateConfig.src or (
-                   pkgs.fetchurl rec {
-                     name = "${crateConfig.crateName}-${crateConfig.version}.tar.gz";
diff --git a/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch b/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch
deleted file mode 100644
index 52793270e6e8..000000000000
--- a/third_party/overlays/patches/crate2nix-run-tests-in-build-source.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 7cf084f73f7d15fe0538a625182fa7179c083b3d Mon Sep 17 00:00:00 2001
-From: Raito Bezarius <masterancpp@gmail.com>
-Date: Tue, 16 Jan 2024 02:10:48 +0100
-Subject: [PATCH] fix(template): run tests in `/build/source` instead `/build`
-
-Previously, the source tree was located inline in `/build` during tests, this was a mistake
-because the crates more than often are built in `/build/source` as per the `sourceRoot` system.
-
-This can cause issues with test binaries hardcoding `/build/source/...` as their choice for doing things,
-causing them to be confused in the test phase which is relocated without rewriting the paths inside test binaries.
-
-We fix that by relocating ourselves in the right hierarchy.
-
-This is a "simple" fix in the sense that more edge cases could exist but they are hard to reason about
-because they would be crates using custom `sourceRoot`, i.e. having `crate.sourceRoot` set and then it becomes
-a bit hard to reproduce the hierarchy, you need to analyze whether the path is absolute or relative,
-
-If it's relative, you can just reuse it and reproduce that specific hierarchy.
-If it's absolute, you need to cut the "absolute" meaningless part, e.g. `$NIX_BUILD_TOP/` and proceed like
-it's a relative path IMHO.
----
- crate2nix/Cargo.nix                                  | 10 ++++++++++
- crate2nix/templates/nix/crate2nix/default.nix        | 10 ++++++++++
-
-diff --git a/Cargo.nix b/Cargo.nix
-index 6ef7a49..172ff34 100644
---- a/Cargo.nix
-+++ b/Cargo.nix
-@@ -2889,6 +2889,16 @@ rec {
-           # recreate a file hierarchy as when running tests with cargo
- 
-           # the source for test data
-+          # It's necessary to locate the source in $NIX_BUILD_TOP/source/
-+          # instead of $NIX_BUILD_TOP/
-+          # because we compiled those test binaries in the former and not the latter.
-+          # So all paths will expect source tree to be there and not in the build top directly.
-+          # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself.
-+          # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot`
-+          # do exist but it's very hard to reason about them, so let's wait until the first bug report.
-+          mkdir -p source/
-+          cd source/
-+
-           ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src}
- 
-           # build outputs
-diff --git a/crate2nix/templates/nix/crate2nix/default.nix b/crate2nix/templates/nix/crate2nix/default.nix
-index e4fc2e9..dfb14c4 100644
---- a/templates/nix/crate2nix/default.nix
-+++ b/templates/nix/crate2nix/default.nix
-@@ -135,6 +135,16 @@ rec {
-           # recreate a file hierarchy as when running tests with cargo
- 
-           # the source for test data
-+          # It's necessary to locate the source in $NIX_BUILD_TOP/source/
-+          # instead of $NIX_BUILD_TOP/
-+          # because we compiled those test binaries in the former and not the latter.
-+          # So all paths will expect source tree to be there and not in the build top directly.
-+          # For example: $NIX_BUILD_TOP := /build in general, if you ask yourself.
-+          # TODO(raitobezarius): I believe there could be more edge cases if `crate.sourceRoot`
-+          # do exist but it's very hard to reason about them, so let's wait until the first bug report.
-+          mkdir -p source/
-+          cd source/
-+
-           ${pkgs.buildPackages.xorg.lndir}/bin/lndir ${crate.src}
- 
-           # build outputs
--- 
-2.43.0
-
diff --git a/third_party/overlays/patches/treefmt-fix-no-cache.patch b/third_party/overlays/patches/treefmt-fix-no-cache.patch
new file mode 100644
index 000000000000..2ad9d595e106
--- /dev/null
+++ b/third_party/overlays/patches/treefmt-fix-no-cache.patch
@@ -0,0 +1,43 @@
+From 601af097720079ea40db100b1dd6aefba4685e7c Mon Sep 17 00:00:00 2001
+From: Florian Klink <flokli@flokli.de>
+Date: Mon, 1 Jul 2024 17:34:08 +0300
+Subject: [PATCH] fix: only try opening the cache if cache is enabled
+
+Otherwise `--no-cache` still fails to open the cache.
+---
+ cli/format.go | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/cli/format.go b/cli/format.go
+index 492a4f3..8ccf578 100644
+--- a/cli/format.go
++++ b/cli/format.go
+@@ -118,9 +118,11 @@ func (f *Format) Run() (err error) {
+ 		f.formatters[name] = formatter
+ 	}
+ 
+-	// open the cache
+-	if err = cache.Open(f.TreeRoot, f.ClearCache, f.formatters); err != nil {
+-		return err
++	// open the cache if configured
++	if !f.NoCache {
++		if cache.Open(f.TreeRoot, f.ClearCache, f.formatters); err != nil {
++			return err
++		}
+ 	}
+ 
+ 	// create an app context and listen for shutdown
+@@ -148,7 +150,9 @@ func (f *Format) Run() (err error) {
+ 	f.processedCh = make(chan *walk.File, cap(f.filesCh))
+ 
+ 	// start concurrent processing tasks in reverse order
+-	eg.Go(f.updateCache(ctx))
++	if !f.NoCache {
++		eg.Go(f.updateCache(ctx))
++	}
+ 	eg.Go(f.applyFormatters(ctx))
+ 	eg.Go(f.walkFilesystem(ctx))
+ 
+-- 
+2.44.1
+
diff --git a/third_party/overlays/tvl.nix b/third_party/overlays/tvl.nix
index f2260be8b8fb..3835f07c9664 100644
--- a/third_party/overlays/tvl.nix
+++ b/third_party/overlays/tvl.nix
@@ -79,10 +79,6 @@ depot.nix.readTree.drvTargets {
     };
   });
 
-  # nix-serve does not work with nix 2.4
-  # https://github.com/edolstra/nix-serve/issues/28
-  nix-serve = super.nix-serve.override { nix = self.nix_2_3; };
-
   # Avoid builds of mkShell derivations in CI.
   mkShell = super.lib.makeOverridable (args: (super.mkShell args).overrideAttrs (_: {
     passthru = {
@@ -90,19 +86,12 @@ depot.nix.readTree.drvTargets {
     };
   }));
 
-  # https://github.com/googleapis/google-cloud-go/pull/9665
-  cbtemulator = super.cbtemulator.overrideAttrs (old: {
-    patches = old.patches or [ ] ++ [
-      ./patches/cbtemulator-uds.patch
-    ];
-  });
-
   crate2nix = super.crate2nix.overrideAttrs (old: {
     patches = old.patches or [ ] ++ [
+      # TODO(Kranzes): Remove in next release.
+      ./patches/crate2nix-0001-Fix-Use-mkDerivation-with-src-instead-of-runCommand.patch
       # https://github.com/nix-community/crate2nix/pull/301
       ./patches/crate2nix-tests-debug.patch
-      # TODO(Kranzes): drop on next release
-      ./patches/crate2nix-drop-darwin-explicit-dontstrip.patch
     ];
   });
 
@@ -114,6 +103,25 @@ depot.nix.readTree.drvTargets {
     ];
   });
 
+  # https://github.com/NixOS/nixpkgs/pull/329415/files
+  grpc-health-check = super.rustPlatform.buildRustPackage {
+    pname = "grpc-health-check";
+    version = "unstable-2022-08-19";
+
+    src = super.fetchFromGitHub {
+      owner = "paypizza";
+      repo = "grpc-health-check";
+      rev = "f61bb5e10beadc5ed53144cc540d66e19fc510bd";
+      hash = "sha256-nKut9c1HHIacdRcmvlXe0GrtkgCWN6sxJ4ImO0CIDdo=";
+    };
+
+    cargoHash = "sha256-lz+815iE+oXBQ3PfqBO0QBpZY6x1SNR7OU7BjkRszzI=";
+
+    nativeBuildInputs = [ super.protobuf ];
+    # tests fail
+    doCheck = false;
+  };
+
   # Imports a patch that fixes usage of this package on versions
   # >=1.9. The patch has been proposed upstream, but so far with no
   # reactions from the maintainer:
@@ -123,6 +131,11 @@ depot.nix.readTree.drvTargets {
     patches = (old.patches or [ ]) ++ [ ./patches/tpm2-pkcs11-190-dbupgrade.patch ];
   });
 
+  # Dependency isn't supported by Python 3.12
+  html5validator = super.html5validator.override {
+    python3 = self.python311;
+  };
+
   # macFUSE bump containing fix for https://github.com/osxfuse/osxfuse/issues/974
   # https://github.com/NixOS/nixpkgs/pull/320197
   fuse =
@@ -135,4 +148,31 @@ depot.nix.readTree.drvTargets {
             hash = "sha256-ucTzO2qdN4QkowMVvC3+4pjEVjbwMsB0xFk+bvQxwtQ=";
           };
         }) else super.fuse;
+
+  # somebody renamed 'utillinux' upstream, but didn't rename all use-cases,
+  # leading to some packages being broken.
+  #
+  # temporarily restore the old name to make things work again.
+  utillinux = self.util-linux;
+
+  # Override niri to a version with interactive move until a new release is cut upstream.
+  niri =
+    let
+      src = self.fetchFromGitHub {
+        owner = "yalter";
+        repo = "niri";
+        rev = "0866990b7d706cdb3af2e9f0008bb9e7281a0e26";
+        hash = "sha256:088yb86pryrcklwggx072dhswhjvx9ylkzdhrfkpfc56a85mp6vk";
+      };
+    in
+    super.niri.overrideAttrs (old: {
+      inherit src;
+      cargoDeps = self.rustPlatform.importCargoLock {
+        lockFile = "${src}/Cargo.lock";
+        outputHashes = {
+          "smithay-0.3.0" = "sha256:10ihl9hvvi8aw30qv8ihv888ngr7wf7p9nwabf2jvhlc9443jq35";
+          "libspa-0.8.0" = "sha256:1n8ngihd75i3vgbfnfhpj8mi6shlrhbhvwfyms14m03613jp37lj";
+        };
+      };
+    });
 }
diff --git a/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch
new file mode 100644
index 000000000000..0f4a6219b298
--- /dev/null
+++ b/third_party/radicle-explorer/0001-remove-dependency-on-plausible.patch
@@ -0,0 +1,78 @@
+From cc4718cbea1bd70de21a2be515a944802246ffc7 Mon Sep 17 00:00:00 2001
+From: Vincent Ambo <mail@tazj.in>
+Date: Sun, 15 Sep 2024 03:08:28 +0300
+Subject: [PATCH] remove dependency on plausible
+
+We don't need spyware, thanks.
+---
+ package-lock.json | 9 ---------
+ package.json      | 1 -
+ src/App.svelte    | 8 --------
+ 3 files changed, 18 deletions(-)
+
+diff --git a/package-lock.json b/package-lock.json
+index d52de6c0..d96e342f 100644
+--- a/package-lock.json
++++ b/package-lock.json
+@@ -29,7 +29,6 @@
+         "marked-katex-extension": "^5.1.1",
+         "marked-linkify-it": "^3.1.11",
+         "md5": "^2.3.0",
+-        "plausible-tracker": "^0.3.9",
+         "svelte": "^4.2.19",
+         "twemoji": "^14.0.2",
+         "zod": "^3.23.8"
+@@ -3697,14 +3696,6 @@
+         "url": "https://github.com/sponsors/jonschlinkert"
+       }
+     },
+-    "node_modules/plausible-tracker": {
+-      "version": "0.3.9",
+-      "resolved": "https://registry.npmjs.org/plausible-tracker/-/plausible-tracker-0.3.9.tgz",
+-      "integrity": "sha512-hMhneYm3GCPyQon88SZrVJx+LlqhM1kZFQbuAgXPoh/Az2YvO1B6bitT9qlhpiTdJlsT5lsr3gPmzoVjb5CDXA==",
+-      "engines": {
+-        "node": ">=10"
+-      }
+-    },
+     "node_modules/playwright": {
+       "version": "1.46.1",
+       "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.46.1.tgz",
+diff --git a/package.json b/package.json
+index 6d569ad9..61e8d892 100644
+--- a/package.json
++++ b/package.json
+@@ -73,7 +73,6 @@
+     "marked-katex-extension": "^5.1.1",
+     "marked-linkify-it": "^3.1.11",
+     "md5": "^2.3.0",
+-    "plausible-tracker": "^0.3.9",
+     "svelte": "^4.2.19",
+     "twemoji": "^14.0.2",
+     "zod": "^3.23.8"
+diff --git a/src/App.svelte b/src/App.svelte
+index 8161c390..4281ba61 100644
+--- a/src/App.svelte
++++ b/src/App.svelte
+@@ -1,6 +1,4 @@
+ <script lang="ts">
+-  import Plausible from "plausible-tracker";
+-
+   import * as router from "@app/lib/router";
+   import { unreachable } from "@app/lib/utils";
+ 
+@@ -28,12 +26,6 @@
+ 
+   void router.loadFromLocation();
+ 
+-  if (import.meta.env.PROD) {
+-    const plausible = Plausible({ domain: "app.radicle.xyz" });
+-
+-    plausible.enableAutoPageviews();
+-  }
+-
+   $: document.documentElement.setAttribute("data-codefont", $codeFont);
+   $: document.documentElement.setAttribute("data-theme", $theme);
+ </script>
+-- 
+2.46.0
+
diff --git a/third_party/radicle-explorer/default.nix b/third_party/radicle-explorer/default.nix
new file mode 100644
index 000000000000..7bf7dc3798d9
--- /dev/null
+++ b/third_party/radicle-explorer/default.nix
@@ -0,0 +1,66 @@
+# radicle-explorer is the web UI for Radicle.
+#
+# They have an upstream Nix derivation, but it only works with experimental
+# features Nix and is quite messy, so this is a copy of the relevant parts.
+{ lib, pkgs, ... }:
+
+let
+  twemoji-assets = pkgs.fetchFromGitHub {
+    owner = "twitter";
+    repo = "twemoji";
+    rev = "v14.0.2";
+    hash = "sha256-YoOnZ5uVukzi/6bLi22Y8U5TpplPzB7ji42l+/ys5xI=";
+  };
+
+  httpdSrc = pkgs.radicle-httpd.src;
+in
+lib.fix (self: pkgs.buildNpmPackage rec {
+  pname = "radicle-explorer";
+  version = (builtins.fromJSON (builtins.readFile "${src}/package.json")).version;
+
+  # source should be synced with the httpd, which is already in nixpkgs
+  src = pkgs.fetchgit {
+    inherit (httpdSrc) url rev;
+    hash = "sha256:09m13238h6j7g02r6332ihgyyzbjx90pgz14rz29pgv7936h6il8";
+  };
+
+  # This might change during nixpkgs bumps and will need updating. Need to fix
+  # upstream so that there is a normal, callable derivation.
+  npmDepsHash = "sha256:1hbrzfjkfc0q8qk03yi6qb9zqm57h7hnkn7fl0yxkrzbrljaljaz";
+
+  patches = [
+    ./0001-remove-dependency-on-plausible.patch
+  ];
+
+  postPatch = ''
+    patchShebangs --build ./scripts
+    mkdir -p "public/twemoji"
+    cp -t public/twemoji -r -- ${twemoji-assets}/assets/svg/*
+    : >scripts/install-twemoji-assets
+  '';
+  dontConfigure = true;
+  doCheck = false;
+
+  installPhase = ''
+    runHook preInstall
+    mkdir -p "$out"
+    cp -r -t "$out" build/*
+    runHook postInstall
+  '';
+
+  # Override the build-time configuration with other preferred seeds which are
+  # displayed on the landing page.
+  passthru.withPreferredSeeds = seeds:
+    let
+      originalConfig = builtins.fromJSON (builtins.readFile "${src}/config/default.json");
+      config = originalConfig // {
+        preferredSeeds = seeds;
+      };
+      newConfig = pkgs.writeText "local.json" (builtins.toJSON config);
+    in
+    self.overrideAttrs (_: {
+      preBuild = ''
+        cp ${newConfig} config/local.json
+      '';
+    });
+})
diff --git a/third_party/rust-crates/default.nix b/third_party/rust-crates/default.nix
index 697e47cddefc..a473a8346a6b 100644
--- a/third_party/rust-crates/default.nix
+++ b/third_party/rust-crates/default.nix
@@ -292,130 +292,4 @@ depot.nix.readTree.drvTargets rec{
     sha256 = "1kd047p8jv6mhmfzddjvfa2nwkfrb3l1wml6lfm51n1cr06cc9lz";
   };
 
-  libz-sys = buildRustCrate {
-    pname = "libz-sys";
-    version = "1.1.2";
-    sha256 = "1y7v6bkwr4b6yaf951p1ns7mx47b29ziwdd5wziaic14gs1gwq30";
-    buildDependencies = [
-      cc
-      pkg-config
-    ];
-  };
-
-  libgit2-sys = buildRustCrate {
-    pname = "libgit2-sys";
-    version = "0.16.2+1.7.2";
-    sha256 = "0bs446idbmg8s13jvb0ck6qmrskcdn2mp3d4mn9ggxbmiw4ryd3g";
-    dependencies = [
-      libc
-      libz-sys
-    ];
-    libPath = "lib.rs";
-    libName = "libgit2_sys";
-    # TODO: this should be available via `pkgs.defaultCrateOverrides`,
-    # I thought that was included by default?
-    nativeBuildInputs = [ pkg-config ];
-    buildInputs = [ pkgs.zlib pkgs.libgit2 ];
-    buildDependencies = [
-      cc
-      pkg-config
-    ];
-    env.LIBGIT2_NO_VENDOR = "1";
-  };
-
-  matches = buildRustCrate {
-    pname = "matches";
-    version = "0.1.8";
-    sha256 = "03hl636fg6xggy0a26200xs74amk3k9n0908rga2szn68agyz3cv";
-    libPath = "lib.rs";
-  };
-
-  percent-encoding = buildRustCrate {
-    pname = "percent-encoding";
-    version = "2.1.0";
-    sha256 = "0i838f2nr81585ckmfymf8l1x1vdmx6n8xqvli0lgcy60yl2axy3";
-    libPath = "lib.rs";
-  };
-
-  form_urlencoded = buildRustCrate {
-    pname = "form_urlencoded";
-    version = "1.0.1";
-    sha256 = "0rhv2hfrzk2smdh27walkm66zlvccnnwrbd47fmf8jh6m420dhj8";
-    dependencies = [
-      matches
-      percent-encoding
-    ];
-  };
-
-  tinyvec_macros = buildRustCrate {
-    pname = "tinyvec_macros";
-    version = "0.1.0";
-    sha256 = "0aim73hyq5g8b2hs9gjq2sv0xm4xzfbwp5fdyg1frljqzkapq682";
-  };
-
-  tinyvec = buildRustCrate {
-    pname = "tinyvec";
-    version = "1.2.0";
-    sha256 = "1c95nma20kiyrjwfsk7hzd5ir6yy4bm63fmfbfb4dm9ahnlvdp3y";
-    features = [ "alloc" ];
-    dependencies = [
-      tinyvec_macros
-    ];
-  };
-
-  unicode-normalization = buildRustCrate {
-    pname = "unicode-normalization";
-    version = "0.1.17";
-    sha256 = "0w4s0avzlf7pzcclhhih93aap613398sshm6jrxcwq0f9lhis11c";
-    dependencies = [
-      tinyvec
-    ];
-  };
-
-  unicode-bidi = buildRustCrate {
-    pname = "unicode-bidi";
-    version = "0.3.5";
-    sha256 = "193jzlxj1dfcms2381lyd45zh4ywlicj9lzcfpid1zbkmfarymkz";
-    dependencies = [
-      matches
-    ];
-  };
-
-  idna = buildRustCrate {
-    pname = "idna";
-    version = "0.2.3";
-    sha256 = "0hwypd0fpym9lmd4bbqpwyr5lhrlvmvzhi1vy9asc5wxwkzrh299";
-    dependencies = [
-      matches
-      unicode-normalization
-      unicode-bidi
-    ];
-  };
-
-  url = buildRustCrate {
-    pname = "url";
-    version = "2.2.1";
-    sha256 = "1ci1djafh83qhpzbmxnr9w5gcrjs3ghf8rrxdy4vklqyji6fvn5v";
-    dependencies = [
-      form_urlencoded
-      idna
-      matches
-      percent-encoding
-    ];
-  };
-
-
-  git2 = buildRustCrate {
-    pname = "git2";
-    edition = "2018";
-    version = "0.18.1";
-    sha256 = "1d1wm8cn37svyxgvzfapwilkkc9d2x7fcrgciwn8b2pv9aqz102k";
-    dependencies = [
-      bitflags
-      libc
-      libgit2-sys
-      log
-      url
-    ];
-  };
 }
diff --git a/third_party/sources/sources.json b/third_party/sources/sources.json
index 8844eddc9c15..eef1ffee9c98 100644
--- a/third_party/sources/sources.json
+++ b/third_party/sources/sources.json
@@ -5,10 +5,22 @@
         "homepage": "https://matrix.to/#/#agenix:nixos.org",
         "owner": "ryantm",
         "repo": "agenix",
-        "rev": "c2fc0762bbe8feb06a2e59a364fa81b3a57671c9",
-        "sha256": "1lpkwinlax40b7xgzspbkm9rsi4a1x48hxhixnni4irxxwnav0ah",
+        "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41",
+        "sha256": "1x8nd8hvsq6mvzig122vprwigsr3z2skanig65haqswn7z7amsvg",
         "type": "tarball",
-        "url": "https://github.com/ryantm/agenix/archive/c2fc0762bbe8feb06a2e59a364fa81b3a57671c9.tar.gz",
+        "url": "https://github.com/ryantm/agenix/archive/f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41.tar.gz",
+        "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+    },
+    "gitignore.nix": {
+        "branch": "master",
+        "description": "Nix functions for filtering local git sources",
+        "homepage": "",
+        "owner": "hercules-ci",
+        "repo": "gitignore.nix",
+        "rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
+        "sha256": "02wxkdpbhlm3yk5mhkhsp3kwakc16xpmsf2baw57nz1dg459qv8w",
+        "type": "tarball",
+        "url": "https://github.com/hercules-ci/gitignore.nix/archive/637db329424fd7e46cf4185293b9cc8c88c95394.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "home-manager": {
@@ -17,10 +29,10 @@
         "homepage": "https://nix-community.github.io/home-manager/",
         "owner": "nix-community",
         "repo": "home-manager",
-        "rev": "a7117efb3725e6197dd95424136f79147aa35e5b",
-        "sha256": "02q3ck1hjs8xzdhfikqxrnsfs9vh4p7rmdha3vbp6nkkdbdvhgg7",
+        "rev": "93435d27d250fa986bfec6b2ff263161ff8288cb",
+        "sha256": "0vf36nfm1l77493jsyc3xzjndd79ayrvzkpc7yzvgzirs766ggww",
         "type": "tarball",
-        "url": "https://github.com/nix-community/home-manager/archive/a7117efb3725e6197dd95424136f79147aa35e5b.tar.gz",
+        "url": "https://github.com/nix-community/home-manager/archive/93435d27d250fa986bfec6b2ff263161ff8288cb.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "impermanence": {
@@ -29,10 +41,10 @@
         "homepage": "",
         "owner": "nix-community",
         "repo": "impermanence",
-        "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
-        "sha256": "1mig6ns8l5iynsm6pfbnx2b9hmr592s1kqbw6gq1n25czdlcniam",
+        "rev": "e337457502571b23e449bf42153d7faa10c0a562",
+        "sha256": "0l242sa21jv53lkjh180dp5x9ip1blrz3gbks9m604kmk520csqb",
         "type": "tarball",
-        "url": "https://github.com/nix-community/impermanence/archive/a33ef102a02ce77d3e39c25197664b7a636f9c30.tar.gz",
+        "url": "https://github.com/nix-community/impermanence/archive/e337457502571b23e449bf42153d7faa10c0a562.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "naersk": {
@@ -41,10 +53,10 @@
         "homepage": "",
         "owner": "nmattia",
         "repo": "naersk",
-        "rev": "fa19d8c135e776dc97f4dcca08656a0eeb28d5c0",
-        "sha256": "1mif058gcbw5d5yixsmzalqlr0h9m9mmbsgv8v4r2mmsbw83k2x0",
+        "rev": "3fb418eaf352498f6b6c30592e3beb63df42ef11",
+        "sha256": "0v6ncaqm8q2mdv1jhkjjwi1sx4firlhjxpw4wachkwkriyjnkz5g",
         "type": "tarball",
-        "url": "https://github.com/nmattia/naersk/archive/fa19d8c135e776dc97f4dcca08656a0eeb28d5c0.tar.gz",
+        "url": "https://github.com/nmattia/naersk/archive/3fb418eaf352498f6b6c30592e3beb63df42ef11.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "napalm": {
@@ -53,10 +65,10 @@
         "homepage": "",
         "owner": "nix-community",
         "repo": "napalm",
-        "rev": "edcb26c266ca37c9521f6a97f33234633cbec186",
-        "sha256": "0ai1ax380nnpz0mbgbc5vdzafyjilcmdj7kgv087x2vagpprb4yy",
+        "rev": "e1babff744cd278b56abe8478008b4a9e23036cf",
+        "sha256": "04h62p4hxw7fhclki7hcn739hhig3rh9q4njp24j7bm0dk2kj8h6",
         "type": "tarball",
-        "url": "https://github.com/nix-community/napalm/archive/edcb26c266ca37c9521f6a97f33234633cbec186.tar.gz",
+        "url": "https://github.com/nix-community/napalm/archive/e1babff744cd278b56abe8478008b4a9e23036cf.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "nixpkgs": {
@@ -65,10 +77,10 @@
         "homepage": "",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "051f920625ab5aabe37c920346e3e69d7d34400e",
-        "sha256": "08lin51g5x2vv89rs6vmqxnyy8pfysh0wdp6mdxw6l86dpm2rbg2",
+        "rev": "2768c7d042a37de65bb1b5b3268fc987e534c49d",
+        "sha256": "17pikpqk1icgy4anadd9yg3plwfrsmfwv1frwm78jg2rf84jcmq2",
         "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/051f920625ab5aabe37c920346e3e69d7d34400e.tar.gz",
+        "url": "https://github.com/NixOS/nixpkgs/archive/2768c7d042a37de65bb1b5b3268fc987e534c49d.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "nixpkgs-stable": {
@@ -77,10 +89,10 @@
         "homepage": "",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "a2e1d0414259a144ebdc048408a807e69e0565af",
-        "sha256": "1jv90bz3s7j294fhpb29k735fg3xfs9z848szicqarpbz7wfg03g",
+        "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5",
+        "sha256": "1f5d2g1p6nfwycpmrnnmc2xmcszp804adp16knjvdkj8nz36y1fg",
         "type": "tarball",
-        "url": "https://github.com/NixOS/nixpkgs/archive/a2e1d0414259a144ebdc048408a807e69e0565af.tar.gz",
+        "url": "https://github.com/NixOS/nixpkgs/archive/205fd4226592cc83fd4c0885a3e4c9c400efabb5.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "rust-overlay": {
@@ -89,10 +101,10 @@
         "homepage": "",
         "owner": "oxalica",
         "repo": "rust-overlay",
-        "rev": "6dc3e45fe4aee36efeed24d64fc68b1f989d5465",
-        "sha256": "0vqgkzbfdj920lbm1dy8kylrv2gk4ard38lb3i20xvp2mp1d39n2",
+        "rev": "17cadbc36da05e75197d082decb382a5f4208e30",
+        "sha256": "0vh5nlmvig418d15w7yz3ls0x56jdwlvbs9kgr7ri0lsng2v2ykr",
         "type": "tarball",
-        "url": "https://github.com/oxalica/rust-overlay/archive/6dc3e45fe4aee36efeed24d64fc68b1f989d5465.tar.gz",
+        "url": "https://github.com/oxalica/rust-overlay/archive/17cadbc36da05e75197d082decb382a5f4208e30.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     },
     "rustsec-advisory-db": {
@@ -101,10 +113,10 @@
         "homepage": "https://rustsec.org",
         "owner": "RustSec",
         "repo": "advisory-db",
-        "rev": "af76d4423761499f954411bb3071dcc72e6b0450",
-        "sha256": "167qxr66j638km3z7zk2drjdr4bgqz77hr35vkwdp0lbafmd6y1c",
+        "rev": "c586bd65ec3543e2fe2f21e358f0645220822325",
+        "sha256": "17my60z1yg5yn9l4wp8a0gqwfyx2njai2nhghj3dkljhvkgsn30n",
         "type": "tarball",
-        "url": "https://github.com/RustSec/advisory-db/archive/af76d4423761499f954411bb3071dcc72e6b0450.tar.gz",
+        "url": "https://github.com/RustSec/advisory-db/archive/c586bd65ec3543e2fe2f21e358f0645220822325.tar.gz",
         "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
     }
 }