Files
rpi-tor-relay-panel/install.sh
2025-11-07 09:47:03 +01:00

192 lines
5.1 KiB
Bash

#!/usr/bin/env bash
set -euo pipefail
C_RESET="\033[0m"; C_DIM="\033[2m"; C_BOLD="\033[1m"
C_RED="\033[31m"; C_GRN="\033[32m"; C_BLU="\033[34m"; C_YEL="\033[33m"
info(){ echo -e "${C_BLU}${C_RESET} $*"; }
ok(){ echo -e "${C_GRN}${C_RESET} $*"; }
warn(){ echo -e "${C_YEL}!${C_RESET} $*"; }
fail(){ echo -e "${C_RED}${C_RESET} $*"; }
if [[ $EUID -ne 0 ]]; then fail "Run as root (sudo)."; exit 1; fi
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PANEL_ROOT="/var/www/torpanel"
PANEL_PUBLIC="$PANEL_ROOT/public"
STATE_DIR="/var/lib/torpanel"
LOG_DIR="/var/log/torpanel"
ETC_APP="/etc/torpanel"
TOR_ETC="/etc/tor"
TOR_TORRC_D="$TOR_ETC/torrc.d"
TOR_PANEL_CONF="$TOR_TORRC_D/99-torpanel.conf"
NGX_SITE_AVAIL="/etc/nginx/sites-available/torpanel"
NGX_SITE_ENABL="/etc/nginx/sites-enabled/torpanel"
SUDOERS_FILE="/etc/sudoers.d/torpanel"
COLLECTOR_SRC="$SCRIPT_DIR/bin/torpanel-collect.py"
COLLECTOR_BIN="/usr/local/bin/torpanel-collect.py"
SVC="/etc/systemd/system/torpanel-collector.service"
TIMER="/etc/systemd/system/torpanel-collector.timer"
export DEBIAN_FRONTEND=noninteractive
echo -e "${C_BOLD}Installing TorPanel...${C_RESET}"
info "Updating apt and installing packages"
apt-get update -y >/dev/null
apt-get install -y --no-install-recommends \
tor tor-geoipdb nginx rsync \
php-fpm php-cli php-json php-curl php-zip php-common php-opcache \
python3 >/dev/null
ok "Packages installed"
PHPV=$(php -r 'echo PHP_MAJOR_VERSION.".".PHP_MINOR_VERSION;')
PHP_FPM_SVC="php${PHPV}-fpm"
PHP_SOCK="/run/php/php${PHPV}-fpm.sock"
ln -sf "$PHP_SOCK" /run/php/php-fpm.sock || true
info "Preparing directories"
install -d "$PANEL_PUBLIC" "$STATE_DIR" "$LOG_DIR" "$ETC_APP"
touch "$STATE_DIR/stats.json"
rsync -a --delete "$SCRIPT_DIR/web/" "$PANEL_PUBLIC/"
chown -R www-data:www-data "$PANEL_ROOT" "$STATE_DIR" "$LOG_DIR"
chmod 750 "$PANEL_ROOT" "$STATE_DIR" "$LOG_DIR"
chown root:www-data "$ETC_APP"; chmod 770 "$ETC_APP"
ok "Web files deployed"
info "Writing Nginx site"
cat > "$NGX_SITE_AVAIL" <<'NGINX'
server {
listen 80 default_server;
server_name _;
root /var/www/torpanel/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php-fpm.sock;
}
location ~ /\. {
deny all;
}
}
NGINX
rm -f /etc/nginx/sites-enabled/default || true
ln -sf "$NGX_SITE_AVAIL" "$NGX_SITE_ENABL"
ok "Nginx site enabled"
info "Writing torrc defaults"
install -d "$TOR_TORRC_D"
cat > "$TOR_PANEL_CONF" <<'TORRC'
## --- Managed by TorPanel ---
SocksPort 0
ORPort 9001
ExitRelay 0
ExitPolicy reject *:*
Nickname RaspberryRelay
ContactInfo contact@admin.com
BandwidthRate 5 MB
BandwidthBurst 10 MB
AccountingMax 100 GB
AccountingStart month 1 00:00
ControlPort 0
ControlSocket /run/tor/control
CookieAuthentication 1
CookieAuthFileGroupReadable 1
# --- End TorPanel block ---
TORRC
ok "torrc written"
info "Setting permissions for Tor managed config"
chown root:www-data "$TOR_TORRC_D"; chmod 775 "$TOR_TORRC_D"
chown root:www-data "$TOR_PANEL_CONF"; chmod 664 "$TOR_PANEL_CONF"
ok "Permissions applied"
info "Granting www-data access to Tor cookie"
usermod -aG debian-tor www-data || true
ok "Permissions set"
info "Allowing www-data to control tor (limited)"
cat > "$SUDOERS_FILE" <<'SUD'
www-data ALL=NOPASSWD:/bin/systemctl reload tor, /bin/systemctl restart tor, /bin/systemctl start tor, /bin/systemctl stop tor
SUD
chmod 440 "$SUDOERS_FILE"
ok "Sudoers entry created"
info "Installing collector"
install -m 0755 "$COLLECTOR_SRC" "$COLLECTOR_BIN"
chown www-data:www-data "$COLLECTOR_BIN"
cat > "$SVC" <<'UNIT'
[Unit]
Description=TorPanel minute collector
After=tor.service
Wants=tor.service
[Service]
Type=oneshot
User=www-data
Group=www-data
SupplementaryGroups=debian-tor
ExecStart=/usr/bin/env python3 /usr/local/bin/torpanel-collect.py
NoNewPrivileges=yes
ProtectSystem=strict
ProtectHome=yes
ProtectClock=yes
ProtectHostname=yes
ProtectKernelLogs=yes
ProtectKernelModules=yes
ProtectKernelTunables=yes
PrivateTmp=yes
PrivateDevices=yes
PrivateUsers=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
UMask=0077
ReadWriteDirectories=/var/lib/torpanel
ReadOnlyPaths=/run/tor /etc/tor
RestrictAddressFamilies=AF_UNIX
SystemCallFilter=@system-service
CapabilityBoundingSet=
[Install]
WantedBy=timers.target
UNIT
cat > "$TIMER" <<'TIMER'
[Unit]
Description=Run TorPanel collector every minute
[Timer]
OnBootSec=30sec
OnUnitActiveSec=60sec
AccuracySec=15sec
Persistent=true
[Install]
WantedBy=timers.target
TIMER
ok "Systemd units installed"
info "Restarting services"
systemctl daemon-reload
systemctl enable --now tor
systemctl enable "$PHP_FPM_SVC" nginx >/dev/null
systemctl restart "$PHP_FPM_SVC"
systemctl restart nginx
systemctl enable --now torpanel-collector.timer
ok "Services running"
IP=$(hostname -I 2>/dev/null | awk '{print $1}')
echo
echo -e "${C_BOLD}All set!${C_RESET}"
echo -e " URL: ${C_GRN}http://$IP/${C_RESET}"
echo -e " First run: you'll see a setup page to create the admin user."
echo -e " Tip: forward ${C_BOLD}TCP/9001${C_RESET} to your Pi for a publicly reachable relay."