넥스트클라우드 자동설치 스크립트

1. 넥스트클라우드 자동설치 스크립트 생성 1) 아래 스크립트를 복사해서 우분투 터미널에 그대로 복사 붙여넣기 후 엔터 cat > setup-nextcloud.sh <<'__SCRIPT__' #!/usr/bin/env bash set -euo pipefail # ========================================== # Nextcloud 올인원 (OCC 미사용 · 권한 안전판) # - 자동 포트(8080→8081→8088→8888) # - Docker/Compose + MariaDB + Redis + Cron # - PHP/MariaDB 튜닝 (파일 쓰기는 sudo tee로 권한 문제 방지) # - systemd 등록/자동시작 # - INSTALL_INFO 생성 + 콘솔 출력 (최적화 명령어는 '주석' 안내) # - 관리자 계정은 웹 UI에서 생성 # - --update-site <domain> : SITE_URL/ TRUSTED_DOMAINS 갱신 + 재기동 # ========================================== PORT="${PORT:-}" TZ="${TZ:-Asia/Seoul}" BASE_DIR="${BASE_DIR:-$HOME/nextcloud}" SITE_URL="${SITE_URL:-}" PROXY_NET="${PROXY_NET:-proxy}" NC_IMAGE="${NC_IMAGE:-nextcloud:apache}" DB_IMAGE="${DB_IMAGE:-mariadb:11}" REDIS_IMAGE="${REDIS_IMAGE:-redis:7-alpine}" PHP_MEMORY_LIMIT="${PHP_MEMORY_LIMIT:-1024M}" PHP_UPLOAD_LIMIT="${PHP_UPLOAD_LIMIT:-8G}" banner(){ echo; echo "==[ $* ]=="; } have(){ command -v "$1" >/dev/null 2>&1; } rand(){ openssl rand -base64 24 | tr -d '\n=' | cut -c1-32; } # -------- update-site (도메인 갱신 전용, 견고판) -------- if [[ "${1:-}" == "--update-site" ]]; then NEW_DOMAIN="${2:-}" [[ -z "$NEW_DOMAIN" ]] && { echo "예) --update-site cloud.example.com"; exit 1; } : "${BASE_DIR:=$HOME/nextcloud}" # 혹시 비어 있으면 보정 ENV_FILE="${BASE_DIR}/.env" COMPOSE_FILE="${BASE_DIR}/docker-compose.yml" [[ -f "$ENV_FILE" ]] || { echo "오류: .env 없음 -> $ENV_FILE"; exit 1; } [[ -f "$COMPOSE_FILE" ]] || { echo "오류: docker-compose.yml 없음 -> $COMPOSE_FILE"; exit 1; } # 키가 없으면 생성 후 덮어쓰기 grep -q '^SITE_URL=' "$ENV_FILE" || echo 'SITE_URL=""' >> "$ENV_FILE" grep -q '^TRUSTED_DOMAINS=' "$ENV_FILE" || echo 'TRUSTED_DOMAINS=""' >> "$ENV_FILE" sed -i "s|^SITE_URL=.*|SITE_URL=${NEW_DOMAIN}|" "$ENV_FILE" sed -i "s|^TRUSTED_DOMAINS=.*|TRUSTED_DOMAINS=${NEW_DOMAIN}|" "$ENV_FILE" echo "✅ .env 갱신 완료:" grep -E '^(SITE_URL|TRUSTED_DOMAINS)=' "$ENV_FILE" || true echo "🔁 컨테이너 재기동..." docker compose -f "$COMPOSE_FILE" --env-file "$ENV_FILE" up -d echo "✅ 재기동 완료" exit 0 fi # ---- 자동 포트 선택 ---- pick_port() { local preferred="${1:-}" local cands=() [[ -n "$preferred" ]] && cands+=("$preferred") cands+=(8080 8081 8088 8888) local seen="" ; local uniq=() for p in "${cands[@]}"; do [[ " $seen " =~ " $p " ]] || { uniq+=("$p"); seen="$seen $p"; }; done for p in "${uniq[@]}"; do if have ss && ss -ltn | grep -qE "LISTEN.*[:.]${p}[[:space:]]"; then continue; fi echo "$p"; return 0 done echo "사용 가능한 포트 없음: ${uniq[*]}" >&2; exit 1 } PORT="$(pick_port "${PORT:-}")" # ---- 패키지/도커 ---- banner "필수 패키지 설치" sudo apt-get update -y sudo apt-get install -y ca-certificates curl gnupg lsb-release openssl if ! have docker; then banner "Docker 설치"; curl -fsSL https://get.docker.com | sh sudo usermod -aG docker "${SUDO_USER:-$USER}" || true fi if ! docker compose version >/dev/null 2>&1; then sudo apt-get install -y docker-compose-plugin fi # ---- 디렉토리 & 권한 ---- banner "디렉토리 준비: ${BASE_DIR}" sudo mkdir -p "${BASE_DIR}"/{db/conf.d,app,redis,data,php,backups} sudo chown -R "${USER}:${USER}" "${BASE_DIR}" # ---- .env ---- DB_ROOT_PASS="$(rand)" DB_PASS="$(rand)" NC_DB="nextcloud" NC_DB_USER="nextcloud" TRUSTED_DOMAINS="${SITE_URL}" cat > "${BASE_DIR}/.env" <<EOF PORT="${PORT}" TZ="${TZ}" SITE_URL="${SITE_URL}" TRUSTED_DOMAINS="${TRUSTED_DOMAINS}" NC_IMAGE="${NC_IMAGE}" DB_IMAGE="${DB_IMAGE}" REDIS_IMAGE="${REDIS_IMAGE}" NC_DB="${NC_DB}" NC_DB_USER="${NC_DB_USER}" DB_PASS="${DB_PASS}" DB_ROOT_PASS="${DB_ROOT_PASS}" PHP_MEMORY_LIMIT="${PHP_MEMORY_LIMIT}" PHP_UPLOAD_LIMIT="${PHP_UPLOAD_LIMIT}" BASE_DIR="${BASE_DIR}" PROXY_NET="${PROXY_NET}" EOF # ---- MariaDB 튜닝 (sudo tee 사용) ---- banner "MariaDB 튜닝" sudo tee "${BASE_DIR}/db/conf.d/nextcloud.cnf" >/dev/null <<'CNF' [mysqld] innodb_buffer_pool_size=512M innodb_log_file_size=128M innodb_flush_method=O_DIRECT innodb_flush_log_at_trx_commit=2 query_cache_type=0 query_cache_size=0 CNF sudo chown "${USER}:${USER}" "${BASE_DIR}/db/conf.d/nextcloud.cnf" # ---- PHP(opcache) 튜닝 ---- banner "PHP(opcache) 튜닝" tee "${BASE_DIR}/php/zz-nextcloud.ini" >/dev/null <<'INI' opcache.enable=1 opcache.enable_cli=1 opcache.memory_consumption=256 opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.validate_timestamps=1 opcache.revalidate_freq=60 opcache.jit=1255 opcache.jit_buffer_size=64M INI # ---- docker-compose.yml ---- banner "docker-compose.yml 생성" tee "${BASE_DIR}/docker-compose.yml" >/dev/null <<'YAML' name: nextcloud-stack services: db: image: ${DB_IMAGE} container_name: nextcloud-db restart: unless-stopped environment: - MARIADB_DATABASE=${NC_DB} - MARIADB_USER=${NC_DB_USER} - MARIADB_PASSWORD=${DB_PASS} - MARIADB_ROOT_PASSWORD=${DB_ROOT_PASS} volumes: - ${BASE_DIR}/db:/var/lib/mysql - ${BASE_DIR}/db/conf.d/nextcloud.cnf:/etc/mysql/conf.d/nextcloud.cnf:ro redis: image: ${REDIS_IMAGE} container_name: nextcloud-redis restart: unless-stopped command: ["redis-server","--save","","--appendonly","no"] volumes: - ${BASE_DIR}/redis:/data app: image: ${NC_IMAGE} container_name: nextcloud-app restart: unless-stopped depends_on: - db - redis environment: - MYSQL_HOST=db - MYSQL_DATABASE=${NC_DB} - MYSQL_USER=${NC_DB_USER} - MYSQL_PASSWORD=${DB_PASS} - REDIS_HOST=redis - TZ=${TZ} - PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT} - PHP_UPLOAD_LIMIT=${PHP_UPLOAD_LIMIT} - NEXTCLOUD_TRUSTED_DOMAINS=${TRUSTED_DOMAINS} volumes: - ${BASE_DIR}/app:/var/www/html - ${BASE_DIR}/data:/var/www/html/data - ${BASE_DIR}/php/zz-nextcloud.ini:/usr/local/etc/php/conf.d/zz-nextcloud.ini:ro ports: - "${PORT}:80" networks: - default - proxynet cron: image: ${NC_IMAGE} container_name: nextcloud-cron restart: unless-stopped entrypoint: /cron.sh volumes: - ${BASE_DIR}/app:/var/www/html - ${BASE_DIR}/data:/var/www/html/data depends_on: - app networks: default: driver: bridge proxynet: name: ${PROXY_NET} external: true YAML # 외부 프록시 네트워크 없으면 compose에서 제거 if ! docker network inspect "${PROXY_NET}" >/dev/null 2>&1; then banner "외부 프록시 네트워크(${PROXY_NET}) 없음 → compose에서 제거" sed -i '/^ proxynet:/,/^$/d' "${BASE_DIR}/docker-compose.yml" sed -i '/- proxynet/d' "${BASE_DIR}/docker-compose.yml" fi # ---- systemd 등록 ---- banner "systemd 유닛 등록" SERVICE_FILE="/etc/systemd/system/nextcloud-compose.service" sudo bash -s <<EOF cat > "$SERVICE_FILE" <<UNIT [Unit] Description=Nextcloud (Docker Compose) Requires=docker.service After=docker.service [Service] Type=oneshot RemainAfterExit=yes WorkingDirectory=${BASE_DIR} ExecStart=/usr/bin/docker compose --env-file ${BASE_DIR}/.env up -d ExecStop=/usr/bin/docker compose --env-file ${BASE_DIR}/.env down TimeoutStartSec=0 [Install] WantedBy=multi-user.target UNIT systemctl daemon-reload systemctl enable nextcloud-compose EOF # ---- 기동 ---- banner "컨테이너 기동 (포트: ${PORT})" docker compose -f "${BASE_DIR}/docker-compose.yml" --env-file "${BASE_DIR}/.env" up -d # ---- INSTALL_INFO (최적화 명령어는 '주석' 안내) ---- set -a; . "${BASE_DIR}/.env"; set +a tee "${BASE_DIR}/INSTALL_INFO" >/dev/null << INFO [Nextcloud 설치 요약] - 접속: http://서버IP:${PORT} - 폴더: ${BASE_DIR} - 도메인(SITE_URL): ${SITE_URL:-"(미지정)"} / 신뢰 도메인: ${TRUSTED_DOMAINS:-"(미지정)"} [DB] - DB: ${NC_DB} - USER: ${NC_DB_USER} - PASS: ${DB_PASS} - ROOT_PASS: ${DB_ROOT_PASS} [안내] - 관리자 계정은 브라우저로 접속한 뒤 초기 설치 화면에서 직접 생성하세요. - 아래 '수동 최적화(추천)'는 필요할 때 복사/붙여넣기해서 실행하면 됩니다. (주의: occ는 컨테이너 웹루트에서 실행해야 함 → -w /var/www/html) # ===== 수동 최적화(추천) ===== # 1) 캐시/락(권장: APCu + Redis) # docker exec -u www-data -w /var/www/html nextcloud-app php occ config:system:set memcache.local --value='\OC\Memcache\APCu' # docker exec -u www-data -w /var/www/html nextcloud-app php occ config:system:set memcache.locking --value='\OC\Memcache\Redis' # docker exec -u www-data -w /var/www/html nextcloud-app php occ config:system:set redis host --value='redis' # 2) DB 최적화(인덱스/BigInt 변환) # docker exec -u www-data -w /var/www/html nextcloud-app php occ db:add-missing-indices # docker exec -u www-data -w /var/www/html nextcloud-app php occ db:convert-filecache-bigint --no-interaction # 3) 백그라운드 작업을 cron으로 # docker exec -u www-data -w /var/www/html nextcloud-app php occ background:cron # 4) 기타 유용한 설정 # - 한국 전화/지역 포맷: # docker exec -u www-data -w /var/www/html nextcloud-app php occ config:system:set default_phone_region --value='KR' # - 로깅 레벨(1=ERROR, 2=WARNING, 3=INFO): # docker exec -u www-data -w /var/www/html nextcloud-app php occ config:system:set loglevel --value='2' INFO chmod 600 "${BASE_DIR}/INSTALL_INFO" cat "${BASE_DIR}/INSTALL_INFO" banner "설치 완료!" echo "접속: http://서버IP:${PORT}" echo "요약 파일: ${BASE_DIR}/INSTALL_INFO" __SCRIPT__ chmod +x setup-nextcloud.sh echo "생성 완료: ./setup-nextcloud.sh (OCC 미사용 · 권한 안전판)" 2) 스크립트 실행 ( 넥스트클라우드 설치) ① 기본 설치(자동포트 선택) ▶ bash setup-nextcloud.sh ② 도메인 있을 경우 도메인 자동설정 설치 ▶ SITE_URL="cloud.example.com 도메인정보" bash setup-nextcloud.sh ③ 설치 완료된 상태에서 도메인 적용 업데이트 ▶bash setup-nextcloud.sh --update-site cloud.newdomain.com도메인정보 2. 넥스트 클라우드 완벽 제거 및 삭제 스크립트 생성 1) 아래 스크립트를 복사해서 우분투 터미널에 그대로 복사 붙여넣기 후 엔터 cat > uninstall-nextcloud.sh <<'__UNINSTALL__' #!/usr/bin/env bash set -euo pipefail # ========================= # Nextcloud Docker 스택 완전 제거기 # - docker compose down -v (볼륨 포함) # - 남은 컨테이너/네트워크/볼륨/파일 정리 # - systemd 유닛 삭제 및 데몬 리로드 # - 기본 경로: ~/nextcloud ( .env 있으면 그 값을 우선 사용 ) # 옵션: # --dry-run : 실제 삭제 대신 수행할 작업만 출력 # --force : 확인 질문 없이 바로 진행 # --keep-data : 데이터 디렉터리/파일은 보존 (도커 리소스만 제거) # --purge-images : 관련 이미지까지 삭제(nextcloud/mariadb/redis) # --base-dir DIR : 기본 경로 지정(기본: ~/nextcloud) # ========================= DRYRUN=0 FORCE=0 KEEP_DATA=0 PURGE_IMAGES=0 BASE_DIR="${HOME}/nextcloud" log(){ echo "[*] $*"; } run(){ if [[ "$DRYRUN" -eq 1 ]]; then echo " ↳ (dry-run) $*"; else eval "$@"; fi; } # ---- parse args ---- while [[ $# -gt 0 ]]; do case "$1" in --dry-run) DRYRUN=1 ;; --force) FORCE=1 ;; --keep-data) KEEP_DATA=1 ;; --purge-images) PURGE_IMAGES=1 ;; --base-dir) BASE_DIR="${2:-}"; shift ;; -h|--help) cat <<USAGE 사용법: bash uninstall-nextcloud.sh [옵션] --dry-run 실제 삭제 없이 계획만 출력 --force 확인 없이 진행 --keep-data 데이터/설치 폴더 보존 --purge-images 도커 이미지까지 삭제(nextcloud/mariadb/redis) --base-dir DIR 기본 경로 지정 (기본: ~/nextcloud) USAGE exit 0;; *) echo "알 수 없는 옵션: $1" ; exit 1 ;; esac shift done # ---- sanity ---- command -v docker >/dev/null 2>&1 || { echo "docker 명령을 찾을 수 없습니다."; exit 1; } # ---- .env 탐색 ---- ENV_FILE="" if [[ -f "${BASE_DIR}/.env" ]]; then ENV_FILE="${BASE_DIR}/.env" else # 흔한 위치 추가 탐색 for p in "./.env" "/opt/nextcloud/.env"; do [[ -f "$p" ]] && ENV_FILE="$p" && break done fi if [[ -n "$ENV_FILE" ]]; then log ".env 찾음: $ENV_FILE" # shellcheck disable=SC2046 set -a && . "$ENV_FILE" && set +a # .env에 BASE_DIR 정의가 있으면 덮어쓰기 if [[ -n "${BASE_DIR:-}" && -n "${BASE_DIR## }" ]]; then : else BASE_DIR="${BASE_DIR:-$HOME/nextcloud}" fi else log ".env 를 찾지 못함. 기본 경로로 진행: ${BASE_DIR}" fi # 리소스명(우리 설치 스크립트와 일치) STACK_NAME="nextcloud-stack" SERVICE_NAME="nextcloud-compose" C_APP="nextcloud-app" C_DB="nextcloud-db" C_REDIS="nextcloud-redis" C_CRON="nextcloud-cron" C_PV="nextcloud-previewgen" # 확인 if [[ "$FORCE" -eq 0 ]]; then echo "다음 리소스를 제거합니다:" echo " - 컨테이너/네트워크/볼륨(docker compose down -v)" echo " - 남은 컨테이너(${C_APP}, ${C_DB}, ${C_REDIS}, ${C_CRON}, ${C_PV}) 및 익명 볼륨" echo " - systemd 유닛: ${SERVICE_NAME}" if [[ "$KEEP_DATA" -eq 0 ]]; then echo " - 설치/데이터 폴더: ${BASE_DIR}" else echo " - 설치/데이터 폴더는 보존 (--keep-data)" fi [[ "$PURGE_IMAGES" -eq 1 ]] && echo " - 도커 이미지(nextcloud, mariadb, redis) 삭제 (--purge-images)" read -r -p "정말 진행할까요? (YES 입력 시 진행): " ANS [[ "$ANS" == "YES" ]] || { echo "중단."; exit 0; } fi # ---- compose down -v ---- if [[ -f "${BASE_DIR}/docker-compose.yml" ]]; then log "docker compose down -v 실행" if [[ -n "$ENV_FILE" ]]; then run "docker compose -f '${BASE_DIR}/docker-compose.yml' --env-file '${ENV_FILE}' down -v || true" else run "docker compose -f '${BASE_DIR}/docker-compose.yml' down -v || true" fi else log "compose 파일을 찾지 못함: ${BASE_DIR}/docker-compose.yml (개별 자원 기준으로 정리)" fi # ---- 개별 컨테이너 강제 정리 ---- for c in "$C_PV" "$C_CRON" "$C_APP" "$C_DB" "$C_REDIS"; do if docker ps -a --format '{{.Names}}' | grep -qx "$c"; then log "컨테이너 제거: $c" run "docker rm -f '$c' || true" fi done # ---- 네트워크 정리(내부 브리지만) ---- # 설치시 기본 'nextcloud-stack_default' 가 생김. 외부 PROXY_NET은 건드리지 않음. if docker network ls --format '{{.Name}}' | grep -qx "${STACK_NAME}_default"; then log "네트워크 제거: ${STACK_NAME}_default" run "docker network rm '${STACK_NAME}_default' || true" fi # ---- 볼륨/익명 볼륨 추가 정리 ---- # compose down -v 로 대부분 제거되지만 혹시 모를 익명 볼륨 청소 log "dangling 볼륨 정리" run "docker volume prune -f || true" # ---- 이미지 제거(옵션) ---- if [[ "$PURGE_IMAGES" -eq 1 ]]; then log "관련 이미지 제거(nextcloud, mariadb, redis)" run "docker images --format '{{.Repository}}:{{.Tag}} {{.ID}}' | awk '/^(nextcloud|mariadb|redis)(:|$)/{print \$2}' | xargs -r docker rmi -f || true" fi # ---- systemd 유닛 제거 ---- if [[ -f "/etc/systemd/system/${SERVICE_NAME}.service" ]]; then log "systemd 유닛 중지/비활성화/삭제: ${SERVICE_NAME}" run "sudo systemctl stop '${SERVICE_NAME}' || true" run "sudo systemctl disable '${SERVICE_NAME}' || true" run "sudo rm -f '/etc/systemd/system/${SERVICE_NAME}.service'" run "sudo systemctl daemon-reload" fi # ---- 파일/폴더 삭제 ---- if [[ "$KEEP_DATA" -eq 0 ]]; then if [[ -d "$BASE_DIR" ]]; then log "설치 폴더 삭제: ${BASE_DIR}" run "sudo rm -rf '${BASE_DIR}'" fi else log "설치 폴더 보존 (--keep-data)" fi log "정리 완료!" echo "Tip:" echo " - 완전 초기화를 원하면 --purge-images 추가" echo " - 데이터 보존하고 스택만 지우려면 --keep-data 사용" __UNINSTALL__ chmod +x uninstall-nextcloud.sh echo "생성 완료: ./uninstall-nextcloud.sh (도움말: -h 또는 --help)" 2) 스크립트 실행 ( 넥스트클라우드 완벽삭제 ) ① 질문 없이 강제 제거 ▶ bash uninstall-nextcloud.sh --force ② 데이터는 남기고 도커 리소스만 제거 ▶ bash uninstall-nextcloud.sh --keep-data ③ 모든 데이터 완벽 제거 ▶ bash uninstall-nextcloud.sh --force --purge-images

공개 마지막 업데이트: 2025-09-28 09:46:40 AM