NextCloud Docker + Nginx + Let's Encrypt SSL 인증서 통합 설치 가이드

NextCloud를 Docker Compose로 배포하고 HTTPS 적용하기

이 문서는 NextCloud를 컨테이너 기반으로 안정적으로 운영하기 위해 Docker Compose를 활용한 설치 방법을 설명합니다. 데이터베이스로 MariaDB를 사용하며, Nginx를 통해 Let's Encrypt 기반의 무료 SSL 인증서를 자동으로 발급받아 보안 연결을 구축합니다.

Nginx 설정 파일 준비

먼저 웹 서버 구성에 필요한 디렉터리를 생성합니다.

mkdir -p /opt/nextcloud/conf.d

다음과 같이 가상 호스트 설정 파일을 작성합니다.

nano /opt/nextcloud/conf.d/cloud.conf

아래 내용을 입력합니다. 도메인 변수 ${DOMAIN}는 나중에 환경에서 치환됩니다.

upstream php_backend {
    server app:9000;
}

server {
    listen 80;
    listen 443 ssl http2;
    server_name ${DOMAIN};

    client_max_body_size 20G;

    # HTTP 요청은 자동으로 HTTPS로 리다이렉트
    if ($server_port = 80) {
        return 301 https://$host$request_uri;
    }

    # SSL 인증서 경로 (Let's Encrypt 자동 갱신 대응)
    ssl_certificate /etc/letsencrypt/live/${DOMAIN}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/${DOMAIN}/privkey.pem;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA256:!aNULL:!MD5:!EXPORT:!DES:!RC4:!PSK:!SRP:!CAMELLIA;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;

    # 보안 헤더 추가
    add_header X-Content-Type-Options nosniff;
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-XSS-Protection "1; mode=block";
    add_header Referrer-Policy no-referrer;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Robots-Tag none;
    add_header X-Download-Options noopen;
    fastcgi_hide_header X-Powered-By;

    root /var/www/html;

    # 정적 리소스 처리 및 보안 제한
    location = /robots.txt {
        allow all;
        log_not_found off;
        access_log off;
    }

    location ~ ^/(data|config|\.git|\.ht|db_) {
        deny all;
    }

    # CardDAV, CalDAV 리다이렉트
    location = /.well-known/carddav { return 301 $scheme://$host/remote.php/dav; }
    location = /.well-known/caldav  { return 301 $scheme://$host/remote.php/dav; }

    # Gzip 압축 활성화
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml;

    # PHP 핸들러 라우팅
    location ~ \.php(?:$|/) {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
        fastcgi_param HTTPS on;
        fastcgi_param modHeadersAvailable true;
        fastcgi_pass php_backend;
        fastcgi_intercept_errors on;
        fastcgi_request_buffering off;
    }

    # 정적 콘텐츠 캐싱
    location ~* \.(?:css|js|woff2?|svg|gif|png|ico|jpg|jpeg)$ {
        try_files $uri /index.php$request_uri;
        expires 1y;
        add_header Cache-Control "public, immutable";
        access_log off;
    }

    # 기본 요청 처리
    location / {
        rewrite ^ /index.php$request_uri;
    }
}

Docker Compose 배포 스크립트 작성

다음 명령어로 컴포즈 정의 파일을 생성합니다.

nano /opt/nextcloud/docker-compose.yml

내용은 아래와 같습니다:

version: '3'

volumes:
  cert-data:
  nc-data:
  db-data:

services:
  web:
    image: staticfloat/nginx-certbot
    ports:
      - "80:80"
      - "443:443"
    environment:
      CERTBOT_EMAIL: admin@yourdomain.com
      DOMAIN: cloud.yourdomain.com
      ENVSUBST_VARS: DOMAIN
    volumes:
      - ./conf.d:/etc/nginx/user.conf.d:ro
      - cert-data:/etc/letsencrypt
      - nc-data:/var/www/html
    restart: unless-stopped

  database:
    image: mariadb:10.6
    command: --transaction-isolation=READ-COMMITTED --binlog-format=ROW
    environment:
      MYSQL_DATABASE: nextclouddb
      MYSQL_USER: ncuser
      MYSQL_PASSWORD: secure_db_password_2024!
      MYSQL_ROOT_PASSWORD: root_super_secret!@
    volumes:
      - db-data:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d:ro
    restart: unless-stopped

  app:
    image: nextcloud:fpm-alpine
    volumes:
      - nc-data:/var/www/html
      - ./custom_apps:/var/www/html/custom_apps
      - ./config:/var/www/html/config
      - ./data:/var/www/html/data
    restart: unless-stopped

  scheduler:
    image: alpine:latest
    depends_on:
      - app
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    entrypoint: |
      sh -c 'while true; do
        docker exec -u www-data app php cron.php;
        sleep 900;
      done'
    restart: always

기본 설정 사항

  • 도메인 및 이메일: CERTBOT_EMAILDOMAIN 값을 실제 사용할 주소로 변경하세요.
  • 데이터베이스 비밀번호: 예시 값은 반드시 강력한 임의 문자열로 교체해야 합니다.
  • DNS 설정: 도메인 A 레코드가 서버 공인 IP를 가리키고 있어야 하며, 포트 80/443이 방화벽에서 열려 있어야 인증서 발급이 가능합니다.

서비스 시작 및 초기화

모든 설정 완료 후 다음 명령어로 서비스를 백그라운드 실행합니다.

cd /opt/nextcloud
docker-compose up -d

브라우저에서 https://cloud.yourdomain.com 접속 후 웹 설치 마법사를 통해 관리자 계정을 생성합니다.

설치 후 최적화 작업

NextCloud 콘솔 명령어를 사용해 성능과 호환성을 개선합니다.

docker-compose exec app php occ db:add-missing-indices
docker-compose exec app php occ db:convert-filecache-bigint
docker-compose exec app php occ maintenance:mode --off

기존 파일 가져오기

로컬에 있는 데이터를 NextCloud에 추가하려면 먼저 해당 사용자의 files 디렉터리에 복사합니다.

cp -r /backup/import_data/* /opt/nextcloud/data/admin/files/

복사 후 파일 스캔을 수행하여 인덱싱합니다.

docker-compose exec app php occ files:scan --all

추가 기능 설치 (예: FFmpeg)

미디어 썸네일 생성을 위해 FFmpeg를 컨테이너 내부에 설치합니다.

docker exec -it nextcloud_app_1 apk add --no-cache ffmpeg

백업 및 이전 절차

시스템 전체를 백업하려면 다음 순서를 따릅니다.

  1. 컨테이너 중지
  2. docker-compose -f /opt/nextcloud/docker-compose.yml down
  3. 전체 디렉터리 압축
  4. tar -czf backup-nextcloud-full.tar.gz -C /opt nextcloud
  5. 새 서버로 전송
  6. scp backup-nextcloud-full.tar.gz user@new-server:/opt
  7. 복원 후 재시작
  8. tar -xzf /opt/backup-nextcloud-full.tar.gz -C /opt
    cd /opt/nextcloud && docker-compose up -d

이 방법을 통해 데이터와 설정을 동일하게 복제할 수 있습니다.

태그: NextCloud Docker Compose nginx Let's Encrypt MariaDB

7월 1일 16:39에 게시됨