OtōtoOtōto

(•)The installer

What the install command runs.

This is the script https://ototo.sh serves to curl -fsSL https://ototo.sh | sh. It fetches the newest release for your machine, checks its checksums against Otōto's release key (written into the script, and at /release-key.txt), checks the package against them, and only then runs the package's installer, which asks before it changes anything. Read it here, or copy or save it and run it yourself.

Download get.sh

  1. sh get.sh

    Runs it from the file you saved. sh get.sh --dry-run checks and downloads, then stops; sh get.sh --base-url http://gpu:8000/v1 names your model server.

  2. curl -fsSL https://ototo.sh | diff - get.sh

    Prints nothing when your copy is the one ototo.sh serves now. Its SHA-256 is ebf0f8645046257546ff98cdf77fc945e1927f3657aa5847c3e47dd31eafbfd8.

#!/bin/sh
# Installs Otōto, or updates it:
#   curl -fsSL https://ototo.sh | sh                 (sh -s -- --yes: let install.sh write its changes without asking)
# It fetches the newest release for this machine from the download channel, checks that its checksums are signed by
# Otōto's release key (below; also https://ototo.dev/release-key.txt) and that the package matches them, then unpacks
# it into ~/.ototo/update and runs its install.sh, as `ototo update` does. Nothing is installed until both checks pass.
#
#   --dry-run            check and download, then stop
#   OTOTO_CHANNEL_URL    another channel (default https://ototo.sh/beta), e.g. your organisation's mirror
#   OTOTO_UPDATE_TOKEN   a tester's token, for a channel that asks for one
# Needs curl, ssh-keygen, shasum or sha256sum, and unzip (macOS) or tar.
set -eu

KEY='ototo-release namespaces="ototo-release" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGbY61jh3KUm7ENWQfvQ3wrrH9Hd+OxlR2AQL8AZvvqE'
CHANNEL=${OTOTO_CHANNEL_URL:-https://ototo.sh/beta}
CHANNEL=${CHANNEL%/}
DRY=
if [ "${1:-}" = "--dry-run" ]; then DRY=1; shift; fi

fail() { echo "ototo: $*" >&2; exit 1; }
for tool in curl ssh-keygen; do command -v "$tool" > /dev/null || fail "needs $tool"; done

case "$(uname -s)-$(uname -m)" in
  Darwin-arm64) PLATFORM=macos-arm64 ;;
  Linux-x86_64) PLATFORM=linux-x86_64 ;;
  Linux-aarch64 | Linux-arm64) PLATFORM=linux-arm64 ;;
  *) fail "there is no Otōto package for $(uname -s) $(uname -m)" ;;
esac

T=$(mktemp -d)
trap 'rm -rf "$T"' EXIT
fetch() { # <file in the channel> <where>
  if [ -n "${OTOTO_UPDATE_TOKEN:-}" ]; then
    curl -fsSL -H "Authorization: Bearer $OTOTO_UPDATE_TOKEN" "$CHANNEL/$1" -o "$2" || fail "could not download $CHANNEL/$1"
  else
    curl -fsSL "$CHANNEL/$1" -o "$2" || fail "could not download $CHANNEL/$1 (a channel for testers needs OTOTO_UPDATE_TOKEN)"
  fi
}

# The newest release's checksums, their signature after them: checked against the key above.
fetch latest.txt "$T/latest.txt"
sed '/^-----BEGIN SSH SIGNATURE-----$/,$d' "$T/latest.txt" > "$T/sums"
sed -n '/^-----BEGIN SSH SIGNATURE-----$/,$p' "$T/latest.txt" > "$T/sums.sig"
printf '%s\n' "$KEY" > "$T/release-key"
ssh-keygen -Y verify -f "$T/release-key" -I ototo-release -n ototo-release -s "$T/sums.sig" < "$T/sums" > /dev/null 2>&1 \
  || fail "$CHANNEL/latest.txt is not signed by Otōto's release key: nothing installed"

PACKAGE=$(awk -v p="-$PLATFORM." '{ f = $2; sub(/^\*/, "", f); if (index(f, p)) { print f; exit } }' "$T/sums")
[ -n "$PACKAGE" ] || fail "the newest release on $CHANNEL has no package for $PLATFORM"
WANT=$(awk -v f="$PACKAGE" '{ g = $2; sub(/^\*/, "", g); if (g == f) print $1 }' "$T/sums")
echo "Otōto: downloading $PACKAGE"
fetch "$PACKAGE" "$T/$PACKAGE"
if command -v shasum > /dev/null; then GOT=$(shasum -a 256 "$T/$PACKAGE" | awk '{print $1}'); else GOT=$(sha256sum "$T/$PACKAGE" | awk '{print $1}'); fi
[ "$GOT" = "$WANT" ] || fail "$PACKAGE does not match its signed checksum: nothing installed"
echo "  ✓ signed by Otōto's release key, and the package matches its checksum"
if [ -n "$DRY" ]; then echo "  (--dry-run: nothing installed)"; exit 0; fi

# Where `ototo update` unpacks too: the package stays, so install.sh's "Undo all" can name its uninstall.sh.
WORK="$HOME/.ototo/update"
rm -rf "$WORK"
mkdir -p "$WORK"
chmod 700 "$HOME/.ototo" "$WORK"
case "$PACKAGE" in
  *.zip) unzip -q -o "$T/$PACKAGE" -d "$WORK" ;;
  *) tar xzf "$T/$PACKAGE" -C "$WORK" ;;
esac
INSTALL=$(ls "$WORK"/*/install.sh 2> /dev/null | head -1)
[ -n "$INSTALL" ] || fail "the package has no install.sh"
# Run through a pipe, this script's stdin is the script itself: install.sh asks its questions on the terminal.
if (exec < /dev/tty) 2> /dev/null; then sh "$INSTALL" "$@" < /dev/tty; else sh "$INSTALL" "$@"; fi
get.sh70 lines, from the same file ototo.sh serves.