diff --git a/tor_install.sh b/tor_install.sh new file mode 100644 index 0000000..495bd06 --- /dev/null +++ b/tor_install.sh @@ -0,0 +1,128 @@ +#!/usr/bin/env bash +# SPDX-License-Identifier: CC0-1.0 +# Dedicated to the public domain under CC0 1.0 Universal. +# See https://creativecommons.org/publicdomain/zero/1.0/ +# This script is not affiliated with or endorsed by The Tor Project. + +set -Eeuo pipefail +IFS=$'\n\t' + +# ------------------------------- logging -------------------------------------- +# Plain ASCII, no icons or emojis. +c_green() { printf '\033[0;32m%s\033[0m\n' "$*"; } +c_yellow() { printf '\033[1;33m%s\033[0m\n' "$*"; } +c_red() { printf '\033[0;31m%s\033[0m\n' "$*"; } +log() { c_green "INFO: $*"; } +warn() { c_yellow "WARN: $*"; } +die() { c_red "ERROR: $*"; exit 1; } + +# Print a helpful line number on failure. +trap 'die "Error on or near line $LINENO. Exiting."' ERR + +# ------------------------------- root check ----------------------------------- +# We must be root to modify APT sources and install packages. +if [[ ${EUID:-0} -ne 0 ]]; then + if command -v sudo >/dev/null 2>&1; then + exec sudo -E -- "$0" "$@" + else + die "Please run as root (or install sudo)." + fi +fi + +# Make APT non-interactive and a bit more resilient. +export DEBIAN_FRONTEND=noninteractive +APT_FLAGS=(-y -o Dpkg::Use-Pty=0 -o Acquire::Retries=3 -o Acquire::http::No-Cache=true) + +# --------------------------- detect codename ---------------------------------- +# We need the Debian/Ubuntu codename (e.g., bookworm, bullseye, noble, jammy). +OS_ID='' CODENAME='' +if [[ -r /etc/os-release ]]; then + # shellcheck disable=SC1091 + . /etc/os-release + OS_ID="${ID:-}" + CODENAME="${VERSION_CODENAME:-}" +fi +if [[ -z ${CODENAME} ]]; then + if command -v lsb_release >/dev/null 2>&1; then + CODENAME="$(lsb_release -cs 2>/dev/null || true)" + fi +fi +[[ -z ${CODENAME} ]] && die "Could not determine distro codename. Aborting." + +log "Distro ID: ${OS_ID:-unknown}, Codename: ${CODENAME}" + +# ------------------------------ prerequisites --------------------------------- +# Minimal tools to fetch keys and manage repos. +log "Ensuring prerequisites..." +apt-get update "${APT_FLAGS[@]}" +apt-get install "${APT_FLAGS[@]}" --no-install-recommends \ + ca-certificates gnupg curl lsb-release + +# ------------------------ configure Tor Project repo -------------------------- +# This section is the whole point: always use the Tor Project APT repository. + +log "Configuring Tor Project APT repository..." + +# Create a dedicated system keyring directory if needed. +install -d -m 0755 /usr/share/keyrings + +# Download the Tor Project archive signing key to a temporary file. +# Official key fingerprint: +# A3C4 F0F9 79CA A22C DBA8 F512 EE8C BC9E 886D DD89 +KEY_URL="https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc" +TMP_KEY="$(mktemp)" +curl -fsSL "$KEY_URL" -o "$TMP_KEY" + +# Verify the fingerprint before trusting the key. +FPR_EXPECTED="A3C4 F0F9 79CA A22C DBA8 F512 EE8C BC9E 886D DD89" +FPR_SEEN="$(gpg --show-keys --with-colons "$TMP_KEY" 2>/dev/null | awk -F: '/^fpr:/ {print $10; exit}' | sed 's/.\{4\}/& /g' | sed 's/ $//')" +if [[ "$FPR_SEEN" != "$FPR_EXPECTED" ]]; then + rm -f "$TMP_KEY" + die "Tor Project key fingerprint mismatch. Expected '$FPR_EXPECTED' but saw '$FPR_SEEN'." +fi + +# Install the verified key into a dedicated keyring file. +gpg --dearmor < "$TMP_KEY" > /usr/share/keyrings/torproject-org-archive.gpg +rm -f "$TMP_KEY" + +# Write the source list entry, pinned to the keyring. +# Note: if the Tor Project does not publish packages for your codename or arch, +# APT operations will fail, which is intentional for this script. +SRC_LINE="deb [signed-by=/usr/share/keyrings/torproject-org-archive.gpg] https://deb.torproject.org/torproject.org ${CODENAME} main" +SRC_FILE="/etc/apt/sources.list.d/torproject-org.list" +printf '%s\n' "$SRC_LINE" > "$SRC_FILE" + +# Refresh APT indices from the Tor Project repo. +apt-get update "${APT_FLAGS[@]}" + +# ------------------------------- installation --------------------------------- +# Install Tor from the Tor Project repository, plus their keyring package +# to keep keys maintained via APT. +log "Installing tor and deb.torproject.org-keyring from the Tor Project repo..." +apt-get install "${APT_FLAGS[@]}" --no-install-recommends tor deb.torproject.org-keyring + +# ------------------------------- post-install --------------------------------- +# Show version and attempt to enable and start the service on systemd systems. +if command -v tor >/dev/null 2>&1; then + log "Tor installed. Version:" + tor --version || true + + if command -v systemctl >/dev/null 2>&1; then + # Try common service names. Ignore errors if a given unit does not exist. + systemctl enable --now tor.service >/dev/null 2>&1 || true + systemctl enable --now tor@default.service >/dev/null 2>&1 || true + + # Print a simple status hint if neither service is active. + if ! systemctl is-active --quiet tor.service 2>/dev/null \ + && ! systemctl is-active --quiet tor@default.service 2>/dev/null; then + warn "Tor service is not active. You can start it with:" + warn " systemctl start tor.service" + warn " or" + warn " systemctl start tor@default.service" + fi + else + warn "Systemd not detected. Use your init system to manage the Tor daemon." + fi +else + die "Tor did not install correctly." +fi