#!/usr/bin/env bash # Развёртывание Nextcloud через Docker Compose # Запускать БЕЗ sudo: ./install.sh [домен_или_ip] set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" cd "${SCRIPT_DIR}" # shellcheck source=../lib/common.sh source "${SCRIPT_DIR}/../lib/common.sh" drop_root_if_sudo "${SCRIPT_DIR}/install.sh" "$@" RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' log_info() { echo -e "${GREEN}[INFO]${NC} $*"; } log_warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } log_error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } DOMAIN="" DOCKER_AUTO="prompt" prompt_path() { local label="$1" local default="$2" local value="" read -r -p "${label} [${default}]: " value echo "${value:-$default}" } parse_args() { local args=() while [[ $# -gt 0 ]]; do case "$1" in --install-docker) DOCKER_AUTO="yes"; shift ;; --skip-docker) DOCKER_AUTO="skip"; shift ;; -h|--help) echo "Использование: ./install.sh [--install-docker|--skip-docker] [домен]" exit 0 ;; *) args+=("$1"); shift ;; esac done DOMAIN="${args[0]:-}" } ensure_docker_ready() { ensure_docker "${SCRIPT_DIR}/install-docker.sh" "${DOCKER_AUTO}" || { log_error "Docker недоступен. Установите вручную:" log_error " sudo ./install-docker.sh $(id -un)" exit 1 } } prompt_storage_paths() { echo "" echo "=== Пути хранения (вне nextcloud_install) ===" CONFIG_DIR="$(prompt_path "Конфиг Nextcloud (config.php)" "${NEXTCLOUD_CONFIG_DIR:-/var/nextcloud/config}")" DATADIR="$(prompt_path "Файлы пользователей" "${NEXTCLOUD_DATADIR:-/mnt/hgfs/nextcloud_data}")" APPDATA="$(prompt_path "appdata (App Store, превью)" "${NEXTCLOUD_APPDATA:-/var/nextcloud/appdata}")" CUSTOM_APPS="$(prompt_path "Приложения из магазина" "${NEXTCLOUD_CUSTOM_APPS:-/var/nextcloud/custom_apps}")" BACKUP_DIR="$(prompt_path "Каталог бэкапов" "${NEXTCLOUD_BACKUP_DIR:-/var/nextcloud/backups}")" sed -i "s|^NEXTCLOUD_CONFIG_DIR=.*|NEXTCLOUD_CONFIG_DIR=${CONFIG_DIR}|" .env sed -i "s|^NEXTCLOUD_DATADIR=.*|NEXTCLOUD_DATADIR=${DATADIR}|" .env sed -i "s|^NEXTCLOUD_APPDATA=.*|NEXTCLOUD_APPDATA=${APPDATA}|" .env sed -i "s|^NEXTCLOUD_CUSTOM_APPS=.*|NEXTCLOUD_CUSTOM_APPS=${CUSTOM_APPS}|" .env sed -i "s|^NEXTCLOUD_BACKUP_DIR=.*|NEXTCLOUD_BACKUP_DIR=${BACKUP_DIR}|" .env # shellcheck disable=SC1091 source .env } prepare_env() { if [[ ! -f ".env" ]]; then bash "${SCRIPT_DIR}/setup-env.sh" "${DOMAIN}" fi grep -q 'CHANGE_ME' .env && { log_error "В .env остались CHANGE_ME — пересоздайте: rm .env && ./setup-env.sh"; exit 1; } # shellcheck disable=SC1091 source .env if [[ -z "${NEXTCLOUD_INSTANCEID:-}" ]]; then NEXTCLOUD_INSTANCEID="$(openssl rand -base64 48 | tr -dc 'a-z0-9' | head -c 12)" echo "NEXTCLOUD_INSTANCEID=${NEXTCLOUD_INSTANCEID}" >> .env log_warn "Добавлен NEXTCLOUD_INSTANCEID в .env" fi if [[ -t 0 ]]; then prompt_storage_paths elif [[ -z "${NEXTCLOUD_CONFIG_DIR:-}" ]]; then log_error "Задайте NEXTCLOUD_CONFIG_DIR в .env или запустите ./install.sh в интерактивном терминале" exit 1 fi } config_write() { config_write_file "$1" } restore_config_defaults() { local src="${SCRIPT_DIR}/config.defaults" local cfg="${NEXTCLOUD_CONFIG_DIR}" if [[ ! -d "${src}" ]]; then log_warn "Нет ${src}/ — пропуск шаблонов config" return 0 fi log_info "Проверка config для установки/переустановки..." prepare_config_for_reinstall "${src}" "${cfg}" "${NEXTCLOUD_INSTANCEID}" } ensure_instanceid_config() { # shellcheck disable=SC1091 source .env local cfg="${NEXTCLOUD_CONFIG_DIR}" config_write_file "${cfg}/instanceid.config.php" < '${NEXTCLOUD_INSTANCEID}', ); EOF config_write_file "${cfg}/datadir.config.php" <<'EOF' false, ); EOF fix_config_permissions "${cfg}" log_info "instanceid → ${NEXTCLOUD_INSTANCEID}" } prepare_host_dirs() { # shellcheck disable=SC1091 source .env local dirs=( "${NEXTCLOUD_CONFIG_DIR}" "${NEXTCLOUD_DATADIR}" "${NEXTCLOUD_APPDATA}" "${NEXTCLOUD_CUSTOM_APPS}" ) for d in "${dirs[@]}"; do if [[ ! -d "${d}" ]]; then log_info "Создание ${d}" fi ensure_host_dir "${d}" chown_wwwdata_dir "${d}" done if [[ ! -d "${NEXTCLOUD_BACKUP_DIR}" ]]; then log_info "Создание ${NEXTCLOUD_BACKUP_DIR}" fi ensure_host_dir "${NEXTCLOUD_BACKUP_DIR}" sudo chown "$(id -u):$(id -g)" "${NEXTCLOUD_BACKUP_DIR}" sudo chmod 0775 "${NEXTCLOUD_BACKUP_DIR}" sudo touch "${NEXTCLOUD_DATADIR}/.ncdata" 2>/dev/null || true sudo chown 33:33 "${NEXTCLOUD_DATADIR}/.ncdata" 2>/dev/null || true log_info "Хранилище (вне nextcloud_install):" echo " config → ${NEXTCLOUD_CONFIG_DIR}" echo " data → ${NEXTCLOUD_DATADIR}" echo " appdata → ${NEXTCLOUD_APPDATA} (appdata_${NEXTCLOUD_INSTANCEID})" echo " custom_apps → ${NEXTCLOUD_CUSTOM_APPS}" echo " backups → ${NEXTCLOUD_BACKUP_DIR}" } prepare_dirs() { prepare_host_dirs restore_config_defaults ensure_instanceid_config } deploy_stack() { log_info "Загрузка образов..." run_compose pull log_info "Запуск контейнеров..." run_compose up -d ensure_app_code_ready local waited=0 port port="$(grep '^NEXTCLOUD_PORT=' .env | cut -d= -f2 || echo 8080)" log_info "Ожидание Nextcloud на порту ${port}..." while [[ ${waited} -lt 120 ]]; do curl -sf "http://127.0.0.1:${port}/status.php" &>/dev/null && break sleep 5; waited=$((waited + 5)); echo -n "." done echo "" # shellcheck disable=SC1091 source .env ensure_nextcloud_installed "${port}" || true fix_config_permissions "${NEXTCLOUD_CONFIG_DIR}" } print_summary() { # shellcheck disable=SC1091 source .env log_info "=== Nextcloud (Docker) развёрнут ===" echo " URL: http://127.0.0.1:${NEXTCLOUD_PORT:-8080}" echo " Логин: ${NEXTCLOUD_ADMIN_USER:-admin} (пароль в .env)" echo " config: ${NEXTCLOUD_CONFIG_DIR}" echo " data: ${NEXTCLOUD_DATADIR}" log_warn "HTTPS: ./enable-docker-ssl.sh your.domain (порт 8443)" } main() { parse_args "$@" log_info "Docker-установка Nextcloud" ensure_docker_ready prepare_env prepare_dirs deploy_stack print_summary } main "$@"