Ctrl K
ComunidadGuías…

install.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/bin/sh
# muxdeck installer
#
#   curl -fsSL https://raw.githubusercontent.com/josecarlosrivas/muxdeck/main/install.sh | sh
#
# Environment overrides (all optional):
#   MUXDECK_BIN_DIR   install location                    (default /usr/local/bin)
#   MUXDECK_MODE      run | service | cloud | binary | update  (default: ask on a TTY, else binary)
#   MUXDECK_PORT      port for service/cloud mode         (default 8300)
#   MUXDECK_CLOUD_URL account server for cloud mode       (default https://cloud.muxdeck.app)
set -eu

REPO="josecarlosrivas/muxdeck"
BIN_DIR="${MUXDECK_BIN_DIR:-/usr/local/bin}"
MODE="${MUXDECK_MODE:-}"
PORT="${MUXDECK_PORT:-8300}"
CLOUD_URL="${MUXDECK_CLOUD_URL:-https://cloud.muxdeck.app}"

say() { printf '%s\n' "$*"; }
err() { printf 'muxdeck install: %s\n' "$*" >&2; exit 1; }

# --- platform detection ---
os=$(uname -s); arch=$(uname -m)
case "$os" in
  Linux)  os=linux ;;
  Darwin) os=darwin ;;
  *) err "unsupported OS: $os (linux and macOS only)" ;;
esac
case "$arch" in
  x86_64|amd64)  arch=amd64 ;;
  aarch64|arm64) arch=arm64 ;;
  *) err "unsupported architecture: $arch" ;;
esac

# --- tmux check ---
if command -v tmux >/dev/null 2>&1; then
  say "+ tmux found: $(tmux -V)"
else
  say "! tmux is NOT installed — muxdeck requires it."
  case "$os" in
    linux)  say "  install it first, e.g.: sudo apt install tmux   (or dnf / pacman / apk)" ;;
    darwin) say "  install it first, e.g.: brew install tmux" ;;
  esac
  say "  continuing — muxdeck will work as soon as tmux is present."
fi

# --- download ---
asset="muxdeck-$os-$arch"
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
say "+ downloading $asset (latest release)"
if ! curl -fsSL -o "$tmp/muxdeck" "https://github.com/$REPO/releases/latest/download/$asset"; then
  if command -v gh >/dev/null 2>&1; then
    say "  direct download failed, retrying via gh"
    gh release download -R "$REPO" -p "$asset" -O "$tmp/muxdeck" || err "download failed"
  else
    err "download failed (https://github.com/$REPO/releases)"
  fi
fi
chmod +x "$tmp/muxdeck"

# --- install ---
prev_version=$("$BIN_DIR/muxdeck" -version 2>/dev/null || true)
# BIN_DIR may not exist (fresh macOS has no /usr/local/bin); install(1) won't create it.
if [ ! -d "$BIN_DIR" ]; then
  say "+ creating $BIN_DIR"
  mkdir -p "$BIN_DIR" 2>/dev/null || sudo mkdir -p "$BIN_DIR"
fi
if [ -w "$BIN_DIR" ]; then
  install -m 755 "$tmp/muxdeck" "$BIN_DIR/muxdeck"
else
  say "+ installing to $BIN_DIR (needs sudo)"
  sudo install -m 755 "$tmp/muxdeck" "$BIN_DIR/muxdeck"
fi
say "+ installed: $("$BIN_DIR/muxdeck" -version 2>/dev/null || echo "muxdeck (pre-0.3 release)") at $BIN_DIR/muxdeck"

# --- mode selection ---
if [ -z "$MODE" ] && [ -r /dev/tty ]; then
  say ""
  say "How do you want to run muxdeck?"
  say "  1) Try it now  — foreground on http://127.0.0.1:$PORT, ^C to stop"
  say "  2) Service     — starts at boot, listens on all interfaces, token-protected"
  say "  3) Cloud       — starts at boot on loopback, reachable through your muxdeck cloud relay"
  say "  4) Nothing     — just the binary, I'll run it myself"
  if [ -n "$prev_version" ]; then
    say "  5) Update      — you had $prev_version; keep its setup, restart the service"
  fi
  printf 'Choose [1-5, default 1]: '
  read -r choice </dev/tty || choice=""
  case "$choice" in
    2) MODE=service ;;
    3) MODE=cloud ;;
    4) MODE=binary ;;
    5) MODE=update ;;
    *) MODE=run ;;
  esac
fi
[ -n "$MODE" ] || MODE=binary

gen_token() {
  LC_ALL=C tr -dc 'A-HJ-KM-NP-TV-Z2-9' </dev/urandom | head -c 6
}

# install_service <listen-addr> [token] — systemd unit or launchd agent,
# running as the invoking user, starting at boot.
install_service() {
  addr=$1; svc_token=${2:-}
  env_line="MUXDECK_ADDR=$addr"
  [ -n "$svc_token" ] && env_line="$env_line MUXDECK_TOKEN=$svc_token"
  if [ "$os" = linux ]; then
    command -v systemctl >/dev/null 2>&1 || err "service mode needs systemd on Linux"
    unit=/etc/systemd/system/muxdeck.service
    [ -e "$unit" ] && say "! $unit already exists — overwriting"
    sudo tee "$unit" >/dev/null <<EOF
[Unit]
Description=muxdeck web terminal for tmux
After=network-online.target

[Service]
User=$(id -un)
Environment=$env_line
ExecStart=$BIN_DIR/muxdeck
Restart=on-failure
RestartSec=3
# keep the tmux server (and your sessions) alive across muxdeck restarts
KillMode=process

[Install]
WantedBy=multi-user.target
EOF
    sudo systemctl daemon-reload
    sudo systemctl enable --now muxdeck
    say "+ systemd service 'muxdeck' is running (journalctl -u muxdeck for logs)"
  else
    plist="$HOME/Library/LaunchAgents/com.muxdeck.agent.plist"
    [ -e "$plist" ] && say "! $plist already exists — overwriting"
    mkdir -p "$HOME/Library/LaunchAgents"
    {
      printf '%s\n' '<?xml version="1.0" encoding="UTF-8"?>'
      printf '%s\n' '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">'
      printf '%s\n' '<plist version="1.0"><dict>'
      printf '%s\n' '  <key>Label</key><string>com.muxdeck.agent</string>'
      printf '  <key>ProgramArguments</key><array><string>%s/muxdeck</string></array>\n' "$BIN_DIR"
      printf '%s\n' '  <key>EnvironmentVariables</key><dict>'
      printf '    <key>MUXDECK_ADDR</key><string>%s</string>\n' "$addr"
      [ -n "$svc_token" ] && printf '    <key>MUXDECK_TOKEN</key><string>%s</string>\n' "$svc_token"
      printf '%s\n' '  </dict>'
      printf '%s\n' '  <key>RunAtLoad</key><true/>'
      printf '%s\n' '  <key>KeepAlive</key><dict><key>SuccessfulExit</key><false/></dict>'
      printf '%s\n' '</dict></plist>'
    } >"$plist"
    launchctl bootout "gui/$(id -u)/com.muxdeck.agent" 2>/dev/null || true
    launchctl bootstrap "gui/$(id -u)" "$plist"
    say "+ launchd agent 'com.muxdeck.agent' is running"
  fi
}

case "$MODE" in
  binary)
    say ""
    say "Run 'muxdeck' for a local instance, 'muxdeck -h' for all options."
    say "Binding beyond localhost (-addr 0.0.0.0:$PORT) auto-generates an access"
    say "code on startup; use -token for a fixed secret or -no-auth to disable."
    ;;

  run)
    say ""
    exec "$BIN_DIR/muxdeck" -addr "127.0.0.1:$PORT"
    ;;

  service)
    token=$(gen_token)
    install_service "0.0.0.0:$PORT" "$token"
    say ""
    say "Access token: $token   (kept in the service definition; change it there)"
    say "Listening on port $PORT on all interfaces. Likely addresses:"
    if [ "$os" = linux ]; then
      hostname -I 2>/dev/null | tr ' ' '\n' | sed "/^$/d; s|^|  http://|; s|\$|:$PORT|" || true
    else
      for ifc in en0 en1; do ipconfig getifaddr "$ifc" 2>/dev/null || true; done \
        | sed "s|^|  http://|; s|\$|:$PORT|"
    fi
    say ""
    say "How you expose it is up to you: keep it LAN/VPN-only, front it with a"
    say "reverse proxy, or use built-in TLS (-tls-cert/-tls-key). HTTPS is required"
    say "for installing the PWA on phones/tablets."
    ;;

  update)
    new_version=$("$BIN_DIR/muxdeck" -version 2>/dev/null || echo "muxdeck (unknown)")
    say ""
    if [ -z "$prev_version" ]; then
      say "No previous install was found — this was a fresh install of $new_version."
      say "Re-run the installer to pick a run mode, or just run 'muxdeck'."
    elif [ "$prev_version" = "$new_version" ]; then
      say "Already current: $new_version (binary refreshed in place)."
    else
      say "Updated: $prev_version -> $new_version."
    fi
    # The binary is swapped; a running service keeps the old one until
    # restarted. Restart it where we can tell which shape this machine has.
    restart_cmd=""
    if [ "$os" = linux ]; then
      if systemctl is-enabled muxdeck >/dev/null 2>&1; then
        restart_cmd="sudo systemctl restart muxdeck"
      elif systemctl --user is-enabled muxdeck >/dev/null 2>&1; then
        restart_cmd="systemctl --user restart muxdeck"
      fi
    else
      if launchctl print "gui/$(id -u)/com.muxdeck.agent" >/dev/null 2>&1; then
        restart_cmd="launchctl kickstart -k gui/$(id -u)/com.muxdeck.agent"
      fi
    fi
    if [ -n "$restart_cmd" ]; then
      printf 'Restart the muxdeck service now? [Y/n]: '
      if read -r yn 2>/dev/null </dev/tty; then
        case "$yn" in
          [Nn]*) say "Not restarted — run: $restart_cmd" ;;
          *) $restart_cmd && say "+ service restarted on $new_version" ;;
        esac
      else
        # No usable terminal — never restart a service behind the user's back.
        say ""
        say "Now restart the service: $restart_cmd"
      fi
    else
      say "No muxdeck service found here — if one runs another way, restart it yourself."
    fi
    ;;

  cloud)
    # Loopback and tokenless: nothing to reach directly, nothing to leak.
    # The relay is the front door and its gate does the authenticating.
    install_service "127.0.0.1:$PORT"
    say "+ waiting for the daemon"
    i=0
    until curl -fsS -o /dev/null "http://127.0.0.1:$PORT/api/sessions" 2>/dev/null; do
      i=$((i+1)); [ "$i" -ge 30 ] && err "daemon did not come up on 127.0.0.1:$PORT"
      sleep 1
    done
    say ""
    # The CLI's own after-claim instructions are for manual setups; keep its
    # claim-code line and speak the cloud flow ourselves.
    setup_out=$(MUXDECK_URL="http://127.0.0.1:$PORT" "$BIN_DIR/muxdeck" relay setup "$CLOUD_URL" 2>&1) || {
      printf '%s\n' "$setup_out"; err "relay setup failed"
    }
    printf '%s\n' "$setup_out" | grep -i "claim code" || printf '%s\n' "$setup_out"
    say ""
    say "Claim this machine: open $CLOUD_URL, sign in, and enter the code"
    say "under Daemons. The installer finishes the connection for you."
    if [ -r /dev/tty ]; then
      printf 'Press Enter once you have claimed the code ... '
      read -r _ </dev/tty || true
      MUXDECK_URL="http://127.0.0.1:$PORT" "$BIN_DIR/muxdeck" relay on
      sleep 2
      MUXDECK_URL="http://127.0.0.1:$PORT" "$BIN_DIR/muxdeck" relay || true
      say ""
      say "Done — this machine now appears in your muxdeck apps."
    else
      say "After claiming, run: muxdeck relay on   (then 'muxdeck relay' to check)"
    fi
    ;;
esac