214 lines
6.8 KiB
Bash
214 lines
6.8 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
|
echo "Run this installer as root (sudo)."
|
|
exit 1
|
|
fi
|
|
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
repo_root="$(cd "${script_dir}/.." && pwd)"
|
|
|
|
default_nc_path="/var/www/nextcloud"
|
|
read -r -p "Nextcloud path [${default_nc_path}]: " nc_path
|
|
nc_path="${nc_path:-$default_nc_path}"
|
|
|
|
if [[ ! -f "${nc_path}/occ" ]]; then
|
|
echo "Could not find occ at ${nc_path}/occ. Please check the Nextcloud path."
|
|
exit 1
|
|
fi
|
|
|
|
occ() {
|
|
if command -v sudo >/dev/null 2>&1; then
|
|
sudo -u www-data php "${nc_path}/occ" "$@"
|
|
else
|
|
runuser -u www-data -- php "${nc_path}/occ" "$@"
|
|
fi
|
|
}
|
|
|
|
detect_nc_url() {
|
|
local url
|
|
set +e
|
|
url="$(occ config:system:get overwrite.cli.url 2>/dev/null)"
|
|
if [[ -z "$url" ]]; then
|
|
url="$(occ config:system:get trusted_domains 0 2>/dev/null)"
|
|
if [[ -n "$url" && "$url" != http* ]]; then
|
|
url="https://${url}"
|
|
fi
|
|
fi
|
|
set -e
|
|
echo "$url"
|
|
}
|
|
|
|
nc_url="$(detect_nc_url)"
|
|
read -r -p "Nextcloud URL [${nc_url:-https://cloud.example.com}]: " nc_url_input
|
|
nc_url="${nc_url_input:-$nc_url}"
|
|
if [[ -z "$nc_url" ]]; then
|
|
echo "Nextcloud URL is required."
|
|
exit 1
|
|
fi
|
|
|
|
nc_host="${nc_url#*://}"
|
|
nc_host="${nc_host%%/*}"
|
|
base_domain="$nc_host"
|
|
if [[ "$nc_host" == *.* ]]; then
|
|
base_domain="${nc_host#*.}"
|
|
fi
|
|
|
|
default_broker_host="qortalbroker.${base_domain}"
|
|
read -r -p "Broker hostname [${default_broker_host}]: " broker_host
|
|
broker_host="${broker_host:-$default_broker_host}"
|
|
|
|
read -r -p "Broker external URL [https://${broker_host}]: " broker_url
|
|
broker_url="${broker_url:-https://${broker_host}}"
|
|
|
|
read -r -p "Nextcloud service user [admin]: " nc_service_user
|
|
nc_service_user="${nc_service_user:-admin}"
|
|
read -r -p "Nextcloud service password [admin123]: " nc_service_password
|
|
nc_service_password="${nc_service_password:-admin123}"
|
|
|
|
read -r -p "External Auth base URL [http://127.0.0.1:3191]: " ext_auth_url
|
|
ext_auth_url="${ext_auth_url:-http://127.0.0.1:3191}"
|
|
read -r -p "External Auth app ID: " ext_auth_app_id
|
|
read -r -p "External Auth app secret: " ext_auth_app_secret
|
|
|
|
if [[ ! "${ext_auth_url}" =~ ^https?://(127\.0\.0\.1|localhost) ]]; then
|
|
echo "Warning: External Auth is not local. Ensure secondary wallet encryption is enabled."
|
|
fi
|
|
|
|
gen_secret() {
|
|
tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 32
|
|
}
|
|
|
|
default_db_pass="$(gen_secret)"
|
|
read -r -p "Broker DB password [${default_db_pass}]: " broker_db_password
|
|
broker_db_password="${broker_db_password:-$default_db_pass}"
|
|
|
|
default_oidc_secret="$(gen_secret)"
|
|
read -r -p "OIDC client secret [${default_oidc_secret}]: " oidc_secret
|
|
oidc_secret="${oidc_secret:-$default_oidc_secret}"
|
|
|
|
default_broker_internal_token="$(gen_secret)"
|
|
read -r -p "Broker internal API token [${default_broker_internal_token}]: " broker_internal_token
|
|
broker_internal_token="${broker_internal_token:-$default_broker_internal_token}"
|
|
|
|
broker_dir="/opt/qortal-broker"
|
|
mkdir -p "${broker_dir}"
|
|
|
|
compose_src="${repo_root}/deploy/docker-compose.broker.yml"
|
|
compose_dst="${broker_dir}/docker-compose.yml"
|
|
cp "${compose_src}" "${compose_dst}"
|
|
|
|
cat > "${broker_dir}/.env" <<EOF
|
|
BROKER_BUILD_CONTEXT=${repo_root}/services/qortal-oidc-broker
|
|
BROKER_PORT=3000
|
|
BROKER_DB_NAME=qortal_broker
|
|
BROKER_DB_USER=qortal_broker
|
|
BROKER_DB_PASSWORD=${broker_db_password}
|
|
BROKER_DATABASE_URL=postgresql://qortal_broker:${broker_db_password}@broker_db:5432/qortal_broker
|
|
|
|
NEXTCLOUD_BASE_URL=${nc_url}
|
|
NEXTCLOUD_PUBLIC_URL=${nc_url}
|
|
NEXTCLOUD_SERVICE_USER=${nc_service_user}
|
|
NEXTCLOUD_SERVICE_PASSWORD=${nc_service_password}
|
|
|
|
QORTAL_EXTERNAL_AUTH_BASE_URL=${ext_auth_url}
|
|
QORTAL_EXTERNAL_AUTH_APP_ID=${ext_auth_app_id}
|
|
QORTAL_EXTERNAL_AUTH_APP_SECRET=${ext_auth_app_secret}
|
|
BROKER_INTERNAL_API_TOKEN=${broker_internal_token}
|
|
# Optional comma-separated browser origins for CORS.
|
|
BROKER_CORS_ALLOWED_ORIGINS=${nc_url}
|
|
|
|
OIDC_ISSUER=${broker_url}
|
|
OIDC_CLIENT_ID=nextcloud-local
|
|
OIDC_CLIENT_SECRET=${oidc_secret}
|
|
OIDC_REDIRECT_URI_ALLOWLIST=${nc_url}/apps/user_oidc/code
|
|
OIDC_POLICY_MODE=link_only
|
|
OIDC_AUTO_PROVISION_GUARD=invite_or_allowlist
|
|
OIDC_INVITE_TTL_SECONDS=604800
|
|
OIDC_AUTH_REQUEST_TTL_SECONDS=600
|
|
OIDC_AUTH_CODE_TTL_SECONDS=120
|
|
OIDC_ACCESS_TOKEN_TTL_SECONDS=600
|
|
OIDC_ID_TOKEN_TTL_SECONDS=600
|
|
EOF
|
|
|
|
echo "Copying Nextcloud app..."
|
|
mkdir -p "${nc_path}/custom_apps"
|
|
if command -v rsync >/dev/null 2>&1; then
|
|
rsync -a "${repo_root}/nextcloud/custom_apps/qortal_integration/" "${nc_path}/custom_apps/qortal_integration/"
|
|
else
|
|
rm -rf "${nc_path}/custom_apps/qortal_integration"
|
|
cp -R "${repo_root}/nextcloud/custom_apps/qortal_integration" "${nc_path}/custom_apps/qortal_integration"
|
|
fi
|
|
|
|
echo "Enabling Nextcloud apps..."
|
|
occ app:enable qortal_integration || true
|
|
occ app:enable user_oidc || true
|
|
occ config:app:set qortal_integration broker_internal_api_token --value="${broker_internal_token}" || true
|
|
|
|
echo "Configuring user_oidc provider..."
|
|
set +e
|
|
occ user_oidc:provider qortal \
|
|
-c nextcloud-local \
|
|
-s "${oidc_secret}" \
|
|
-d "${broker_url}/.well-known/openid-configuration" \
|
|
--scope="openid profile email" \
|
|
--mapping-uid=sub \
|
|
--mapping-display-name=name \
|
|
--mapping-email=email
|
|
set -e
|
|
|
|
if ! command -v docker >/dev/null 2>&1; then
|
|
echo "Docker is required but not installed. Install Docker and re-run docker compose manually."
|
|
exit 1
|
|
fi
|
|
|
|
if docker compose version >/dev/null 2>&1; then
|
|
docker_compose="docker compose"
|
|
elif command -v docker-compose >/dev/null 2>&1; then
|
|
docker_compose="docker-compose"
|
|
else
|
|
echo "Docker Compose not found."
|
|
exit 1
|
|
fi
|
|
|
|
echo "Starting broker containers..."
|
|
${docker_compose} -f "${compose_dst}" --env-file "${broker_dir}/.env" up -d
|
|
|
|
echo "Configuring Apache reverse proxy..."
|
|
if ! a2enmod proxy proxy_http headers ssl >/dev/null 2>&1; then
|
|
echo "Warning: failed to enable Apache modules (proxy/proxy_http/headers/ssl)."
|
|
fi
|
|
|
|
apache_site="/etc/apache2/sites-available/qortalbroker.conf"
|
|
cat > "${apache_site}" <<EOF
|
|
<VirtualHost *:80>
|
|
ServerName ${broker_host}
|
|
ProxyPreserveHost On
|
|
ProxyPass / http://127.0.0.1:3000/
|
|
ProxyPassReverse / http://127.0.0.1:3000/
|
|
RequestHeader set X-Forwarded-Proto "https"
|
|
ErrorLog \${APACHE_LOG_DIR}/qortalbroker_error.log
|
|
CustomLog \${APACHE_LOG_DIR}/qortalbroker_access.log combined
|
|
</VirtualHost>
|
|
EOF
|
|
|
|
a2ensite qortalbroker.conf >/dev/null 2>&1 || true
|
|
systemctl reload apache2 || true
|
|
|
|
read -r -p "Run certbot for ${broker_host}? (y/N): " run_certbot
|
|
if [[ "${run_certbot}" == "y" || "${run_certbot}" == "Y" ]]; then
|
|
read -r -p "Let's Encrypt email: " le_email
|
|
if command -v certbot >/dev/null 2>&1; then
|
|
certbot --apache -d "${broker_host}" -m "${le_email}" --agree-tos --redirect --non-interactive
|
|
else
|
|
echo "certbot is not installed. Install it and rerun manually."
|
|
fi
|
|
fi
|
|
|
|
echo "Install complete."
|
|
echo "Broker URL: ${broker_url}"
|
|
echo "Nextcloud URL: ${nc_url}"
|
|
echo "OIDC provider configured with client_id=nextcloud-local"
|
|
echo "If login fails, verify DNS for ${broker_host} and Apache proxy."
|