Furst/install.sh
nak0x 2b017197d0 Add a usage guide and an install script
GUIDE.md covers the parts a README does not: what happens when you click a
link, making the proxy stick, the handful of commands worth knowing, and
what to do when a page comes out wrong — which it will, since extraction is
heuristic.

install.sh builds the workspace, installs the four binaries, writes starter
configs, fetches the blocklists, sets up a systemd user service for the
proxy, and offers to register furst as the default browser. Every
system-changing step can be skipped, and the default-browser change is
prompted rather than assumed; a non-interactive run declines it.

Re-running never overwrites a config that already exists, so it is safe
after editing rules. --uninstall removes binaries, service and desktop
entry while keeping configs, and --purge takes those too.

The script passes --workspace to cargo, which is the mistake to avoid here:
the root package is only furst, so a bare build silently skips the other
three binaries.
2026-09-06 23:19:34 +02:00

273 lines
8.0 KiB
Bash
Executable File

#!/usr/bin/env bash
#
# Build and install the furst toolset. Safe to re-run: it never overwrites a
# config you have edited, and every system-changing step can be skipped.
#
# ./install.sh --help
set -euo pipefail
PREFIX="${HOME}/.local/bin"
CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/furst"
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/furst"
UNIT_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/systemd/user"
DESKTOP="${XDG_DATA_HOME:-$HOME/.local/share}/applications/furst.desktop"
BINARIES=(furst furst-read furst-serve furst-proxy)
HANDLERS=(mpv yt-dlp zathura nsxiv surf firefox)
MODE=install
DO_BUILD=1
DO_LISTS=1
DO_SERVICE=1
DO_BROWSER=ask
PURGE=0
if [ -t 1 ]; then
B=$'\033[1m'; DIM=$'\033[2m'; GREEN=$'\033[32m'; YELLOW=$'\033[33m'; RED=$'\033[31m'; R=$'\033[0m'
else
B=; DIM=; GREEN=; YELLOW=; RED=; R=
fi
step() { printf '\n%s==>%s %s%s%s\n' "$GREEN" "$R" "$B" "$1" "$R"; }
info() { printf ' %s\n' "$1"; }
skip() { printf ' %s%s%s\n' "$DIM" "$1" "$R"; }
warn() { printf ' %s!%s %s\n' "$YELLOW" "$R" "$1"; }
die() { printf '\n%serror:%s %s\n' "$RED" "$R" "$1" >&2; exit 1; }
usage() {
cat <<'EOF'
install.sh — build and install the furst toolset
USAGE
./install.sh [OPTIONS]
OPTIONS
--prefix <dir> where to install binaries (default ~/.local/bin)
--no-build install from an existing target/release build
--no-lists skip downloading the proxy blocklists
--no-service skip the systemd user service for the proxy
--no-default-browser do not register furst as the default browser
-y, --yes answer every prompt with yes
--uninstall remove binaries, service and desktop entry
--purge with --uninstall, also remove configs and caches
-h, --help this
The install never overwrites an existing config file, so re-running it after
editing your rules is safe.
EOF
}
while [ $# -gt 0 ]; do
case "$1" in
--prefix) PREFIX="${2:?--prefix needs a directory}"; shift 2 ;;
--no-build) DO_BUILD=0; shift ;;
--no-lists) DO_LISTS=0; shift ;;
--no-service) DO_SERVICE=0; shift ;;
--no-default-browser) DO_BROWSER=no; shift ;;
-y|--yes) DO_BROWSER=yes; shift ;;
--uninstall) MODE=uninstall; shift ;;
--purge) PURGE=1; shift ;;
-h|--help) usage; exit 0 ;;
*) die "unknown option $1 (--help for usage)" ;;
esac
done
# ---------------------------------------------------------------- uninstall ---
if [ "$MODE" = uninstall ]; then
step "Removing the service"
if command -v systemctl >/dev/null 2>&1; then
systemctl --user disable --now furst-proxy.service 2>/dev/null || true
rm -f "$UNIT_DIR/furst-proxy.service" "$UNIT_DIR/furst-serve.service"
systemctl --user daemon-reload 2>/dev/null || true
info "stopped and removed"
else
skip "no systemctl"
fi
step "Removing binaries"
for b in "${BINARIES[@]}"; do
if [ -e "$PREFIX/$b" ]; then rm -f "$PREFIX/$b"; info "removed $PREFIX/$b"; fi
done
step "Removing the desktop entry"
rm -f "$DESKTOP"
info "removed $DESKTOP"
warn "your default browser is now unset — pick one in your desktop settings,"
warn "or run: xdg-settings set default-web-browser firefox.desktop"
if [ "$PURGE" = 1 ]; then
step "Purging configs and caches"
rm -rf "$CONFIG_DIR" "$CACHE_DIR" "${XDG_CACHE_HOME:-$HOME/.cache}/furst-read"
info "removed $CONFIG_DIR and caches"
else
step "Kept"
info "$CONFIG_DIR and caches — remove with --uninstall --purge"
fi
printf '\n%sUninstalled.%s\n\n' "$B" "$R"
exit 0
fi
# ------------------------------------------------------------------- build ---
cd "$(dirname "$0")"
if [ "$DO_BUILD" = 1 ]; then
step "Building"
command -v cargo >/dev/null 2>&1 || die "cargo not found — install rust first"
info "$(cargo --version)"
# --workspace matters: the root package is only furst, so a bare build would
# silently skip the other three.
cargo build --release --workspace
info "built 4 binaries"
else
step "Skipping build"
fi
for b in "${BINARIES[@]}"; do
[ -x "target/release/$b" ] || die "target/release/$b missing — run without --no-build"
done
# ----------------------------------------------------------------- install ---
step "Installing to $PREFIX"
mkdir -p "$PREFIX"
for b in "${BINARIES[@]}"; do
install -m755 "target/release/$b" "$PREFIX/$b"
info "$b $(du -h "$PREFIX/$b" | cut -f1)"
done
case ":$PATH:" in
*":$PREFIX:"*) ;;
*) warn "$PREFIX is not on your \$PATH — add this to ~/.zshrc:"
warn " export PATH=\"$PREFIX:\$PATH\"" ;;
esac
export PATH="$PREFIX:$PATH"
# ----------------------------------------------------------------- configs ---
step "Writing starter configs"
mkdir -p "$CONFIG_DIR"
init_config() {
local file="$1" cmd="$2"
if [ -e "$CONFIG_DIR/$file" ]; then
skip "$file already exists, left alone"
else
"$PREFIX/$cmd" --init >/dev/null && info "$file"
fi
}
init_config rules.toml furst
init_config home.toml furst-serve
init_config proxy.toml furst-proxy
# ---------------------------------------------------------------- handlers ---
step "Checking handlers"
missing=()
for h in "${HANDLERS[@]}"; do
command -v "$h" >/dev/null 2>&1 || missing+=("$h")
done
if [ ${#missing[@]} -eq 0 ]; then
info "all present"
else
warn "not installed: ${missing[*]}"
warn "rules naming them fall through to the next handler; install with:"
warn " sudo pacman -S mpv yt-dlp zathura zathura-pdf-mupdf nsxiv surf"
fi
# --------------------------------------------------------------- blocklists ---
if [ "$DO_LISTS" = 1 ]; then
step "Fetching blocklists"
if "$PREFIX/furst-proxy" --update 2>&1 | sed 's/^/ /'; then :; else
warn "could not fetch — the proxy will run with only its built-in rules"
fi
else
step "Skipping blocklists"
skip "run 'furst-proxy --update' later"
fi
# ------------------------------------------------------------------ service ---
if [ "$DO_SERVICE" = 1 ] && command -v systemctl >/dev/null 2>&1; then
step "Installing the proxy service"
mkdir -p "$UNIT_DIR"
cat > "$UNIT_DIR/furst-proxy.service" <<EOF
[Unit]
Description=furst filtering proxy
After=network-online.target
[Service]
ExecStart=$PREFIX/furst-proxy
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
EOF
# The reader starts itself on demand, so this one is offered, not enabled.
cat > "$UNIT_DIR/furst-serve.service" <<EOF
[Unit]
Description=furst reader server (optional; it also starts on demand)
[Service]
ExecStart=$PREFIX/furst-serve
Restart=on-failure
RestartSec=5
[Install]
WantedBy=default.target
EOF
systemctl --user daemon-reload 2>/dev/null || true
if systemctl --user enable --now furst-proxy.service 2>/dev/null; then
info "furst-proxy.service enabled and started"
else
warn "could not start the service — run it yourself with: furst-proxy &"
fi
skip "furst-serve.service written but not enabled (the reader autostarts)"
else
step "Skipping the service"
skip "start the proxy yourself: furst-proxy &"
fi
# ---------------------------------------------------------- default browser ---
step "Default browser"
if [ "$DO_BROWSER" = ask ]; then
if [ -t 0 ]; then
printf ' Register furst as your default browser? [y/N] '
read -r reply
case "$reply" in [yY]*) DO_BROWSER=yes ;; *) DO_BROWSER=no ;; esac
else
DO_BROWSER=no
fi
fi
if [ "$DO_BROWSER" = yes ]; then
"$PREFIX/furst" --install 2>&1 | sed 's/^/ /'
else
skip "not changed — run 'furst --install' when you want it"
fi
# -------------------------------------------------------------------- done ---
cat <<EOF
${B}Installed.${R}
Add to ~/.zshrc so everything uses the proxy:
eval "\$(furst-proxy --env)"
Firefox needs it set manually: Settings > Network Settings > Manual,
127.0.0.1 port 8228, and tick "Also use this proxy for HTTPS".
Reader home http://127.0.0.1:7714/
Proxy status http://furst.proxy/
Read ${B}GUIDE.md${R} next. The command to remember is:
furst --explain <url>
EOF