feat(extras): add silent-send module + new extras category

Adds services/silent-send.sh — installs the Silent Send browser extension
(client-side PII redaction for AI chat). Non-docker module: installs git +
Node.js >=18 (NodeSource) + npm, clones outis1one/silent-send to ~/silent-send,
runs npm install (readies web-ext for Firefox build/sign), optionally builds a
signed Firefox .xpi, and prints per-browser load/build instructions. README
written to the checkout.

Introduces a new 'extras' category for non-docker add-ons pulled from other
repos, wired into setup.sh CATEGORY_ORDER (gaming -> extras -> backup) with an
is_installed marker. MODULAR.md groups list updated.

Bumps version to 0.9.9.
This commit is contained in:
Claude
2026-06-03 18:11:07 +00:00
parent d9b19b5f56
commit 527808d610
5 changed files with 234 additions and 3 deletions
+15
View File
@@ -4,6 +4,21 @@ All notable changes to this project. Versions follow `MAJOR.MINOR.PATCH`.
The project is pre-1.0 while the modular system reaches parity with the
monolithic `ubuntu-post-install-*.sh` scripts.
## [0.9.9] - 2026-06-03
### Added
- **New `extras` category** for non-Docker add-ons sourced from other repos —
things that build/install on the host instead of running as a container.
Inserted into `CATEGORY_ORDER` between `gaming` and `backup`.
- `services/silent-send.sh` *(extras)* — installs the **Silent Send** browser
extension (redacts PII before it's sent to AI chatbots). Installs the build
toolchain (git, Node.js ≥18 via NodeSource, npm), clones
`outis1one/silent-send` to `~/silent-send`, runs `npm install` so the Firefox
build/sign tooling (`web-ext`) is ready, optionally builds a signed Firefox
`.xpi` (with Mozilla API creds), and prints load-unpacked / build instructions
per browser. README written to the checkout. No server/container.
- `is_installed` marker for `silent-send` (checks `~/silent-send/.git`).
## [0.9.8] - 2026-06-03
### Added
+4 -1
View File
@@ -72,7 +72,10 @@ single shared compose file.
## Groups
`base` · `homelab` · `utilities` · `media` · `cameras` · `gaming` · `backup`.
`base` · `homelab` · `utilities` · `media` · `cameras` · `gaming` · `extras` ·
`backup`. `extras` holds non-Docker add-ons pulled from other repos (e.g. the
`silent-send` browser extension) — things that install/build on the host rather
than running as a container, so this script stays a single entry point for them.
The guided menu (`sudo ./setup.sh`) shows the **required** packages first with a
cancel option, then offers **Caddy** (most services proxy through it), then a
**category menu you loop through** — pick a category, tick services (already
+1 -1
View File
@@ -1 +1 @@
0.9.8
0.9.9
+212
View File
@@ -0,0 +1,212 @@
#!/bin/bash
# services/silent-send.sh — Silent Send browser extension (PII redaction for AI chat).
# Part of the modular post-install system (sourced by setup.sh).
#
# NON-DOCKER module. Silent Send is a browser extension (Chrome/Brave/Firefox/
# Safari) that intercepts personal info before it's sent to AI chatbots and
# swaps in user-defined substitutes — entirely client-side, no server/container.
#
# Because it ships as source you load into a browser, this module:
# 1. installs the build toolchain (git, Node.js >= 18, npm),
# 2. clones the repo to ~/silent-send (or a path you choose),
# 3. runs `npm install` so the Firefox build/sign tooling (web-ext) is ready,
# 4. optionally builds a signed Firefox .xpi (needs free Mozilla API creds),
# 5. prints exactly how to load/build it in each browser.
#
# Source: https://github.com/outis1one/silent-send
register_service silent-send extras "Browser extension: redact PII before it reaches AI chatbots"
install_silent-send() {
# Non-docker — no require_docker.
local SS_REPO="https://github.com/outis1one/silent-send.git"
local SS_DIR="$ACTUAL_HOME/silent-send"
cat << "EOF"
╔═══════════════════════════════════════════════════════╗
║ ║
║ SILENT SEND ║
║ Redact PII before it reaches AI chatbots ║
(browser extension — Chrome / Brave / Firefox)
║ ║
╚═══════════════════════════════════════════════════════╝
EOF
echo ""
echo " A browser extension that intercepts names, emails, secrets and other"
echo " personal data before it's sent to AI services, swapping in your own"
echo " substitutes. All client-side — there is no server or container."
echo ""
if [ "$DRY_RUN" = true ]; then
echo "[DRY-RUN] silent-send install would:"
echo " - Install build deps: git, Node.js >= 18 (NodeSource 22.x), npm"
echo " - Clone $SS_REPO into $SS_DIR (or update if already present)"
echo " - Run 'npm install' in $SS_DIR (Firefox build/sign tooling: web-ext)"
echo " - Optionally build a signed Firefox .xpi (needs Mozilla API creds)"
echo " - Print load-unpacked + build/sign instructions for each browser"
return 0
fi
# ── Clone location ────────────────────────────────────────────────────────
prompt_text " Clone location [$SS_DIR]:" "$SS_DIR" SS_DIR
SS_DIR="${SS_DIR/#\~/$ACTUAL_HOME}"
SS_DIR="${SS_DIR%/}"
# ── 1. git ─────────────────────────────────────────────────────────────────
if ! command -v git >/dev/null 2>&1; then
log_info "Installing git..."
apt-get install -y git >/dev/null 2>&1 || { log_error "Failed to install git."; return 1; }
fi
log_success "git: $(git --version | awk '{print $3}')"
# ── 2. Node.js >= 18 + npm (needed to build/sign for Firefox & Safari) ──────
local NODE_MAJOR=0
command -v node >/dev/null 2>&1 && NODE_MAJOR=$(node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1)
if ! [ "$NODE_MAJOR" -ge 18 ] 2>/dev/null; then
log_warning "Node.js >= 18 required for building/signing (found: $(node -v 2>/dev/null || echo none))."
local INSTALL_NODE=""
prompt_yn " Install Node.js 22 LTS from NodeSource now? (y/n):" "y" INSTALL_NODE
if [ "$INSTALL_NODE" = "y" ] || [ "$INSTALL_NODE" = "Y" ]; then
log_info "Installing Node.js 22 LTS..."
curl -fsSL https://deb.nodesource.com/setup_22.x | bash - >/dev/null 2>&1
apt-get install -y nodejs >/dev/null 2>&1
NODE_MAJOR=$(node -v 2>/dev/null | sed 's/^v//' | cut -d. -f1)
fi
fi
if [ "$NODE_MAJOR" -ge 18 ] 2>/dev/null; then
log_success "Node.js: $(node -v) npm: $(npm -v 2>/dev/null || echo '?')"
else
log_warning "Node.js < 18 — Chrome 'load unpacked' still works, but the Firefox"
log_warning "signed build won't. Install Node 18+ later, then run 'npm install' in $SS_DIR."
fi
# ── 3. Clone / update the repo ──────────────────────────────────────────────
if [ -d "$SS_DIR/.git" ]; then
log_info "Updating existing checkout in $SS_DIR..."
git -C "$SS_DIR" pull --ff-only || log_warning "Could not fast-forward — keeping current checkout."
else
log_info "Cloning $SS_REPO$SS_DIR..."
git clone --depth 1 "$SS_REPO" "$SS_DIR" || { log_error "Clone failed."; return 1; }
fi
log_success "Source ready at $SS_DIR"
# ── 4. npm install (build/sign tooling: web-ext) ────────────────────────────
if command -v npm >/dev/null 2>&1; then
log_info "Installing npm dependencies (this readies the Firefox build/sign tooling)..."
( cd "$SS_DIR" && npm install ) \
|| log_warning "npm install reported errors — Chrome 'load unpacked' still works without it."
fi
# ── 5. Optional: build a signed Firefox .xpi ────────────────────────────────
# Needs free Mozilla API credentials. Skipped in unattended mode.
if [ "$UNATTENDED" != true ] && [ "$NODE_MAJOR" -ge 18 ] 2>/dev/null; then
echo ""
local DO_FF=""
prompt_yn " Build a signed Firefox .xpi now? (needs free Mozilla API creds) (y/n):" "n" DO_FF
if [ "$DO_FF" = "y" ] || [ "$DO_FF" = "Y" ]; then
echo ""
echo " Get credentials (free) at:"
echo " https://addons.mozilla.org/developers/addon/api/key/"
echo ""
local FF_KEY="" FF_SECRET=""
prompt_text " WEB_EXT_API_KEY (e.g. user:12345678:901), blank to skip:" "" FF_KEY
prompt_text " WEB_EXT_API_SECRET, blank to skip:" "" FF_SECRET
if [ -n "$FF_KEY" ] && [ -n "$FF_SECRET" ]; then
cat > "$SS_DIR/.env" << ENVEOF
WEB_EXT_API_KEY="$FF_KEY"
WEB_EXT_API_SECRET="$FF_SECRET"
ENVEOF
chmod 600 "$SS_DIR/.env"
log_info "Signing (first run takes 1-5 min)..."
if ( cd "$SS_DIR" && npm run sign:firefox ); then
log_success "Signed .xpi written to $SS_DIR/dist/firefox-signed/"
else
log_warning "Signing failed — check the output above. You can retry: (cd $SS_DIR && npm run sign:firefox)"
fi
else
echo " Skipping Firefox signing (no credentials entered)."
fi
fi
fi
# ── 6. Hand the checkout back to the user ───────────────────────────────────
chown -R "$ACTUAL_USER:$ACTUAL_USER" "$SS_DIR" 2>/dev/null || true
# ── 7. README ───────────────────────────────────────────────────────────────
write_readme "$SS_DIR" << MD
# Silent Send
Browser extension that intercepts personal information (names, emails,
usernames, hostnames, phone numbers, API keys, tokens, SSNs, credit cards…)
before it's sent to AI chatbots, swapping in your own substitutes. Everything
runs client-side in the browser — there is no server or container.
Source checkout: \`$SS_DIR\` · Upstream: https://github.com/outis1one/silent-send
## Load it in your browser
### Chrome / Brave (no build needed)
1. Open \`chrome://extensions/\` (or \`brave://extensions/\`)
2. Turn on **Developer mode** (top-right)
3. **Load unpacked** → select \`$SS_DIR\`
4. Refresh any open AI chat tabs after code updates
### Firefox (signed, persistent)
A signed \`.xpi\` is required for a permanent install:
\`\`\`bash
cd $SS_DIR
cp .env.example .env # then add your Mozilla API key/secret
npm run sign:firefox # → dist/firefox-signed/*.xpi
\`\`\`
Open the \`.xpi\` in Firefox (File → Open File) to install.
Temporary test session (no signing): \`npm run run:firefox\`.
### Safari (macOS only)
\`\`\`bash
npm install && ./build-safari.sh
open "safari-build/Silent Send.xcodeproj" # then Product → Run in Xcode
\`\`\`
## Updating
\`\`\`bash
cd $SS_DIR && git pull && npm install
\`\`\`
Then reload the extension (Chrome/Brave: the reload icon on the extensions
page; Firefox: re-sign and re-open the new .xpi).
## Configure
Use the extension's popup/options UI to set your identity, substitution
mappings, custom domains, and to import/export your config.
MD
# ── 8. Summary ──────────────────────────────────────────────────────────────
echo ""
echo "═══════════════════════════════════════════════════════"
echo " SILENT SEND — READY"
echo "═══════════════════════════════════════════════════════"
echo ""
echo " Source checkout: $SS_DIR"
echo ""
# Note which browsers are present to point the user at the right steps.
local _found=()
command -v google-chrome >/dev/null 2>&1 || command -v google-chrome-stable >/dev/null 2>&1 && _found+=("Chrome")
command -v brave-browser >/dev/null 2>&1 && _found+=("Brave")
command -v chromium >/dev/null 2>&1 || command -v chromium-browser >/dev/null 2>&1 && _found+=("Chromium")
command -v firefox >/dev/null 2>&1 && _found+=("Firefox")
if [ "${#_found[@]}" -gt 0 ]; then
echo " Browsers detected on this machine: ${_found[*]}"
else
echo " No browser detected here — load the extension on whichever machine"
echo " has your browser (the checkout above is what you point it at)."
fi
echo ""
echo " Chrome / Brave → chrome://extensions → Developer mode → Load unpacked"
echo " → select $SS_DIR"
echo " Firefox → cd $SS_DIR && cp .env.example .env (add Mozilla creds)"
echo " → npm run sign:firefox → open dist/firefox-signed/*.xpi"
echo ""
echo " Full instructions: $SS_DIR/README.md"
echo ""
log_success "Silent Send installed. Load it in your browser to start redacting."
}
+2 -1
View File
@@ -20,7 +20,7 @@ set -uo pipefail
HERE="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Category display order (groups not listed here are appended alphabetically).
CATEGORY_ORDER=(base homelab utilities media cameras gaming backup)
CATEGORY_ORDER=(base homelab utilities media cameras gaming extras backup)
# Service ordering hint within a category (lower = earlier). Default 50.
declare -A SERVICE_PRIORITY=( [caddy]=1 [crowdsec]=2 [authelia]=3 )
@@ -79,6 +79,7 @@ is_installed() {
base) command -v ncdu >/dev/null 2>&1 ;;
glow) command -v glow >/dev/null 2>&1 ;;
crowdsec) command -v cscli >/dev/null 2>&1 ;;
silent-send) [ -d "$ACTUAL_HOME/silent-send/.git" ] ;;
*) [ -e "$DOCKER_DIR/$1" ] ;;
esac
}