Files
AriWeb-Suite/docs/RUNBOOK-0.1.1.md
T
zzabisagent-labandClaude Fable 5.1 83e3604b24 bear hal21.ariweb.net HAL 전용 부트스트랩 기록: RUNBOOK §7(절차·검증·되돌리기), VERSION_HISTORY, 로컬 E2E 보고서 갱신(빌드 ab75b7d)
- docs/RUNBOOK-0.1.1.md §7: 호스트별 certbot(webroot) 인증서, --acme /var/www/html --portal-host none 부트스트랩, 검증 결과, 되돌리기
- VERSION_HISTORY.md: 배포 artifact(main ab75b7d, hal sha256 f574d875…)와 5단계 거짓 경고 결함 기록

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-27 03:12:18 +00:00

11 KiB

0.1.1 배포·검증 절차(RUNBOOK)

대상: ariweb.net 호스트(ssh hostinger, 187.53.133.173, master 계정, sudo, Node 22.23, nginx, 와일드카드 인증서 *.ariweb.net). 원칙(§32): HAL 먼저, 그 뒤 모든 모듈은 HAL 작업으로만. 개별 서버에 임의 접속해 일반 배포하지 않는다.

0. 사전 조건(운영자 조치)

  • DNS(hosting.co.kr 패널): hal.ariweb.net A 187.53.133.173, my.ariweb.net A 187.53.133.173. 레코드 전에는 curl --resolve 로만 확인된다.
  • 검증용 메일 수신 주소(자동 응답 메일함) — 메일 활성화의 실제 왕복 확인에 필요(PUT /internal/ops/mail/policy {verifier}).

1. 릴리스 artifact(개발 PC, main 병합 뒤)

git checkout main && git pull
node scripts/release.mjs build          # 전체 테스트 → dist/0.1.1/{hal,portal,agent,webmaker,arimail}-0.1.1.tar.gz + manifest.json
scp -r dist/0.1.1 hostinger:/tmp/ariweb-dist-0.1.1

2. HAL 부트스트랩(최초 1회, 서버에서)

ssh hostinger
tar -xzf /tmp/ariweb-dist-0.1.1/hal-0.1.1.tar.gz -C /tmp/ariweb-hal-src   # deploy/ 스크립트를 쓰기 위해 풀어 둔다
bash /tmp/ariweb-hal-src/deploy/bootstrap-hal.sh --dist /tmp/ariweb-dist-0.1.1 --host hal.ariweb.net --cert /etc/letsencrypt/live/wh-wild-ariweb.net

출력된 운영자 설정 토큰(1회) 으로 첫 운영자를 만든다: POST https://hal.ariweb.net/ops/api/setup {setupToken, login, password} (허용 네트워크 밖이면 node hal/index.mjs grant --login <id> 로 접근권 URL 발급). 확인: curl -s https://hal.ariweb.net/api/health 의 version·db·jobs·bootstrap.halRunningVersion.

DNS 레코드가 아직 없으면 같은 서버의 Agent·포털이 https://hal.ariweb.net 에 닿도록 /etc/hosts 에 127.0.0.1 hal.ariweb.net my.ariweb.net 을 임시로 둔다(cloud-init 이 /etc/hosts 를 관리하는 호스트는 재부팅 때 지워질 수 있다 — DNS 레코드가 생기면 필요 없다). 부트스트랩은 my.ariweb.net nginx 접근 경로(→ 127.0.0.1:8910)도 함께 만든다. HAL 만 두는 호스트(예: bear hal21.ariweb.net, 포털은 다른 호스트)는 --portal-host none 으로 포털 접근 경로를 만들지 않고, 인증서가 호스트별 certbot(webroot /var/www/html)이면 --cert /etc/letsencrypt/live/<호스트> --acme /var/www/html 을 준다(§7 참조).

3. 첫 Node Agent(같은 서버, 역할 control)

운영자 콘솔 › 서버 › 새 서버(역할 control, 위치 ariweb.net) → 등록 토큰(10분·1회) →

curl -fsSL https://hal.ariweb.net/agent/v1/install.sh | bash -s -- --hal https://hal.ariweb.net --token <토큰> --role control

운영자 승인 → bootstrap.complete=true, 수동 설치 잠김. 모듈 기술서는 서버 역할을 배포 조건으로 두지 않으므로 한 대(control)에 portal·webmaker·arimail 을 모두 둘 수 있다. 포털 연동 키: node hal/index.mjs link-portal 의 출력 값을 포털 보관소에 1회 입력한다. 포털 데이터 디렉터리(/srv/ariweb/portal/data)는 배포 전에 만들어 보관소를 먼저 채워도 된다(같은 lib/vault.mjs). 값을 화면·로그에 남기지 않으려면 서버 안에서 파이프로 바로 넣는다.

4. 모듈 배포(HAL 작업)

운영자 콘솔 › 배포 릴리스 › 0.1.1 승인 확인 → 모듈 배포 순서: portal → webmaker → arimail → (agent 갱신). 각 작업의 대상별 결과·실제 버전·건강 상태를 확인한다. HAL 자체 건강이 실패하면 나머지를 배포하지 않는다.

  • portal: /srv/ariweb/portal, 유닛 ariweb-portal, nginx my.ariweb.net(와일드카드 인증서). 포털 보관소에 service:hal(link-portal 출력), sso:webmaker, arimail:* 키 입력.
  • webmaker: 기존 /srv/webmaker + /data/webmaker 유지(HAL 모듈 설명자가 기존 유닛명·데이터 경로를 발견해 보존), 설정 ariweb.portalUrl·ariweb.secret.
  • arimail: 기존 /srv/arihakdang-mail 유지(실행 계정 arihakdang — Agent 가 deploy/module-as-user.sh 로 그 계정이 파일 작업을 하게 한다), 마이그레이션 0009_ariweb_queue.sql 적용(유닛의 EnvironmentFile 의 DB_FILE). 포털 › 운영자 › 메일 서버 등록(POST /internal/ops/mail/servers)에 setup-token(<appDir>/data/setup-token)·usage-key(기본 도메인 설정의 USAGE_API_KEY)를 넣고, 고객 도메인의 ARIWEB_SSO_SECRET 은 포털이 서비스 생성 때 스스로 넣는다.
  • 도입 모듈의 실제 버전은 REVISION.json 의 Suite 버전(0.1.1)이고 상류 버전(1.7.3·1.0.11)은 upstreamVersion 으로 함께 보인다.

4-1. 실제 배포(2026-10-26)에서 확인한 운영 사실

  • 서버가 한 대(역할 control)면 사이트 배포·백업 저장은 control 서버가 대체한다(pickServer). 백업을 같은 서버에 두려면 운영자 override(/internal/ops/backup/options/:id/override-same-server)가 필요하다.
  • 포털 메일 서버 등록(POST /ops/api/portal/mail/servers): baseUrl https://webmail.ariweb.net, internalUrl http://127.0.0.1:8790, setupUrl https://mail.arihakdang.com:8791(AriMail 전체 설정 API 는 기본 도메인 호스트에서만 응답하므로 기본 도메인 이름을 쓰고, 설정 포트가 loopback 전용이라 서버 /etc/hosts 에 127.0.0.1 mail.arihakdang.com 을 둔다), 비밀은 setup-token(<appDir>/data/setup-token)·usage-key(없으면 POST /api/setup/usage-key {action:'generate'} 로 발급, 기본 도메인 Host 로).
  • 발신 메일: 포털 보관소 mailer:resend-key(Webmaker 보관소의 Resend 키 재사용), 설정 mailer: resend, mailFrom no-reply@ariweb.net. 검증 때는 resendBase 를 로컬 포획 서버로 돌려 링크를 꺼냈고, 끝난 뒤 되돌렸다.
  • 수정 artifact 를 같은 릴리스(0.1.1)로 다시 내려면 node hal/index.mjs register-release --manifest <manifest> --approve 로 재등록(기존 버전은 artifact·커밋이 갱신된다)한 뒤 운영자 콘솔에서 agent → hal → 바뀐 모듈 순으로 배포한다. bootstrap-release --commit 으로 건강 응답의 main 커밋도 맞춘다.
  • 검증 데이터(*@check.ariweb.net 계정, check-*/solo-*.ariweb.net 도메인·메일 서비스)는 운영자 취소로 정리했고 보존 기간 뒤 삭제된다.

5. 검증(Release 0.1.1 완료 조건 34개)

docs/verification/ 의 로컬 E2E 결과와 실제 환경 확인 기록을 함께 둔다. 각 흐름은 버튼 성공이 아니라 최종 화면·외부 접속·실제 메일 왕복·실제 사용량·실제 배포 버전으로 판정한다. 충족하지 못한 흐름은 완료로 표시하지 않는다.

6. 되돌리기

  • 모듈: 운영자 콘솔 › 모듈 › 되돌리기(이전 릴리스 디렉터리 유지, 3개 보관).
  • HAL: deploy/hal-restore.sh + 재해복구 절차(§34, 기존 제어 위치 중지 확인 뒤 --takeover).

7. HAL 전용 호스트 부트스트랩 — bear hal21.ariweb.net (2026-10-27)

대상: bear(ssh bear, 192.168.20.23 / 공인 121.152.149.45, master 계정, sudo NOPASSWD, Ubuntu 24.04, nginx 1.24, Node v24.22(엔진 요구 ≥22.13 충족), certbot 2.9 nginx 플러그인·certbot.timer). 기존 운영(Webmaker webmaker.ibit.kr·hs-company.ariweb.net, Gitea source.ibit.kr, Matrix, board/file/office/xmap, 기본 서버 wh-default.conf)은 건드리지 않는다. 이 호스트에는 HAL 만 둔다(포털·Webmaker·AriMail·Agent 는 다음 단계).

# 개발 PC: main 이 깨끗한 상태(미추적 파일 없음)에서 빌드 — 전체 테스트 뒤 dist/0.1.1 (manifest.mainCommit = HEAD, dirty=false)
node scripts/release.mjs build && node scripts/release.mjs verify --dist dist/0.1.1
scp -r dist/0.1.1 bear:ariweb-deploy-0.1.1/dist

# bear: 호스트별 인증서(기존 인증서는 ibit.kr 7개뿐, ariweb.net 와일드카드 없음). 기본 서버가 /.well-known/acme-challenge/ 를 /var/www/html 로 서비스하므로 webroot 로 발급한다(nginx 설정을 건드리지 않음)
sudo certbot certonly --webroot -w /var/www/html -d hal21.ariweb.net --non-interactive --keep-until-expiring
sudo certbot reconfigure --cert-name hal21.ariweb.net --deploy-hook "systemctl reload nginx"   # 갱신 뒤 reload(installer 가 없으므로)
# bear: 부트스트랩(출력에 1회 설정 토큰이 있으므로 0600 파일로만 받는다)
cd ~/ariweb-deploy-0.1.1 && mkdir -p -m 700 src && tar -xzf dist/hal-0.1.1.tar.gz -C src
umask 077; bash src/deploy/bootstrap-hal.sh --dist ~/ariweb-deploy-0.1.1/dist --host hal21.ariweb.net \
  --cert /etc/letsencrypt/live/hal21.ariweb.net --acme /var/www/html --portal-host none > bootstrap.log 2>&1
  • --acme /var/www/html: HAL vhost 의 acme 경로를 webroot 발급 경로와 같게 둔다(아니면 vhost 가 생긴 뒤 갱신 실패).
  • 만든 것: /srv/ariweb/hal/{releases/0.1.1,current,data(0700)}, /var/www/ariweb-sites, 유닛 ariweb-hal(enabled, 127.0.0.1:8900), nginx sites-available/ariweb-hal.conf(+enabled 링크), conf.d/awstats.conf(log_format awstats — 기존 wmstats 와 이름이 다름), /etc/sudoers.d/ariweb-agent(master 는 이미 NOPASSWD ALL 이라 추가 권한 없음). 포털 vhost 는 만들지 않았다.
  • 비밀값: 설정 토큰은 /srv/ariweb/hal/data/setup.token(0600)과 ~/ariweb-deploy-0.1.1/bootstrap.log(0600)에만 있다. 첫 운영자 생성(POST /ops/api/setup)은 이 단계에서 하지 않았다 — /ops 는 허용 네트워크(기본 사설망 CIDR) 또는 접근권이 필요하다.
  • 알려진 사소한 결함: 5단계의 https://<host> 자체 확인은 nginx reload 직후 바로 실행되어 새 vhost 가 아직 적용되기 전에 "unrecognized name" 경고가 날 수 있다(거짓 경고, 몇 초 뒤 정상). 다음 릴리스에서 reload 뒤 짧은 대기를 넣는다.

검증(2026-10-27 03:08~03:12 UTC, 모두 통과): systemctl is-active/is-enabled ariweb-hal active/enabled · 127.0.0.1:8900 리슨(MainPID) · nginx -t 성공 후 reload, 기존 nginx 설정 파일 12개 sha256 변화 없음 · https://hal21.ariweb.net/api/health 외부(LAN 밖 fetch·LAN NAT 양쪽)에서 200, 인증서 CN=hal21.ariweb.net(Let's Encrypt, 2027-01-25 만료), HTTP→HTTPS 301 · 건강 응답 version 0.1.1·mainCommit ab75b7d·artifactSha256 f574d875…·bootstrap.complete=false(첫 Agent 전) · systemctl restart ariweb-hal 뒤 재기동·건강 ok(NRestarts 0, enabled 로 재부팅 지속; 서버 재부팅은 기존 서비스 중단이라 하지 않음) · 기존 서비스 회귀: nginx/webmaker/webmaker-setup/webmaker-gitea-reverse-tunnel/docker/certbot.timer active, 기존 vhost 8개 응답 코드 배포 전과 동일 · certbot reconfigure 의 모의 갱신 성공, renew_hook = systemctl reload nginx.

되돌리기(HAL 만 제거, 기존 서비스 영향 없음):

sudo systemctl disable --now ariweb-hal && sudo rm /etc/systemd/system/ariweb-hal.service && sudo systemctl daemon-reload
sudo rm /etc/nginx/sites-enabled/ariweb-hal.conf /etc/nginx/sites-available/ariweb-hal.conf /etc/nginx/conf.d/awstats.conf && sudo nginx -t && sudo systemctl reload nginx
sudo rm /etc/sudoers.d/ariweb-agent; sudo rm -rf /srv/ariweb /var/www/ariweb-sites      # 데이터 포함 — 보관이 필요하면 /srv/ariweb/hal/data 먼저 복사
sudo certbot delete --cert-name hal21.ariweb.net                                        # 인증서까지 지울 때만