install.sh 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. #!/bin/sh
  2. # ---------------------------------------------------------------------------
  3. # WeBrake installer — run INSIDE an existing Alpine Linux LXC container.
  4. #
  5. # wget -qO- https://gogs.av2x.dev/av2x/WeBrake/raw/main/install.sh | ash
  6. #
  7. # This script never touches the Proxmox host. It:
  8. # 1. Installs Python, HandBrakeCLI and VA-API drivers via apk
  9. # 2. Pulls app.py / index.html / update.sh from the repo
  10. # 3. Generates a local token.json (never fetched from, or pushed to, the repo)
  11. # 4. Registers and starts an OpenRC service
  12. # ---------------------------------------------------------------------------
  13. set -eu
  14. REPO_RAW="${WEBRAKE_REPO:-https://gogs.av2x.dev/av2x/WeBrake/raw/main}"
  15. APP_DIR="/opt/webrake"
  16. DATA_DIR="/var/lib/webrake"
  17. PORT="${WEBRAKE_PORT:-8090}"
  18. say() { printf '\033[1;33m[WeBrake]\033[0m %s\n' "$*"; }
  19. die() { printf '\033[1;31m[WeBrake]\033[0m %s\n' "$*" >&2; exit 1; }
  20. # --- sanity: Alpine, root, inside a container -------------------------------
  21. [ "$(id -u)" = "0" ] || die "Run as root inside the Alpine container."
  22. [ -f /etc/alpine-release ] || die "This installer only supports Alpine Linux (run it inside the LXC, not on the Proxmox host)."
  23. if [ -r /proc/1/environ ] && grep -qa 'container=' /proc/1/environ 2>/dev/null; then :; fi
  24. say "Installing packages via apk..."
  25. # HandBrake lives in the community repository — make sure it is enabled.
  26. if ! grep -Eq '^[^#].*community' /etc/apk/repositories; then
  27. ALPINE_VER=$(cut -d. -f1,2 /etc/alpine-release)
  28. echo "https://dl-cdn.alpinelinux.org/alpine/v${ALPINE_VER}/community" >> /etc/apk/repositories
  29. say "Enabled the Alpine community repository."
  30. fi
  31. apk update
  32. apk add --no-cache python3 py3-flask wget ca-certificates
  33. if ! apk add --no-cache handbrake >/dev/null 2>&1; then
  34. say "handbrake not in this release's community repo — trying edge/community..."
  35. apk add --no-cache handbrake \
  36. --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community \
  37. --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main \
  38. || die "Could not install HandBrakeCLI via apk. Install it manually, then re-run."
  39. fi
  40. # VA-API / QSV userspace drivers (harmless if no GPU is passed through)
  41. apk add --no-cache libva libva-utils mesa-va-gallium intel-media-driver 2>/dev/null || \
  42. say "GPU driver packages unavailable on this release — software encoding will still work."
  43. command -v HandBrakeCLI >/dev/null || die "HandBrakeCLI is not on PATH after install."
  44. say "HandBrake: $(HandBrakeCLI --version 2>&1 | head -n1)"
  45. # --- fetch application files from the repo ----------------------------------
  46. say "Pulling application files from ${REPO_RAW} ..."
  47. mkdir -p "$APP_DIR" "$DATA_DIR"
  48. for f in app.py index.html update.sh; do
  49. wget -q -O "$APP_DIR/$f.new" "$REPO_RAW/$f" || die "Failed to fetch $f from the repo."
  50. mv "$APP_DIR/$f.new" "$APP_DIR/$f"
  51. done
  52. chmod +x "$APP_DIR/update.sh"
  53. # --- generate token.json locally (NEVER pulled from or pushed to the repo) --
  54. if [ ! -f "$APP_DIR/token.json" ]; then
  55. say "Generating local token.json ..."
  56. python3 - "$APP_DIR/token.json" <<'PY'
  57. import json, secrets, sys, os
  58. path = sys.argv[1]
  59. with open(path, "w") as f:
  60. json.dump({
  61. "api_token": secrets.token_urlsafe(32),
  62. "secret_key": secrets.token_urlsafe(32),
  63. "note": "Generated locally by WeBrake. Do not commit this file."
  64. }, f, indent=2)
  65. os.chmod(path, 0o600)
  66. PY
  67. else
  68. say "Existing token.json found — keeping it."
  69. fi
  70. # --- OpenRC service ----------------------------------------------------------
  71. say "Registering OpenRC service..."
  72. cat > /etc/init.d/webrake <<EOF
  73. #!/sbin/openrc-run
  74. name="WeBrake"
  75. description="WeBrake HandBrake web UI"
  76. command="/usr/bin/python3"
  77. command_args="$APP_DIR/app.py"
  78. command_background="yes"
  79. directory="$APP_DIR"
  80. pidfile="/run/webrake.pid"
  81. output_log="/var/log/webrake.log"
  82. error_log="/var/log/webrake.log"
  83. export WEBRAKE_PORT="$PORT"
  84. depend() {
  85. need net
  86. }
  87. EOF
  88. chmod +x /etc/init.d/webrake
  89. rc-update add webrake default >/dev/null 2>&1 || true
  90. rc-service webrake restart >/dev/null 2>&1 || rc-service webrake start
  91. IP=$(ip -4 addr show scope global 2>/dev/null | awk '/inet /{print $2}' | cut -d/ -f1 | head -n1)
  92. TOKEN=$(python3 -c "import json;print(json.load(open('$APP_DIR/token.json'))['api_token'])")
  93. say "----------------------------------------------------------------"
  94. say "WeBrake is up."
  95. say " URL: http://${IP:-<container-ip>}:${PORT}"
  96. say " API token: ${TOKEN}"
  97. say " Token file: $APP_DIR/token.json (local only — never in the repo)"
  98. say " Update: $APP_DIR/update.sh"
  99. if [ ! -e /dev/dri ] && [ ! -e /dev/nvidia0 ]; then
  100. say " GPU: no /dev/dri or /dev/nvidia* visible. To enable hardware"
  101. say " encoding, add a device passthrough to this container's"
  102. say " config on the Proxmox host (see README), then restart it."
  103. fi
  104. say "----------------------------------------------------------------"