#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" broker_dir="/opt/qortal-broker" env_file="" compose_file="" rebuild_qortal="0" usage() { cat < Broker runtime dir (default: /opt/qortal-broker) --env-file Env file override (default: /.env) --compose-file Compose file override (default: /docker-compose.yml) --qortal Rebuild qortal_node before recreating host-hybrid services -h, --help Show this help USAGE } read_kv() { local key="$1" local file="$2" local line="" if [[ -z "${file}" || ! -f "${file}" ]]; then return 1 fi line="$(grep -m1 -E "^${key}=" "${file}" 2>/dev/null || true)" [[ -n "${line}" ]] || return 1 printf '%s' "${line#*=}" } resolve_path() { local raw="${1:-}" if [[ -z "${raw}" ]]; then printf '%s' "" return 0 fi if [[ "${raw}" == /* ]]; then printf '%s' "${raw}" return 0 fi printf '%s' "${repo_root}/${raw}" } ensure_qortal_data_permissions() { local data_dir="${1:-}" if [[ -z "${data_dir}" || ! -d "${data_dir}" ]]; then return 0 fi if [[ "${EUID:-$(id -u)}" -eq 0 ]]; then chown -R 1000:100 "${data_dir}" >/dev/null 2>&1 || true chmod -R u+rwX,g+rwX "${data_dir}" >/dev/null 2>&1 || true return 0 fi if command -v sudo >/dev/null 2>&1; then if sudo -n chown -R 1000:100 "${data_dir}" >/dev/null 2>&1 || sudo chown -R 1000:100 "${data_dir}" >/dev/null 2>&1; then sudo chmod -R u+rwX,g+rwX "${data_dir}" >/dev/null 2>&1 || true return 0 fi fi echo "Warning: could not repair Qortal data ownership for ${data_dir}." >&2 } ensure_docker_cmd() { if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then DOCKER_CMD=(docker) return 0 fi if command -v sudo >/dev/null 2>&1; then if sudo -n docker info >/dev/null 2>&1 || sudo docker info >/dev/null 2>&1; then DOCKER_CMD=(sudo docker) return 0 fi fi echo "docker access is required to restart the host-hybrid stack." >&2 exit 1 } contains_service() { local needle="$1" shift local item for item in "$@"; do if [[ "${item}" == "${needle}" ]]; then return 0 fi done return 1 } while [[ $# -gt 0 ]]; do case "$1" in --broker-dir) broker_dir="${2:-}" shift 2 ;; --broker-dir=*) broker_dir="${1#*=}" shift ;; --env-file) env_file="${2:-}" shift 2 ;; --env-file=*) env_file="${1#*=}" shift ;; --compose-file) compose_file="${2:-}" shift 2 ;; --compose-file=*) compose_file="${1#*=}" shift ;; --qortal) rebuild_qortal="1" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" >&2 usage exit 1 ;; esac done broker_dir="$(resolve_path "${broker_dir}")" env_file="${env_file:-${broker_dir}/.env}" compose_file="${compose_file:-${broker_dir}/docker-compose.yml}" env_file="$(resolve_path "${env_file}")" compose_file="$(resolve_path "${compose_file}")" if [[ ! -f "${env_file}" ]]; then echo "Missing env file: ${env_file}" >&2 exit 1 fi if [[ ! -f "${compose_file}" ]]; then echo "Missing compose file: ${compose_file}" >&2 exit 1 fi source "${script_dir}/lib-compose-project.sh" export_compose_project_name_from_env "${env_file}" || true ensure_docker_cmd profiles="$(read_kv "COMPOSE_PROFILES" "${env_file}" || true)" services=("broker_db" "broker") if [[ ",${profiles}," == *",external-auth,"* ]]; then services+=("external_auth") fi if [[ ",${profiles}," == *",qortal,"* || "${rebuild_qortal}" == "1" ]]; then if [[ -x "${repo_root}/scripts/ensure-qortal-settings.sh" ]]; then "${repo_root}/scripts/ensure-qortal-settings.sh" --target-dir "${broker_dir}/qortal/data" fi if [[ -x "${repo_root}/scripts/ensure-qortal-start-args.sh" ]]; then "${repo_root}/scripts/ensure-qortal-start-args.sh" --target-dir "${broker_dir}/qortal/data" "${env_file}" fi if ! contains_service "qortal_node" "${services[@]}"; then services+=("qortal_node") fi ensure_qortal_data_permissions "${broker_dir}/qortal/data" fi echo "Recreating host-hybrid services:" printf ' %s\n' "${services[@]}" if [[ "${rebuild_qortal}" == "1" ]]; then echo "Rebuilding qortal_node with --no-cache..." "${DOCKER_CMD[@]}" compose -f "${compose_file}" --env-file "${env_file}" build --no-cache qortal_node fi compose_up_args=(-d --force-recreate) if [[ "${rebuild_qortal}" == "1" ]]; then compose_up_args+=(--build) fi "${DOCKER_CMD[@]}" compose -f "${compose_file}" --env-file "${env_file}" up "${compose_up_args[@]}" "${services[@]}" broker_port="$(read_kv "BROKER_PORT" "${env_file}" || true)" broker_port="${broker_port:-3000}" external_auth_port="$(read_kv "EXTERNAL_AUTH_PORT" "${env_file}" || true)" external_auth_port="${external_auth_port:-3191}" curl -fsS --max-time 15 "http://127.0.0.1:${broker_port}/.well-known/openid-configuration" >/dev/null 2>&1 || true if [[ ",${profiles}," == *",external-auth,"* ]]; then curl -fsS --max-time 15 "http://127.0.0.1:${external_auth_port}/health" >/dev/null 2>&1 || true fi echo "Host-hybrid services restarted."