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.
273 lines
8.0 KiB
Bash
Executable File
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
|