#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" source "${script_dir}/lib-compose-project.sh" compose_file="" env_file="" app_service="app" db_service="db" log_tail="80" usage() { cat < --env-file [options] Collect basic diagnostics when Nextcloud OCC never becomes ready. Options: --compose-file Docker compose file to inspect (required) --env-file Env file to inspect (required) --app-service Nextcloud app service name (default: app) --db-service Database service name (default: db) --log-tail Number of recent log lines to print (default: 80) -h, --help Show this help USAGE } read_kv() { local key="$1" local line line="$(grep -m1 -E "^${key}=" "${env_file}" || true)" if [[ -z "${line}" ]]; then return 1 fi echo "${line#*=}" } ensure_docker_access() { local docker_path="" docker_path="$(type -P docker || true)" if [[ -z "${docker_path}" ]]; then echo "docker is required" exit 1 fi if "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=("${docker_path}") return 0 fi if ! command -v sudo >/dev/null 2>&1; then echo "docker is installed but this user cannot access it, and sudo is unavailable." exit 1 fi if sudo -n "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=(sudo "${docker_path}") return 0 fi echo "docker requires elevated privileges on this machine." echo "You may be prompted for your sudo password." if sudo "${docker_path}" info >/dev/null 2>&1; then DOCKER_CMD=(sudo "${docker_path}") return 0 fi echo "Unable to access docker, even with sudo." exit 1 } docker() { "${DOCKER_CMD[@]}" "$@" } while [[ $# -gt 0 ]]; do case "$1" in --compose-file) compose_file="${2:-}" shift 2 ;; --compose-file=*) compose_file="${1#*=}" shift ;; --env-file) env_file="${2:-}" shift 2 ;; --env-file=*) env_file="${1#*=}" shift ;; --app-service) app_service="${2:-}" shift 2 ;; --app-service=*) app_service="${1#*=}" shift ;; --db-service) db_service="${2:-}" shift 2 ;; --db-service=*) db_service="${1#*=}" shift ;; --log-tail) log_tail="${2:-}" shift 2 ;; --log-tail=*) log_tail="${1#*=}" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" usage exit 1 ;; esac done if [[ -z "${compose_file}" || -z "${env_file}" ]]; then usage exit 1 fi if [[ "${compose_file}" != /* ]]; then compose_file="${repo_root}/${compose_file}" fi if [[ "${env_file}" != /* ]]; then env_file="${repo_root}/${env_file}" fi if [[ ! -f "${compose_file}" ]]; then echo "Missing compose file: ${compose_file}" exit 1 fi if [[ ! -f "${env_file}" ]]; then echo "Missing env file: ${env_file}" exit 1 fi export_compose_project_name_from_env "${env_file}" || true ensure_docker_access mysql_db="$(read_kv "MYSQL_DATABASE" || true)" mysql_user="$(read_kv "MYSQL_USER" || true)" mysql_password="$(read_kv "MYSQL_PASSWORD" || true)" compose_project="${COMPOSE_PROJECT_NAME:-}" db_container_id="$(docker compose -f "${compose_file}" --env-file "${env_file}" ps -q "${db_service}" 2>/dev/null || true)" echo "Nextcloud OCC readiness diagnostics" echo " compose_file=${compose_file}" echo " env_file=${env_file}" echo " app_service=${app_service}" echo " db_service=${db_service}" echo " compose_project=${compose_project:-}" echo echo "Compose status:" docker compose -f "${compose_file}" --env-file "${env_file}" ps || true if [[ -n "${db_container_id}" ]]; then echo echo "DB container mounts:" docker inspect "${db_container_id}" --format '{{ range .Mounts }}{{ .Type }} {{ if .Name }}{{ .Name }}{{ else }}{{ .Source }}{{ end }} -> {{ .Destination }}{{ println }}{{ end }}' 2>/dev/null || true fi echo echo "OCC status attempt:" docker compose -f "${compose_file}" --env-file "${env_file}" exec -T --user www-data "${app_service}" php occ status 2>&1 || true echo echo "config/config.php presence:" docker compose -f "${compose_file}" --env-file "${env_file}" exec -T "${app_service}" sh -lc ' if [ -f /var/www/html/config/config.php ]; then echo "present" else echo "missing" fi ' 2>&1 || true if [[ -n "${mysql_db}" && -n "${mysql_user}" && -n "${mysql_password}" ]]; then echo echo "Database schema probe (oc_appconfig):" schema_probe_output="$(docker compose -f "${compose_file}" --env-file "${env_file}" exec -T "${db_service}" \ mariadb -u"${mysql_user}" -p"${mysql_password}" "${mysql_db}" \ -e "SHOW TABLES LIKE 'oc_appconfig';" 2>&1 || true)" if [[ -n "${schema_probe_output}" ]]; then printf '%s\n' "${schema_probe_output}" else echo " " echo " Likely cause: database exists but Nextcloud schema was never initialized in this MariaDB volume." echo " Common reason: Compose project name changed, so this cloud attached to a fresh db_data volume." fi fi echo echo "Recent ${app_service} logs:" docker compose -f "${compose_file}" --env-file "${env_file}" logs --tail "${log_tail}" "${app_service}" 2>&1 || true echo echo "Recent ${db_service} logs:" docker compose -f "${compose_file}" --env-file "${env_file}" logs --tail "${log_tail}" "${db_service}" 2>&1 || true