feat: codify fnos cutvideo tunnel routing
This commit is contained in:
170
scripts/deploy_fnos_cutvideo_tunnel.sh
Executable file
170
scripts/deploy_fnos_cutvideo_tunnel.sh
Executable file
@@ -0,0 +1,170 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(CDPATH= cd -- "$(dirname "$0")/.." && pwd)"
|
||||
|
||||
export CODEX_HOME="${CODEX_HOME:-$HOME/.codex}"
|
||||
export FNOS_SKILL="${FNOS_SKILL:-$CODEX_HOME/skills/fnos-hyzq-deploy}"
|
||||
export FNOS_SCP="${FNOS_SCP:-$FNOS_SKILL/scripts/fnos_scp.sh}"
|
||||
|
||||
FNOS_HOST="${FNOS_HOST:-192.168.31.188}"
|
||||
FNOS_USER="${FNOS_USER:-krisolo}"
|
||||
WINDOWS_HOST="${WINDOWS_HOST:-192.168.31.18}"
|
||||
WINDOWS_USER="${WINDOWS_USER:-kris}"
|
||||
WINDOWS_SSH_ALIAS="${WINDOWS_SSH_ALIAS:-shuziren-win}"
|
||||
CUTVIDEO_FORWARD_PORT="${CUTVIDEO_FORWARD_PORT:-19186}"
|
||||
STORYFORGE_COMPAT_FORWARD_PORT="${STORYFORGE_COMPAT_FORWARD_PORT:-19181}"
|
||||
FNOS_TUNNEL_KEY_PATH="${FNOS_TUNNEL_KEY_PATH:-/home/$FNOS_USER/.ssh/cutvideo_lan_tunnel}"
|
||||
FNOS_TUNNEL_SCRIPT_PATH="${FNOS_TUNNEL_SCRIPT_PATH:-/home/$FNOS_USER/codex_start_cutvideo_tunnel_on_fnos.sh}"
|
||||
FNOS_TUNNEL_CRON_SCRIPT_PATH="${FNOS_TUNNEL_CRON_SCRIPT_PATH:-/home/$FNOS_USER/codex_enable_cutvideo_tunnel_cron_on_fnos.sh}"
|
||||
|
||||
need_cmd() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "missing required command: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
shell_quote() {
|
||||
python3 - "$1" <<'PY'
|
||||
import shlex
|
||||
import sys
|
||||
print(shlex.quote(sys.argv[1]))
|
||||
PY
|
||||
}
|
||||
|
||||
need_cmd python3
|
||||
need_cmd ssh
|
||||
need_cmd scp
|
||||
need_cmd expect
|
||||
need_cmd ssh-keygen
|
||||
|
||||
if [ -z "${FNOS_PASSWORD:-}" ]; then
|
||||
need_cmd security
|
||||
fi
|
||||
|
||||
resolve_fnos_password() {
|
||||
if [ -n "${FNOS_PASSWORD:-}" ]; then
|
||||
printf '%s' "$FNOS_PASSWORD"
|
||||
return 0
|
||||
fi
|
||||
security find-internet-password -s "$FNOS_HOST" -a "$FNOS_USER" -w
|
||||
}
|
||||
|
||||
run_fnos_cmd() {
|
||||
local remote_cmd="$1"
|
||||
local remote_cmd_quoted
|
||||
remote_cmd_quoted="$(shell_quote "$remote_cmd")"
|
||||
export FNOS_REMOTE_CMD_QUOTED="$remote_cmd_quoted"
|
||||
export FNOS_REMOTE_HOST="$FNOS_HOST"
|
||||
export FNOS_REMOTE_USER="$FNOS_USER"
|
||||
export FNOS_REMOTE_PASSWORD="$FNOS_PASSWORD_VALUE"
|
||||
/usr/bin/expect <<'EOF'
|
||||
set timeout -1
|
||||
set pw $env(FNOS_REMOTE_PASSWORD)
|
||||
set host $env(FNOS_REMOTE_HOST)
|
||||
set user $env(FNOS_REMOTE_USER)
|
||||
set remote_cmd_quoted $env(FNOS_REMOTE_CMD_QUOTED)
|
||||
set argv [list ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $user@$host "sh -lc $remote_cmd_quoted"]
|
||||
spawn {*}$argv
|
||||
expect {
|
||||
-re {Are you sure you want to continue connecting \(yes/no(/\[fingerprint\])?\)\?} {
|
||||
send "yes\r"
|
||||
exp_continue
|
||||
}
|
||||
-re {[Pp]assword:} {
|
||||
send "$pw\r"
|
||||
exp_continue
|
||||
}
|
||||
eof
|
||||
}
|
||||
catch wait result
|
||||
set exit_code [lindex $result 3]
|
||||
exit $exit_code
|
||||
EOF
|
||||
}
|
||||
|
||||
TMPDIR_DEPLOY="$(mktemp -d)"
|
||||
trap 'rm -rf "$TMPDIR_DEPLOY"' EXIT
|
||||
|
||||
FNOS_PASSWORD_VALUE="$(resolve_fnos_password)"
|
||||
START_SCRIPT_LOCAL="$TMPDIR_DEPLOY/codex_start_cutvideo_tunnel_on_fnos.sh"
|
||||
CRON_SCRIPT_LOCAL="$TMPDIR_DEPLOY/codex_enable_cutvideo_tunnel_cron_on_fnos.sh"
|
||||
|
||||
echo "[1/6] ensure fnOS tunnel key"
|
||||
FNOS_PUBKEY="$(
|
||||
run_fnos_cmd "mkdir -p ~/.ssh && chmod 700 ~/.ssh && if [ ! -f ~/.ssh/cutvideo_lan_tunnel ]; then ssh-keygen -t ed25519 -N '' -f ~/.ssh/cutvideo_lan_tunnel >/dev/null; fi && cat ~/.ssh/cutvideo_lan_tunnel.pub"
|
||||
)"
|
||||
FNOS_PUBKEY="$(printf '%s\n' "$FNOS_PUBKEY" | tail -n 1)"
|
||||
|
||||
echo "[2/6] authorize fnOS key on Windows OpenSSH"
|
||||
ssh "$WINDOWS_SSH_ALIAS" "powershell -NoProfile -Command \"\
|
||||
\$adminKeys='C:\\ProgramData\\ssh\\administrators_authorized_keys'; \
|
||||
\$userKeys='C:\\Users\\$WINDOWS_USER\\.ssh\\authorized_keys'; \
|
||||
\$pub='$FNOS_PUBKEY'; \
|
||||
New-Item -ItemType Directory -Force -Path 'C:\\ProgramData\\ssh' | Out-Null; \
|
||||
if (-not (Test-Path \$adminKeys)) { New-Item -ItemType File -Force -Path \$adminKeys | Out-Null }; \
|
||||
if (-not (Select-String -Path \$adminKeys -SimpleMatch \$pub -Quiet)) { Add-Content -Path \$adminKeys -Value \$pub }; \
|
||||
New-Item -ItemType Directory -Force -Path 'C:\\Users\\$WINDOWS_USER\\.ssh' | Out-Null; \
|
||||
if (-not (Test-Path \$userKeys)) { New-Item -ItemType File -Force -Path \$userKeys | Out-Null }; \
|
||||
if (-not (Select-String -Path \$userKeys -SimpleMatch \$pub -Quiet)) { Add-Content -Path \$userKeys -Value \$pub }; \
|
||||
Write-Output 'WINDOWS_AUTHORIZED_OK'\""
|
||||
|
||||
echo "[3/6] verify fnOS -> Windows key login"
|
||||
run_fnos_cmd "ssh -i $FNOS_TUNNEL_KEY_PATH -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null $WINDOWS_USER@$WINDOWS_HOST cmd /c echo FNOS_WINDOWS_TUNNEL_OK"
|
||||
|
||||
cat >"$START_SCRIPT_LOCAL" <<EOF
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
TUNNEL_KEY="$FNOS_TUNNEL_KEY_PATH"
|
||||
LOG_FILE="/home/$FNOS_USER/cutvideo_lan_tunnel.log"
|
||||
|
||||
pkill -f "${CUTVIDEO_FORWARD_PORT}:127.0.0.1:7860" >/dev/null 2>&1 || true
|
||||
|
||||
nohup ssh \\
|
||||
-i "\$TUNNEL_KEY" \\
|
||||
-o StrictHostKeyChecking=no \\
|
||||
-o UserKnownHostsFile=/dev/null \\
|
||||
-o ExitOnForwardFailure=yes \\
|
||||
-o ServerAliveInterval=30 \\
|
||||
-o ServerAliveCountMax=3 \\
|
||||
-g \\
|
||||
-N \\
|
||||
-L 0.0.0.0:${CUTVIDEO_FORWARD_PORT}:127.0.0.1:7860 \\
|
||||
-L 0.0.0.0:${STORYFORGE_COMPAT_FORWARD_PORT}:127.0.0.1:8081 \\
|
||||
$WINDOWS_USER@$WINDOWS_HOST \\
|
||||
>"\$LOG_FILE" 2>&1 &
|
||||
|
||||
sleep 2
|
||||
pgrep -af "${CUTVIDEO_FORWARD_PORT}:127.0.0.1:7860"
|
||||
EOF
|
||||
|
||||
cat >"$CRON_SCRIPT_LOCAL" <<EOF
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
|
||||
SCRIPT_PATH="$FNOS_TUNNEL_SCRIPT_PATH"
|
||||
TMP_CRON="\$(mktemp)"
|
||||
|
||||
crontab -l 2>/dev/null | grep -v "codex_start_cutvideo_tunnel_on_fnos.sh" >"\$TMP_CRON" || true
|
||||
echo "@reboot \$SCRIPT_PATH" >>"\$TMP_CRON"
|
||||
crontab "\$TMP_CRON"
|
||||
rm -f "\$TMP_CRON"
|
||||
|
||||
crontab -l
|
||||
EOF
|
||||
|
||||
echo "[4/6] upload fnOS tunnel scripts"
|
||||
"$FNOS_SCP" "/home/$FNOS_USER" "$START_SCRIPT_LOCAL" "$CRON_SCRIPT_LOCAL"
|
||||
|
||||
echo "[5/6] start tunnel and enable reboot recovery"
|
||||
run_fnos_cmd "chmod +x $FNOS_TUNNEL_SCRIPT_PATH $FNOS_TUNNEL_CRON_SCRIPT_PATH && $FNOS_TUNNEL_SCRIPT_PATH && $FNOS_TUNNEL_CRON_SCRIPT_PATH"
|
||||
|
||||
echo "[6/6] verify forwarded ports"
|
||||
curl -fsS "http://$FNOS_HOST:$CUTVIDEO_FORWARD_PORT/api/bootstrap" >/dev/null
|
||||
curl -fsS "http://$FNOS_HOST:$STORYFORGE_COMPAT_FORWARD_PORT/" >/dev/null
|
||||
|
||||
echo "fnOS cutvideo tunnel ready:"
|
||||
echo " cutvideo: http://$FNOS_HOST:$CUTVIDEO_FORWARD_PORT"
|
||||
echo " storyforge-live-compat: http://$FNOS_HOST:$STORYFORGE_COMPAT_FORWARD_PORT"
|
||||
@@ -54,7 +54,7 @@ LOCAL_OPENAI_API_KEY="${LOCAL_OPENAI_API_KEY:-}"
|
||||
N8N_BASE_URL="${N8N_BASE_URL:-${HOST_LAN_IP:+http://$HOST_LAN_IP:5670}}"
|
||||
ASR_HTTP_BASE_URL="${ASR_HTTP_BASE_URL:-${HOST_LAN_IP:+http://$HOST_LAN_IP:8088}}"
|
||||
HUOBAO_BASE_URL="${HUOBAO_BASE_URL:-${HOST_LAN_IP:+http://$HOST_LAN_IP:5678}}"
|
||||
CUTVIDEO_BASE_URL="${CUTVIDEO_BASE_URL:-http://192.168.31.18:7860}"
|
||||
CUTVIDEO_BASE_URL="${CUTVIDEO_BASE_URL:-http://$FNOS_HOST:19186}"
|
||||
LIVE_RECORDER_BASE_URL="${LIVE_RECORDER_BASE_URL:-http://192.168.31.188:19106}"
|
||||
CLOUD_DB_PATH="${CLOUD_DB_PATH:-/home/ubuntu/storyforge/data/collector/storyforge.db}"
|
||||
CLOUD_DB_SNAPSHOT_PATH="${CLOUD_DB_SNAPSHOT_PATH:-/home/ubuntu/storyforge/data/collector/storyforge-fnos-sync.db}"
|
||||
|
||||
Reference in New Issue
Block a user