config: 사이트 도메인·서버 설정을 .env 로 중앙화 + 설치기 자동 종료 복구

- dotenv 도입, src/shared/env.ts 추가
  - loadEnv() 가 프로젝트 루트 .env 를 로드 (override=false: 쉘 env 우선)
  - getSiteBaseUrl() / getManifestUrl() 헬퍼
- 서버/설치기/리소스팩설치기 진입점에서 loadEnv() 호출
- 설치기 두 종의 기본 MANIFEST_URL 을 SITE_BASE_URL 기반으로 변경
  (운영 도메인을 한 곳에서만 바꾸면 됨)
- .env.example 템플릿 + .gitignore 에 .env 추가
- README / docs/admin-site.md 에 환경변수 표·사용법 추가
- installer/renderer.js: 4단계 완료 후 자동 종료 다시 활성화
This commit is contained in:
2026-05-13 02:55:58 +09:00
parent 894a86a117
commit 69ed4ad744
11 changed files with 117 additions and 10 deletions

View File

@@ -10,6 +10,7 @@ import type { ChildProcess } from 'node:child_process'
import type { Manifest, PackDefinition, PackList } from '../shared/types.js'
import { normalizePackDefinition } from '../shared/store.js'
import { getAppDataDir, getMcCustomDir } from '../shared/paths.js'
import { loadEnv, getManifestUrl } from '../shared/env.js'
import type { RpFetchedPack } from './types.js'
import { ensureYtDlpExe } from './ytdlp.js'
import { ensureFfmpegExe } from './ffmpeg.js'
@@ -17,6 +18,8 @@ import { downloadMusicTrack } from './music.js'
import { downloadImage, normalizeToCover, coverFileName } from './images.js'
import { buildResourcepackZip } from './pack.js'
loadEnv()
interface RpInstallerState {
manifestUrl: string
baseUrl: string
@@ -68,7 +71,7 @@ function acquireMusicStartSlot(): Promise<void> {
return slot
}
const DEFAULT_MANIFEST_URL = process.env.MANIFEST_URL ?? 'http://127.0.0.1:3000/manifest.json'
const DEFAULT_MANIFEST_URL = getManifestUrl()
const state: RpInstallerState = {
manifestUrl: DEFAULT_MANIFEST_URL,

View File

@@ -20,6 +20,9 @@ import type {
} from './types.js'
import type { Manifest, PackDefinition } from '../shared/types.js'
import { normalizePackDefinition } from '../shared/store.js'
import { loadEnv, getManifestUrl } from '../shared/env.js'
loadEnv()
interface InstallerState {
manifestUrl: string
@@ -31,7 +34,7 @@ interface InstallerState {
configEditorPort: number | null
}
const DEFAULT_MANIFEST_URL = process.env.MANIFEST_URL ?? 'http://127.0.0.1:3000/manifest.json'
const DEFAULT_MANIFEST_URL = getManifestUrl()
const state: InstallerState = {
manifestUrl: DEFAULT_MANIFEST_URL,

View File

@@ -3,9 +3,12 @@ import session from 'express-session'
import path from 'node:path'
import fsp from 'node:fs/promises'
import { manifestRootPath, manifestDirPath, fileDirPath, viewsDirPath, publicDirPath } from '../shared/paths.js'
import { loadEnv } from '../shared/env.js'
import { indexRouter } from './routes/index.js'
import { opRouter } from './routes/op.js'
loadEnv()
const PORT = Number(process.env.PORT ?? 3000)
// 터미널에서 Ctrl+클릭으로 바로 열 수 있도록 기본값은 127.0.0.1.
// 외부 노출이 필요할 때만 HOST=0.0.0.0 환경변수로 덮어씀.

33
src/shared/env.ts Normal file
View File

@@ -0,0 +1,33 @@
import path from 'node:path'
import fs from 'node:fs'
import dotenv from 'dotenv'
import { projectRoot } from './paths.js'
/**
* 프로젝트 루트의 `.env` 를 읽어 `process.env` 에 주입.
*
* - 이미 설정된 환경변수는 덮어쓰지 않음(쉘에서 넘긴 값이 우선).
* - 파일이 없으면 조용히 통과 — 운영 환경에서는 시스템 env 만으로도 동작해야 함.
* - 서버/설치기/리소스팩설치기 진입점에서 한 번씩 호출.
*/
export function loadEnv(): void {
const envPath = path.join(projectRoot, '.env')
if (!fs.existsSync(envPath)) return
dotenv.config({ path: envPath, override: false, quiet: true })
}
/**
* 사이트 베이스 URL. 관리 사이트가 호스팅되는 외부 주소(설치기가 manifest 를
* 받아가는 도메인). 기본값은 로컬 개발용 `http://127.0.0.1:3000`.
*/
export function getSiteBaseUrl(): string {
const raw = (process.env.SITE_BASE_URL ?? 'http://127.0.0.1:3000').trim()
return raw.replace(/\/+$/, '')
}
/** 사이트 베이스 URL + `/manifest.json`. `MANIFEST_URL` 가 따로 지정되면 그 값을 우선. */
export function getManifestUrl(): string {
const explicit = process.env.MANIFEST_URL?.trim()
if (explicit) return explicit
return `${getSiteBaseUrl()}/manifest.json`
}