#!/bin/sh # Rechazo device agent installer (Linux x86_64 / aarch64, systemd). Needs an enrollment code from your organisation's admin. # # curl -fsSL https://get.rechazo.study/install.sh | sudo sh -s -- --code RZE-XXXX-XXXX-XXXX # # What it does, in order: downloads the release, VERIFIES ITS ed25519 SIGNATURE (and sha256) against the public key embedded # below (nothing is installed if that fails), installs /usr/local/bin/rechazo (root-owned; refuses a user-writable location), # installs and starts the systemd service, then enrolls this device with your code (read from stdin, never from argv), which also # writes the Claude Code managed settings. # # Options: --code CODE (or RECHAZO_ENROLL_CODE) --server URL (default https://rechazo-api.airedcell.dev) --version X # --dry-run (download and verify, print what it would do, change nothing) # --uninstall (stop the service, remove the managed settings, the binary, the unit and /etc/rechazo; no code needed) # For testing a release locally, RECHAZO_BASE_URL may be a file:// URL; the signature is checked either way. set -eu BASE_URL="${RECHAZO_BASE_URL:-https://get.rechazo.study}" SERVER="${RECHAZO_SERVER:-https://rechazo-api.airedcell.dev}" VERSION="latest" CODE="${RECHAZO_ENROLL_CODE:-}" DRY_RUN=0 UNINSTALL=0 BIN=/usr/local/bin/rechazo UNIT=/etc/systemd/system/rechazo.service die() { printf 'rechazo install: %s\n' "$*" >&2; exit 1; } say() { printf '%s\n' "$*"; } write_public_key() { cat >"$1" <<'RELEASE_KEY' -----BEGIN PUBLIC KEY----- MCowBQYDK2VwAyEAVF0a2tAfI4FOcdKDRnwBibaV+4r3m1l5myvMYMXAQcI= -----END PUBLIC KEY----- RELEASE_KEY } while [ $# -gt 0 ]; do case "$1" in --code) CODE="${2:?--code needs a value}"; shift 2 ;; --server) SERVER="${2:?--server needs a value}"; shift 2 ;; --version) VERSION="${2:?--version needs a value}"; shift 2 ;; --dry-run) DRY_RUN=1; shift ;; --uninstall) UNINSTALL=1; shift ;; -h | --help) sed -n '2,14p' "$0" 2>/dev/null || true; exit 0 ;; *) die "unknown option: $1" ;; esac done if [ "$UNINSTALL" = 1 ]; then [ "$(id -u)" = 0 ] || die "run as root: sudo sh install.sh --uninstall" [ -x "$BIN" ] && "$BIN" managed-settings remove >/dev/null 2>&1 || true systemctl disable --now rechazo.service >/dev/null 2>&1 || true rm -f "$BIN" "$UNIT" rm -rf /etc/rechazo /run/rechazo systemctl daemon-reload >/dev/null 2>&1 || true say "Rechazo removed from this device. Ask your admin to revoke the device in the dashboard if it should stop showing there." exit 0 fi [ -n "$CODE" ] || die "an enrollment code from your organisation is required: re-run with --code RZE-XXXX-XXXX-XXXX (ask your admin; codes are single-use and expire)" case "$CODE" in RZE-????-????-????) ;; *) die "that doesn't look like an enrollment code (expected RZE-XXXX-XXXX-XXXX)" ;; esac case "$VERSION" in *[!A-Za-z0-9._-]*) die "invalid version" ;; esac [ "$(uname -s)" = Linux ] || die "this installer supports Linux only" case "$(uname -m)" in x86_64 | amd64) ARCH=x86_64 ;; aarch64 | arm64) ARCH=aarch64 ;; *) die "unsupported CPU architecture: $(uname -m) (x86_64 and aarch64 only)" ;; esac if [ "$DRY_RUN" = 0 ]; then [ "$(id -u)" = 0 ] || die "run as root: curl -fsSL ${BASE_URL}/install.sh | sudo sh -s -- --code " [ -d /run/systemd/system ] || die "systemd is required (the agent runs as a root-owned service)" fi for tool in openssl tar install; do command -v "$tool" >/dev/null 2>&1 || die "'$tool' is required"; done if command -v curl >/dev/null 2>&1; then fetch() { curl -fsSL --proto '=https,file' --max-time 120 -o "$2" "$1"; } else command -v wget >/dev/null 2>&1 || die "curl or wget is required" fetch() { wget -q -O "$2" "$1"; } fi TMP="$(mktemp -d)" trap 'rm -rf "$TMP"' EXIT write_public_key "$TMP/release.pub" grep -q '@RELEASE_PUBLIC''_KEY@' "$TMP/release.pub" && die "this copy of the installer has no release key embedded; download it from ${BASE_URL}/install.sh" NAME="rechazo-linux-${ARCH}.tar.gz" say "Downloading ${NAME} (${VERSION})…" fetch "${BASE_URL}/${VERSION}/${NAME}" "$TMP/$NAME" || die "could not download ${BASE_URL}/${VERSION}/${NAME}" fetch "${BASE_URL}/${VERSION}/${NAME}.sig" "$TMP/$NAME.sig" || die "could not download the signature" if openssl pkeyutl -verify -pubin -inkey "$TMP/release.pub" -rawin -in "$TMP/$NAME" -sigfile "$TMP/$NAME.sig" >/dev/null 2>&1; then say "Signature OK." else die "THE SIGNATURE DOES NOT MATCH. The download was altered or is not from Rechazo. Nothing was installed." fi if fetch "${BASE_URL}/${VERSION}/${NAME}.sha256" "$TMP/$NAME.sha256" 2>/dev/null; then [ "$(cut -d' ' -f1 "$TMP/$NAME.sha256")" = "$(openssl dgst -sha256 -r "$TMP/$NAME" | cut -d' ' -f1)" ] || die "the download is corrupt (sha256 mismatch). Nothing was installed." fi mkdir "$TMP/pkg" tar -xzf "$TMP/$NAME" -C "$TMP/pkg" --no-same-owner rechazo rechazo.service || die "the release archive is malformed" [ -f "$TMP/pkg/rechazo" ] && [ ! -L "$TMP/pkg/rechazo" ] || die "the release archive is malformed" # The binary must sit where no unprivileged user can replace it (or its directories). for dir in /usr/local/bin /usr/local /usr; do [ -d "$dir" ] || continue if [ "$(stat -c %u "$dir")" != 0 ] || [ $(($(stat -c 0%a "$dir") & 18)) -ne 0 ]; then if [ "$DRY_RUN" = 1 ]; then say "WARNING: $dir is not root-owned and closed to group/other writes; a real install would refuse." else die "$dir is writable by non-root users; refusing to install the agent there" fi fi done if [ "$DRY_RUN" = 1 ]; then say "Dry run: would install $BIN, $UNIT, start the service and enroll against $SERVER. Nothing was changed." exit 0 fi install -d -m 0755 -o root -g root /usr/local/bin install -m 0755 -o root -g root "$TMP/pkg/rechazo" "$BIN" install -m 0644 -o root -g root "$TMP/pkg/rechazo.service" "$UNIT" install -d -m 0700 -o root -g root /etc/rechazo systemctl daemon-reload systemctl enable rechazo.service >/dev/null 2>&1 || true systemctl restart rechazo.service || die "the service did not start; see: systemctl status rechazo" say "Service started. Enrolling this device…" # The code goes in on stdin so it never shows up in `ps`. printf '%s' "$CODE" | "$BIN" enroll - --server "$SERVER" || die "enrollment failed; the service is installed, run: sudo rechazo enroll --server $SERVER" say "Done. Check it with: systemctl status rechazo and rechazo status"