Files
Server-scripts/docker_compose/mediahost/nextcloud/fix_config.sh
T
2026-10-01 14:07:55 +00:00

516 lines
13 KiB
Bash

#!/usr/bin/env bash
set -Eeuo pipefail
CONTAINER="nextcloud"
OVERRIDE="/var/www/html/config/zz-docker-env.config.php"
FIX=false
if [[ "${1:-}" == "--fix" ]]; then
FIX=true
fi
PASS=0
FAIL=0
pass() {
echo "PASS: $1"
PASS=$((PASS + 1))
}
fail() {
echo "FAIL: $1"
FAIL=$((FAIL + 1))
}
# ============================================================
# Basic checks
# ============================================================
echo "=========================================="
echo " Nextcloud Docker configuration checker"
echo "=========================================="
echo
if ! docker inspect "$CONTAINER" >/dev/null 2>&1; then
echo "FAIL: Docker container '$CONTAINER' does not exist"
exit 1
fi
if [[ "$(docker inspect -f '{{.State.Running}}' "$CONTAINER")" != "true" ]]; then
echo "FAIL: Docker container '$CONTAINER' is not running"
exit 1
fi
if [[ ! -f ".env" ]]; then
echo "FAIL: .env not found"
exit 1
fi
# ============================================================
# Read .env
# ============================================================
declare -A ENV
while IFS='=' read -r key value; do
key="${key//$'\r'/}"
value="${value//$'\r'/}"
# Ignore empty lines
[[ -z "${key// /}" ]] && continue
# Ignore comments
[[ "$key" =~ ^[[:space:]]*# ]] && continue
# Trim whitespace
key="${key#"${key%%[![:space:]]*}"}"
key="${key%"${key##*[![:space:]]}"}"
# Remove "export "
key="${key#export }"
# Remove quotes
value="${value#\"}"
value="${value%\"}"
value="${value#\'}"
value="${value%\'}"
ENV["$key"]="$value"
done < .env
MYSQL_PASSWORD="${ENV[MYSQL_PASSWORD]:-}"
MYSQL_ROOT_PASSWORD="${ENV[MYSQL_ROOT_PASSWORD]:-}"
REDIS_PASSWORD="${ENV[REDIS_PASSWORD]:-}"
NEXTCLOUD_ADMIN_USER="${ENV[NEXTCLOUD_ADMIN_USER]:-}"
NEXTCLOUD_ADMIN_PASSWORD="${ENV[NEXTCLOUD_ADMIN_PASSWORD]:-}"
NEXTCLOUD_DOMAIN="${ENV[NEXTCLOUD_DOMAIN]:-}"
# ============================================================
# Environment checks
# ============================================================
echo "Checking .env variables"
echo "-----------------------"
for name in \
MYSQL_PASSWORD \
MYSQL_ROOT_PASSWORD \
REDIS_PASSWORD \
NEXTCLOUD_ADMIN_USER \
NEXTCLOUD_ADMIN_PASSWORD \
NEXTCLOUD_DOMAIN
do
if [[ -n "${ENV[$name]:-}" ]]; then
pass "$name is defined"
else
fail "$name is missing"
fi
done
echo
# ============================================================
# Read config.php
#
# PHP runs ONLY inside Docker.
# No PHP is required on the host.
# ============================================================
CONFIG_JSON="$(
docker exec "$CONTAINER" php -r '
$CONFIG = [];
include "/var/www/html/config/config.php";
echo json_encode([
"dbhost" =>
$CONFIG["dbhost"] ?? "",
"dbname" =>
$CONFIG["dbname"] ?? "",
"dbuser" =>
$CONFIG["dbuser"] ?? "",
"dbpassword" =>
$CONFIG["dbpassword"] ?? "",
"redis_host" =>
$CONFIG["redis"]["host"] ?? "",
"redis_password" =>
$CONFIG["redis"]["password"] ?? "",
"overwriteprotocol" =>
$CONFIG["overwriteprotocol"] ?? "",
"overwrite_cli_url" =>
$CONFIG["overwrite.cli.url"] ?? "",
"trusted_domains" =>
$CONFIG["trusted_domains"] ?? [],
"trusted_proxies" =>
$CONFIG["trusted_proxies"] ?? []
]);
'
)"
# ============================================================
# Extract configuration
# ============================================================
DB_HOST="$(jq -r '.dbhost' <<< "$CONFIG_JSON")"
DB_NAME="$(jq -r '.dbname' <<< "$CONFIG_JSON")"
DB_USER="$(jq -r '.dbuser' <<< "$CONFIG_JSON")"
DB_PASSWORD="$(jq -r '.dbpassword' <<< "$CONFIG_JSON")"
REDIS_HOST="$(jq -r '.redis_host' <<< "$CONFIG_JSON")"
REDIS_PASSWORD_CONFIG="$(jq -r '.redis_password' <<< "$CONFIG_JSON")"
OVERWRITE_PROTOCOL="$(jq -r '.overwriteprotocol' <<< "$CONFIG_JSON")"
OVERWRITE_CLI_URL="$(jq -r '.overwrite_cli_url' <<< "$CONFIG_JSON")"
# ============================================================
# Database
# ============================================================
echo "Checking database configuration"
echo "-------------------------------"
if [[ "$DB_HOST" == "mariadb" ]]; then
pass "dbhost = mariadb"
else
fail "dbhost: expected mariadb, got $DB_HOST"
fi
if [[ "$DB_NAME" == "nextcloud" ]]; then
pass "dbname = nextcloud"
else
fail "dbname: expected nextcloud, got $DB_NAME"
fi
if [[ "$DB_USER" == "nextcloud" ]]; then
pass "dbuser = nextcloud"
else
fail "dbuser: expected nextcloud, got $DB_USER"
fi
if [[ "$MYSQL_PASSWORD" == "$DB_PASSWORD" ]]; then
pass "dbpassword"
else
fail "dbpassword"
fi
echo
# ============================================================
# Redis
# ============================================================
echo "Checking Redis configuration"
echo "----------------------------"
if [[ "$REDIS_HOST" == "redis" ]]; then
pass "redis host = redis"
else
fail "redis host: expected redis, got $REDIS_HOST"
fi
if [[ "$REDIS_PASSWORD" == "$REDIS_PASSWORD_CONFIG" ]]; then
pass "redis password"
else
fail "redis password"
echo " expected: [hidden]"
echo " actual: [hidden]"
fi
echo
# ============================================================
# URL
# ============================================================
echo "Checking Nextcloud URL configuration"
echo "------------------------------------"
if [[ "$OVERWRITE_PROTOCOL" == "https" ]]; then
pass "overwriteprotocol = https"
else
fail "overwriteprotocol: expected https, got $OVERWRITE_PROTOCOL"
fi
EXPECTED_URL="https://${NEXTCLOUD_DOMAIN}"
if [[ "$OVERWRITE_CLI_URL" == "$EXPECTED_URL" ]]; then
pass "overwrite.cli.url = $EXPECTED_URL"
else
fail "overwrite.cli.url"
echo " expected: $EXPECTED_URL"
echo " actual: $OVERWRITE_CLI_URL"
fi
echo
# ============================================================
# Trusted domains
# ============================================================
echo "Checking trusted domains"
echo "-----------------------"
if jq -e \
--arg domain "$NEXTCLOUD_DOMAIN" \
'.trusted_domains | index($domain) != null' \
<<< "$CONFIG_JSON" >/dev/null
then
pass "trusted_domains contains $NEXTCLOUD_DOMAIN"
else
fail "trusted_domains does not contain $NEXTCLOUD_DOMAIN"
fi
echo
# ============================================================
# Trusted proxies
# ============================================================
echo "Checking trusted proxies"
echo "------------------------"
if jq -e \
'.trusted_proxies | index("172.16.0.0/12") != null' \
<<< "$CONFIG_JSON" >/dev/null
then
pass "trusted_proxies contains 172.16.0.0/12"
else
fail "trusted_proxies does not contain 172.16.0.0/12"
fi
echo
# ============================================================
# FIX
# ============================================================
if [[ "$FIX" == true ]]; then
echo "=========================================="
echo " Fixing Nextcloud configuration"
echo "=========================================="
echo
# --------------------------------------------------------
# Backup existing override
# --------------------------------------------------------
if docker exec "$CONTAINER" test -f "$OVERRIDE"; then
BACKUP="/var/www/html/config/zz-docker-env.config.php.backup.$(date +%Y%m%d-%H%M%S)"
docker exec "$CONTAINER" \
cp "$OVERRIDE" "$BACKUP"
echo "Backup created:"
echo " $BACKUP"
echo
fi
# --------------------------------------------------------
# Generate override INSIDE the container.
#
# Therefore PHP is NOT required on the host.
# --------------------------------------------------------
docker exec \
-e MYSQL_PASSWORD="$MYSQL_PASSWORD" \
-e REDIS_PASSWORD="$REDIS_PASSWORD" \
-e NEXTCLOUD_DOMAIN="$NEXTCLOUD_DOMAIN" \
"$CONTAINER" \
php -r '
$mysql = getenv("MYSQL_PASSWORD");
$redis = getenv("REDIS_PASSWORD");
$domain = getenv("NEXTCLOUD_DOMAIN");
$file = "/var/www/html/config/zz-docker-env.config.php";
$config = "<?php\n\n";
$config .= "\$CONFIG[\"dbhost\"] = "
. var_export("mariadb", true)
. ";\n";
$config .= "\$CONFIG[\"dbname\"] = "
. var_export("nextcloud", true)
. ";\n";
$config .= "\$CONFIG[\"dbuser\"] = "
. var_export("nextcloud", true)
. ";\n";
$config .= "\$CONFIG[\"dbpassword\"] = "
. var_export($mysql, true)
. ";\n\n";
$config .= "\$CONFIG[\"redis\"][\"host\"] = "
. var_export("redis", true)
. ";\n";
$config .= "\$CONFIG[\"redis\"][\"port\"] = 6379;\n";
$config .= "\$CONFIG[\"redis\"][\"password\"] = "
. var_export($redis, true)
. ";\n\n";
$config .= "\$CONFIG[\"overwriteprotocol\"] = "
. var_export("https", true)
. ";\n";
$config .= "\$CONFIG[\"overwrite.cli.url\"] = "
. var_export("https://" . $domain, true)
. ";\n\n";
$config .= "\$CONFIG[\"trusted_domains\"][] = "
. var_export($domain, true)
. ";\n";
$config .= "\$CONFIG[\"trusted_proxies\"][] = "
. var_export("172.16.0.0/12", true)
. ";\n";
file_put_contents($file, $config);
'
# --------------------------------------------------------
# Permissions
# --------------------------------------------------------
docker exec "$CONTAINER" \
chown www-data:www-data "$OVERRIDE"
docker exec "$CONTAINER" \
chmod 640 "$OVERRIDE"
echo "Configuration override written:"
echo " $OVERRIDE"
echo
# --------------------------------------------------------
# Show the file WITHOUT exposing passwords
# --------------------------------------------------------
echo "Configuration written:"
docker exec "$CONTAINER" \
sed -E \
's/(password"\] = ).*/\1"[HIDDEN]";/' \
"$OVERRIDE"
echo
# --------------------------------------------------------
# Verify
# --------------------------------------------------------
echo "=========================================="
echo " Verification"
echo "=========================================="
echo
# Important:
# config.php itself is not modified.
# Nextcloud loads the additional config file.
#
# Re-read effective Nextcloud configuration.
EFFECTIVE_JSON="$(
docker exec "$CONTAINER" php -r '
$CONFIG = [];
include "/var/www/html/config/config.php";
if (file_exists("/var/www/html/config/zz-docker-env.config.php")) {
include "/var/www/html/config/zz-docker-env.config.php";
}
echo json_encode([
"dbhost" => $CONFIG["dbhost"] ?? "",
"dbname" => $CONFIG["dbname"] ?? "",
"dbuser" => $CONFIG["dbuser"] ?? "",
"dbpassword" => $CONFIG["dbpassword"] ?? "",
"redis_host" => $CONFIG["redis"]["host"] ?? "",
"redis_password" => $CONFIG["redis"]["password"] ?? "",
"overwriteprotocol" =>
$CONFIG["overwriteprotocol"] ?? "",
"overwrite_cli_url" =>
$CONFIG["overwrite.cli.url"] ?? "",
"trusted_domains" =>
$CONFIG["trusted_domains"] ?? [],
"trusted_proxies" =>
$CONFIG["trusted_proxies"] ?? []
]);
'
)"
EFFECTIVE_REDIS_PASSWORD="$(
jq -r '.redis_password' <<< "$EFFECTIVE_JSON"
)"
EFFECTIVE_DOMAINS="$(
jq -r '.trusted_domains[]?' <<< "$EFFECTIVE_JSON"
)"
if [[ "$EFFECTIVE_REDIS_PASSWORD" == "$REDIS_PASSWORD" ]]; then
pass "Redis password fixed"
else
fail "Redis password was not fixed"
fi
if grep -Fxq "$NEXTCLOUD_DOMAIN" <<< "$EFFECTIVE_DOMAINS"; then
pass "trusted_domains fixed"
else
fail "trusted_domains was not fixed"
fi
echo
echo "=========================================="
echo " Fix complete"
echo "=========================================="
exit 0
fi
# ============================================================
# Summary
# ============================================================
echo "=========================================="
echo "Result"
echo "=========================================="
echo "PASS: $PASS"
echo "FAIL: $FAIL"
if [[ "$FAIL" -eq 0 ]]; then
echo
echo "PASS: configuration is consistent."
exit 0
else
echo
echo "FAIL: configuration has mismatches."
echo
echo "Run:"
echo
echo " $0 --fix"
echo
exit 1
fi