This commit is contained in:
eric
2026-05-16 19:24:30 -05:00
parent 19beec12a5
commit 75a0ca4e31
260 changed files with 51345 additions and 1 deletions

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env bash
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="business"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
# Keep the business profile focused on the livestream stack.
ENABLE_HOMEPAGE=0
ENABLE_FILEBROWSER=0
ENABLE_COCKPIT=0
ENABLE_NETDATA=0
ensure_live_user
normalize_repo_root
install_base_packages
install_media_packages
configure_adb_udev
install_nodejs
install_docker_stack
install_android_panel
prepare_python_runtime
prepare_web_console
install_live_console_service
configure_sudoers
configure_mdns
install_browser_stack
install_neko_browser
install_redroid
prepare_mitmproxy
prepare_vscode_server
prepare_uptime_kuma
prepare_openclaw
install_pulseaudio_service
install_kmscube_service
prepare_srs
run_hardware_probe
# 与 install-hub 一致:装 Caddy live-edgehttp://live.local:80 → 本机控制平面 PORT默认 8001
install_live_edge_proxy
print_summary "business"

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="hub"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
# Keep the hub profile independent from the livestream business stack.
ENABLE_SRS=0
ensure_live_user
normalize_repo_root
install_base_packages
install_media_packages
configure_adb_udev
install_nodejs
install_docker_stack
install_android_panel
prepare_python_runtime
prepare_web_console
install_live_console_service
configure_sudoers
configure_mdns
configure_wifi_profile
install_shellcrash
install_browser_stack
install_neko_browser
install_redroid
prepare_mitmproxy
prepare_vscode_server
prepare_uptime_kuma
prepare_openclaw
install_pulseaudio_service
install_kmscube_service
install_webtty
install_cockpit
install_netdata
prepare_homepage
prepare_filebrowser
run_hardware_probe
install_live_edge_proxy
print_summary "hub"

View File

@@ -0,0 +1,27 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
PROFILE="${1:-all}"
case "$PROFILE" in
hub|core|sh)
exec bash "$ROOT_DIR/scripts/linux/install_hub.sh" "${@:2}"
;;
business|app|sh2)
exec bash "$ROOT_DIR/scripts/linux/install_business.sh" "${@:2}"
;;
all|full)
bash "$ROOT_DIR/scripts/linux/install_hub.sh" "${@:2}"
bash "$ROOT_DIR/scripts/linux/install_business.sh" "${@:2}"
;;
*)
cat <<USAGE
Usage:
scripts/linux/install_stack.sh hub
scripts/linux/install_stack.sh business
scripts/linux/install_stack.sh all
USAGE
exit 1
;;
esac

View File

@@ -0,0 +1,64 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "$0")/../.." && pwd)"
CONFIG_DIR="$ROOT_DIR/config"
[ -f "$CONFIG_DIR/system-stack.env" ] && set -a && . "$CONFIG_DIR/system-stack.env" && set +a
[ -f "$CONFIG_DIR/hardware.env" ] && set -a && . "$CONFIG_DIR/hardware.env" && set +a
case "$(uname -m)" in
x86_64|amd64)
browser_bin="$(
command -v google-chrome 2>/dev/null \
|| command -v google-chrome-stable 2>/dev/null \
|| command -v chromium 2>/dev/null \
|| command -v chromium-browser 2>/dev/null \
|| true
)"
;;
*)
browser_bin="$(
command -v chromium 2>/dev/null \
|| command -v chromium-browser 2>/dev/null \
|| command -v google-chrome 2>/dev/null \
|| command -v google-chrome-stable 2>/dev/null \
|| true
)"
;;
esac
if [ -z "$browser_bin" ]; then
echo "MESSAGE=Chromium or Google Chrome is not installed"
exit 1
fi
profile_dir="${BROWSER_PROFILE_DIR:-$HOME/.local/share/live-browser/profile}"
start_url="${BROWSER_START_URL:-https://www.tiktok.com/live}"
locale="${BROWSER_LOCALE:-zh-CN}"
debug_port="${BROWSER_REMOTE_DEBUG_PORT:-9222}"
mkdir -p "$profile_dir"
args=(
"--user-data-dir=$profile_dir"
"--password-store=basic"
"--lang=$locale"
"--no-first-run"
"--restore-last-session"
"--remote-debugging-port=$debug_port"
"--start-maximized"
"--ozone-platform-hint=auto"
)
if [ "${LIVE_BROWSER_HWACCEL:-auto}" = "disabled" ]; then
args+=("--disable-gpu")
fi
if [ -n "${BROWSER_EXTRA_FLAGS:-}" ]; then
# shellcheck disable=SC2206
extra_flags=(${BROWSER_EXTRA_FLAGS})
args+=("${extra_flags[@]}")
fi
exec "$browser_bin" "${args[@]}" "$start_url"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
# 排查「live.local refused to connect」多为 :80 无进程、服务未起、或跨机 mDNS/防火墙。
# 在设备本机执行: sudo bash scripts/linux/probe_live_access.sh
set +euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="probe"
# shellcheck source=scripts/linux/lib/common.sh
. "$SELF_DIR/lib/common.sh"
load_env
echo "=== Probe: refused to connect (no listener / firewall / wrong host) ==="
echo "Note: 502 = reverse proxy up but upstream dead; refused = nothing accepting TCP."
echo ""
echo "--- Host / IP ---"
echo "hostname: $(hostname 2>/dev/null)"
LAN_IP=""
LAN_IP="$(detect_preferred_lan_ip || true)"
echo "guess LAN IP: ${LAN_IP:-unknown}"
echo ""
echo "--- systemd (need root for full status) ---"
for u in live-console live-edge; do
if systemctl is-active "$u.service" >/dev/null 2>&1; then
echo "$u.service: active"
else
echo "$u.service: INACTIVE — run: sudo systemctl status $u.service"
fi
done
echo ""
echo "--- TCP listeners :80 and :${PORT} ---"
if command -v ss >/dev/null 2>&1; then
ss -tlnp 2>/dev/null | grep -E ":80\\b|:${PORT}\\b" || echo "(no LISTEN on :80 or :${PORT})"
else
netstat -tlnp 2>/dev/null | grep -E ":80\\b|:${PORT}\\b" || true
fi
echo ""
echo "--- Loopback checks ---"
if curl -sf -m 5 "http://127.0.0.1:${PORT}/health" >/dev/null; then
echo "OK http://127.0.0.1:${PORT}/health"
else
echo "FAIL http://127.0.0.1:${PORT}/health → fix live-console first: journalctl -u live-console.service -n 60"
fi
code="$(curl -sS -m 5 -o /dev/null -w '%{http_code}' "http://127.0.0.1/" 2>/dev/null)"
if [ "$code" = "000" ] || [ -z "$code" ]; then
echo "FAIL http://127.0.0.1/ (port 80) — live-edge/Caddy not listening or connection refused"
echo " Try: sudo bash scripts/linux/reinstall_live_edge.sh && sudo systemctl restart live-edge.service"
elif [ "$code" = "502" ]; then
echo "WARN http://127.0.0.1/ → 502 — Caddy up but upstream :${PORT} down; restart live-console"
else
echo "OK http://127.0.0.1/ → HTTP $code"
fi
echo ""
echo "--- From your phone/PC browser ---"
echo "1) Same WiFi/LAN as this box."
echo "2) Try: http://${LAN_IP}:${PORT}/ (direct control plane, bypasses :80 and mDNS)"
echo "3) live.local needs mDNS (Android often OK; Windows may need Bonjour or use IP)."
echo "4) If OK on IP but not live.local: Avahi on this host — systemctl status avahi-daemon"
echo ""
if ! systemctl is-active live-console.service >/dev/null 2>&1; then
echo "=== Fix live-console (your case: edge OK, :${PORT} down) ==="
echo "sudo systemctl reset-failed live-console.service 2>/dev/null || true"
echo "sudo systemctl enable --now live-console.service"
echo "sleep 3 && curl -sf http://127.0.0.1:${PORT}/health && echo OK || echo still failing — logs:"
echo "sudo journalctl -u live-console.service -n 80 --no-pager"
echo ""
echo "After git pull / code update, prefer: sudo bash upgrade-live.sh"
echo "Only systemd unit changed? sudo bash refresh-live-unit.sh"
echo ""
fi

View File

@@ -0,0 +1,13 @@
#!/usr/bin/env bash
# git pull 后若只改了 systemd 模板(如 StartLimit执行本脚本重写 live-console.service 并 enable --now
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="refresh-unit"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
log "Rewriting /etc/systemd/system/live-console.service from repo"
install_live_console_service
log "Done. Check: systemctl status live-console.service --no-pager"

View File

@@ -0,0 +1,10 @@
#!/usr/bin/env bash
# 仅重装 Caddy 边缘反代http://live.local → :PORT需已存在 live-console
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="edge"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
install_live_edge_proxy

View File

@@ -0,0 +1,25 @@
#!/usr/bin/env bash
set -euo pipefail
DEVICE="${KMSCUBE_DRM_DEVICE:-/dev/dri/card0}"
if ! command -v kmscube >/dev/null 2>&1; then
echo "kmscube is not installed" >&2
exit 127
fi
if [ ! -e "$DEVICE" ]; then
for candidate in /dev/dri/card*; do
if [ -e "$candidate" ]; then
DEVICE="$candidate"
break
fi
done
fi
if [ ! -e "$DEVICE" ]; then
echo "No DRM card device found" >&2
exit 1
fi
exec kmscube -D "$DEVICE"

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="uninstall"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
log "Stopping systemd services"
for svc in live-edge.service live-console.service live-webtty.service live-android-panel.service live-pulseaudio.service live-kmscube.service netdata cockpit.socket shellcrash.service avahi-daemon; do
systemctl stop "$svc" >/dev/null 2>&1 || true
systemctl disable "$svc" >/dev/null 2>&1 || true
done
log "Stopping dockerized services"
for compose_file in \
"$ROOT_DIR/services/srs/docker-compose.yml" \
"$ROOT_DIR/services/homepage/docker-compose.yml" \
"$ROOT_DIR/services/filebrowser/docker-compose.yml" \
"$ROOT_DIR/services/neko/docker-compose.yml" \
"$ROOT_DIR/services/mitmproxy/docker-compose.yml" \
"$ROOT_DIR/services/vscode-server/docker-compose.yml" \
"$ROOT_DIR/services/uptime-kuma/docker-compose.yml" \
"$ROOT_DIR/services/openclaw/docker-compose.yml"
do
[ -f "$compose_file" ] || continue
compose_in_service_dir "$compose_file" down >/dev/null 2>&1 || true
done
log "Stopping Redroid default instance"
if command -v docker >/dev/null 2>&1; then
docker rm -f "${REDROID_INSTANCE_PREFIX:-redroid13}-1" >/dev/null 2>&1 || true
fi
log "Removing systemd unit files"
rm -f /etc/systemd/system/live-edge.service
rm -f /etc/systemd/system/live-console.service
rm -f /etc/systemd/system/live-webtty.service
rm -f /etc/systemd/system/live-android-panel.service
rm -f /etc/systemd/system/live-pulseaudio.service
rm -f /etc/systemd/system/live-kmscube.service
rm -f /etc/sudoers.d/live-control-plane
systemctl daemon-reload
cat <<EOF
Uninstall completed for the managed live stack.
Repository files were kept in place:
$ROOT_DIR
EOF

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env bash
# 将 ffmpeg 升级到含 -stats_period约 4.4+),供 douyin_youtube_ffplay / robust_relay 使用。
# Debian 11 默认 4.3.x先试强制从 bullseye-backports 安装;仍不行则用 arm64 静态包到 /usr/local/bin。
set -euo pipefail
if [[ ${EUID:-0} -ne 0 ]]; then
exec sudo bash "$0" "$@"
fi
have_stats_period() {
command -v ffmpeg >/dev/null 2>&1 || return 1
# ffmpeg 把 -h full 打到 stderr不能 2>/dev/null 否则永远匹配不到
ffmpeg -hide_banner -h full 2>&1 | grep -qE 'stats_period'
}
install_johnvansickle_arm64_static() {
local url="https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-arm64-static.tar.xz"
local td dir
td=$(mktemp -d)
trap 'rm -rf "$td"' EXIT
echo "[INFO] 下载 arm64 静态 ffmpegjohnvansickle…"
if command -v curl >/dev/null 2>&1; then
curl -fsSL -o "$td/ff.tar.xz" "$url"
elif command -v wget >/dev/null 2>&1; then
wget -q -O "$td/ff.tar.xz" "$url"
else
echo "需要 curl 或 wget" >&2
return 1
fi
tar -xJf "$td/ff.tar.xz" -C "$td"
dir=$(find "$td" -maxdepth 1 -type d -name 'ffmpeg-*-arm64-static' | head -1)
if [[ ! -d "$dir" ]]; then
echo "解压后未找到 ffmpeg-*-arm64-static" >&2
return 1
fi
install -m 0755 "$dir/ffmpeg" /usr/local/bin/ffmpeg
install -m 0755 "$dir/ffprobe" /usr/local/bin/ffprobe
hash -r
trap - EXIT
rm -rf "$td"
echo "[INFO] 已写入 /usr/local/bin/ffmpegPATH 中优先于 /usr/bin 时生效)"
}
if have_stats_period; then
echo "[OK] 当前 ffmpeg 已支持 -stats_period"
command -v ffmpeg
ffmpeg -version | head -1
exit 0
fi
if [[ ! -r /etc/os-release ]]; then
echo "无法读取 /etc/os-release" >&2
if [[ "$(uname -m)" == aarch64 ]]; then
install_johnvansickle_arm64_static || exit 1
have_stats_period && exit 0
fi
exit 1
fi
# shellcheck source=/dev/null
. /etc/os-release
case "${ID:-}" in
debian)
case "${VERSION_CODENAME:-}" in
bullseye)
BP=/etc/apt/sources.list.d/bullseye-backports.list
if ! grep -qE 'bullseye-backports' /etc/apt/sources.list /etc/apt/sources.list.d/*.list 2>/dev/null; then
echo "deb http://deb.debian.org/debian bullseye-backports main" >"$BP"
fi
apt-get update -qq
echo "[INFO] ffmpeg 可用版本apt-cache madison前几行:"
apt-cache madison ffmpeg 2>/dev/null | head -12 || true
# 显式指定发行版,避免仍选中 bullseye 主源的 4.3.9
apt-get install -y ffmpeg/bullseye-backports || true
;;
bookworm|trixie|sid)
apt-get update -qq
apt-get install -y ffmpeg
;;
*)
echo "未内置规则的 Debian 代号: ${VERSION_CODENAME}" >&2
;;
esac
;;
ubuntu)
apt-get update -qq
apt-get install -y ffmpeg
;;
*)
echo "发行版 ${ID:-unknown}:跳过 apt 规则" >&2
;;
esac
if have_stats_period; then
echo "[OK] apt 升级后已支持 -stats_period"
command -v ffmpeg
ffmpeg -version | head -1
exit 0
fi
if [[ "$(uname -m)" == aarch64 ]]; then
echo "[WARN] apt 仍未提供带 -stats_period 的 ffmpeg改用静态包" >&2
install_johnvansickle_arm64_static
fi
ffmpeg -version | head -1 || true
if have_stats_period; then
echo "[OK] 当前 ffmpeg 已支持 -stats_period"
command -v ffmpeg
exit 0
fi
echo "[FATAL] 仍无法使用 -stats_period请检查网络或手动安装 ffmpeg 4.4+aarch64" >&2
exit 1

View File

@@ -0,0 +1,56 @@
#!/usr/bin/env bash
# 代码已更新git pull后执行刷新 venv、重建 web-console、重启控制面与 Caddy 边缘。
# 不需要也不应代替首次装机;不等价于 install-hub / install-business / install-all。
set -euo pipefail
SELF_DIR="$(cd "$(dirname "$0")" && pwd)"
INSTALL_TAG="upgrade"
. "$SELF_DIR/lib/common.sh"
ensure_root "$@"
load_env
# git pull 若以 root 执行,避免 live 用户无法写 venv / node_modules
chown -R live:live "$ROOT_DIR" || true
log "Refreshing Python venv + requirements"
prepare_python_runtime
log "Rebuilding web-console (npm)"
prepare_web_console
log "Restarting live-console.service"
systemctl daemon-reload
systemctl restart live-console.service
if [ "${ENABLE_LIVE_EDGE_PROXY:-1}" = "1" ]; then
log "Regenerating Caddyfile and restarting live-edge.service"
install_live_edge_proxy
else
log "ENABLE_LIVE_EDGE_PROXY is not 1 — skipping live-edge (direct :${PORT})"
fi
ok=0
for _ in 1 2 3 4 5 6; do
if curl -sf -m 6 "http://127.0.0.1:${PORT}/health" >/dev/null; then
ok=1
break
fi
sleep 2
done
if [ "$ok" = 1 ]; then
log "Health check OK on http://127.0.0.1:${PORT}/health"
else
log "WARN: health check failed — see: journalctl -u live-console.service -n 80 --no-pager"
exit 1
fi
cat <<EOF
Upgrade done. Open:
http://${HOSTNAME_ALIAS}.local/ (port 80, if live-edge active)
http://${HOSTNAME_ALIAS}.local:${PORT}/ (direct)
Next time after git pull, run: sudo bash upgrade-live.sh
(No need for install-all.sh unless you change OS-level stack or first install.)
EOF

View File

@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -euo pipefail
cd "$(cd "$(dirname "$0")/../.." && pwd)"
exec bash -l