Nextcloud 의 External Storage 앱에서 SMB/CIFS 를 고르면 두 가지 방식 중 하나를 쓴다. libsmbclient 를 감싼 PHP 확장(smbclient) 이 있으면 그것을 쓰고, 없으면 외부 명령 smbclient 를 호출한다. 확장 쪽이 훨씬 빠르고 안정적이라, 컨테이너로 운영한다면 이미지에 넣어 두는 것이 사실상 필수다.
확장이 없으면 관리 화면의 외부 저장소 설정에서 SMB 항목이 아예 안 보이거나, 저장해도 연결 확인에서 실패한다.
php -m | grep -i smbclient
php --ri smbclient
컨테이너 안에서 본다.
docker exec -it nextcloud php -m | grep -i smbclient
공식 nextcloud 이미지는 PHP 를 docker-php-* 도구로 관리한다. PECL 로 빌드하고 docker-php-ext-enable 로 켠다.
FROM nextcloud:31-apache
RUN set -eux; \
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends libsmbclient-dev; \
pecl install smbclient; \
docker-php-ext-enable smbclient; \
apt-mark auto '.*' > /dev/null; \
apt-mark manual $savedAptMark > /dev/null; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*
빌드에는 libsmbclient-dev 가 필요하지만 실행에는 런타임 라이브러리 libsmbclient 만 있으면 된다. 위 방식은 공식 이미지가 쓰는 관용구로, 빌드 의존성만 자동 제거하고 런타임 의존성은 남긴다.
배포판 PHP 대신 Sury 저장소의 PHP 를 쓰는 구성이라면 확장을 넣는 경로가 다르다. /etc/php/<버전>/mods-available/ 에 ini 를 두고 phpenmod 로 켠다.
RUN set -eux; \
apt-get update; \
apt-get install -y --no-install-recommends \
ca-certificates curl lsb-release gnupg apt-transport-https; \
mkdir -p /usr/share/keyrings; \
curl -fsSL https://packages.sury.org/php/apt.gpg \
| gpg --dearmor -o /usr/share/keyrings/sury.gpg; \
echo "deb [signed-by=/usr/share/keyrings/sury.gpg] https://packages.sury.org/php/ trixie main" \
> /etc/apt/sources.list.d/sury-php.list; \
rm -rf /var/lib/apt/lists/*; \
apt-get update; \
apt-get install -y --no-install-recommends \
php8.3-dev php-pear libsmbclient-dev gcc make autoconf pkg-config; \
pecl install smbclient; \
echo "extension=smbclient.so" > /etc/php/8.3/mods-available/smbclient.ini; \
phpenmod smbclient; \
rm -rf /var/lib/apt/lists/*
빠뜨리기 쉬운 것들이다.
mkdir -p /usr/share/keyrings — 디렉터리가 없으면 gpg --dearmor -o 가 실패한다.apt-get update 를 다시 돌린다. 기존 캐시에는 Sury 목록이 없다.trixie 다. lsb_release -cs 로 뽑아 쓰면 이미지 베이스가 바뀌어도 깨지지 않는다.php8.3-dev 와 php-pear 가 있어야 pecl install 이 컴파일할 수 있다.저장소가 제대로 잡혔는지 확인한다.
apt-cache policy | grep -A4 sury
cat /etc/apt/sources.list.d/sury-php.list
배포판 PHP 와 Sury PHP 가 섞이면 확장이 엉뚱한 디렉터리에 설치돼 php -m 에 안 잡힌다. php -i | grep extension_dir 로 실제 확장 디렉터리를 확인하고, pecl 이 거기에 넣었는지 본다.
관리자 계정으로 앱 → External storage support 를 켠 뒤, 설정 → 관리 → 외부 저장소에서 SMB/CIFS 를 추가한다.
| 항목 | 값 |
|---|---|
| 호스트 | SMB 서버 주소 |
| 공유 이름 | 공유 폴더 이름. 경로를 통째로 넣지 않는다 |
| 원격 하위 폴더 | 공유 안의 경로 |
| 사용자 · 비밀번호 | 접근 계정 |
| 도메인 | 워크그룹 또는 AD 도메인 |
공유 이름과 하위 폴더를 구분하는 것이 중요하다. //server/H-Movies/Animations 는 공유 H-Movies + 하위 폴더 Animations 다. 공유 칸에 전체 경로를 넣으면 연결되지 않는다.
occ 로도 등록할 수 있다.
occ files_external:create "SMB Share" smb password::password \
--config host=${SMB_HOST} \
--config share=${SMB_SHARE} \
--config domain=${SMB_DOMAIN} \
--config user=${SMB_USER} \
--config password=${SMB_PASSWORD}
occ files_external:list
occ files_external:verify <mount-id>
| 증상 | 원인 |
|---|---|
| 외부 저장소 목록에 SMB 가 없다 | smbclient 확장도 smbclient 명령도 없다 |
| 연결 확인에서 실패한다 | 공유 이름과 하위 폴더를 구분하지 않았다 |
NT_STATUS_ACCESS_DENIED |
계정 권한 또는 도메인 값이 틀렸다 |
NT_STATUS_CONNECTION_REFUSED |
방화벽 445 차단, 또는 SMB1 만 허용하는 서버 |
| 한글 파일명이 깨진다 | 서버의 unix charset · dos charset 설정. 최신 Samba 는 UTF-8 이 기본이다 |
| 목록은 보이는데 쓰기가 안 된다 | 공유가 read only = yes 이거나 서버 쪽 디렉터리 권한 |
SMB1(NT1)은 최신 Samba 클라이언트에서 기본적으로 꺼져 있다. 상대가 SMB1 만 지원하는 오래된 NAS 라면 서버를 SMB2 이상으로 올리는 것이 순서다. 클라이언트에서 SMB1 을 되살리는 것은 권하지 않는다.