Files
web-page-backend/nginx/default.conf
gahusb 6f8b199548 feat: Agent Office — AI 에이전트 가상 오피스 (#2)
## Summary
- 2D 픽셀아트 가상 오피스에서 AI 에이전트(Stock, Music)가 실제 작업 수행
- FastAPI + WebSocket 실시간 상태 동기화 + 텔레그램 봇 양방향 알림/승인
- BaseAgent FSM (idle/working/waiting/reporting/break), 서비스 프록시 패턴
- Docker Compose 서비스 (port 18900) + Nginx WebSocket 프록시

## Changes (13 commits)
- Backend scaffold: config, db, models, Dockerfile
- WebSocket manager + Service proxy
- BaseAgent FSM + StockAgent + MusicAgent
- Telegram bot + Scheduler
- FastAPI main (REST + WS endpoints)
- Infrastructure: docker-compose + nginx
- Code review fixes: HTTPException, async polling, input validation

Reviewed-on: #2
2026-04-11 13:35:24 +09:00

237 lines
7.3 KiB
Plaintext

server {
listen 80;
server_name _;
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
root /usr/share/nginx/html;
index index.html;
# index.html은 캐시 금지 (배포 반영 핵심)
location = /index.html {
add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0";
try_files $uri =404;
}
# 정적 리소스는 장기 캐시 (Vite 해시 파일)
location /assets/ {
add_header Cache-Control "public, max-age=31536000, immutable";
try_files $uri =404;
}
# music media — Nginx가 직접 오디오 파일 서빙
location ^~ /media/music/ {
alias /data/music/;
expires 30d;
add_header Cache-Control "public, max-age=2592000" always;
add_header Accept-Ranges bytes always; # 오디오 스트리밍 범위 요청 지원
autoindex off;
}
# music API — 변수 기반 proxy_pass + $request_uri로 전체 경로 전달
location /api/music/ {
resolver 127.0.0.11 valid=10s;
set $music_backend music-lab:8000;
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;
proxy_read_timeout 660s;
proxy_pass http://$music_backend$request_uri;
}
# realestate API
location /api/realestate/ {
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;
proxy_pass http://realestate-lab:8000/api/realestate/;
}
# travel thumbnails (generated by travel-proxy, stored in /data/thumbs)
location ^~ /media/travel/.thumb/ {
alias /data/thumbs/;
expires 30d;
add_header Cache-Control "public, max-age=2592000, immutable" always;
autoindex off;
}
# travel media (images) - nginx가 직접 파일 서빙
location ^~ /media/travel/ {
alias /data/travel/; # ✅ /media/travel/... -> /data/travel/...
expires 7d;
add_header Cache-Control "public, max-age=604800" always;
# 옵션: 폴더리스팅 막기
autoindex off;
}
# 기타 정적 파일(예: vite.svg 등) 기본 캐시(원하면 조정)
location ~* \.(?:ico|png|jpg|jpeg|gif|svg|webp|css|js)$ {
add_header Cache-Control "public, max-age=604800";
try_files $uri =404;
}
# travel API
location /api/travel/ {
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;
proxy_pass http://travel-proxy:8000/api/travel/;
}
# stock API
location /api/stock/ {
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;
proxy_pass http://stock-lab:8000/api/stock/;
}
# trade API (Stock Lab Proxy)
location /api/trade/ {
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;
proxy_pass http://stock-lab:8000/api/trade/;
}
# blog-marketing API
location /api/blog-marketing/ {
resolver 127.0.0.11 valid=10s;
set $blog_backend blog-lab:8000;
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;
proxy_read_timeout 120s;
proxy_pass http://$blog_backend$request_uri;
}
# portfolio API (Stock Lab) — trailing slash 유무 모두 매칭
location /api/portfolio {
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;
proxy_pass http://stock-lab:8000/api/portfolio;
}
# agent-office API + WebSocket
location /api/agent-office/ {
resolver 127.0.0.11 valid=10s;
set $agent_office_backend agent-office:8000;
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;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400s;
proxy_pass http://$agent_office_backend$request_uri;
}
# API 프록시 (여기가 포인트: /api/ 중복 제거)
location /api/ {
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;
proxy_pass http://backend:8000;
}
# Fear & Greed Index (CNN 공개 API)
# 프로덕션 nginx에서는 아래 proxy_pass 추가 필요:
location /ext/feargreed {
proxy_pass https://production.dataviz.cnn.io/index/fearandgreed/graphdata;
proxy_set_header Host production.dataviz.cnn.io;
}
# VIX (CBOE 변동성 지수) — Yahoo Finance 공개 API
# 프로덕션 nginx에서는 아래 proxy_pass 추가 필요:
location /ext/vix {
proxy_pass https://query1.finance.yahoo.com/v8/finance/chart/%5EVIX?interval=1d&range=1d;
proxy_set_header Host query1.finance.yahoo.com;
}
# 미국 10년물 국채 금리 (^TNX) — Yahoo Finance
# 프로덕션 nginx 설정 필요:
location /ext/treasury {
proxy_pass https://query1.finance.yahoo.com/v8/finance/chart/%5ETNX?interval=1d&range=1d;
proxy_set_header Host query1.finance.yahoo.com;
}
# WTI 원유 선물 (CL=F) — Yahoo Finance
# 프로덕션 nginx 설정 필요:
location /ext/wti {
proxy_pass https://query1.finance.yahoo.com/v8/finance/chart/CL%3DF?interval=1d&range=1d;
proxy_set_header Host query1.finance.yahoo.com;
}
# Brent 원유 선물 (BZ=F) — Yahoo Finance
# 프로덕션 nginx 설정 필요:
location /ext/brent {
proxy_pass https://query1.finance.yahoo.com/v8/finance/chart/BZ%3DF?interval=1d&range=1d;
proxy_set_header Host query1.finance.yahoo.com;
}
# webhook receiver (handle both /webhook and /webhook/)
location = /webhook {
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;
proxy_pass http://deployer:9000/webhook;
}
location /webhook/ {
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;
proxy_pass http://deployer:9000/webhook;
}
# SPA 라우팅 (마지막에 두는 게 안전)
location / {
try_files $uri $uri/ /index.html;
}
# gzip (옵션)
gzip on;
gzip_types text/plain text/css application/json application/javascript application/xml+rss;
gzip_min_length 1024;
}