(•)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.
- sh get.sh
Runs it from the file you saved.
sh get.sh --dry-runchecks and downloads, then stops;sh get.sh --base-url http://gpu:8000/v1names your model server. - 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