fix: allow Nginx to read NAS card assets

This commit is contained in:
2026-06-19 11:26:50 +09:00
parent daf534c328
commit 0c74f994fd
6 changed files with 76 additions and 0 deletions

View File

@@ -150,6 +150,9 @@ function createGameCardInstances(importedCards) {
`/volume1/docker/projects/apps/uniare/config/www/images`를 컨테이너에 읽기
전용으로 연결하고 `/card-assets` 경로로 제공한다.
- 기존 Uniare의 `config/www/images`에는 쓰기 작업을 수행하지 않는다.
- NAS 카드 파일 소유자 UID가 `1000`이므로 Nginx 워커는 `cardreader`
사용자(UID 1000)로 실행한다. 이 기준을 바꾸기 전에는 실제 NAS 파일
소유자를 다시 확인한다.
- 로컬 Socket.IO 서버 기본 포트는 `31873`을 사용한다.
- 운영 환경에서는 Socket.IO 포트를 브라우저에 직접 노출하지 않고 같은
도메인의 `/socket.io` 경로로 리버스 프록시한다.

View File

@@ -10,8 +10,12 @@ RUN npm run build
FROM nginx:1.27-alpine AS runtime
RUN adduser -D -H -u 1000 -G wheel cardreader \
&& sed -i 's/user nginx;/user cardreader wheel;/' /etc/nginx/nginx.conf
COPY docker/nginx.conf /etc/nginx/conf.d/default.conf
COPY --from=builder /app/dist /usr/share/nginx/html
RUN chmod -R a+rX /usr/share/nginx/html
EXPOSE 80

View File

@@ -242,6 +242,10 @@ docker exec playuniare-web ls /srv/uniare-card-images
이 경로 역시 같은 시리즈 폴더를 보여야 한다.
Play Uniare의 Nginx 작업 프로세스는 기존 카드 파일 소유자와 같은 UID
`1000`의 `cardreader` 사용자로 실행된다. 원본 카드 폴더는 계속 읽기 전용으로
마운트되므로 시뮬레이터가 파일을 수정하거나 삭제할 수 없다.
## 새 버전 업데이트
### 안전한 권장 순서
@@ -375,6 +379,59 @@ docker compose \
컨테이너 내부의 80 포트는 다른 컨테이너와 같아도 괜찮다. `.env`에 설정하는
NAS 호스트 포트만 겹치지 않으면 된다.
## 카드 이미지가 `403 Forbidden`인 경우
로그에 다음 내용이 있으면 Nginx 작업 사용자가 NAS 카드 파일을 읽지 못한
것이다.
```text
open() "/srv/uniare-card-images/..." failed (13: Permission denied)
```
현재 Docker 이미지는 기존 카드 파일 소유자 UID `1000`에 맞춘 `cardreader`
사용자를 사용한다. 최신 소스를 받은 후 이미지를 반드시 다시 빌드한다.
```bash
cd /volume1/docker/projects/apps/playuniare
git pull
docker compose \
-f compose.test.yaml \
-f compose.test.nas.yaml \
down
docker compose \
-f compose.test.yaml \
-f compose.test.nas.yaml \
up -d --build
```
Nginx 워커 사용자를 확인하려면:
```bash
docker exec playuniare-test-web ps aux
```
`nginx: worker process`가 `cardreader`로 표시되어야 한다.
카드 파일 읽기를 직접 확인하려면:
```bash
docker exec playuniare-test-web \
su -s /bin/sh cardreader -c \
'head -c 10 /srv/uniare-card-images/ua03/EX01BT_HTR-2-001.png >/dev/null && echo READ_OK'
```
`READ_OK`가 나오면 다음 주소에서 카드가 보여야 한다.
```text
http://NAS_IP:41808/card-assets/ua03/EX01BT_HTR-2-001.png
```
NAS에서 카드 파일 소유자의 UID가 `1000`이 아닌 경우에는 임의로 폴더 권한을
`777`로 변경하지 말고, 실제 UID를 확인한 뒤 Docker 실행 사용자 정책을
조정한다.
## 배포 체크리스트
- [ ] 로컬 `npm run build` 성공

View File

@@ -50,3 +50,11 @@
- 기존 테스트 포트 `18080`이 NAS의 다른 서비스와 충돌했다.
- 테스트 기본 포트를 `41808`, 운영 기본 포트를 `41809`로 변경했다.
- NAS별 포트 충돌에 대응할 수 있도록 `.env`와 Compose 변수로 관리한다.
## 2026-06-19: NAS 카드 이미지 ACL 대응
- NAS 카드 파일은 POSIX 권한이 열려 있어도 ACL 때문에 기본 Nginx UID
`101`에서 읽기가 거부되었다.
- 카드 파일 소유자 UID가 `1000`인 것을 확인했다.
- Nginx 워커를 UID `1000`의 `cardreader` 사용자로 실행하도록 변경했다.
- Vue 정적 파일에는 빌드 단계에서 명시적인 읽기 권한을 적용했다.

View File

@@ -116,5 +116,7 @@ Play Uniare 컨테이너 내부:
- `config/www`는 기존 `index.html`이 존재하는 실제 웹 루트다.
- Docker bind mount는 `images` 폴더만 읽기 전용으로 연결한다.
- Play Uniare는 기존 카드 이미지를 읽을 수 있지만 수정하거나 삭제할 수 없다.
- Nginx 작업 프로세스는 NAS 카드 파일 소유자와 같은 UID `1000`의
`cardreader` 사용자로 실행한다.
- 카드 이미지 URL은 `/card-assets/<series>/<fileName>` 형식을 사용한다.
- 같은 Play Uniare 도메인으로 제공되므로 별도의 CORS 설정이 필요하지 않다.

View File

@@ -15,3 +15,5 @@
문서화했다.
- NAS HTTP 포트 충돌을 해결하기 위해 테스트·운영 포트를 환경변수로
변경하고 `port is already allocated` 복구 절차를 추가했다.
- NAS ACL로 인한 카드 이미지와 favicon의 403 오류를 해결하기 위해 Nginx
워커 UID와 정적 파일 권한을 조정했다.