Ctrl K
ComunidadGuías…

install.sh

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
#!/usr/bin/env bash

# MiroTalk Call-Me installer for Ubuntu 22.04 and 24.04.
# Run from the repository root with: sudo ./install.sh

set -Eeuo pipefail

readonly NODE_MAJOR=24
readonly DOCKER_IMAGE='mirotalk/cme:latest'
readonly CONFIG_FILE='public/config.js'
readonly CONFIG_TEMPLATE='public/config.template.js'
readonly ENV_FILE='.env'
readonly ENV_TEMPLATE='.env.template'
readonly COMPOSE_FILE='docker-compose.yml'
readonly COMPOSE_TEMPLATE='docker-compose.template.yml'

if [[ -t 1 ]] && command -v tput >/dev/null 2>&1 && [[ -n "${TERM:-}" ]]; then
    readonly RED="$(tput setaf 1)"
    readonly YELLOW="$(tput setaf 3)"
    readonly MAGENTA="$(tput setaf 5)"
    readonly RESET="$(tput sgr0)"
else
    readonly RED=''
    readonly YELLOW=''
    readonly MAGENTA=''
    readonly RESET=''
fi

log() {
    local level="$1"
    shift
    local color="$MAGENTA"

    case "$level" in
        warning) color="$YELLOW" ;;
        error) color="$RED" ;;
    esac

    printf '%s :: %b%s%b\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$color" "$*" "$RESET"
}

die() {
    log error "$*" >&2
    exit 1
}

on_error() {
    local exit_code=$?
    log error "Installation failed near line ${BASH_LINENO[0]} (exit ${exit_code})." >&2
    exit "$exit_code"
}

trap on_error ERR

confirm() {
    local prompt="$1"
    local default_answer="${2:-y}"
    local answer
    local hint='[y/N]'

    [[ "$default_answer" == 'y' ]] && hint='[Y/n]'

    while true; do
        read -r -p "$prompt $hint " answer
        answer="${answer:-$default_answer}"
        case "$answer" in
            [Yy]|[Yy][Ee][Ss]) return 0 ;;
            [Nn]|[Nn][Oo]) return 1 ;;
            *) printf 'Please answer yes or no.\n' ;;
        esac
    done
}

require_command() {
    command -v "$1" >/dev/null 2>&1 || die "Required command not found: $1"
}

copy_if_missing() {
    local source_file="$1"
    local destination_file="$2"

    if [[ -e "$destination_file" ]]; then
        log warning "Keeping existing ${destination_file}"
        return
    fi

    cp "$source_file" "$destination_file"
    if [[ -n "${SUDO_UID:-}" && -n "${SUDO_GID:-}" ]]; then
        chown "$SUDO_UID:$SUDO_GID" "$destination_file"
    fi
    log info "Created ${destination_file} from ${source_file}"
}

run_as_project_user() {
    if [[ -n "${SUDO_USER:-}" && "$SUDO_USER" != 'root' ]]; then
        sudo -u "$SUDO_USER" -- "$@"
    else
        "$@"
    fi
}

install_nodejs() {
    local installed_major=0

    if command -v node >/dev/null 2>&1; then
        installed_major="$(node --version | sed -E 's/^v([0-9]+).*/\1/')"
    fi

    if (( installed_major >= NODE_MAJOR )); then
        log info "Node.js $(node --version) already satisfies the requirement"
        return
    fi

    log info "Installing Node.js ${NODE_MAJOR}.x"
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl gnupg
    install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key \
        | gpg --dearmor --yes -o /etc/apt/keyrings/nodesource.gpg
    printf 'deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_%s.x nodistro main\n' "$NODE_MAJOR" \
        > /etc/apt/sources.list.d/nodesource.list
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y nodejs
}

install_docker() {
    if command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1; then
        log info 'Docker Engine and Compose v2 are already installed'
        return
    fi

    log info 'Installing Docker Engine and Compose v2'
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl gnupg
    install -m 0755 -d /etc/apt/keyrings
    curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
    chmod a+r /etc/apt/keyrings/docker.asc

    printf 'deb [arch=%s signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu %s stable\n' \
        "$(dpkg --print-architecture)" "$VERSION_CODENAME" > /etc/apt/sources.list.d/docker.list
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y \
        containerd.io docker-buildx-plugin docker-ce docker-ce-cli docker-compose-plugin
    systemctl enable --now docker
}

[[ "$(uname -s)" == 'Linux' ]] || die 'This installer supports Linux only.'
[[ "$EUID" -eq 0 ]] || die 'Run this installer as root: sudo ./install.sh'
[[ -r /etc/os-release ]] || die 'Unable to identify this Linux distribution.'

. /etc/os-release
[[ "${ID:-}" == 'ubuntu' ]] || die 'This installer currently supports Ubuntu only.'
[[ "${VERSION_ID:-}" == '22.04' || "${VERSION_ID:-}" == '24.04' ]] || \
    log warning "Ubuntu ${VERSION_ID:-unknown} has not been tested; continuing anyway."

cd "$(dirname "${BASH_SOURCE[0]}")"
[[ -f package.json && -f package-lock.json && -f "$CONFIG_TEMPLATE" && -f "$ENV_TEMPLATE" ]] || \
    die 'Run this script from a complete MiroTalk Call-Me checkout.'

log info "MiroTalk Call-Me installer on Ubuntu ${VERSION_ID:-unknown}"

if confirm 'Use Docker?' y; then
    if confirm 'Install or update Docker dependencies?' y; then
        install_docker
    fi

    require_command docker
    docker compose version >/dev/null 2>&1 || \
        die "Docker Compose v2 is required (the command is 'docker compose')."

    copy_if_missing "$ENV_TEMPLATE" "$ENV_FILE"
    copy_if_missing "$COMPOSE_TEMPLATE" "$COMPOSE_FILE"

    if confirm 'Use the official Docker image?' y; then
        log info "Pulling ${DOCKER_IMAGE}"
        docker pull "$DOCKER_IMAGE"
    else
        log info "Building ${DOCKER_IMAGE} from this checkout"
        docker build --tag "$DOCKER_IMAGE" .
    fi

    log info 'Starting MiroTalk Call-Me in the background'
    docker compose up -d
    docker compose ps
else
    if confirm 'Install or update Node.js?' y; then
        install_nodejs
    fi

    require_command node
    require_command npm
    node_major="$(node --version | sed -E 's/^v([0-9]+).*/\1/')"
    (( node_major >= NODE_MAJOR )) || \
        die "Node.js ${NODE_MAJOR} or newer is required; found $(node --version)."

    copy_if_missing "$CONFIG_TEMPLATE" "$CONFIG_FILE"
    copy_if_missing "$ENV_TEMPLATE" "$ENV_FILE"

    log info 'Installing npm dependencies from the lockfile'
    run_as_project_user npm ci

    log info 'Starting MiroTalk Call-Me (press Ctrl+C to stop)'
    run_as_project_user npm start
fi