#!/bin/bash # Root-requiring installation steps for ytstream. # # susan has no passwordless sudo, so everything needing root is collected here for # the operator to run in one go: # # sudo /opt/ytstream/deploy/deploy.sh # # This is the only command needed. It creates the state directory, builds the venv # by calling bootstrap.sh as the service user, and only then installs and starts # the units. # # That ordering is not cosmetic. An earlier version installed the units first and # told the operator to run bootstrap.sh separately โ€” but bootstrap.sh needs the # state directory, which only this script can create, so neither could go first. # The units started, failed 203/EXEC against a venv that did not exist yet, and # restart-looped until the venv appeared. set -euo pipefail REPO=/opt/ytstream STATE=/var/lib/ytstream VENV=$STATE/venv SERVICE_USER=susan HOSTNAME_=tube.jihakuz.xyz if [[ $EUID -ne 0 ]]; then echo "This script needs root. Run: sudo $0" >&2 exit 1 fi say() { printf '\n\033[1m==> %s\033[0m\n' "$1"; } say "Creating $STATE" # root-owned directory, group-writable by `automation` so susan's cron job and the # admin server can both write the database. install -d -o "$SERVICE_USER" -g automation -m 0770 "$STATE" say "Building the virtualenv" if [[ -x $VENV/bin/ytstream ]]; then echo " already present at $VENV" else # As the service user, so the venv is not left root-owned. Absolute path: # runuser lives in /sbin, which is not always on the invoking PATH. /sbin/runuser -u "$SERVICE_USER" -- bash "$REPO/deploy/bootstrap.sh" fi # Refuse to start units that cannot possibly work. Restart=always would otherwise # turn a missing venv into a restart loop in the journal. if [[ ! -x $VENV/bin/ytstream ]]; then echo "The virtualenv was not built. Fix that, then re-run $0." >&2 exit 1 fi say "Installing the /usr/local/bin shim" cat > /usr/local/bin/ytstream </dev/null; then echo " $HOSTNAME_ is already served by an existing vhost." echo " Repoint its proxy_pass to http://127.0.0.1:8086 by hand, then:" echo " nginx -t && systemctl reload nginx" echo " (Deliberately not edited automatically โ€” that block also serves" echo " other names and owns the TLS certificate.)" else echo " No existing vhost found. Install one proxying to 127.0.0.1:8086" echo " and run: certbot --nginx -d $HOSTNAME_" fi say "Done" cat <<'EOF' Remaining steps, all as susan and none needing root: ytstream set-password # admin UI login ytstream set-jellyfin-key # verified against the live server ytstream set-youtube-key # verified against the live API ytstream add-source @cflux1030 # the mirrored account ytstream sync # queues the subscriptions ytstream pending # review them ytstream approve --all # or approve a subset by id ytstream run # first real cycle ytstream doctor # confirm everything is wired up Then add the cron entries from deploy/crontab.fragment to susan's crontab. EOF