#!/usr/bin/env bash set -euo pipefail script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" repo_root="$(cd "${script_dir}/.." && pwd)" env_file="${repo_root}/.env.devprod" ram_gb_override="" apply_changes="0" force_overwrite="0" print_json="0" usage() { cat <<'USAGE' Usage: ./scripts/evaluate-set-size-defaults.sh [options] Recommend Docker/Nextcloud publish-size defaults based on host RAM and, optionally, write them into the env file. This script targets the current repo's Apache-based Nextcloud image (`nextcloud:34-apache`). It does not tune PHP-FPM pool.d because this stack does not use PHP-FPM by default. Options: --env-file Env file to inspect/update (default: .env.devprod) --ram-gb Override detected host RAM in GiB for evaluation --apply Write recommended values into the env file --force Overwrite existing values when used with --apply --json Print recommendations as JSON -h, --help Show this help USAGE } while [[ $# -gt 0 ]]; do case "$1" in --env-file) env_file="${2:-}" shift 2 ;; --env-file=*) env_file="${1#*=}" shift ;; --ram-gb) ram_gb_override="${2:-}" shift 2 ;; --ram-gb=*) ram_gb_override="${1#*=}" shift ;; --apply) apply_changes="1" shift ;; --force) force_overwrite="1" shift ;; --json) print_json="1" shift ;; -h|--help) usage exit 0 ;; *) echo "Unknown option: $1" usage exit 1 ;; esac done if [[ "${env_file}" != /* ]]; then env_file="${repo_root}/${env_file}" fi if [[ ! -f "${env_file}" ]]; then echo "Missing env file: ${env_file}" exit 1 fi read_kv() { local key="$1" local line line="$(grep -m1 -E "^${key}=" "${env_file}" || true)" if [[ -z "${line}" ]]; then return 1 fi echo "${line#*=}" } set_kv() { local key="$1" local value="$2" local esc esc="${value//\\/\\\\}" esc="${esc//&/\\&}" esc="${esc//|/\\|}" if grep -q "^${key}=" "${env_file}"; then sed -i -E "s|^${key}=.*|${key}=${esc}|" "${env_file}" else printf '%s=%s\n' "${key}" "${value}" >> "${env_file}" fi } detect_ram_gb() { if [[ -n "${ram_gb_override}" ]]; then printf '%s\n' "${ram_gb_override}" return 0 fi if [[ -r /proc/meminfo ]]; then local mem_kib mem_kib="$(awk '/^MemTotal:/ { print $2 }' /proc/meminfo)" if [[ -n "${mem_kib}" ]]; then awk -v kib="${mem_kib}" 'BEGIN { printf "%.1f\n", kib / 1024 / 1024 }' return 0 fi fi echo "0" } format_one_decimal() { awk -v value="${1:-0}" 'BEGIN { printf "%.1f", value }' } recommend_for_ram_gb() { local ram_gb="$1" if awk -v n="${ram_gb}" 'BEGIN { exit !(n < 8) }'; then echo "32mb|5G|5G|512M|blank" return 0 fi if awk -v n="${ram_gb}" 'BEGIN { exit !(n < 16) }'; then echo "64mb|5G|5G|768M|blank" return 0 fi if awk -v n="${ram_gb}" 'BEGIN { exit !(n < 32) }'; then echo "128mb|5G|5G|1024M|blank" return 0 fi if awk -v n="${ram_gb}" 'BEGIN { exit !(n < 64) }'; then echo "192mb|5G|5G|1536M|blank" return 0 fi echo "256mb|5G|5G|2048M|blank" } should_write_key() { local key="$1" local current_value current_value="$(read_kv "${key}" || true)" if [[ "${force_overwrite}" == "1" ]]; then return 0 fi [[ -z "${current_value}" ]] } ram_gb_detected="$(detect_ram_gb)" if ! [[ "${ram_gb_detected}" =~ ^[0-9]+([.][0-9]+)?$ ]]; then echo "Could not determine RAM in GiB." exit 1 fi IFS='|' read -r broker_limit upload_limit post_limit php_memory_limit publish_limit_mode <<<"$(recommend_for_ram_gb "${ram_gb_detected}")" nextcloud_image="$(read_kv "NEXTCLOUD_IMAGE" || true)" nextcloud_image="${nextcloud_image:-nextcloud:34-apache}" if [[ "${print_json}" == "1" ]]; then printf '{\n' printf ' "envFile": "%s",\n' "${env_file}" printf ' "detectedRamGiB": %s,\n' "$(format_one_decimal "${ram_gb_detected}")" printf ' "nextcloudImage": "%s",\n' "${nextcloud_image}" printf ' "phpRuntimeModel": "apache_mod_php",\n' printf ' "recommendations": {\n' printf ' "BROKER_REQUEST_BODY_LIMIT": "%s",\n' "${broker_limit}" printf ' "NEXTCLOUD_PHP_UPLOAD_MAX_FILESIZE": "%s",\n' "${upload_limit}" printf ' "NEXTCLOUD_PHP_POST_MAX_SIZE": "%s",\n' "${post_limit}" printf ' "NEXTCLOUD_PHP_MEMORY_LIMIT": "%s",\n' "${php_memory_limit}" printf ' "QORTAL_FILES_PUBLISH_MAX_SIZE": ""\n' printf ' },\n' printf ' "notes": [\n' printf ' "This stack uses nextcloud:34-apache by default, so PHP-FPM pool.d tuning does not apply.",\n' printf ' "Nextcloud PHP upload/post limits are intentionally decoupled from QDN publish limits and default to 5G.",\n' printf ' "QORTAL_FILES_PUBLISH_MAX_SIZE is intentionally left blank so publish limits stay broker-oriented unless explicitly overridden.",\n' printf ' "For a VM with about 30 GiB RAM, the recommended profile is 128mb broker body limit, 5G PHP upload/post, and 1024M PHP memory."\n' printf ' ]\n' printf '}\n' exit 0 fi echo "Size default evaluation" echo " Env file: ${env_file}" echo " Detected RAM: $(format_one_decimal "${ram_gb_detected}") GiB" echo " Nextcloud image: ${nextcloud_image}" echo " PHP runtime model: Apache mod_php" echo echo "Recommended values" echo " BROKER_REQUEST_BODY_LIMIT=${broker_limit}" echo " NEXTCLOUD_PHP_UPLOAD_MAX_FILESIZE=${upload_limit}" echo " NEXTCLOUD_PHP_POST_MAX_SIZE=${post_limit}" echo " NEXTCLOUD_PHP_MEMORY_LIMIT=${php_memory_limit}" echo " QORTAL_FILES_PUBLISH_MAX_SIZE=" echo echo "Notes" echo " - This stack is Apache-based, so PHP-FPM pool.d tuning does not apply." echo " - Nextcloud PHP upload/post limits are intentionally decoupled from QDN publish limits and default to 5G." echo " - Leaving QORTAL_FILES_PUBLISH_MAX_SIZE blank keeps publish size broker-oriented unless explicitly overridden." echo " - For a VM with about 30 GiB RAM, the recommended profile is 128mb broker body limit, 5G PHP upload/post, and 1024M PHP memory." if [[ "${apply_changes}" != "1" ]]; then echo echo "Dry run only. Re-run with --apply to write missing values." echo "Use --force with --apply if you want to overwrite existing values." exit 0 fi changed_keys=() skipped_keys=() for pair in \ "BROKER_REQUEST_BODY_LIMIT=${broker_limit}" \ "NEXTCLOUD_PHP_UPLOAD_MAX_FILESIZE=${upload_limit}" \ "NEXTCLOUD_PHP_POST_MAX_SIZE=${post_limit}" \ "NEXTCLOUD_PHP_MEMORY_LIMIT=${php_memory_limit}" do key="${pair%%=*}" value="${pair#*=}" if should_write_key "${key}"; then set_kv "${key}" "${value}" changed_keys+=("${key}") else skipped_keys+=("${key}") fi done if should_write_key "QORTAL_FILES_PUBLISH_MAX_SIZE"; then set_kv "QORTAL_FILES_PUBLISH_MAX_SIZE" "" changed_keys+=("QORTAL_FILES_PUBLISH_MAX_SIZE") else skipped_keys+=("QORTAL_FILES_PUBLISH_MAX_SIZE") fi echo if [[ "${#changed_keys[@]}" -gt 0 ]]; then echo "Updated ${env_file}:" printf ' %s\n' "${changed_keys[@]}" else echo "No env values were changed." fi if [[ "${#skipped_keys[@]}" -gt 0 ]]; then echo "Skipped existing keys:" printf ' %s\n' "${skipped_keys[@]}" fi