#!/usr/bin/env bash set -euo pipefail repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" env_file="${repo_root}/.env.devprod" source "${repo_root}/scripts/lib-compose-project.sh" usage() { cat </dev/null | tr -d '\r[:space:]' || true)" if [[ "${cron_uid}" == "33" ]]; then echo "Cron container user verified: 33 (www-data)." return 0 fi echo "Warning: cron container is running as UID ${cron_uid:-unknown}, expected 33 (www-data)." echo "Recreate cron container to apply compose user settings:" echo " docker compose -f ${compose_file} --env-file ${env_file} up -d --force-recreate --no-deps cron" return 1 } mode="nossl" extauth="auto" while [[ $# -gt 0 ]]; do case "$1" in --mode) mode="${2:-}" shift 2 ;; --mode=*) mode="${1#*=}" shift ;; --ssl) mode="ssl" shift ;; --nossl) mode="nossl" shift ;; --extauth) extauth="1" shift ;; --no-extauth) extauth="0" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" usage exit 1 ;; esac done if [[ "${mode}" != "ssl" && "${mode}" != "nossl" ]]; then echo "Invalid mode: ${mode}" usage exit 1 fi if [[ ! -f "${env_file}" ]]; then echo "Missing ${env_file}." echo "Run: ./scripts/install-production-docker.sh --guided" exit 1 fi if ! export_compose_project_name_from_env "${env_file}"; then warn_missing_compose_project_name "${env_file}" fi compose_file="${repo_root}/docker-compose.devprod.nossl.yml" if [[ "${mode}" == "ssl" ]]; then compose_file="${repo_root}/docker-compose.devprod.yml" fi nextcloud_custom_apps_path="$(resolve_path_from_env "NEXTCLOUD_CUSTOM_APPS_PATH" "./nextcloud/custom_apps")" mkdir -p "${repo_root}/nextcloud/html" "${repo_root}/nextcloud/data" "${nextcloud_custom_apps_path}" "${repo_root}/qortal/data" if [[ -x "${repo_root}/scripts/ensure-user-oidc-app.sh" ]]; then NEXTCLOUD_CUSTOM_APPS_PATH="${nextcloud_custom_apps_path}" "${repo_root}/scripts/ensure-user-oidc-app.sh" fi if [[ -x "${repo_root}/scripts/ensure-qortal-integration-app.sh" ]]; then NEXTCLOUD_CUSTOM_APPS_PATH="${nextcloud_custom_apps_path}" "${repo_root}/scripts/ensure-qortal-integration-app.sh" fi if [[ -x "${repo_root}/scripts/ensure-qortal-settings.sh" ]]; then "${repo_root}/scripts/ensure-qortal-settings.sh" fi if [[ -x "${repo_root}/scripts/ensure-qortal-start-args.sh" ]]; then "${repo_root}/scripts/ensure-qortal-start-args.sh" "${env_file}" fi if [[ -x "${repo_root}/scripts/select-qortal-p2p-port.sh" ]]; then "${repo_root}/scripts/select-qortal-p2p-port.sh" "${env_file}" fi if [[ -f "${repo_root}/scripts/ensure-broker-internal-token.sh" ]]; then bash "${repo_root}/scripts/ensure-broker-internal-token.sh" "${env_file}" fi if [[ -x "${repo_root}/scripts/ensure-oidc-signing-key.sh" ]]; then "${repo_root}/scripts/ensure-oidc-signing-key.sh" "${env_file}" fi if [[ -x "${repo_root}/scripts/sync-public-env-urls.sh" ]]; then "${repo_root}/scripts/sync-public-env-urls.sh" \ --env-file "${env_file}" \ --mode "${mode}" fi broker_internal_api_token="$(read_kv "BROKER_INTERNAL_API_TOKEN" || true)" if [[ -z "${broker_internal_api_token}" ]]; then echo "BROKER_INTERNAL_API_TOKEN is missing in ${env_file}" echo "Run: bash scripts/ensure-broker-internal-token.sh ${env_file}" exit 1 fi export BROKER_INTERNAL_API_TOKEN="${broker_internal_api_token}" broker_cors_allowed_origins="$(read_kv "BROKER_CORS_ALLOWED_ORIGINS" || true)" export BROKER_CORS_ALLOWED_ORIGINS="${broker_cors_allowed_origins:-}" echo "Broker auth env loaded from ${env_file}: token_set=yes cors_origins=${broker_cors_allowed_origins:-}" current_profiles="" if command -v rg >/dev/null 2>&1; then profiles_line="$(rg -m1 '^COMPOSE_PROFILES=' "${env_file}" || true)" else profiles_line="$(grep -m1 -E '^COMPOSE_PROFILES=' "${env_file}" || true)" fi if [[ -n "${profiles_line}" ]]; then current_profiles="${profiles_line#COMPOSE_PROFILES=}" fi if [[ "${extauth}" == "1" ]]; then if [[ -z "${current_profiles}" ]]; then current_profiles="external-auth" elif [[ ",${current_profiles}," != *",external-auth,"* ]]; then current_profiles="${current_profiles},external-auth" fi elif [[ "${extauth}" == "0" ]]; then filtered=() IFS=',' read -r -a profile_parts <<< "${current_profiles}" for p in "${profile_parts[@]}"; do p_trimmed="$(echo "${p}" | tr -d '[:space:]')" [[ -z "${p_trimmed}" ]] && continue [[ "${p_trimmed}" == "external-auth" ]] && continue filtered+=("${p_trimmed}") done current_profiles="$(IFS=','; echo "${filtered[*]}")" else external_auth_base_url="$(read_kv "QORTAL_EXTERNAL_AUTH_BASE_URL" || true)" if [[ "${external_auth_base_url}" == *"external_auth"* ]]; then if [[ -z "${current_profiles}" ]]; then current_profiles="external-auth" elif [[ ",${current_profiles}," != *",external-auth,"* ]]; then current_profiles="${current_profiles},external-auth" fi fi fi if [[ -n "${current_profiles}" ]]; then export COMPOSE_PROFILES="${current_profiles}" else unset COMPOSE_PROFILES || true fi echo "Using compose file: ${compose_file}" echo "Using profiles: ${COMPOSE_PROFILES:-}" echo "Starting stack..." if [[ "${mode}" == "ssl" ]]; then if [[ -n "${COMPOSE_PROFILES:-}" ]]; then (cd "${repo_root}" && COMPOSE_PROFILES="${COMPOSE_PROFILES}" make up-devprod) else (cd "${repo_root}" && make up-devprod) fi else if [[ -n "${COMPOSE_PROFILES:-}" ]]; then (cd "${repo_root}" && COMPOSE_PROFILES="${COMPOSE_PROFILES}" make up-devprod-nossl) else (cd "${repo_root}" && make up-devprod-nossl) fi fi if [[ -x "${repo_root}/scripts/ensure-nextcloud-apps-writable.sh" ]]; then if ! "${repo_root}/scripts/ensure-nextcloud-apps-writable.sh" --mode "${mode}" --env-file "${env_file}"; then echo "Warning: could not guarantee Nextcloud apps directory writeability." echo "Apps page and app install/update operations may fail until fixed." fi fi verify_cron_container_user || true cron_mode_status=1 for _ in $(seq 1 18); do if docker compose -f "${compose_file}" --env-file "${env_file}" exec -T --user www-data app php occ status >/dev/null 2>&1; then if docker compose -f "${compose_file}" --env-file "${env_file}" exec -T --user www-data app php occ config:system:set backgroundjobs_mode --value=cron >/dev/null 2>&1; then cron_mode_status=0 fi break fi sleep 5 done if [[ "${cron_mode_status}" -eq 0 ]]; then echo "Nextcloud background jobs mode set to cron." else echo "Warning: could not set Nextcloud background jobs mode to cron yet." echo "Run manually once OCC is ready:" echo " docker compose -f ${compose_file} --env-file ${env_file} exec -T --user www-data app php occ config:system:set backgroundjobs_mode --value=cron" fi nextcloud_url_sync_status=0 if [[ -x "${repo_root}/scripts/ensure-nextcloud-url-config.sh" ]]; then set +e "${repo_root}/scripts/ensure-nextcloud-url-config.sh" \ --compose-file "${compose_file}" \ --env-file "${env_file}" nextcloud_url_sync_status=$? set -e fi if [[ "${nextcloud_url_sync_status}" -eq 0 ]]; then echo "Nextcloud URL config synchronized from ${env_file}." else echo "Warning: could not synchronize Nextcloud URL config from ${env_file}." echo "Run manually once OCC is ready:" echo " ./scripts/ensure-nextcloud-url-config.sh --compose-file ${compose_file} --env-file ${env_file}" fi qortal_runtime_sync_status=0 if [[ -x "${repo_root}/scripts/ensure-qortal-integration-runtime-config.sh" ]]; then set +e "${repo_root}/scripts/ensure-qortal-integration-runtime-config.sh" \ --compose-file "${compose_file}" \ --env-file "${env_file}" >/dev/null 2>&1 qortal_runtime_sync_status=$? set -e fi if [[ "${qortal_runtime_sync_status}" -eq 0 ]]; then echo "NuQloud identity provider runtime config synchronized from ${env_file}." else echo "Warning: could not synchronize NuQloud identity provider runtime config yet." echo "Run manually once OCC and broker are ready:" echo " ./scripts/ensure-qortal-integration-runtime-config.sh --compose-file ${compose_file} --env-file ${env_file}" fi echo echo "Done."