Files
uniare.sori.studio/nginx/default.conf
zenn 97215f155d 정합성·보안·인덱스 개선
- health/시작 로그 버전을 package.json 기준으로 동적화
- express-rate-limit으로 로그인·이메일 쓰기 요청 IP 기준 제한, trust proxy 설정
- nginx 보안 헤더(nosniff·X-Frame-Options·Referrer-Policy) 추가
- 공개 덱 목록용 복합 인덱스 추가
- 서버 페이지네이션은 후속 과제로 todo에 기록

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-07-03 16:49:49 +09:00

101 lines
3.1 KiB
Plaintext

server {
listen 80;
server_name _;
root /usr/share/nginx/html;
index index.html;
client_max_body_size 25m;
# 텍스트 자산 gzip 압축 (이미지는 제외)
gzip on;
gzip_vary on;
gzip_comp_level 6;
gzip_min_length 1024;
gzip_proxied any;
gzip_types
text/plain
text/css
application/javascript
application/json
image/svg+xml
application/manifest+json;
# 보안 헤더 (add_header가 없는 location에 상속됨)
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# 공유 링크 → 덱 로드 페이지
location ~ ^/d/([A-Za-z0-9]+)$ {
return 302 /cardList.html?d=$1;
}
# API → 백엔드 컨테이너
location /api/ {
proxy_pass http://uniare-api:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 25m;
}
# HTML — 배포 직후 반영
location ~* \.html$ {
add_header Cache-Control "no-cache, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
try_files $uri =404;
}
# 핵심 JS — 구 URL(?v= 없음)도 최신 파일 제공 (CDN immutable 회피)
location = /script/deck-favorites.js {
add_header Cache-Control "no-cache, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
location = /script/api.js {
add_header Cache-Control "no-cache, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
location = /script/auth-form.js {
add_header Cache-Control "no-cache, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
# CSS — 배포 후 즉시 반영 (immutable 사용 안 함)
location ~* \.css$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
# JS — immutable 제거 (이미지보다 짧게 재검증)
location ~* \.js$ {
expires 1h;
add_header Cache-Control "public, must-revalidate";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
# 이미지 등 — 내용이 고정된 정적 자산이므로 장기 캐시
location ~* \.(png|jpg|jpeg|gif|webp|ico|svg|woff2?)$ {
expires 30d;
add_header Cache-Control "public, immutable";
add_header X-Content-Type-Options "nosniff" always;
try_files $uri =404;
}
location / {
try_files $uri $uri/ /index.html;
}
}