폐쇄망에 설치 파일이나 저장소 미러를 놓고 브라우저와 curl 로 받아 가게 할 때 Apache httpd 를 파일 서버로 쓴다. 필요한 기능에 따라 두 단계로 나뉜다.
| 목적 | 필요한 모듈 |
|---|---|
| 목록 보기와 내려받기 | mod_autoindex (기본 포함) |
| 브라우저나 탐색기에서 올리고 지우기 | mod_dav, mod_dav_fs |
<VirtualHost *:80>
DocumentRoot "/srv/files"
<Directory "/srv/files">
Options Indexes FollowSymLinks
AllowOverride None
Require all granted
IndexOptions FancyIndexing HTMLTable NameWidth=* VersionSort Charset=UTF-8
</Directory>
</VirtualHost>
Options Indexes 가 목록을 만든다. IndexOptions 의 Charset=UTF-8 을 빼면 한글 파일명이 깨진다.
특정 디렉터리만 목록을 감추려면 그 디렉터리에서 -Indexes 를 준다.
<Directory "/srv/files/private">
Options -Indexes
</Directory>
LoadModule dav_module modules/mod_dav.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule authn_file_module modules/mod_authn_file.so
DavLockDB /var/lib/dav/lockdb
<VirtualHost *:443>
DocumentRoot "/srv/files"
SSLEngine on
SSLCertificateFile /etc/pki/tls/certs/files.example.com.crt
SSLCertificateKeyFile /etc/pki/tls/private/files.example.com.key
<Directory "/srv/files">
Dav On
Options Indexes
Require all granted
<LimitExcept GET HEAD OPTIONS PROPFIND>
AuthType Basic
AuthName "webdav"
AuthBasicProvider file
AuthUserFile /etc/httpd/dav.passwd
Require valid-user
</LimitExcept>
</Directory>
</VirtualHost>
sudo mkdir -p /var/lib/dav
sudo chown apache:apache /var/lib/dav /srv/files
sudo htpasswd -c /etc/httpd/dav.passwd uploader
sudo chown root:apache /etc/httpd/dav.passwd
sudo chmod 640 /etc/httpd/dav.passwd
LimitExcept 를 쓰면 읽기는 익명으로 열어 두고 쓰기 동작(PUT·DELETE·MKCOL·MOVE)에만 인증을 요구할 수 있다. 인증 없이 Dav On 을 열어 두면 누구나 파일을 덮어쓰고 지울 수 있다.
Basic 인증은 자격 증명을 그대로 실어 보내므로 반드시 TLS 위에서 쓴다. 평문 80번 포트에 그대로 두지 않는다.
Digest 인증을 쓰려면 지시어와 도구가 모두 달라진다. 자주 틀리는 부분이다. AuthType Digest 에는 AuthDigestProvider file 과 AuthDigestDomain 이 함께 필요하고, 암호 파일은 htpasswd 나 htdbm 이 아니라 htdigest 로 만들어야 한다. 형식이 서로 달라 섞어 쓰면 인증이 통과되지 않는다.
sudo htdigest -c /etc/httpd/dav.digest webdav uploader
DavLockDB 를 지정하지 않으면 잠금이 필요한 클라이언트(윈도우 탐색기 등)에서 동작하지 않는다. 디렉터리 소유자를 httpd 실행 계정으로 맞춰 둔다.
공식 httpd 이미지는 모듈 파일을 포함하지만 WebDAV 관련 LoadModule 줄은 주석 상태다. 이미지를 새로 만들 필요 없이 설정만 바꾸면 된다.
FROM httpd:2.4
RUN sed -i \
-e 's|^#\(LoadModule dav_module\)|\1|' \
-e 's|^#\(LoadModule dav_fs_module\)|\1|' \
/usr/local/apache2/conf/httpd.conf
COPY file-server.conf /usr/local/apache2/conf/extra/file-server.conf
RUN echo "Include conf/extra/file-server.conf" >> /usr/local/apache2/conf/httpd.conf
EXPOSE 80
docker build -t file-server:1.0 .
docker run -d -p 8080:80 -v /srv/files:/srv/files file-server:1.0
파일을 컨테이너 이미지에 넣지 않고 볼륨에서 읽게 한다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: file-server
spec:
replicas: 1
selector:
matchLabels:
app: file-server
template:
metadata:
labels:
app: file-server
spec:
containers:
- name: httpd
image: harbor.example.com/library/file-server:1.0
ports:
- containerPort: 80
volumeMounts:
- name: files
mountPath: /srv/files
volumes:
- name: files
persistentVolumeClaim:
claimName: file-server-pvc
쓰기가 필요하면 accessModes 를 정한다. 여러 복제본이 같은 볼륨에 써야 한다면 ReadWriteMany 를 지원하는 스토리지(NFS, CephFS)여야 한다. 그렇지 않으면 복제본을 하나로 둔다.
컨테이너 실행 사용자와 볼륨 소유자가 맞지 않아 쓰기가 막히는 경우가 흔하다. securityContext.fsGroup 으로 맞추고, 스토리지가 이를 반영하지 않으면 initContainer 로 소유자를 바꾼다.
securityContext:
runAsUser: 1000
fsGroup: 1000
Ingress 로 노출할 때 업로드 크기 제한을 확인한다. nginx ingress controller 의 기본값은 1MB 이고 넘으면 413 이 난다.
annotations:
nginx.ingress.kubernetes.io/proxy-body-size: "2048m"