From 1af47c9a5caa9e994017202af328d6db28b0c2dd Mon Sep 17 00:00:00 2001 From: Harivansh Rathi Date: Wed, 1 Apr 2026 23:43:11 -0400 Subject: [PATCH] add agent-browser + BW browser auth sync for netty - Add chromium to netty system packages - Add home/agent-browser.nix: configures agent-browser to use nix chromium headless, installs via npm on first activation (Linux only) - Add scripts/sync-bw-browser-auth.sh: imports all BW login items into agent-browser encrypted auth vault via --password-stdin - Add just sync-browser-auth target --- home/agent-browser.nix | 28 +++++++++++ home/common.nix | 1 + hosts/netty/configuration.nix | 1 + justfile | 3 ++ scripts/sync-bw-browser-auth.sh | 87 +++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+) create mode 100644 home/agent-browser.nix create mode 100755 scripts/sync-bw-browser-auth.sh diff --git a/home/agent-browser.nix b/home/agent-browser.nix new file mode 100644 index 0000000..5e49d6d --- /dev/null +++ b/home/agent-browser.nix @@ -0,0 +1,28 @@ +{ + config, + lib, + pkgs, + hostConfig, + ... +}: +lib.mkIf (!hostConfig.isDarwin) { + # agent-browser user-level config: point at nix chromium, run headless + home.file.".agent-browser/config.json".text = builtins.toJSON { + executablePath = "${pkgs.chromium}/bin/chromium"; + args = "--no-sandbox,--disable-gpu,--disable-dev-shm-usage"; + }; + + # Install agent-browser globally via npm at activation time + home.activation.installAgentBrowser = lib.hm.dag.entryAfter [ "writeBoundary" ] '' + export PATH="${ + lib.makeBinPath [ + pkgs.nodejs_22 + pkgs.coreutils + ] + }:$PATH" + + if ! command -v agent-browser >/dev/null 2>&1; then + npm install -g agent-browser 2>/dev/null || true + fi + ''; +} diff --git a/home/common.nix b/home/common.nix index eba4f83..0fac942 100644 --- a/home/common.nix +++ b/home/common.nix @@ -3,6 +3,7 @@ _module.args.theme = import ../lib/theme.nix { inherit config; }; imports = [ + ./agent-browser.nix ./bat.nix ./eza.nix ./claude.nix diff --git a/hosts/netty/configuration.nix b/hosts/netty/configuration.nix index 07d179a..a91d9b0 100644 --- a/hosts/netty/configuration.nix +++ b/hosts/netty/configuration.nix @@ -108,6 +108,7 @@ in virtualisation.docker.enable = true; environment.systemPackages = packageSets.extras ++ [ + pkgs.chromium pkgs.php ]; diff --git a/justfile b/justfile index 8637f42..6b6b707 100644 --- a/justfile +++ b/justfile @@ -28,5 +28,8 @@ secrets-sync: ./scripts/render-bw-shell-secrets.sh ./scripts/restore-bw-files.sh +sync-browser-auth: + ./scripts/sync-bw-browser-auth.sh + switch-netty: ssh root@netty "nixos-rebuild switch --flake github:harivansh-afk/nix#netty --refresh" diff --git a/scripts/sync-bw-browser-auth.sh b/scripts/sync-bw-browser-auth.sh new file mode 100755 index 0000000..d019a79 --- /dev/null +++ b/scripts/sync-bw-browser-auth.sh @@ -0,0 +1,87 @@ +#!/usr/bin/env bash +set -euo pipefail +export NODE_NO_WARNINGS=1 + +if ! command -v bw >/dev/null 2>&1; then + echo "bw is not installed" >&2 + exit 1 +fi + +if ! command -v jq >/dev/null 2>&1; then + echo "jq is not installed" >&2 + exit 1 +fi + +if ! command -v agent-browser >/dev/null 2>&1; then + echo "agent-browser is not installed" >&2 + exit 1 +fi + +if [[ "${BW_SESSION:-}" == "" ]]; then + echo 'BW_SESSION is not set. Run: export BW_SESSION="$(bw unlock --raw)"' >&2 + exit 1 +fi + +bw sync --session "${BW_SESSION}" >/dev/null 2>&1 || true + +items_json="$(bw list items --session "${BW_SESSION}")" + +# type 1 = login items; filter to those with a username, password, and at least one URI +login_items="$(printf '%s' "${items_json}" | jq -c ' + [.[] | select( + .type == 1 and + .login.username != null and + .login.username != "" and + .login.password != null and + .login.password != "" and + (.login.uris // []) | length > 0 + )] +')" + +count="$(printf '%s' "${login_items}" | jq 'length')" +printf 'Found %d login items with credentials and URIs\n' "${count}" + +imported=0 +skipped=0 +failed=0 + +printf '%s' "${login_items}" | jq -c '.[]' | while IFS= read -r item; do + name="$(printf '%s' "${item}" | jq -r '.name')" + username="$(printf '%s' "${item}" | jq -r '.login.username')" + password="$(printf '%s' "${item}" | jq -r '.login.password')" + uri="$(printf '%s' "${item}" | jq -r '.login.uris[0].uri')" + + # Sanitize name for use as agent-browser profile name: + # keep only alphanumeric, hyphens, underscores; collapse runs; truncate + safe_name="$(printf '%s' "${name}" | tr -cs 'A-Za-z0-9_-' '-' | sed 's/^-//;s/-$//' | head -c 64)" + + if [[ -z "${safe_name}" ]]; then + printf 'SKIP (empty name after sanitize): %s\n' "${name}" + skipped=$((skipped + 1)) + continue + fi + + # Skip items whose URI is not an http(s) URL + case "${uri}" in + http://*|https://*) + ;; + *) + printf 'SKIP (non-http URI): %s -> %s\n' "${name}" "${uri}" + skipped=$((skipped + 1)) + continue + ;; + esac + + if printf '%s' "${password}" | agent-browser auth save "${safe_name}" \ + --url "${uri}" \ + --username "${username}" \ + --password-stdin >/dev/null 2>&1; then + printf 'OK: %s (%s)\n' "${safe_name}" "${uri}" + imported=$((imported + 1)) + else + printf 'FAIL: %s (%s)\n' "${safe_name}" "${uri}" >&2 + failed=$((failed + 1)) + fi +done + +printf '\nDone. imported=%d skipped=%d failed=%d\n' "${imported}" "${skipped}" "${failed}"