feat(runtime): publish images from dedicated origin
This commit is contained in:
@@ -58,10 +58,19 @@ webhook 누락 시 `docker compose exec runtime pnpm sync:image`로 현재 이
|
||||
branch의 fast-forward를 요청할 때만 사용합니다. 두 파일은 runtime에 read-only로
|
||||
mount되며 원문은 환경 변수나 브라우저 bundle에 들어가지 않습니다.
|
||||
|
||||
`IMAGE_PUBLIC_URL`의 기본값은 `https://sam-image.hided.net`입니다. runtime은
|
||||
이를 Gateway·game frontend의 공개 이미지 origin과 사용자 아이콘 URL에 함께
|
||||
주입합니다. 정적 게임 이미지는 `/game`, 공용 아이콘은 `/icons`, Core2026
|
||||
사용자 아이콘은 서버 발급 경로 `users/core2026/<파일>`을 `/icons` base 아래에
|
||||
붙여 읽습니다. 업로드 권한값은
|
||||
URL query나 `VITE_*`가 아니라 `IMAGE_UPLOAD_CORE2026_SECRET_FILE`이 가리키는
|
||||
mode 0600 secret 파일에만 둡니다.
|
||||
|
||||
## 데이터와 복구 경계
|
||||
|
||||
- PostgreSQL, Redis, Core clone/worktree, PM2 상태, Caddy 인증서와 user icon은
|
||||
named volume 또는 `data/image`에 보존됩니다.
|
||||
- PostgreSQL, Redis, Core clone/worktree, PM2 상태와 Caddy 인증서는 named
|
||||
volume에 보존됩니다. 새 user icon은 외부 이미지 서비스가 보존하며 runtime의
|
||||
user icon volume은 기존 설치 호환용입니다.
|
||||
- `/image/*`는 앱 artifact가 아니며 `data/image/`의 별도 운영 자산을 제공합니다.
|
||||
- 일반 `docker compose down`은 volume을 보존합니다. `down --volumes`는 DB와
|
||||
release 상태를 삭제하는 파괴적 명령이므로 backup 없이 실행하지 않습니다.
|
||||
|
||||
+3
-2
@@ -72,7 +72,7 @@ services:
|
||||
KAKAO_REDIRECT_URI: ${PUBLIC_SCHEME:-https}://${DOMAIN:?set DOMAIN in .env}/gateway/oauth/callback
|
||||
GATEWAY_PUBLIC_URL: ${PUBLIC_SCHEME:-https}://${DOMAIN:?set DOMAIN in .env}/gateway/
|
||||
GATEWAY_USER_ICON_DIR: /srv/data/user-icons
|
||||
GATEWAY_USER_ICON_PUBLIC_URL: ${PUBLIC_SCHEME:-https}://${DOMAIN:?set DOMAIN in .env}/gateway/api/user-icons
|
||||
GATEWAY_USER_ICON_PUBLIC_URL: ${IMAGE_PUBLIC_URL:-https://sam-image.hided.net}/icons
|
||||
GATEWAY_IMAGE_UPLOAD_URL: ${IMAGE_SERVICE_URL:-https://sam-image.hided.net}
|
||||
GATEWAY_IMAGE_UPLOAD_SECRET_FILE: /run/secrets/image_upload_core2026_secret
|
||||
GATEWAY_SHARED_ICON_PUBLIC_URL: ${IMAGE_PUBLIC_URL:-https://sam-image.hided.net}/icons
|
||||
@@ -100,7 +100,8 @@ services:
|
||||
VITE_GATEWAY_API_URL: /gateway/api/trpc
|
||||
VITE_GAME_API_URL_TEMPLATE: /{profile}/api/trpc
|
||||
VITE_GAME_WEB_URL_TEMPLATE: /{profile}/
|
||||
VITE_GATEWAY_USER_ICON_BASE_URL: /gateway/api/user-icons
|
||||
VITE_IMAGE_PUBLIC_URL: ${IMAGE_PUBLIC_URL:-https://sam-image.hided.net}
|
||||
VITE_GATEWAY_USER_ICON_BASE_URL: ${IMAGE_PUBLIC_URL:-https://sam-image.hided.net}/icons
|
||||
VITE_PREVIEW_ALLOWED_HOSTS: ${DOMAIN:?set DOMAIN in .env}
|
||||
PM2_HOME: /srv/data/pm2
|
||||
TZ: ${TZ:-Asia/Seoul}
|
||||
|
||||
@@ -22,9 +22,12 @@ export const validateComposeModel = (model, mode) => {
|
||||
for (const key of [
|
||||
'GATEWAY_IMAGE_UPLOAD_URL',
|
||||
'GATEWAY_SHARED_ICON_PUBLIC_URL',
|
||||
'GATEWAY_USER_ICON_PUBLIC_URL',
|
||||
'GAME_IMAGE_UPLOAD_URL',
|
||||
'GAME_CONTENT_IMAGE_PUBLIC_URL',
|
||||
'IMAGE_SYNC_URL',
|
||||
'VITE_IMAGE_PUBLIC_URL',
|
||||
'VITE_GATEWAY_USER_ICON_BASE_URL',
|
||||
]) {
|
||||
if (!runtime.environment?.[key]) errors.push(`${key} must be configured`);
|
||||
}
|
||||
|
||||
@@ -11,11 +11,14 @@ const safeRuntime = {
|
||||
GATEWAY_IMAGE_UPLOAD_URL: 'https://sam-image.hided.net',
|
||||
GATEWAY_IMAGE_UPLOAD_SECRET_FILE: '/run/secrets/image_upload_core2026_secret',
|
||||
GATEWAY_SHARED_ICON_PUBLIC_URL: 'https://sam-image.hided.net/icons',
|
||||
GATEWAY_USER_ICON_PUBLIC_URL: 'https://sam-image.hided.net/icons',
|
||||
GAME_IMAGE_UPLOAD_URL: 'https://sam-image.hided.net',
|
||||
GAME_IMAGE_UPLOAD_SECRET_FILE: '/run/secrets/image_upload_core2026_secret',
|
||||
GAME_CONTENT_IMAGE_PUBLIC_URL: 'https://sam-image.hided.net/uploads/core2026',
|
||||
IMAGE_SYNC_URL: 'https://sam-image.hided.net',
|
||||
IMAGE_SYNC_SECRET_FILE: '/run/secrets/image_sync_core2026_secret',
|
||||
VITE_IMAGE_PUBLIC_URL: 'https://sam-image.hided.net',
|
||||
VITE_GATEWAY_USER_ICON_BASE_URL: 'https://sam-image.hided.net/icons',
|
||||
},
|
||||
volumes: [
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user