mirror of
https://github.com/myronblair/kino-app
synced 2026-07-27 21:18:43 -05:00
auto-commit for 39cc8e25-6412-479f-a29a-2a2bbf6e58ba
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"env_image_name": "fastapi_react_mongo_shadcn_base_image_cloud_arm:release-17042026-1",
|
"env_image_name": "fastapi_react_mongo_shadcn_base_image_cloud_arm:release-17042026-1",
|
||||||
"job_id": "08d9a7a1-2a0c-4502-9939-fc5d643c04c4",
|
"job_id": "08d9a7a1-2a0c-4502-9939-fc5d643c04c4",
|
||||||
"created_at": "2026-07-23T21:54:52.675455+00:00Z"
|
"created_at": "2026-07-23T22:02:35.449854+00:00Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,31 @@
|
|||||||
A self-hosted Netflix-style streaming app for movies you legally own.
|
A self-hosted Netflix-style streaming app for movies you legally own.
|
||||||
Built with FastAPI + React + MongoDB.
|
Built with FastAPI + React + MongoDB.
|
||||||
|
|
||||||
## 📖 Deployment
|
## ⚡ One-line install (Proxmox / any Linux with root)
|
||||||
|
|
||||||
**→ See [DEPLOY.md](./DEPLOY.md) for full Proxmox + Docker Compose instructions**
|
```bash
|
||||||
(runs alongside your existing LAMP stack without conflicts).
|
curl -fsSL https://raw.githubusercontent.com/YOU/kino-media-server/main/install.sh | sudo bash
|
||||||
|
```
|
||||||
|
|
||||||
|
Replace `YOU` with your GitHub username. The installer:
|
||||||
|
1. Installs Docker + Compose if missing
|
||||||
|
2. Clones the repo into `/opt/kino`
|
||||||
|
3. Generates a strong `JWT_SECRET` and admin password
|
||||||
|
4. Starts the stack via `docker compose`
|
||||||
|
5. Prints the URL + credentials
|
||||||
|
|
||||||
|
Non-interactive with overrides:
|
||||||
|
```bash
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/YOU/kino-media-server/main/install.sh \
|
||||||
|
| sudo KINO_HTTP_PORT=9000 \
|
||||||
|
MEDIA_ROOT_HOST=/mnt/nas/movies \
|
||||||
|
ADMIN_PASSWORD='choose-your-own' \
|
||||||
|
bash
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📖 Full deployment
|
||||||
|
|
||||||
|
See **[DEPLOY.md](./DEPLOY.md)** for LAMP-coexistence, Apache reverse proxy, Radarr integration, and firewalling.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
|||||||
Executable
+193
@@ -0,0 +1,193 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
#
|
||||||
|
# Kino — one-line installer
|
||||||
|
#
|
||||||
|
# Usage (interactive):
|
||||||
|
# curl -fsSL https://raw.githubusercontent.com/YOU/kino-media-server/main/install.sh | sudo bash
|
||||||
|
#
|
||||||
|
# Usage (non-interactive, override defaults with env):
|
||||||
|
# curl -fsSL .../install.sh | sudo KINO_HTTP_PORT=9000 MEDIA_ROOT_HOST=/mnt/nas/movies bash
|
||||||
|
#
|
||||||
|
# What it does:
|
||||||
|
# 1. Installs Docker + Compose if missing (apt/dnf/yum)
|
||||||
|
# 2. Clones the repo into $KINO_DIR (default /opt/kino)
|
||||||
|
# 3. Generates a strong JWT_SECRET and (if omitted) ADMIN_PASSWORD
|
||||||
|
# 4. Writes .env
|
||||||
|
# 5. Runs `docker compose up -d`
|
||||||
|
# 6. Prints URL + credentials
|
||||||
|
#
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
# ---------- Defaults (override via env) ----------
|
||||||
|
KINO_REPO="${KINO_REPO:-https://github.com/CHANGE_ME/kino-media-server.git}"
|
||||||
|
KINO_BRANCH="${KINO_BRANCH:-main}"
|
||||||
|
KINO_DIR="${KINO_DIR:-/opt/kino}"
|
||||||
|
KINO_HTTP_PORT="${KINO_HTTP_PORT:-8080}"
|
||||||
|
MEDIA_ROOT_HOST="${MEDIA_ROOT_HOST:-${KINO_DIR}/media}"
|
||||||
|
DB_NAME="${DB_NAME:-kino}"
|
||||||
|
ADMIN_EMAIL="${ADMIN_EMAIL:-admin@kino.local}"
|
||||||
|
ADMIN_NAME="${ADMIN_NAME:-Admin}"
|
||||||
|
ADMIN_PASSWORD="${ADMIN_PASSWORD:-}"
|
||||||
|
JWT_SECRET="${JWT_SECRET:-}"
|
||||||
|
|
||||||
|
# ---------- Pretty output ----------
|
||||||
|
c_red() { printf "\033[31m%s\033[0m" "$*"; }
|
||||||
|
c_grn() { printf "\033[32m%s\033[0m" "$*"; }
|
||||||
|
c_ylw() { printf "\033[33m%s\033[0m" "$*"; }
|
||||||
|
c_cyn() { printf "\033[36m%s\033[0m" "$*"; }
|
||||||
|
say() { printf "%s %s\n" "$(c_cyn '›')" "$*"; }
|
||||||
|
ok() { printf "%s %s\n" "$(c_grn '✓')" "$*"; }
|
||||||
|
warn() { printf "%s %s\n" "$(c_ylw '!')" "$*"; }
|
||||||
|
die() { printf "%s %s\n" "$(c_red '✗')" "$*" >&2; exit 1; }
|
||||||
|
|
||||||
|
# ---------- Preflight ----------
|
||||||
|
[ "$(id -u)" -eq 0 ] || die "Run as root (or via sudo). Try: curl -fsSL ... | sudo bash"
|
||||||
|
|
||||||
|
if [ "$KINO_REPO" = "https://github.com/CHANGE_ME/kino-media-server.git" ]; then
|
||||||
|
die "KINO_REPO placeholder — edit install.sh and set your GitHub URL, or pass KINO_REPO=... env var."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- OS detection & package manager ----------
|
||||||
|
if [ -r /etc/os-release ]; then . /etc/os-release; fi
|
||||||
|
OS_ID="${ID:-unknown}"
|
||||||
|
say "Detected OS: ${OS_ID} ${VERSION_ID:-}"
|
||||||
|
|
||||||
|
pkg_install() {
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
|
apt-get update -qq
|
||||||
|
DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends "$@"
|
||||||
|
elif command -v dnf >/dev/null 2>&1; then
|
||||||
|
dnf install -y "$@"
|
||||||
|
elif command -v yum >/dev/null 2>&1; then
|
||||||
|
yum install -y "$@"
|
||||||
|
else
|
||||||
|
die "No supported package manager (apt/dnf/yum) found."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---------- Ensure prerequisites ----------
|
||||||
|
need_pkgs=()
|
||||||
|
command -v curl >/dev/null 2>&1 || need_pkgs+=(curl)
|
||||||
|
command -v git >/dev/null 2>&1 || need_pkgs+=(git)
|
||||||
|
command -v openssl >/dev/null 2>&1 || need_pkgs+=(openssl)
|
||||||
|
command -v ca-certificates >/dev/null 2>&1 || need_pkgs+=(ca-certificates)
|
||||||
|
|
||||||
|
if [ ${#need_pkgs[@]} -gt 0 ]; then
|
||||||
|
say "Installing prerequisites: ${need_pkgs[*]}"
|
||||||
|
pkg_install "${need_pkgs[@]}" >/dev/null
|
||||||
|
ok "Prerequisites installed"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Docker ----------
|
||||||
|
if ! command -v docker >/dev/null 2>&1; then
|
||||||
|
say "Installing Docker via official convenience script"
|
||||||
|
curl -fsSL https://get.docker.com | sh
|
||||||
|
systemctl enable --now docker
|
||||||
|
ok "Docker installed"
|
||||||
|
else
|
||||||
|
ok "Docker already installed ($(docker --version))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! docker compose version >/dev/null 2>&1; then
|
||||||
|
# docker compose plugin missing — install
|
||||||
|
say "Installing docker compose plugin"
|
||||||
|
if command -v apt-get >/dev/null 2>&1; then
|
||||||
|
pkg_install docker-compose-plugin >/dev/null
|
||||||
|
else
|
||||||
|
die "docker compose plugin not found — install it manually for your distro."
|
||||||
|
fi
|
||||||
|
ok "Compose plugin installed"
|
||||||
|
else
|
||||||
|
ok "Docker Compose already available ($(docker compose version --short))"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Clone or update repo ----------
|
||||||
|
if [ -d "$KINO_DIR/.git" ]; then
|
||||||
|
say "Updating existing checkout at $KINO_DIR"
|
||||||
|
git -C "$KINO_DIR" fetch --quiet origin "$KINO_BRANCH"
|
||||||
|
git -C "$KINO_DIR" checkout --quiet "$KINO_BRANCH"
|
||||||
|
git -C "$KINO_DIR" pull --quiet --ff-only origin "$KINO_BRANCH" || warn "git pull skipped (local changes?)"
|
||||||
|
else
|
||||||
|
say "Cloning $KINO_REPO → $KINO_DIR"
|
||||||
|
mkdir -p "$(dirname "$KINO_DIR")"
|
||||||
|
git clone --depth 1 --branch "$KINO_BRANCH" "$KINO_REPO" "$KINO_DIR"
|
||||||
|
ok "Repo cloned"
|
||||||
|
fi
|
||||||
|
|
||||||
|
cd "$KINO_DIR"
|
||||||
|
|
||||||
|
# ---------- Media root ----------
|
||||||
|
mkdir -p "$MEDIA_ROOT_HOST"
|
||||||
|
ok "Media dir ready: $MEDIA_ROOT_HOST"
|
||||||
|
|
||||||
|
# ---------- Secrets ----------
|
||||||
|
if [ -z "$JWT_SECRET" ]; then
|
||||||
|
JWT_SECRET="$(openssl rand -hex 32)"
|
||||||
|
ok "Generated random JWT_SECRET"
|
||||||
|
fi
|
||||||
|
if [ -z "$ADMIN_PASSWORD" ]; then
|
||||||
|
ADMIN_PASSWORD="$(openssl rand -base64 18 | tr -d '/+=' | cut -c1-20)"
|
||||||
|
GENERATED_PASSWORD=1
|
||||||
|
ok "Generated random ADMIN_PASSWORD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Write .env ----------
|
||||||
|
if [ -f .env ]; then
|
||||||
|
cp .env ".env.bak.$(date +%Y%m%d%H%M%S)"
|
||||||
|
warn ".env exists — backed up. Overwriting with new values."
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat > .env <<EOF
|
||||||
|
# Auto-generated by install.sh on $(date -Iseconds)
|
||||||
|
KINO_HTTP_PORT=${KINO_HTTP_PORT}
|
||||||
|
MEDIA_ROOT_HOST=${MEDIA_ROOT_HOST}
|
||||||
|
DB_NAME=${DB_NAME}
|
||||||
|
JWT_SECRET=${JWT_SECRET}
|
||||||
|
JWT_EXPIRE_HOURS=720
|
||||||
|
ADMIN_EMAIL=${ADMIN_EMAIL}
|
||||||
|
ADMIN_PASSWORD=${ADMIN_PASSWORD}
|
||||||
|
ADMIN_NAME=${ADMIN_NAME}
|
||||||
|
EOF
|
||||||
|
chmod 600 .env
|
||||||
|
ok "Wrote $KINO_DIR/.env (chmod 600)"
|
||||||
|
|
||||||
|
# ---------- Build & start ----------
|
||||||
|
say "Building images (first run may take a few minutes — ffmpeg, node build)"
|
||||||
|
docker compose build --pull
|
||||||
|
say "Starting containers"
|
||||||
|
docker compose up -d
|
||||||
|
sleep 4
|
||||||
|
|
||||||
|
# ---------- Health check ----------
|
||||||
|
HOST_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
|
||||||
|
[ -z "$HOST_IP" ] && HOST_IP="localhost"
|
||||||
|
URL="http://${HOST_IP}:${KINO_HTTP_PORT}"
|
||||||
|
|
||||||
|
if curl -fsS --max-time 10 "http://localhost:${KINO_HTTP_PORT}/api/" >/dev/null 2>&1; then
|
||||||
|
ok "Backend healthy at $URL/api/"
|
||||||
|
else
|
||||||
|
warn "Backend not responding yet — check: cd $KINO_DIR && docker compose logs -f backend"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ---------- Done ----------
|
||||||
|
cat <<EOF
|
||||||
|
|
||||||
|
$(c_grn '━━━ Kino is up ━━━')
|
||||||
|
|
||||||
|
URL : $(c_cyn "$URL")
|
||||||
|
Admin : $(c_cyn "$ADMIN_EMAIL")
|
||||||
|
Password : $(c_cyn "$ADMIN_PASSWORD")
|
||||||
|
Config : ${KINO_DIR}/.env
|
||||||
|
Media : ${MEDIA_ROOT_HOST}
|
||||||
|
|
||||||
|
$(c_ylw 'Save the password now — it is only printed once.')
|
||||||
|
|
||||||
|
Manage:
|
||||||
|
cd $KINO_DIR
|
||||||
|
docker compose logs -f backend # live logs
|
||||||
|
docker compose down # stop
|
||||||
|
docker compose up -d # start
|
||||||
|
docker compose pull && docker compose up -d --build # update
|
||||||
|
|
||||||
|
Full docs: $KINO_DIR/DEPLOY.md
|
||||||
|
EOF
|
||||||
Reference in New Issue
Block a user