140 lines
4.5 KiB
Bash
Executable File
140 lines
4.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Run with sudo: sudo bash scripts/install-tor-onion.sh
|
|
# Regenerates Tor + nginx from scripts/onion-nodes.json, installs configs only when
|
|
# they changed, restores backed-up onion keys if any service dirs are missing, and
|
|
# starts/restarts nginx + Tor only when required.
|
|
|
|
set -euo pipefail
|
|
[[ "${EUID}" -eq 0 ]] || { echo "Run as root (sudo)."; exit 1; }
|
|
|
|
REPO="$(cd "$(dirname "$0")/.." && pwd)"
|
|
TORRC="/etc/tor/torrc"
|
|
TOR_INCLUDE="/etc/tor/cyberlux-nodes.conf"
|
|
|
|
if ! command -v node >/dev/null 2>&1; then
|
|
echo "node is required to run scripts/generate-onion-config.cjs"
|
|
exit 1
|
|
fi
|
|
|
|
install_if_changed() {
|
|
local src="$1" dest="$2" mode="$3"
|
|
if [[ -f "${dest}" ]] && cmp -s "${src}" "${dest}"; then
|
|
return 1
|
|
fi
|
|
install -m "${mode}" "${src}" "${dest}"
|
|
return 0
|
|
}
|
|
|
|
tor_is_active() {
|
|
systemctl is-active --quiet tor@default.service 2>/dev/null || systemctl is-active --quiet tor 2>/dev/null
|
|
}
|
|
|
|
nginx_is_active() {
|
|
systemctl is-active --quiet nginx 2>/dev/null
|
|
}
|
|
|
|
restart_tor() {
|
|
systemctl restart tor@default.service 2>/dev/null || systemctl restart tor
|
|
}
|
|
|
|
start_tor() {
|
|
systemctl start tor@default.service 2>/dev/null || systemctl start tor
|
|
}
|
|
|
|
node "${REPO}/scripts/generate-onion-config.cjs"
|
|
|
|
mkdir -p /etc/tor /etc/nginx/conf.d /etc/nginx/sites-available /etc/nginx/sites-enabled
|
|
touch "${TORRC}"
|
|
|
|
tor_changed=0
|
|
nginx_changed=0
|
|
|
|
if install_if_changed "${REPO}/tor/cyberlux-nodes.conf" "${TOR_INCLUDE}" 0644; then
|
|
tor_changed=1
|
|
fi
|
|
|
|
if grep -qF '%include /etc/tor/cyberlux-onion.conf' "${TORRC}"; then
|
|
sed -i '\|%include /etc/tor/cyberlux-onion.conf|d' "${TORRC}"
|
|
tor_changed=1
|
|
fi
|
|
|
|
if ! grep -qF "${TOR_INCLUDE}" "${TORRC}"; then
|
|
printf '\n%%include %s\n' "${TOR_INCLUDE}" >> "${TORRC}"
|
|
tor_changed=1
|
|
fi
|
|
|
|
if install_if_changed "${REPO}/nginx/cyberlux-ddos-zones.conf" /etc/nginx/conf.d/cyberlux-ddos-zones.conf 0644; then
|
|
nginx_changed=1
|
|
fi
|
|
if install_if_changed "${REPO}/nginx/cyberlux-server-common.inc" /etc/nginx/cyberlux-server-common.inc 0644; then
|
|
nginx_changed=1
|
|
fi
|
|
if install_if_changed "${REPO}/nginx.example.conf" /etc/nginx/sites-available/cyberlux-onion 0644; then
|
|
nginx_changed=1
|
|
fi
|
|
ln -sf /etc/nginx/sites-available/cyberlux-onion /etc/nginx/sites-enabled/cyberlux-onion
|
|
|
|
if [[ -x "${REPO}/scripts/restore-onion-keys.sh" ]]; then
|
|
bash "${REPO}/scripts/restore-onion-keys.sh"
|
|
fi
|
|
|
|
nginx -t
|
|
if command -v tor >/dev/null 2>&1; then
|
|
tor --verify-config -f "${TORRC}" >/dev/null
|
|
fi
|
|
|
|
if (( nginx_changed )); then
|
|
systemctl reload nginx 2>/dev/null || systemctl restart nginx
|
|
elif ! nginx_is_active; then
|
|
systemctl start nginx
|
|
fi
|
|
|
|
if (( tor_changed )); then
|
|
restart_tor
|
|
elif ! tor_is_active; then
|
|
start_tor
|
|
fi
|
|
|
|
# Hidden services proxy to nginx → Next on 127.0.0.1:3000. If Next is down, every .onion returns 502.
|
|
if command -v curl >/dev/null 2>&1; then
|
|
up="$(curl -g -sS -o /dev/null -w "%{http_code}" --connect-timeout 2 --max-time 5 "http://127.0.0.1:3000/" 2>/dev/null)" || up="000"
|
|
if [[ ! "${up}" =~ ^(200|301|302|304)$ ]]; then
|
|
echo "[!] Next.js is not serving on 127.0.0.1:3000 (HTTP ${up}) — onion URLs will fail until it is running." >&2
|
|
echo " Start: cd ${REPO} && npm run start:onion or: sudo systemctl start cyberlux.service" >&2
|
|
echo " Install service: sudo CYBERLUX_USER=\${SUDO_USER:-\$USER} bash ${REPO}/scripts/install-systemd.sh" >&2
|
|
fi
|
|
fi
|
|
|
|
# Refresh repo-root onion-urls.txt while we have root (hostname dirs are 0700 debian-tor).
|
|
if [[ -f "${REPO}/scripts/export-onion-urls.sh" ]]; then
|
|
bash "${REPO}/scripts/export-onion-urls.sh" || true
|
|
fi
|
|
|
|
if [[ "${CYBERLUX_INSTALL_QUIET:-}" == "1" ]]; then
|
|
exit 0
|
|
fi
|
|
|
|
echo ""
|
|
echo "CyberLux Tor nodes (see hostname files):"
|
|
while IFS= read -r dir || [[ -n "${dir}" ]]; do
|
|
[[ -z "${dir}" ]] && continue
|
|
f="/var/lib/tor/${dir}/hostname"
|
|
if [[ -f "$f" ]]; then
|
|
echo " ${dir}: http://$(tr -d '\n' < "$f")"
|
|
else
|
|
echo " ${dir}: (generating…) sudo cat $f"
|
|
fi
|
|
done < "${REPO}/scripts/generated/tor-dirs.txt"
|
|
echo ""
|
|
echo "Config status:"
|
|
echo " • Tor: $([[ ${tor_changed} -eq 1 ]] && echo changed || echo unchanged)"
|
|
echo " • nginx: $([[ ${nginx_changed} -eq 1 ]] && echo changed || echo unchanged)"
|
|
echo ""
|
|
echo "Host hardening:"
|
|
echo " • Next: npm run start:onion (127.0.0.1:3000)"
|
|
echo " • Do not expose 3000 or nginx loopback ports to the public internet."
|
|
echo " • Onion key backup set: /var/backups/cyberlux-onion-keys/current"
|
|
echo " • Optional: sudo bash ${REPO}/scripts/classroom-ufw.sh"
|
|
echo ""
|
|
echo "Start app: cd ${REPO} && ./start.sh or npm run build && npm run start:onion"
|