install.sh 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/bin/sh
  2. # ==========================================================================
  3. # WeBrake installer — run this INSIDE an existing Alpine Linux LXC.
  4. # wget -qO- https://gogs.av2x.dev/av2x/WeBrake/raw/master/install.sh | ash
  5. #
  6. # It will refuse to run on a Proxmox host. Nothing is ever installed from
  7. # the host side; GPU passthru is host *configuration* only (see README).
  8. # Files are pulled from the repo. token.json is generated locally and is
  9. # never fetched from, nor pushed to, the repository.
  10. # ==========================================================================
  11. set -eu
  12. REPO_BASE="${WEBRAKE_REPO_BASE:-https://gogs.av2x.dev/av2x/WeBrake/raw}"
  13. BRANCHES="${WEBRAKE_BRANCH:-master main}"
  14. APP_DIR="/opt/webrake"
  15. DATA_DIR="/var/lib/webrake"
  16. PORT="${WEBRAKE_PORT:-8090}"
  17. say() { printf '\033[1;33m[WeBrake]\033[0m %s\n' "$*"; }
  18. die() { printf '\033[1;31m[WeBrake]\033[0m %s\n' "$*" >&2; exit 1; }
  19. # fetch <dest> <validator-grep> <path> [alt-path…] — tries every branch/path
  20. # combo and validates the payload so a Gogs error/login page is never installed.
  21. fetch() {
  22. dest="$1"; check="$2"; shift 2
  23. for br in $BRANCHES; do
  24. for p in "$@"; do
  25. url="$REPO_BASE/$br/$p"
  26. if wget -q -O "$dest.tmp" "$url" && [ -s "$dest.tmp" ] \
  27. && head -c 4096 "$dest.tmp" | grep -q "$check"; then
  28. mv "$dest.tmp" "$dest"
  29. say " fetched $p (branch: $br)"
  30. return 0
  31. fi
  32. done
  33. done
  34. rm -f "$dest.tmp"
  35. return 1
  36. }
  37. # ---- guard rails ---------------------------------------------------------
  38. [ "$(id -u)" = "0" ] || die "Run as root inside the Alpine container."
  39. command -v pveversion >/dev/null 2>&1 && \
  40. die "This looks like a Proxmox HOST. Run the installer inside the Alpine LXC instead."
  41. [ -f /etc/alpine-release ] || \
  42. die "This installer targets Alpine Linux. /etc/alpine-release not found."
  43. say "Installing on Alpine $(cat /etc/alpine-release)"
  44. # ---- packages ------------------------------------------------------------
  45. say "Installing packages (python3, flask, handbrake, VA-API drivers)…"
  46. apk update >/dev/null
  47. apk add --no-cache python3 py3-flask wget ca-certificates >/dev/null
  48. if ! command -v HandBrakeCLI >/dev/null 2>&1; then
  49. if ! apk add --no-cache handbrake >/dev/null 2>&1; then
  50. say "handbrake not in enabled repos — trying community/testing…"
  51. REL="$(cut -d. -f1,2 /etc/alpine-release)"
  52. apk add --no-cache handbrake \
  53. --repository="https://dl-cdn.alpinelinux.org/alpine/v${REL}/community" \
  54. >/dev/null 2>&1 || \
  55. apk add --no-cache handbrake \
  56. --repository="https://dl-cdn.alpinelinux.org/alpine/edge/community" \
  57. --repository="https://dl-cdn.alpinelinux.org/alpine/edge/main" \
  58. >/dev/null 2>&1 || \
  59. die "Could not install the 'handbrake' package. Enable the community repository in /etc/apk/repositories and re-run."
  60. fi
  61. fi
  62. say "HandBrakeCLI: $(HandBrakeCLI --version 2>/dev/null | head -n1 || echo installed)"
  63. # GPU userspace drivers (harmless if no GPU is passed through)
  64. apk add --no-cache libva libva-utils mesa-va-gallium intel-media-driver libdrm >/dev/null 2>&1 || \
  65. say "VA-API driver packages unavailable on this release — skipping (software encode still works)."
  66. # ---- app files from repo ---------------------------------------------------
  67. say "Pulling application files from ${REPO_BASE} (branches tried: ${BRANCHES})…"
  68. mkdir -p "$APP_DIR/static" "$DATA_DIR/uploads" "$DATA_DIR/output" "$DATA_DIR/jobs"
  69. fetch "$APP_DIR/app.py" "^#!/usr/bin/env python3" "app.py" \
  70. || die "Failed to fetch a valid app.py — check the repo URL, branch name, and that the repo is public."
  71. fetch "$APP_DIR/static/index.html" "^<!DOCTYPE html>" "static/index.html" "index.html" \
  72. || die "Failed to fetch a valid index.html — expected at static/index.html (or repo root) on branch master or main."
  73. fetch "$APP_DIR/update.sh" "^#!/bin/sh" "update.sh" \
  74. || die "Failed to fetch a valid update.sh from the repo."
  75. chmod +x "$APP_DIR/update.sh"
  76. # ---- token.json (generated locally, NEVER from the repo) -------------------
  77. if [ -f "$APP_DIR/token.json" ]; then
  78. say "token.json already exists — keeping existing secrets."
  79. else
  80. say "Generating token.json (local secrets — not stored in the repo)…"
  81. python3 - "$APP_DIR/token.json" <<'PYEOF'
  82. import json, secrets, sys, os
  83. path = sys.argv[1]
  84. tok = {
  85. "api_token": secrets.token_urlsafe(32),
  86. "secret_key": secrets.token_urlsafe(32),
  87. "require_auth": False,
  88. "bots": {}
  89. }
  90. with open(path, "w") as f:
  91. json.dump(tok, f, indent=2)
  92. os.chmod(path, 0o600)
  93. print(" api_token:", tok["api_token"])
  94. PYEOF
  95. say "Set \"require_auth\": true in $APP_DIR/token.json to require this token for all API/bot access."
  96. fi
  97. # ---- OpenRC service ---------------------------------------------------------
  98. say "Installing OpenRC service…"
  99. cat > /etc/init.d/webrake <<EOF
  100. #!/sbin/openrc-run
  101. name="webrake"
  102. description="WeBrake — HandBrake web UI"
  103. command="/usr/bin/python3"
  104. command_args="$APP_DIR/app.py"
  105. command_background=true
  106. pidfile="/run/webrake.pid"
  107. output_log="/var/log/webrake.log"
  108. error_log="/var/log/webrake.log"
  109. export WEBRAKE_PORT="$PORT"
  110. export WEBRAKE_DATA="$DATA_DIR"
  111. depend() {
  112. need net
  113. }
  114. EOF
  115. chmod +x /etc/init.d/webrake
  116. rc-update add webrake default >/dev/null 2>&1 || true
  117. rc-service webrake restart >/dev/null 2>&1 || rc-service webrake start
  118. IP="$(ip -4 addr show scope global 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f1 | head -n1)"
  119. say "Done. WeBrake is running at: http://${IP:-<container-ip>}:${PORT}"
  120. say "Update any time with: $APP_DIR/update.sh"