231 lines
6.6 KiB
Bash
Executable File
231 lines
6.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "${script_dir}/lib-compose-project.sh"
|
|
|
|
compose_file="docker-compose.devprod.yml"
|
|
env_file=".env.devprod"
|
|
restore_core_skeleton="0"
|
|
check_integrity="0"
|
|
purge_existing_user_skeleton="0"
|
|
empty_skeleton_dir="/var/www/html/data/nuqloud-empty-skeleton"
|
|
# Use the mounted Nextcloud tree so the app container can seed the runtime skeleton directly.
|
|
nuqloud_skeleton_source_dir="/var/www/html/nuqloud-skeleton"
|
|
|
|
usage() {
|
|
cat <<'USAGE'
|
|
Usage: ./scripts/configure-nextcloud-defaults.sh [options]
|
|
|
|
Options:
|
|
--compose-file <path> Compose file to use (default: docker-compose.devprod.yml)
|
|
--env-file <path> Env file to use (default: .env.devprod)
|
|
--restore-core-skeleton Restore signed core skeleton files from the configured Nextcloud image
|
|
--purge-existing-user-skeleton
|
|
Remove known Nextcloud skeleton files from existing user file trees
|
|
--check-integrity Run occ integrity:check-core after configuration
|
|
--empty-skeleton-dir <path> NuQloud skeleton directory path (default: /var/www/html/data/nuqloud-empty-skeleton)
|
|
If /var/www/html/nuqloud-skeleton is missing, an empty skeleton is used.
|
|
-h, --help Show this help
|
|
USAGE
|
|
}
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--compose-file)
|
|
compose_file="$2"
|
|
shift 2
|
|
;;
|
|
--env-file)
|
|
env_file="$2"
|
|
shift 2
|
|
;;
|
|
--restore-core-skeleton)
|
|
restore_core_skeleton="1"
|
|
shift
|
|
;;
|
|
--purge-existing-user-skeleton)
|
|
purge_existing_user_skeleton="1"
|
|
shift
|
|
;;
|
|
--check-integrity)
|
|
check_integrity="1"
|
|
shift
|
|
;;
|
|
--empty-skeleton-dir)
|
|
empty_skeleton_dir="$2"
|
|
shift 2
|
|
;;
|
|
-h|--help)
|
|
usage
|
|
exit 0
|
|
;;
|
|
*)
|
|
echo "Unknown option: $1"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
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() {
|
|
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}")
|
|
echo "Using sudo for docker commands."
|
|
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}")
|
|
echo "Using sudo for docker commands."
|
|
return 0
|
|
fi
|
|
|
|
echo "Unable to access docker, even with sudo."
|
|
exit 1
|
|
}
|
|
|
|
docker() {
|
|
"${DOCKER_CMD[@]}" "$@"
|
|
}
|
|
|
|
read_env_value() {
|
|
local key="$1"
|
|
local line=""
|
|
line="$(grep -m1 -E "^${key}=" "${env_file}" || true)"
|
|
if [[ -z "${line}" ]]; then
|
|
return 1
|
|
fi
|
|
echo "${line#*=}"
|
|
}
|
|
|
|
occ_exec() {
|
|
docker compose -f "${compose_file}" --env-file "${env_file}" exec -T --user www-data app php occ "$@"
|
|
}
|
|
|
|
ensure_docker_access
|
|
|
|
docker compose -f "${compose_file}" --env-file "${env_file}" exec -T -u root app \
|
|
sh -lc '
|
|
set -eu
|
|
rm -rf "$2"
|
|
mkdir -p "$2"
|
|
if [ -d "$1" ]; then
|
|
cp -a "$1/." "$2/"
|
|
else
|
|
echo "NuQloud skeleton source directory not found; using an empty skeleton: $1" >&2
|
|
fi
|
|
find "$2" -name .gitkeep -type f -delete
|
|
chown -R www-data:www-data "$2"
|
|
' sh "${nuqloud_skeleton_source_dir}" "${empty_skeleton_dir}"
|
|
|
|
occ_exec config:system:set skeletondirectory --value="${empty_skeleton_dir}" >/dev/null
|
|
configured_skeleton_dir="$(occ_exec config:system:get skeletondirectory 2>/dev/null | tr -d '\r' || true)"
|
|
if [[ "${configured_skeleton_dir}" != "${empty_skeleton_dir}" ]]; then
|
|
echo "Failed to verify skeletondirectory=${empty_skeleton_dir}"
|
|
exit 1
|
|
fi
|
|
occ_exec app:disable firstrunwizard >/dev/null 2>&1 || true
|
|
|
|
if [[ "${purge_existing_user_skeleton}" == "1" ]]; then
|
|
docker compose -f "${compose_file}" --env-file "${env_file}" exec -T -u root app \
|
|
sh -lc '
|
|
set -eu
|
|
skeleton_source="/var/www/html/core/skeleton"
|
|
data_root="/var/www/html/data"
|
|
removed=0
|
|
|
|
if [ ! -d "${skeleton_source}" ]; then
|
|
echo "Core skeleton source not found: ${skeleton_source}" >&2
|
|
exit 1
|
|
fi
|
|
|
|
for user_files in "${data_root}"/*/files; do
|
|
[ -d "${user_files}" ] || continue
|
|
while IFS= read -r rel; do
|
|
target="${user_files}/${rel#./}"
|
|
if [ -f "${target}" ]; then
|
|
rm -f "${target}"
|
|
removed=$((removed + 1))
|
|
fi
|
|
done <<EOF
|
|
$(cd "${skeleton_source}" && find . -type f ! -path "./Templates/*" | sort)
|
|
EOF
|
|
|
|
while IFS= read -r rel; do
|
|
[ "${rel}" != "." ] || continue
|
|
rmdir "${user_files}/${rel#./}" 2>/dev/null || true
|
|
done <<EOF
|
|
$(cd "${skeleton_source}" && find . -depth -type d ! -path "./Templates" ! -path "./Templates/*" | sort)
|
|
EOF
|
|
done
|
|
|
|
echo "Removed ${removed} existing skeleton file(s)."
|
|
'
|
|
occ_exec files:scan --all >/dev/null
|
|
fi
|
|
|
|
if [[ "${restore_core_skeleton}" == "1" ]]; then
|
|
nextcloud_image="$(read_env_value "NEXTCLOUD_IMAGE" || true)"
|
|
nextcloud_image="${nextcloud_image:-nextcloud:34-apache}"
|
|
echo "Restoring core skeleton files from ${nextcloud_image}..."
|
|
if ! docker run --rm --entrypoint sh "${nextcloud_image}" -lc '
|
|
set -eu
|
|
for candidate in /usr/src/nextcloud/core/skeleton /var/www/html/core/skeleton; do
|
|
if [ -d "${candidate}" ]; then
|
|
cd "${candidate}"
|
|
tar -cf - .
|
|
exit 0
|
|
fi
|
|
done
|
|
echo "Unable to locate core skeleton directory in image." >&2
|
|
exit 1
|
|
' | docker compose -f "${compose_file}" --env-file "${env_file}" exec -T -u root app sh -lc '
|
|
set -eu
|
|
mkdir -p /var/www/html/core/skeleton
|
|
tar -xf - -C /var/www/html/core/skeleton
|
|
'; then
|
|
echo "Failed to restore signed core skeleton files from ${nextcloud_image}."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
if [[ "${check_integrity}" == "1" ]]; then
|
|
occ_exec integrity:check-core
|
|
fi
|
|
|
|
echo "Configured Nextcloud defaults:"
|
|
echo " firstrunwizard disabled"
|
|
echo " skeletondirectory=${empty_skeleton_dir}"
|
|
if [[ "${purge_existing_user_skeleton}" == "1" ]]; then
|
|
echo " existing user skeleton files purged"
|
|
fi
|
|
if [[ "${restore_core_skeleton}" == "1" ]]; then
|
|
echo " core skeleton restored from image"
|
|
fi
|