2026-10-26 11:58:15 +00:00
|
|
|
/**
|
|
|
|
|
* agent/config.mjs — Node Agent 설정과 경로.
|
|
|
|
|
* 데이터 디렉터리(기본 /srv/ariweb/agent/data)의 agent.json 에 id·HAL 주소·역할·사이트(외부 모드)를 두고, 비밀은 같은 디렉터리의 보관소(lib/vault)에 'agent-secret' 로 둔다.
|
|
|
|
|
* 실제 시스템 경로는 환경 변수로 바꿀 수 있어 테스트는 임시 디렉터리에서 돈다.
|
|
|
|
|
*/
|
|
|
|
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, renameSync } from 'node:fs';
|
|
|
|
|
import { join } from 'node:path';
|
|
|
|
|
import { openVault } from '../lib/vault.mjs';
|
|
|
|
|
|
|
|
|
|
export function loadAgentConfig(env = process.env) {
|
|
|
|
|
const dataDir = env.ARIWEB_AGENT_DATA || '/srv/ariweb/agent/data'; mkdirSync(dataDir, { recursive: true, mode: 0o700 });
|
HAL 0.4.0: 통합 설정 관제 — Webmaker·AriMail·Agent 서버 단위 설정을 HAL 이 관리(설정 목록·범위 global/server·비밀값 Vault·유효값 hash, /ops/api/settings·재인증, settings.apply → settings.apply.target → Agent module.configure(HMAC 설정 받기·hash 확인·hal-managed.json 0600·재시작·모듈 적용 확인), /ops/settings 화면·운영 현황 "설정 적용 필요", AI 도구 hal_settings_get/set/apply(비밀값 거부)), 도입 모듈 Webmaker 1.9.0·AriMail 1.1.0(HAL 0.4.0 대응 halCompat, hal-managed 적용·관리 항목 409 managed_by_hal 잠금·"HAL 관리" 표시) 재도입(pin 8f8716c·f959b65, import-sources 미수정 파일 갱신), Agent heartbeat 관리, module-as-user write --mode 600, 개발 지시 v0.4.0(Oz)·docs/HAL-SETTINGS.md·VERSION_HISTORY 0.4.0 — test/hal-040.test.mjs RED → GREEN 5/5, agent 11/11, 전체 31파일 통과
2026-10-29 06:46:45 +00:00
|
|
|
let managedDoc = {}; try { managedDoc = JSON.parse(readFileSync(join(dataDir, 'hal-managed.json'), 'utf8')) || {}; } catch (_) { managedDoc = {}; } const managed = managedDoc.values && typeof managedDoc.values === 'object' ? managedDoc.values : {};
|
2026-10-26 11:58:15 +00:00
|
|
|
const file = join(dataDir, 'agent.json'); let saved = {}; try { saved = existsSync(file) ? JSON.parse(readFileSync(file, 'utf8')) : {}; } catch (_) {}
|
|
|
|
|
const cfg = {
|
|
|
|
|
dataDir, file, ...saved,
|
|
|
|
|
roots: {
|
|
|
|
|
sites: env.ARIWEB_SITES_ROOT || '/var/www/ariweb-sites', // 사이트 파일: <sites>/<siteId>/releases/<n>, current, data(uploads)
|
|
|
|
|
srv: env.ARIWEB_SRV_ROOT || '/srv/ariweb', // 모듈 설치: <srv>/<module>/releases/<ver>, current
|
|
|
|
|
nginx: env.ARIWEB_NGINX_DIR || '/etc/nginx', // sites-available/sites-enabled
|
|
|
|
|
backups: env.ARIWEB_BACKUP_ROOT || '/srv/ariweb/backups', // 백업 저장소
|
|
|
|
|
logs: env.ARIWEB_LOG_DIR || '/var/log/nginx', // 사이트별 접속 로그 aw-<siteId>.access.log
|
|
|
|
|
acme: env.ARIWEB_ACME_WEBROOT || '/var/www/letsencrypt', // certbot webroot
|
|
|
|
|
letsencrypt: env.ARIWEB_LE_DIR || '/etc/letsencrypt/live',
|
|
|
|
|
wildcardCert: env.ARIWEB_WILDCARD_CERT || '', // 플랫폼 와일드카드 인증서 디렉터리(예: /etc/letsencrypt/live/wh-wild-ariweb.net)
|
|
|
|
|
platformDomain: env.ARIWEB_PLATFORM_DOMAIN || 'ariweb.net',
|
|
|
|
|
maintPage: env.ARIWEB_MAINT_PAGE || '/var/www/ariweb-maint.html',
|
|
|
|
|
},
|
HAL 0.4.0: 통합 설정 관제 — Webmaker·AriMail·Agent 서버 단위 설정을 HAL 이 관리(설정 목록·범위 global/server·비밀값 Vault·유효값 hash, /ops/api/settings·재인증, settings.apply → settings.apply.target → Agent module.configure(HMAC 설정 받기·hash 확인·hal-managed.json 0600·재시작·모듈 적용 확인), /ops/settings 화면·운영 현황 "설정 적용 필요", AI 도구 hal_settings_get/set/apply(비밀값 거부)), 도입 모듈 Webmaker 1.9.0·AriMail 1.1.0(HAL 0.4.0 대응 halCompat, hal-managed 적용·관리 항목 409 managed_by_hal 잠금·"HAL 관리" 표시) 재도입(pin 8f8716c·f959b65, import-sources 미수정 파일 갱신), Agent heartbeat 관리, module-as-user write --mode 600, 개발 지시 v0.4.0(Oz)·docs/HAL-SETTINGS.md·VERSION_HISTORY 0.4.0 — test/hal-040.test.mjs RED → GREEN 5/5, agent 11/11, 전체 31파일 통과
2026-10-29 06:46:45 +00:00
|
|
|
// [0.4.0] HAL 통합 설정(module.configure 가 쓰는 <dataDir>/hal-managed.json)이 있으면 그 값이 우선한다(범위 5초~10분)
|
|
|
|
|
heartbeatMs: (() => { const m = Number(managed.heartbeatMs); return Number.isFinite(m) && m >= 5000 && m <= 600000 ? m : Number(env.ARIWEB_AGENT_HEARTBEAT_MS || 30000); })(),
|
|
|
|
|
halManaged: { hash: managedDoc.hash || null, keys: Object.keys(managed) },
|
2026-11-06 08:40:09 +00:00
|
|
|
// [0.4.1] caFile: HAL 공개 주소가 사설 CA·자체 서명 인증서일 때 설치 스크립트가 받아 둔 신뢰 앵커 PEM 경로(agent/index.mjs 가 기동 때 TLS 기본 CA 에 더한다)
|
|
|
|
|
caFile: env.ARIWEB_HAL_CA || saved.caFile || null,
|
|
|
|
|
save(patch) { Object.assign(cfg, patch); const out = {}; for (const k of ['id', 'halUrl', 'serverId', 'kind', 'siteId', 'groupId', 'registeredAt', 'label', 'caFile']) if (cfg[k] !== undefined && cfg[k] !== null) out[k] = cfg[k]; const tmp = file + '.tmp'; writeFileSync(tmp, JSON.stringify(out, null, 1), { mode: 0o600 }); renameSync(tmp, file); },
|
2026-10-26 11:58:15 +00:00
|
|
|
vault: () => openVault(dataDir),
|
|
|
|
|
};
|
|
|
|
|
return cfg;
|
|
|
|
|
}
|