TUISTREAM/install.sh
28allday 959e507a83 Initial commit: TUISTREAM — headless Jellyfin TUI for Omarchy/Arch
Three-tab Bubble Tea TUI (Setup / Manage / Monitor) for setting up and
running a headless Jellyfin server over SSH:

- Setup: install/uninstall Jellyfin, add media drives (single or btrfs
  RAID pool), import an existing detached btrfs pool non-destructively,
  firewall, move Jellyfin storage onto a media drive
- Boot-drive-safe drive classifier (walks LUKS/LVM/RAID to the physical
  disk; never offers a disk hosting /, /boot or swap)
- Keep-existing-filesystem path previews on-disk content, skips starter
  folders when content exists, and grants Jellyfin recursive read access
- Manage: copy from external drives, mount/eject, rename/delete
- Monitor: per-core CPU, load/mem/uptime, btrfs error counters, SMART

Single static binary; installs to /usr/local/bin so sudo can find it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 16:47:18 +01:00

104 lines
3.6 KiB
Bash
Executable file

#!/usr/bin/env bash
#
# install.sh — install TUISTREAM, a TUI for a headless Jellyfin server on
# Omarchy / Arch.
#
# Quick install (nothing to clone — the Once way):
#
# curl -fsSL https://raw.githubusercontent.com/28allday/TUISTREAM/main/install.sh | bash
#
# When run from a git clone it builds from source instead (if Go is present),
# otherwise it downloads the latest released binary for your architecture.
#
# ./install.sh
#
# Environment overrides:
# PREFIX=/somewhere install prefix (default /usr/local → /usr/local/bin)
# TUISTREAM_VERSION=v0.1.0 pin a release (default: latest)
#
# Why /usr/local/bin (not ~/.local/bin): TUISTREAM is a root-by-design tool —
# it installs Jellyfin, edits /etc/fstab and mounts drives, so it's run as
# `sudo tuistream`. /usr/local/bin is on the default Arch sudo secure_path;
# ~/.local/bin is NOT, so a user-local copy wouldn't be found under sudo.
set -euo pipefail
REPO="28allday/TUISTREAM"
PREFIX="${PREFIX:-/usr/local}"
BIN_DIR="$PREFIX/bin"
NAME="tuistream"
BIN="$BIN_DIR/$NAME"
VERSION="${TUISTREAM_VERSION:-latest}"
log() { printf '\033[1;36m==>\033[0m %s\n' "$*"; }
die() { printf '\033[1;31merror:\033[0m %s\n' "$*" >&2; exit 1; }
# If the script lives next to the source tree, we're in a clone.
SCRIPT_DIR=""
if [ -n "${BASH_SOURCE[0]:-}" ] && [ -f "${BASH_SOURCE[0]}" ]; then
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
fi
# Writing to a system prefix needs root; fall back to sudo when we're not it.
SUDO=""
if [ ! -w "$BIN_DIR" ]; then
if command -v sudo >/dev/null 2>&1; then
SUDO="sudo"
else
die "cannot write $BIN_DIR and sudo not available — re-run as root."
fi
fi
$SUDO mkdir -p "$BIN_DIR"
# ---- obtain the binary ---------------------------------------------------
TMPBIN=""
if [ -n "$SCRIPT_DIR" ] && [ -f "$SCRIPT_DIR/go.mod" ] && command -v go >/dev/null 2>&1; then
log "Building $NAME from source..."
TMPBIN="$(mktemp)"
trap 'rm -f "$TMPBIN"' EXIT
( cd "$SCRIPT_DIR" && CGO_ENABLED=0 go build -trimpath -ldflags='-s -w' \
-o "$TMPBIN" "./cmd/$NAME" )
elif [ -n "$SCRIPT_DIR" ] && [ -x "$SCRIPT_DIR/dist/${NAME}-linux-amd64" ]; then
log "Using prebuilt binary from dist/"
TMPBIN="$SCRIPT_DIR/dist/${NAME}-linux-amd64"
else
# Download the released binary for this OS/arch (curl-style install).
os="$(uname -s | tr '[:upper:]' '[:lower:]')"
[ "$os" = "linux" ] || die "TUISTREAM ships Linux binaries only (detected: $os). Clone the repo and build with Go."
case "$(uname -m)" in
x86_64 | amd64) arch=amd64 ;;
aarch64 | arm64) arch=arm64 ;;
*) die "unsupported architecture: $(uname -m)" ;;
esac
asset="${NAME}-${os}-${arch}"
if [ "$VERSION" = "latest" ]; then
url="https://github.com/$REPO/releases/latest/download/$asset"
else
url="https://github.com/$REPO/releases/download/$VERSION/$asset"
fi
log "Downloading $asset ($VERSION)..."
TMPBIN="$(mktemp)"
trap 'rm -f "$TMPBIN"' EXIT
if command -v curl >/dev/null 2>&1; then
curl -fSL --proto '=https' --tlsv1.2 -o "$TMPBIN" "$url"
elif command -v wget >/dev/null 2>&1; then
wget -qO "$TMPBIN" "$url"
else
die "need curl or wget to download the binary."
fi
fi
# ---- install -------------------------------------------------------------
log "Installing to $BIN"
$SUDO install -Dm755 "$TMPBIN" "$BIN"
# Remove any stale ~/.local/bin copy that would shadow the system one under a
# non-sudo PATH (older installs landed there).
OLD="$HOME/.local/bin/$NAME"
if [ -e "$OLD" ]; then
log "Removing stale user-local copy: $OLD"
rm -f "$OLD"
fi
echo
log "Done. Run it with: sudo $NAME"