Expand local_machine docs and automation for connectivity, games, and ops.

Add proxy/VPN/telegram launchd and emergency runbooks; reorganize apps docs;
document JA3 CrossOver runbook and Wine troubleshooting; add GOG/HoMM game
scripts, disk cleanup guides, and gitea push-via-proxy helper. Ignore temp/.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ahauimix
2026-06-01 08:12:19 +03:00
parent a39ef89125
commit 1938b7c743
135 changed files with 9933 additions and 388 deletions

View File

@@ -0,0 +1,51 @@
#!/usr/bin/env bash
# Создать SSH-ключ для туннеля на Windows и добавить публичный ключ на прокси.
# Запускать на машине, с которой ЕСТЬ доступ к 149.154.64.19 (например Mac).
# Приватный ключ остаётся в windows-proxy-key/ — скопировать на Windows в %USERPROFILE%\.ssh\id_ed25519
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
KEY_DIR="${SCRIPT_DIR}/windows-proxy-key"
KEY_FILE="${KEY_DIR}/id_ed25519"
PROXY_HOST="${CURSOR_TUNNEL_HOST:-hsites-ahau}"
echo "=== Ключ для туннеля на Windows (только туннелирование, прав на сервере не нужно) ==="
echo " Прокси: $PROXY_HOST (149.154.64.19)"
echo ""
mkdir -p "$KEY_DIR"
chmod 700 "$KEY_DIR"
if [[ -f "$KEY_FILE" ]]; then
echo "Ключ уже есть: $KEY_FILE"
echo "Публичный ключ на сервере уже добавлен (если скрипт выполнялся до конца)."
echo ""
echo "Скопируйте на Windows один файл (приватный ключ):"
echo " Источник: $KEY_FILE"
echo " На Windows: %USERPROFILE%\\.ssh\\id_ed25519"
echo ""
exit 0
fi
echo "Создаю ключ в $KEY_DIR ..."
ssh-keygen -t ed25519 -f "$KEY_FILE" -N "" -C "windows-proxy-tunnel"
echo ""
echo "Добавляю публичный ключ на сервер $PROXY_HOST ..."
cat "${KEY_FILE}.pub" | ssh "$PROXY_HOST" "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
echo "[OK] Публичный ключ добавлен в ~/.ssh/authorized_keys на сервере."
echo ""
echo "Проверка подключения с этим ключом..."
ssh -i "$KEY_FILE" -o BatchMode=yes -o ConnectTimeout=10 "$PROXY_HOST" "echo OK" || { echo "Проверка не удалась."; exit 1; }
echo "[OK] Подключение работает."
echo ""
echo "--- Что сделать дальше ---"
echo "1. Скопировать на Windows ОДИН файл (приватный ключ, никому не передавать):"
echo " $KEY_FILE"
echo " На Windows положить в: %USERPROFILE%\\.ssh\\id_ed25519"
echo " (папку .ssh создать, если нет.)"
echo ""
echo "2. На Windows запустить туннель: см. docs/connectivity/WINDOWS_CURSOR_TUNNEL.md"
echo " или: ssh -D 10809 -o ServerAliveInterval=30 -o ServerAliveCountMax=6 ahau@149.154.64.19"
echo ""

View File

@@ -0,0 +1,105 @@
#!/bin/sh
# Сброс сетевого стека macOS после смены хотспота / «интернет не поднимается без перезагрузки».
# Типичная причина в связке с docs/connectivity: системный PAC на localhost:1089 при мёртвом/ещё не
# поднятом PAC-сервере + кэш DNS / WiFi. См. HOTSPOT_NETWORK_EMERGENCY.md
#
# Использование (из корня репозитория):
# ./docs/connectivity/scripts/macos-hotspot-network-recover.sh status
# ./docs/connectivity/scripts/macos-hotspot-network-recover.sh recover
#
# Переменные:
# MACOS_PAC_SERVICES — как в macos-system-pac.sh (по умолчанию Wi-Fi|Thunderbolt Bridge 2)
# WIFI_DEVICE — например en0; иначе авто: первый Device у Hardware Port: Wi-Fi
set -e
ROOT="$(cd "$(dirname "$0")" && pwd)"
PAC_SCRIPT="$ROOT/macos-system-pac.sh"
wifi_device() {
if [ -n "${WIFI_DEVICE:-}" ]; then
printf '%s\n' "$WIFI_DEVICE"
return
fi
# "Device: en0" под блоком "Hardware Port: Wi-Fi"
networksetup -listallhardwareports 2>/dev/null \
| awk '/Hardware Port: Wi-Fi$/ {p=1; next} p && /^Device: / {print $2; exit}'
}
usage() {
printf '%s\n' "Usage: $(basename "$0") status|recover" >&2
exit 1
}
[ "$#" -eq 1 ] || usage
cmd=$1
case "$cmd" in
status)
echo "=== Wi-Fi device (hardware) ==="
wifi_device || true
echo "=== networksetup -listallnetworkservices (excerpt) ==="
networksetup -listallnetworkservices 2>/dev/null | head -15 || true
echo "=== PAC / autoproxy (Wi-Fi + Thunderbolt Bridge 2 if present) ==="
if [ -x "$PAC_SCRIPT" ]; then
MACOS_PAC_SERVICES="${MACOS_PAC_SERVICES:-Wi-Fi|Thunderbolt Bridge 2}" "$PAC_SCRIPT" status || true
fi
echo "=== SOCKS firewall (Wi-Fi) ==="
networksetup -getsocksfirewallproxy "Wi-Fi" 2>/dev/null || true
echo "=== Web proxy (Wi-Fi) ==="
networksetup -getwebproxy "Wi-Fi" 2>/dev/null || true
echo "=== Listener on 1089 (PAC URL default) ==="
if lsof -i :1089 -sTCP:LISTEN 2>/dev/null | head -5; then
:
else
echo "(none — при Enabled PAC в Safari/системе возможны сбои)"
fi
echo "=== Default route ==="
route -n get default 2>/dev/null | head -12 || true
echo "=== Quick reachability (ICMP may be blocked on some hotspots) ==="
ping -c 1 -W 2000 1.1.1.1 >/dev/null 2>&1 && echo "ping 1.1.1.1: ok" || echo "ping 1.1.1.1: fail"
;;
recover)
echo "1) Отключаем автоматический PAC на выбранных сервисах..."
if [ -x "$PAC_SCRIPT" ]; then
MACOS_PAC_SERVICES="${MACOS_PAC_SERVICES:-Wi-Fi|Thunderbolt Bridge 2}" "$PAC_SCRIPT" off
else
echo "WARN: нет $PAC_SCRIPT — вручную: Системные настройки → Сеть → WiFi → Подробнее → Прокси → снять «Автоматическая настройка прокси»" >&2
fi
echo "2) Отключаем системный SOCKS-прокси на Wi-Fi (если был включён Shadowsocks и т.п.)..."
if networksetup -listallnetworkservices 2>/dev/null | grep -Fqx "Wi-Fi"; then
networksetup -setsocksfirewallproxystate "Wi-Fi" off 2>/dev/null || true
fi
echo "3) Сброс DNS-кэша (нужен sudo)..."
if sudo -n true 2>/dev/null; then
sudo dscacheutil -flushcache 2>/dev/null || true
sudo killall -HUP mDNSResponder 2>/dev/null || true
echo " mDNSResponder перезагружен."
else
echo " Пропуск (нет sudo без пароля). Выполните вручную:"
echo " sudo dscacheutil -flushcache; sudo killall -HUP mDNSResponder"
fi
dev="$(wifi_device)"
if [ -n "$dev" ]; then
echo "4) Обновление DHCP на $dev (нужен sudo)..."
if sudo -n true 2>/dev/null; then
sudo ipconfig set "$dev" DHCP 2>/dev/null || true
else
echo " Пропуск. Вручную: sudo ipconfig set $dev DHCP"
fi
echo "5) Краткое выключение/включение WiFi радиомодуля ($dev)..."
networksetup -setairportpower "$dev" off 2>/dev/null || true
sleep 2
networksetup -setairportpower "$dev" on 2>/dev/null || true
else
echo "45) Не удалось определить WiFi device — пропуск DHCP/airport power. Вручную выключите/включите WiFi в меню."
fi
echo "=== Готово. Проверка: ==="
"$0" status
echo ""
echo "Если интернет всё ещё нет: откройте хотспот в браузере (captive portal), затем при необходимости снова включите PAC:"
echo " ./docs/connectivity/scripts/macos-pac-on.sh"
;;
*)
usage
;;
esac

View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec "$(dirname "$0")/macos-system-pac.sh" off

View File

@@ -0,0 +1,2 @@
#!/bin/sh
exec "$(dirname "$0")/macos-system-pac.sh" on

View File

@@ -0,0 +1,76 @@
#!/bin/sh
# Включает/выключает системный «автоматический прокси» (PAC) в macOS через networksetup.
# По умолчанию: PAC http://localhost:1089/proxy.pac на сервисах Wi-Fi и Thunderbolt Bridge 2.
#
# Переменные окружения:
# MACOS_PAC_URL — URL proxy.pac (по умолчанию http://localhost:1089/proxy.pac)
# MACOS_PAC_SERVICES — список имён сетевых сервисов через «|» (см. networksetup -listallnetworkservices)
usage() {
printf '%s\n' "Usage: $(basename "$0") on|off|status" >&2
exit 1
}
[ "$#" -eq 1 ] || usage
cmd=$1
PAC_URL="${MACOS_PAC_URL:-http://localhost:1089/proxy.pac}"
SERVICES="${MACOS_PAC_SERVICES:-Wi-Fi|Thunderbolt Bridge 2}"
svc_exists() {
networksetup -listallnetworkservices 2>/dev/null | grep -Fqx "$1"
}
case "$cmd" in
on)
OLDIFS=$IFS
IFS='|'
for svc in $SERVICES; do
IFS=$OLDIFS
[ -z "$svc" ] && continue
if ! svc_exists "$svc"; then
echo "skip (нет сервиса): $svc" >&2
continue
fi
networksetup -setautoproxyurl "$svc" "$PAC_URL"
networksetup -setautoproxystate "$svc" on
echo "PAC on: $svc"
done
;;
off)
OLDIFS=$IFS
IFS='|'
for svc in $SERVICES; do
IFS=$OLDIFS
[ -z "$svc" ] && continue
if ! svc_exists "$svc"; then
echo "skip (нет сервиса): $svc" >&2
continue
fi
networksetup -setautoproxystate "$svc" off
echo "PAC off: $svc"
done
;;
status)
printf '%s\n' "PAC_URL=$PAC_URL"
printf '%s\n' "SERVICES=$SERVICES"
printf '%s\n' "---"
OLDIFS=$IFS
IFS='|'
for svc in $SERVICES; do
IFS=$OLDIFS
[ -z "$svc" ] && continue
if svc_exists "$svc"; then
echo "[$svc]"
networksetup -getautoproxyurl "$svc"
else
echo "[$svc] (нет такого сервиса)"
fi
done
printf '%s\n' "--- scutil --proxy ---"
scutil --proxy 2>/dev/null || true
;;
*)
usage
;;
esac

View File

@@ -0,0 +1,97 @@
# Setup SSH key for proxy tunneling only (ru.hunab.app / 149.154.64.19).
# Usage: run in PowerShell from repo root or pass path; no admin rights needed.
# The key is ONLY for SSH tunnels (-D SOCKS, -L). User ahau on server needs no extra rights.
param(
[string]$SshDir = "$env:USERPROFILE\.ssh",
[string]$KeyName = "id_ed25519",
[string]$ProxyUser = "ahau",
[string]$ProxyHost = "149.154.64.19"
)
$KeyPath = Join-Path $SshDir $KeyName
$KeyPubPath = "$KeyPath.pub"
Write-Host "=== SSH key for proxy tunnel (Cursor/Telegram) ===" -ForegroundColor Cyan
Write-Host " Server: ${ProxyUser}@${ProxyHost} (ru.hunab.app)"
Write-Host " Purpose: tunneling only. No shell or other rights on server."
Write-Host ""
# Ensure .ssh exists
if (-not (Test-Path $SshDir)) {
New-Item -ItemType Directory -Path $SshDir -Force | Out-Null
Write-Host "[OK] Created $SshDir"
} else {
Write-Host "[OK] Directory exists: $SshDir"
}
# Check OpenSSH
try {
$null = Get-Command ssh -ErrorAction Stop
} catch {
Write-Host "[ERROR] OpenSSH client not found. Install: Settings -> Apps -> Optional features -> OpenSSH Client" -ForegroundColor Red
exit 1
}
if (-not (Test-Path $KeyPath)) {
Write-Host ""
Write-Host "No key found at $KeyPath" -ForegroundColor Yellow
Write-Host " Option A: Copy id_ed25519 (and id_ed25519.pub) from your Mac to $SshDir"
Write-Host " Option B: Generate a new key now (only for tunneling; add .pub to server once)"
$choice = Read-Host "Generate new key? (y/N)"
if ($choice -match '^[yY]') {
ssh-keygen -t ed25519 -f $KeyPath -N '""'
if (-not (Test-Path $KeyPath)) { Write-Host "Key creation failed." -ForegroundColor Red; exit 1 }
Write-Host "[OK] Key created: $KeyPath"
} else {
Write-Host "Copy id_ed25519 and id_ed25519.pub to $SshDir then run this script again."
exit 0
}
} else {
Write-Host "[OK] Key exists: $KeyPath"
}
# Show public key (user must add to server if new)
if (Test-Path $KeyPubPath) {
Write-Host ""
Write-Host "Public key (add one line to ~/.ssh/authorized_keys of ${ProxyUser}@${ProxyHost}):" -ForegroundColor Cyan
Write-Host (Get-Content $KeyPubPath -Raw).Trim()
Write-Host ""
Write-Host "On server (once): append the line above to /home/${ProxyUser}/.ssh/authorized_keys"
Write-Host "This key is only used for tunneling; no sudo or other rights needed for ahau."
} else {
Write-Host "[WARN] No $KeyPubPath found. Generate or copy from Mac." -ForegroundColor Yellow
}
# Test connection
Write-Host ""
Write-Host "Testing connection to ${ProxyUser}@${ProxyHost} ..."
$testResult = & ssh -i $KeyPath -o BatchMode=yes -o ConnectTimeout=10 -o StrictHostKeyChecking=accept-new "${ProxyUser}@${ProxyHost}" "echo OK" 2>&1
if ($LASTEXITCODE -eq 0 -and $testResult -eq "OK") {
Write-Host "[OK] SSH works. You can start the tunnel (cursor-socks-tunnel.ps1 start)." -ForegroundColor Green
} else {
Write-Host "[FAIL] SSH test failed. Ensure the public key is in authorized_keys on the server." -ForegroundColor Red
Write-Host $testResult
exit 1
}
# Optional: ensure config has hsites-ahau
$ConfigPath = Join-Path $SshDir "config"
$configEntry = @"
Host hsites-ahau
HostName $ProxyHost
User $ProxyUser
IdentityFile ~/.ssh/$KeyName
ServerAliveInterval 30
ServerAliveCountMax 6
"@
if (-not (Test-Path $ConfigPath)) {
Set-Content -Path $ConfigPath -Value $configEntry.Trim()
Write-Host "[OK] Created $ConfigPath with Host hsites-ahau"
} elseif ((Get-Content $ConfigPath -Raw) -notmatch "hsites-ahau") {
Add-Content -Path $ConfigPath -Value "`n$configEntry"
Write-Host "[OK] Appended hsites-ahau to $ConfigPath"
}
Write-Host ""
Write-Host "Done. Run: .\docs\cursor\scripts\cursor-socks-tunnel.ps1 start" -ForegroundColor Green

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
# SSH к проду: по умолчанию в конфиге hunab-prod уже через hsites-ahau.
# Если прямой DO доступен — быстрее hunab-prod-direct (пробуем за 8 с).
# HUNAB_PROD_FORCE_VIA=1 — не пробовать прямой, сразу hunab-prod (через RU).
# HUNAB_PROD_FORCE_DIRECT=1 — только hunab-prod-direct.
# Использование: ./ssh-hunab-prod.sh [аргументы ssh]
set -e
KA=( -o ServerAliveInterval=30 -o ServerAliveCountMax=8 -o TCPKeepAlive=yes )
if [ "${HUNAB_PROD_FORCE_DIRECT:-0}" = "1" ]; then
exec ssh "${KA[@]}" hunab-prod-direct "$@"
fi
if [ "${HUNAB_PROD_FORCE_VIA:-0}" != "1" ]; then
if ssh "${KA[@]}" -o BatchMode=yes -o ConnectTimeout=8 -o ConnectionAttempts=1 hunab-prod-direct "exit 0" 2>/dev/null; then
exec ssh "${KA[@]}" hunab-prod-direct "$@"
fi
fi
exec ssh "${KA[@]}" hunab-prod "$@"

View File

@@ -1,26 +1,81 @@
#!/usr/bin/env bash
# SOCKS5-туннель для Telegram (и др. приложений) через прокси 149.154.64.19.
# Порт 1081 — отдельно от Cursor (10809). Использование: ./telegram-socks-tunnel.sh [start|stop|status]
# См. connectivity/PROXY_GUIDE.md
# См. connectivity/PROXY_GUIDE.md (в т.ч. цепочка через DigitalOcean: TELEGRAM_SOCKS_VIA_DO=1)
set -e
TELEGRAM_SOCKS_PORT="${TELEGRAM_SOCKS_PORT:-1081}"
SSH_HOST="${TELEGRAM_TUNNEL_HOST:-ahau@149.154.64.19}"
TELEGRAM_SOCKS_VIA_DO="${TELEGRAM_SOCKS_VIA_DO:-0}"
TELEGRAM_SOCKS_JUMP_HOST="${TELEGRAM_SOCKS_JUMP_HOST:-hsites-ahau}"
TELEGRAM_SOCKS_FINAL_HOST="${TELEGRAM_SOCKS_FINAL_HOST:-hunab@209.38.32.21}"
TELEGRAM_SOCKS_FINAL_PORT="${TELEGRAM_SOCKS_FINAL_PORT:-2222}"
TELEGRAM_SOCKS_FINAL_IDENTITY="${TELEGRAM_SOCKS_FINAL_IDENTITY:-$HOME/.ssh/hunab_deploy_key}"
# Пусто = только loopback (по умолчанию в OpenSSH). 0.0.0.0 — слушать на всех интерфейсах (телефон → SOCKS на Mac по хотспоту).
TELEGRAM_SOCKS_BIND="${TELEGRAM_SOCKS_BIND:-}"
# SOCKS держит много соединений (Telegram); без повышения ulimit — «Too many open files».
TELEGRAM_SSH_STABLE_OPTS="-o TCPKeepAlive=yes -o IPQoS=throughput -o ServerAliveInterval=60 -o ServerAliveCountMax=4"
raise_fd_limit() {
ulimit -n 65536 2>/dev/null || ulimit -n 10240 2>/dev/null || true
}
socks_listening() {
lsof -i :"$TELEGRAM_SOCKS_PORT" -sTCP:LISTEN -t >/dev/null 2>&1
}
kill_listener_on_port() {
# PIDs listening on TELEGRAM_SOCKS_PORT (usually ssh -D; LaunchAgent may respawn — loop a few times)
local i=0
while socks_listening && [ "$i" -lt 20 ]; do
lsof -ti :"$TELEGRAM_SOCKS_PORT" -sTCP:LISTEN 2>/dev/null | xargs kill 2>/dev/null || true
sleep 0.35
i=$((i + 1))
done
}
start() {
if lsof -i :"$TELEGRAM_SOCKS_PORT" -sTCP:LISTEN -t >/dev/null 2>&1; then
echo "SOCKS already listening on 127.0.0.1:$TELEGRAM_SOCKS_PORT"
return 0
if socks_listening; then
if [ "$TELEGRAM_SOCKS_VIA_DO" = "1" ]; then
echo "Port $TELEGRAM_SOCKS_PORT busy — replacing with via-DO tunnel..."
kill_listener_on_port
if socks_listening; then
echo "Port $TELEGRAM_SOCKS_PORT still in use. If LaunchAgent keeps respawning the old tunnel, run:"
echo " launchctl unload \"\$HOME/Library/LaunchAgents/com.hunab.telegram-socks.plist\" 2>/dev/null"
echo " (or ./docs/connectivity/launchd/uninstall.sh) then: TELEGRAM_SOCKS_VIA_DO=1 $0 start"
return 1
fi
else
echo "SOCKS already listening on port $TELEGRAM_SOCKS_PORT"
return 0
fi
fi
raise_fd_limit
local d_spec="$TELEGRAM_SOCKS_PORT"
if [ -n "$TELEGRAM_SOCKS_BIND" ]; then
d_spec="${TELEGRAM_SOCKS_BIND}:${TELEGRAM_SOCKS_PORT}"
fi
if [ "$TELEGRAM_SOCKS_VIA_DO" = "1" ]; then
if ! ssh -o BatchMode=yes -o ConnectTimeout=6 -o ConnectionAttempts=1 hsites-ahau "exit 0" 2>/dev/null; then
echo "Ошибка: hsites-ahau недоступен. TELEGRAM_SOCKS_VIA_DO=1 — только Mac→RU→DO; прямой Mac→DO для SOCKS отключён." >&2
exit 1
fi
# shellcheck disable=SC2086
ssh -D "$TELEGRAM_SOCKS_PORT" -f -N \
$TELEGRAM_SSH_STABLE_OPTS \
telegram-socks-via-do
echo "SOCKS started: 127.0.0.1:$TELEGRAM_SOCKS_PORT -> hsites-ahau -> DO (telegram-socks-via-do)"
else
# shellcheck disable=SC2086
ssh -D "$TELEGRAM_SOCKS_PORT" -f -N \
$TELEGRAM_SSH_STABLE_OPTS \
"$SSH_HOST"
echo "SOCKS tunnel started: 127.0.0.1:$TELEGRAM_SOCKS_PORT -> $SSH_HOST"
fi
ssh -D "$TELEGRAM_SOCKS_PORT" -f -N \
-o ServerAliveInterval=30 \
-o ServerAliveCountMax=6 \
"$SSH_HOST"
echo "SOCKS tunnel started: 127.0.0.1:$TELEGRAM_SOCKS_PORT -> $SSH_HOST"
}
stop() {
pkill -f "ssh.*-D $TELEGRAM_SOCKS_PORT.*$SSH_HOST" 2>/dev/null || true
pkill -f "ssh.*-D $TELEGRAM_SOCKS_PORT" 2>/dev/null || true
echo "Tunnel stopped (if it was running)."
}
@@ -39,7 +94,8 @@ case "${1:-start}" in
status) status ;;
*)
echo "Usage: $0 {start|stop|status}"
echo "Env: TELEGRAM_SOCKS_PORT=$TELEGRAM_SOCKS_PORT, TELEGRAM_TUNNEL_HOST=$SSH_HOST"
echo "Env: TELEGRAM_SOCKS_PORT, TELEGRAM_TUNNEL_HOST (default exit: ru proxy)"
echo " TELEGRAM_SOCKS_VIA_DO=1 — только Mac→RU→DO (telegram-socks-via-do); без прямого DO"
exit 1
;;
esac