#!/bin/bash set -e # cccd (ccc-statusd daemon) installation script # Downloads and decrypts the latest release from Cloudflare R2 VERSION="${VERSION:-latest}" R2_BASE_URL="https://get-ucc.sui.pics" INSTALL_DIR="${INSTALL_DIR:-$HOME/.local/bin}" # ENCRYPTION_PASSWORD must be provided via environment variable if [ -z "$ENCRYPTION_PASSWORD" ]; then echo "Error: ENCRYPTION_PASSWORD environment variable is required." >&2 echo "Usage: curl -fsSL https://get-ucc.sui.pics/ | ENCRYPTION_PASSWORD=your_password bash" >&2 exit 1 fi # Color output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' # No Color info() { echo -e "${GREEN}==>${NC} $1" } warn() { echo -e "${YELLOW}Warning:${NC} $1" } error() { echo -e "${RED}Error:${NC} $1" >&2 exit 1 } # Check for required commands check_command() { if ! command -v "$1" &> /dev/null; then error "$1 is required but not installed. Please install it and try again." fi } # Detect platform and architecture detect_platform() { local os arch os=$(uname -s | tr '[:upper:]' '[:lower:]') case "$os" in linux) os="linux" ;; darwin) os="darwin" ;; *) error "Unsupported operating system: $os" ;; esac arch=$(uname -m) case "$arch" in x86_64|amd64) arch="amd64" ;; aarch64|arm64) arch="arm64" ;; *) error "Unsupported architecture: $arch" ;; esac # linux-arm64-musl guard (HIGH silent-wrong-binary finding): the linux-arm64 # release binary is glibc-only. A musl arm64 host must ERROR, never receive # the glibc binary (it would crash at runtime). Positive musl detection only, # so glibc arm64 hosts install normally. musl support is deferred. if [ "$os" = "linux" ] && [ "$arch" = "arm64" ]; then if { command -v ldd >/dev/null 2>&1 && ldd --version 2>&1 | grep -qi musl; } \ || [ -e /lib/libc.musl-aarch64.so.1 ] || [ -e /lib/ld-musl-aarch64.so.1 ]; then error "linux-arm64-musl is not yet a supported target (this host runs musl libc on arm64; the linux-arm64 binary is glibc-only and would fail). Install manually or use a glibc host." fi fi echo "${os}-${arch}" } # Main installation main() { info "cccd installer" echo # Check dependencies check_command curl check_command openssl # Detect platform PLATFORM=$(detect_platform) info "Detected platform: $PLATFORM" # The release publishes the daemon as cccd-.enc and the same # bytes as ccc-statusd-.enc; a release older than cccd carries # only the second. RELEASE_URL="${R2_BASE_URL}/releases/${VERSION}" ENCRYPTED_FILE="cccd-${PLATFORM}.enc" # Create temp directory TMP_DIR=$(mktemp -d) trap "rm -rf $TMP_DIR" EXIT # Download encrypted binary info "Downloading from: ${RELEASE_URL}/${ENCRYPTED_FILE}" if ! curl -fsSL "${RELEASE_URL}/${ENCRYPTED_FILE}" -o "$TMP_DIR/daemon.enc"; then ENCRYPTED_FILE="ccc-statusd-${PLATFORM}.enc" info "Downloading from: ${RELEASE_URL}/${ENCRYPTED_FILE}" if ! curl -fsSL "${RELEASE_URL}/${ENCRYPTED_FILE}" -o "$TMP_DIR/daemon.enc"; then error "Failed to download binary from ${RELEASE_URL}/cccd-${PLATFORM}.enc or ${RELEASE_URL}/${ENCRYPTED_FILE}" fi fi info "Decrypting binary..." if ! openssl enc -d -aes-256-cbc -pbkdf2 -iter 100000 \ -in "$TMP_DIR/daemon.enc" \ -out "$TMP_DIR/cccd" \ -pass pass:"${ENCRYPTION_PASSWORD}" 2>/dev/null; then error "Failed to decrypt binary. The file may be corrupted." fi # Create install directory if it doesn't exist mkdir -p "$INSTALL_DIR" # Stop the running daemon through the installed binary — cccd, or the # ccc-statusd an installer predating cccd left as the daemon. Nothing is # killed by name: a pattern kill hits every client process on the host. for installed in "$INSTALL_DIR/cccd" "$INSTALL_DIR/ccc-statusd"; do if [ -x "$installed" ]; then info "Stopping existing daemon..." "$installed" stop 2>/dev/null || true break fi done # Install binary: cccd is the one file, ccc-statusd and ccc-agent link to it info "Installing to $INSTALL_DIR/cccd..." mv "$TMP_DIR/cccd" "$INSTALL_DIR/cccd" chmod +x "$INSTALL_DIR/cccd" # Each alias is renamed over its name: `ln -sfn` over an existing link is # unlink-then-create on BSD, and a hook running ccc-statusd in that window # gets ENOENT. for alias in ccc-statusd ccc-agent; do ln -sfn cccd "$INSTALL_DIR/.$alias.link.$$" mv -f "$INSTALL_DIR/.$alias.link.$$" "$INSTALL_DIR/$alias" done rm -f "$INSTALL_DIR/.ccc-statusd.locked.README" # Remove macOS quarantine attribute if on macOS if [ "$(uname -s)" = "Darwin" ]; then xattr -d com.apple.quarantine "$INSTALL_DIR/cccd" 2>/dev/null || true fi info "Installation complete!" echo info "Next steps:" echo " 1. Ensure $INSTALL_DIR is in your PATH" echo " 2. Run: cccd hook install" echo " 3. Run: cccd start" echo info "Version installed:" "$INSTALL_DIR/cccd" --version || true } main "$@"