Files
AriWeb-Suite/modules/webmaker/docs/CONFIG.md
T

15 KiB

설정 파일과 초기 설정 페이지 — v1.5.7 (v1.5.11 개정)

AI Webmaker v1.5.11 · 2026-10-14 · 대상: 운영자·설치 담당자

v1.5.11: 설정 페이지 기본 포트 8795(모든 인터페이스, 겹치면 다음 포트 자동), 서비스의 /setup 도 접속 토큰으로 열림, 맨 위에 설치 점검표·관리자 계정·AI 엔진 인증 카드. 처음 설치 절차는 FIRST-INSTALL.md.

1. 무엇이 바뀌었나 (요구 1·2·3)

1.4.18 까지 1.5.7 부터
서비스 공개 주소, 소스 저장소(Gitea) 주소, AI 실행 파일 경로 같은 환경 정보 systemd 유닛의 Environment= 줄 (PUBLIC_BASE_URL, SITES_GIT_REMOTE …) — 바꾸려면 서버에서 유닛을 편집하고 daemon-reload 설정 파일 data/config.json (권한 0600) — 웹 초기 설정 페이지·관리자 콘솔·명령줄에서 바꾼다
처음 설치할 때 모르는 값 설치 스크립트가 빈 값·임시 값으로 유닛을 써 두고 나중에 사람이 고침 설치가 끝나면 초기 설정 페이지 주소(별도 포트, 기본 8795 — 1.5.7 은 3081) 를 알려 주고 거기서 입력. 1.5.11: 설치 점검표가 끝나기 전에는 서비스 첫 화면도 /setup 으로 넘어간다
기존 운영 서버 — 1.5.7 로 올린 첫 기동 때 유닛의 환경 변수를 그대로 설정 파일에 옮겨 적는다. 운영 값은 바뀌지 않는다
비밀값(토큰·비밀번호) 일부는 유닛, 일부는 보관소 모두 암호화 보관소(data/credentials.json, lib/vault.js). 설정 파일에는 쓰지 않는다

유닛에는 배포 때 정해지는 값만 남는다: PORT, HOST, SITES_ROOT, DATA_ROOT(선택), PATH, HOME, NODE_ENV. 이 값들은 설정 파일에서 바꿀 수 없다(읽기 전용으로 보임) — 포트·경로는 웹서버(nginx/Caddy) 프록시 설정과 함께 바뀌어야 하기 때문이다.

2. 설정 파일 (lib/config.js)

  • 경로: 환경 변수 WEBMAKER_CONFIG > <DATA_ROOT>/config.json (기본 앱 폴더의 data/config.json).
  • 형식: { "version": 1, "updatedAt", "updatedBy": "setup|cli|migrate:env", "values": { "<그룹>.<항목>": 값 } }
  • 우선순위: 설정 파일 > 환경 변수(유닛) > 기본값. 배포 때 정해지는 값(runtime.*)만 환경 변수가 우선.
  • 서비스는 기동 맨 처음 config.apply() 로 파일 값을 process.env 에 넣는다. 그래서 코드의 다른 부분(process.env.PUBLIC_BASE_URL 등)은 그대로다. 파일이 바뀌면(설정 페이지·CLI) 다음 호출부터 새 값을 읽지만, 기동 때 한 번만 읽는 모듈의 값(아래 표 "재시작")은 서비스를 재시작해야 적용된다.
  • 파일이 없으면 지금 환경 변수로 파일을 만든다(migrateFromEnv). 1.5.7 로 올린 기존 서버에서 이 일이 한 번 일어난다 ([config] 설정 파일을 환경 변수에서 만들었습니다 로그).

항목표

그룹 항목 (key) 환경 변수 뜻 기본값 재시작
서비스 service.publicBaseUrl PUBLIC_BASE_URL 사용자가 접속하는 주소. 생성 사이트의 위젯·통계·웹메일 안내 파일이 이 주소를 부른다 (필수) http://192.168.20.66 ○
service.formBaseUrl FORM_BASE_URL 폼 접수 서버 주소 (비우면 공개 주소) ○
service.adminUsers ADMIN_USERS 관리자로 취급할 아이디(쉼표) ○
service.systemdUnit WEBMAKER_SERVICE 설정 페이지 "서비스 재시작" 이 재시작할 유닛 (설치 스크립트가 넣음)
service.setupPort / setupBind WEBMAKER_SETUP_PORT / _BIND 초기 설정 페이지 포트·바인드 (lan = 첫 사설 IPv4, 0.0.0.0 = 전체, 또는 특정 IP) 3081 / lan (setup 서비스)
실행 환경 (읽기 전용) runtime.port host sitesRoot dataRoot statsLog PORT HOST SITES_ROOT DATA_ROOT STATS_LOG 배포 때 정해지는 값 3080 / 127.0.0.1 / /var/www/sites / … —
AI 엔진 ai.claudeBin codexBin CLAUDE_BIN CODEX_BIN 실행 파일 (비우면 자동 탐색) ○
ai.claudeModel claudeMaxTurns openaiMaxTurns allowInsecureTls CLAUDE_MODEL CLAUDE_MAX_TURNS OPENAI_ENGINE_MAX_TURNS CLAUDE_ALLOW_INSECURE_TLS 설치 기본 모델·턴 상한·TLS 완화 claude-opus-5-5 / 80 / 60 / 켬 ○
ai.codexUnsafe CODEX_UNSAFE v1.6.31: 샌드박스를 만들 수 없을 때 기본은 작업 거부(fail-closed). true 면 샌드박스 없이 실행(위험) false ○
ai.maxJobMinutes maxConcurrentJobs WM_MAX_JOB_MINUTES WM_MAX_CONCURRENT_JOBS v1.6.31: 한 AI 작업 최대 시간(분, 15분 무출력도 중단) · 서버 전체 동시 AI 작업 수(넘으면 429) 45 / 4
ai.allowInsecureTls CLAUDE_ALLOW_INSECURE_TLS v1.6.31 부터 기본 false(claude 자식의 TLS 검증 유지). 사내 프록시·자체 서명 인증서 환경에서만 true false ○
서비스(보안) service.trustedProxies WM_TRUSTED_PROXIES v1.6.31: 이 IP 에서 온 연결의 X-Forwarded-For 만 클라이언트 IP 로 믿음(속도 제한·기록). 비우면 루프백만
service.internalAllow WM_INTERNAL_ALLOW v1.6.31: 사용자가 넣는 주소·제공자 URL 이 사설/내부 주소여도 허용할 host:port 목록(쉼표) — 사내 Gitea·Arimail·AI 서버. 그 밖의 내부 주소는 차단
service.siteOrigin WM_SITE_ORIGIN v1.6.31: 생성 사이트 전용 origin(예약 — 사용자 결정 뒤 연결, 비우면 같은 origin) ○
ai.codexSandbox CODEX_SANDBOX codex 샌드박스: auto(커널이 비특권 user namespace 를 허용하면 workspace-write, 아니면 없이 — Ubuntu 24.04 기본 kernel.apparmor_restrict_unprivileged_userns=1 에서는 샌드박스 쓰기가 모두 실패) / workspace-write / none auto (다음 작업부터)
소스 보관 (Gitea) source.provider SOURCE_PROVIDER 연동 모듈 (gitea / none) gitea
source.remote web prefix SITES_GIT_REMOTE SITES_GIT_WEB SITES_GIT_PREFIX 푸시 주소·웹 주소·브랜치 접두어 / / sites (다음 커밋부터)
source.apiUrl user repo GITEA_API_URL GITEA_USER GITEA_REPO API 주소·계정·저장소 (선택) / webmaker / webmaker/sites
source.token — (보관소 gitea) API 토큰 (install-gitea.sh 가 만듦)
메일 연동 (Arimail) mail.provider MAIL_PROVIDER 연동 모듈 (none / arimail) none
mail.url apiUrl domain adminLogin ARIMAIL_URL ARIMAIL_API_URL ARIMAIL_DOMAIN ARIMAIL_ADMIN_LOGIN 공개 주소·내부 API 주소·메일 도메인·관리자 ID / / / admin
mail.adminPassword — (보관소 arimail) 관리자 비밀번호
SSL ssl.acmeDir acmeWaitMin WM_ACME_DIR WM_ACME_WAIT_MIN 와일드카드 인증서 작업 폴더·수동 DNS 대기(분) /var/tmp/webmaker-acme / 40 ○
한도 limits.copyMaxPages copyMaxAssets COPY_MAX_PAGES COPY_MAX_ASSETS 사이트 복사 상한 300 / 5000 ○
외부 API (고급) endpoints.* RESEND_API_BASE OPENPROVIDER_API_BASE GOOGLE_API_BASE GOOGLE_TOKEN_URL INDEXNOW_ENDPOINT 시험용 대체 주소 실제 서비스 주소

관리자 콘솔 › 설정의 값(모델 등급·환율·마진·메일 발송 키·도메인 요율·DNS 공급자·등록 업체(v1.5.36) …)은 그대로 data/settings.json 이다. 설정 파일은 "서비스가 돌아가는 환경" 만 다룬다.

3. 초기 설정 페이지 (setup-server.js, 요구 2)

  • 별도 systemd 서비스 webmaker-setup 이 설정 파일의 service.setupPort(기본 8795, v1.5.11; 겹치면 8796… 을 차례로 잡고 설정 파일에 기록)·setupBind(기본 0.0.0.0 — 공인 IP 만 있는 서버에서도 http://<IP>:8795/ 로 접속; 사설망만 열려면 lan = 첫 사설 IPv4, 도커 브리지 등 가상 인터페이스 제외) 로 전용 페이지를 연다. 설치 스크립트(deploy/install.sh, deploy/remote-install.sh, deploy/remote-update.sh)가 설치·기동하고, 끝나면 접속 주소를 알려 준다: http://<서버 IP>:8795/?token=<접속 토큰> (node scripts/config.js setup-url 로 언제든 다시 본다)
  • 인증: 접속 토큰(data/setup.token, 0600 — 처음 기동 때 생성) 또는 웹메이커 관리자 계정 로그인. 세션은 12시간 쿠키. 로그인 시도는 IP 당 15분 10회.
  • 같은 화면이 서비스 안에도 있다: https://<서비스>/setup (v1.5.11: 로그인 없이 열리고 화면 안에서 접속 토큰 또는 관리자 계정으로 들어온다 — 인증 코드 lib/setupauth.js 를 두 서버가 공용) 과 관리자 콘솔 › 시스템 설정 탭. 화면 코드는 public/setup.js 하나, API 는 lib/setupapi.js 하나다 (/api/setup/* ↔ /api/admin/config/*).
  • 화면 (v1.5.11 맨 위): 설치 점검표(관리자 비밀번호·AI 엔진 인증·서비스 공개 주소 — lib/setupstate.js; 필수 항목이 남아 있으면 서비스 첫 화면 /·/login 이 /setup 으로 302, 끄기 service.setupRedirect=off, 우회 /login?direct=1), 관리자 계정(목록·마지막 로그인, 기본 관리자 admin/admin 만들기, 비밀번호 재설정, 새 관리자), AI 엔진 인증(Claude 서버 로그인/OAuth 토큰/API 키 저장·확인, OpenAI API 키/codex 로그인). 이어서 상태 카드(웹메이커 서비스·설정 페이지 서비스·Gitea·Arimail·Claude(실행 파일+인증)·Codex·Resend, "연결 확인"), 그룹별 설정 카드(출처 배지: 설정 파일/환경 변수/기본값, 재시작 표시, 비밀값은 힌트만), "이 묶음 저장"·"바뀐 값 모두 저장", 서비스 재시작(실행 중 AI 작업이 끝날 때까지 기다린 뒤 sudo systemctl restart), "환경 변수에서 옮겨 적기", 연동 서비스 설치·등록 명령 안내.
  • 재시작 권한: 설치 스크립트가 /etc/sudoers.d/webmaker-setup 에 systemctl restart <유닛> 만 허용하는 줄을 둔다. 없으면 화면이 수동 명령을 알려 준다.
  • 방화벽: v1.5.11 부터 설치·갱신 스크립트가 ufw 에 설정 페이지 포트(8795)를 허용하고 1.5.7 의 3081 사설망 규칙은 지운다(FQDN 을 모르는 서버에서도 http://<IP>:8795/ 가 기본 접속 위치). 접속은 토큰·관리자 로그인·시도 제한(IP 당 15분 10회)으로 보호되지만 관리 화면이므로, 점검이 끝나면 sudo ufw delete allow 8795/tcp 로 닫거나 service.setupBind=lan 으로 바꿔도 된다(서비스 안 /setup·관리자 콘솔 탭은 그대로).
  • 새 설정 항목(v1.5.11): service.setupRedirect(auto/off), service.allowSignup(기본 켬 — 끄면 로그인 화면의 회원가입 탭이 사라지고 API 는 403 "회원가입이 닫혀 있습니다").
  • API(v1.5.11, lib/setupapi.js): GET <base>/ready 점검표, POST <base>/admin/bootstrap|create|password, PUT <base>/ai/claude|openai. 명령줄: node scripts/admin.js bootstrap.

4. 명령줄 (scripts/config.js)

node scripts/config.js list                     # 전체 값과 출처
node scripts/config.js get service.publicBaseUrl
node scripts/config.js set service.publicBaseUrl https://webmaker.example.com   # 여러 쌍 가능
node scripts/config.js set mail.adminPassword '비밀번호'                          # 비밀값 → 보관소
node scripts/config.js unset source.apiUrl
node scripts/config.js import-env --unit /etc/systemd/system/webmaker.service   # 유닛 → 파일 (없는 항목만)
node scripts/config.js check                    # 필수 값 점검 (없으면 종료 코드 2)
node scripts/config.js setup-url                # 초기 설정 페이지 주소(토큰 포함)

환경 변수 DATA_ROOT·WEBMAKER_CONFIG 를 서비스와 같게 준다(기본 앱 폴더의 data/).

5. 기존 서버 올리기 (요구 3)

  1. deploy/remote-update.sh <ssh> <앱 폴더> <유닛> — 코드 갱신·재시작 뒤 (a) 유닛의 환경 변수를 설정 파일로 옮기고 (b) webmaker-setup 서비스를 설치·기동하고 (c) deploy/install-services.sh --check 로 이미 설치된 Gitea·Arimail 을 등록한다. 서비스 기동 로그에 [config] 설정 파일을 환경 변수에서 만들었습니다 가 한 번 찍힌다.
  2. 이후 유닛의 Environment=PUBLIC_BASE_URL=…, SITES_GIT_* 줄은 참고용이다 — 설정 파일이 우선한다. install-gitea.sh 를 다시 실행하면 SITES_GIT_* 줄을 유닛에서 지운다.
  3. 다른 서버로 DB 를 복사할 때(remote-install.sh) 설정 파일과 토큰은 복사하지 않는다(서버마다 다른 값).

6. 자주 나는 메시지

메시지 원인 해결
[config] 설정 파일: … 로그만 있고 값이 바뀌지 않음 바꾼 항목이 "재시작 후 적용" 항목 설정 페이지의 "서비스 재시작" 또는 sudo systemctl restart <유닛>
설정 페이지 "서비스 재시작" → 재시작 실패: sudo: a password is required sudoers 규칙 없음 deploy/install.sh/remote-update.sh 다시 실행(규칙 생성) 또는 서버에서 직접 재시작
접속 토큰이 맞지 않습니다 토큰이 바뀜(data/setup.token 삭제·재생성) node scripts/config.js setup-url 로 새 주소, 또는 관리자 계정으로 로그인
<항목>은(는) 배포 때 정해지는 값이라 여기서 바꿀 수 없습니다 runtime.* 항목 저장 시도 유닛과 웹서버 설정을 함께 고친 뒤 재시작
<항목>은(는) http:// 또는 https:// 로 시작하는 주소여야 합니다 등 형식 오류 안내대로 수정. 저장은 전체가 검증을 통과했을 때만 된다

7. 백업 · 복구 (v1.6.31, 요구 29)

  • deploy/remote-update.sh·deploy/install.sh 가 재시작 전에 node scripts/backup-data.js --tag update 를 실행해 DATA_ROOT 전체를 DATA_ROOT/backups/<UTC시각>-update.tar.gz(0600) 로 묶는다(최근 10개 보관, --keep N, --list). sites/ 의 git 저장소와 통계 로그는 크기 때문에 제외하지 않고 그대로 들어간다 — 용량이 크면 --keep 을 줄인다.
  • 복구: 서비스를 멈추고(sudo systemctl stop <유닛>) tar -xzf DATA_ROOT/backups/<파일> -C DATA_ROOT 뒤 재시작. 특정 파일만 되돌릴 때는 DATA_ROOT/<파일>.bak(직전 저장본) 을 먼저 본다. 손상 파일 목록은 서버 기동 로그 [jsonstore] 와 관리자 콘솔 › 운영 복구에 보인다.
  • 두 운영 서버는 DATA_ROOT 가 다르므로(bear: 앱 폴더 data/, hostinger: /data/webmaker) 백업도 각자 서버에만 남는다 — 서로 복사하지 않는다.