- docs/verification/real-env-0.1.1.md/.json: 배포 경과·결함 수정 요약, 흐름별 단계·증거, 재검증(systemd/nginx/HAL·포털 건강/배포 영수증/모듈 버전) 기록 - docs/RUNBOOK-0.1.1.md: 서버 한 대 운영, 메일 서버 등록 값, 발신 메일, 같은 릴리스 재등록 절차 - VERSION_HISTORY.md 알려진 제한에 실환경 검증 결과 기입. 출시 완료는 선언하지 않음 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
32 KiB
0.1.1 실제 환경 배포·검증 기록 (ariweb.net 호스트, 2026-10-26)
생성: 2026-10-26T14:33:19.592Z · 검증기 real-env-check.mjs(서버에서 실행, 실제 HAL·포털·Node Agent·Webmaker·AriMail 대상) · 배포 기준 main 3951be5
상태 요약
- 배포: HAL 부트스트랩(
deploy/bootstrap-hal.sh) → 첫 운영자 → 첫 Node Agent(역할 control, 승인 → 부트스트랩 완료·수동 설치 잠김) →link-portal→ HAL 작업으로 portal → webmaker → arimail 배포, 이후 수정 artifact 를 같은 릴리스 0.1.1 로 재등록해 HAL 작업으로 agent·hal·portal 갱신. 모든 모듈의 실제 버전 0.1.1·건강 ok(아래 재검증). - 공개 DNS:
hal.ariweb.net·my.ariweb.netA 레코드는 아직 없다(이번 작업은 공개 DNS 를 바꾸지 않았다). 서버/etc/hosts임시 항목으로 같은 서버 안 통신만 확인했고, 외부 주소 접속(흐름 8 등)은 레코드 생성 뒤 확인한다. - 실제 외부 발신 1건: 포털 mailer(Resend,
no-reply@ariweb.net)로icqmomo@gmail.com에 확인 메일 발송 — Resend 수락 id01a17899-8c6e-7574-b85b-3c1015fe94b5(14:24 UTC). 수신함 도착은 사람이 확인한다. - 흐름 판정(34개): 실제 확인 7 · 부분 확인 7 · 미수행 20 · 실패 0. 0.1.1 출시 완료는 선언하지 않는다 — 지시서 기준(최종 화면·외부 접속·실제 메일 왕복·실제 사용량·실제 배포 버전) 중 외부 접속·메일 왕복·Webmaker 페이지 제작이 남아 있다.
사람이 해야 남는 일
- hosting.co.kr 패널에
hal.ariweb.net·my.ariweb.netA 레코드(187.53.133.173) 생성 → 흐름 8·외부 접속 확인. - 메일 왕복 검증용 수신 주소(자동 응답 메일함) 설정(
PUT /internal/ops/mail/policy {verifier}) → 흐름 11. - Webmaker 제작 화면에서 검증 사이트의 페이지를 만들어 저장 → 흐름 5·6·13·14 의 나머지(관리형 배포·백업 실행·복원·외부 확인).
배포 경과와 발견한 결함(모두 코드로 수정해 main 에 반영, VERSION_HISTORY "실제 환경 배포에서 발견한 결함 수정")
- 부트스트랩 4단계 중단 —
/etc/letsencrypt/live는 root 전용이라 일반 계정의 인증서 존재 확인이 거짓 →sudo -n test -f. - 포털 artifact 에 상품정책 시드(
catalog/) 누락 → 릴리스 빌더 경로 추가. - AriMail 은 다른 계정(arihakdang)으로 운영 → Agent 실행 계정 모드(
deploy/module-as-user.sh, sudoers 최소 규칙). 내려받은 artifact 0600·현재 경로 심링크·umask 077 로 만들어진 0700 디렉터리(릴리스 빌더 모드 정규화) 등 권한 문제 4건. - AriMail 마이그레이션이
DB_FILE없이 릴리스 디렉터리에 빈 DB 를 만들 뻔함 → 유닛 EnvironmentFile 을 실행 계정으로 읽어 실행(공백 값 파싱 포함). 사후 절차 실패 시 current 되돌리기. - 도입 모듈 실제 버전이 상류 버전(1.7.3·1.0.11)으로 보고돼 HAL 판정·drift 표시 오류 → REVISION.json 의 Suite 버전 사용(설치 결과·heartbeat 모두).
- Webmaker 운영 유닛의 강화 지시문이 템플릿에 지워질 뻔함 → keepExistingUnit. 데이터 백업이 root 소유 파일(이전 마이그레이션 기록)에 막힘 → 읽기 실패 관대 처리(+서버의 해당 파일 소유권 정정).
- 같은 버전 재설치가 실행 중인 디렉터리를 지움 → 임시 풀기·
<ver>.prev-<시각>보존. 새 유닛(포털) enable 누락. 부트스트랩 릴리스 기록 행 없음(UPDATE 무효). - my.ariweb.net nginx 접근 경로가 어디서도 만들어지지 않음 → 부트스트랩이 설치.
- 서버 한 대(control)라 web·backup 역할 서버를 고를 수 없음 → control 대체. AriMail 설정 API 는 기본 도메인 호스트에서만 응답(Node fetch 는 Host 변경 불가) → 설정 주소를 기본 도메인 이름으로, 서버 hosts 항목.
Release 0.1.1 완료 조건 34개 — 실제 환경 판정
| # | 흐름 | 판정 | 비고 |
|---|---|---|---|
| 1 | 신규 고객 가입과 이메일 확인 | 실제 확인 | 실제 포털·실제 mailer 경로(포획 서버) — 외부 수신함 도착은 별도 1건으로 확인 |
| 2 | 개인 사용자 그룹 생성과 다른 사용자 초대 | 실제 확인 | |
| 3 | 상품 주문, 결제 확인, 권리 활성화 | 실제 확인 | |
| 4 | 초안 사이트 생성 | 실제 확인 | 실제 Webmaker 에 프로젝트 생성(내부 API 서명 호출) |
| 5 | Webmaker에서 페이지 제작 | 부분 확인 | 제작 화면 진입(SSO)은 실제 Webmaker 로 확인 · 페이지 제작(AI 생성·저장)은 사람이 Webmaker 화면에서 수행해야 하므로 미수행 |
| 6 | 관리형 배포 | 부분 확인 | 배포 요청이 거부됨: precheck_failed — 배포 전 확인에서 차단된 항목이 있습니다 (저장본이 없어 배포할 내용이 없음; 사람이 Webmaker 에서 페이지를 저장한 뒤 수행) |
| 7 | 도메인 연결과 HTTPS 발급 | 미수행 | 실제 소유 도메인과 공개 DNS(TXT·A) 변경이 필요 — 이번 작업은 공개 DNS 를 바꾸지 않음 |
| 8 | 외부 주소에서 사이트 확인 | 미수행 | 공개 DNS(my/hal/사이트 도메인) 생성 전 — 외부 주소 접속은 레코드 생성 뒤 확인 |
| 9 | 사이트 정보와 접속·사용량 통계 확인 | 부분 확인 | 화면 데이터 제공 확인 · 실제 접속 통계(awstats 로그 집계)는 공개 DNS 로 외부 방문이 생긴 뒤 확인 가능 |
| 10 | 사이트 대표 메일과 메일함 생성 | 부분 확인 | 실제 AriMail 테넌트·메일함 생성 확인 · 활성화는 도메인 DNS(MX/SPF/DKIM) 반영이 필요해 외부 대기 |
| 11 | 외부 송신, 수신, 회신 확인 | 미수행 | 검증용 수신 주소(자동 응답 메일함)와 고객 도메인 MX 반영 필요 |
| 12 | 독립 메일 서비스 생성 | 실제 확인 | |
| 13 | 백업 옵션 구매와 첫 백업 확인 | 부분 확인 | 백업 옵션 주문·승인·활성화는 실제 확인. 수동 백업 실행은 사이트가 초안(미배포)이라 정기 실행기가 옵션을 site_not_deployed 로 중지해 Agent 백업까지 가지 않음(설계대로) — Webmaker 에서 페이지를 저장·배포한 뒤 다시 수행. 판정은 검증기의 시간 초과를 운영자가 DB 상태(옵션 paused: site_not_deployed)로 확인해 부분 확인으로 정정 |
| 14 | 백업 복원과 외부 사이트 확인 | 미수행 | 복원 승인(3단계)·외부 사이트 확인은 공개 DNS 와 복원 대상 배포본 필요(흐름 6 선행) |
| 15 | 관리형 사이트 서버 이전과 외부 확인 | 미수행 | 관리 서버가 1대뿐이라 서버 간 이전 미수행 |
| 16 | 외부 배포 사이트 생성과 배포 | 미수행 | 외부 Linux 서버 없음 |
| 17 | 사용량 경고와 한도 동작 확인 | 미수행 | 실제 사용량이 한도에 이르려면 운영 트래픽·시간 경과 필요 |
| 18 | 상품 축소 보류와 정리 후 적용 | 미수행 | 축소 보류는 실제 사용 중 리소스가 필요(로컬 E2E 확인) |
| 19 | 사이트 수 반환과 대표 메일의 독립 전환 | 미수행 | 사이트 수 반환·독립 전환은 흐름 10 활성화(외부 DNS) 뒤 가능 |
| 20 | 사이트 소유권 이전 | 미수행 | 두 번째 소유자 그룹의 심사 절차를 포함해 로컬 E2E 로 확인, 실환경 미수행 |
| 21 | 중지, 해지, 보존 예정일 표시 | 미수행 | 보존 예정일 표시는 시간 경과 필요(로컬 E2E 확인) |
| 22 | HAL 우선 배포 후 HAL을 통한 전체 모듈 배포 | 실제 확인 | HAL 부트스트랩 → 첫 Agent → HAL 작업으로 portal·webmaker·arimail·agent 배포, 실제 버전 0.1.1·건강 ok |
| 23 | 실패 작업의 재시도와 되돌리기 | 미수행 | 실패 작업 재시도·되돌리기는 배포 중 실제로 2회 발생(백업 실패→재시도 성공, 마이그레이션 실패→되돌리기) — 기록은 VERSION_HISTORY·이 문서의 배포 경과 참고 |
| 24 | 운영자 승인, 감사 기록, 고객 알림의 일치 | 부분 확인 | |
| 25 | HAL, 로그인, 비밀정보 관리, 인증서 기반의 재해복구 훈련 | 미수행 | 재해복구 훈련은 다른 호스트 복원이 필요(로컬 E2E 부분 확인) |
| 26 | 새로 고침, 재로그인, HAL 재시작 후 진행 작업 상태 유지 | 실제 확인 | |
| 27 | 마지막 사이트 수·용량·메일함 동시 요청 시 하나만 성공 | 미수행 | 동시 요청 경합은 로컬 E2E 로 확인, 실환경 미수행 |
| 28 | 외부 Linux 서버 Agent 연결·배포·재배포·제거·실패 정리 | 미수행 | 외부 Linux 서버 없음 |
| 29 | HAL 장애 중 기존 서비스 유지와 신규 변경 제한 표시 | 미수행 | HAL 장애 상태 표시는 로컬 E2E 로 확인(흐름 26 에서 재시작 중 복구만 실환경 확인) |
| 30 | 모듈 업데이트, 일부 서버 실패, 대상별 되돌리기와 상태 조정 | 부분 확인 | 모듈 갱신(수정 artifact 재등록 → HAL 작업으로 agent·hal 갱신) 4건 완료 확인 · 일부 서버 실패·대상별 되돌리기는 서버 1대뿐이라 미수행 |
| 31 | 긴급 복구의 승인 부족·만료 자격·허용 범위 밖 작업 거부와 정상 복구 | 미수행 | 긴급 복구 절차는 로컬 E2E 로 확인 |
| 32 | Source 옵션 만료 후 30일 read-only, clone·export와 삭제 완료 | 미수행 | Source 옵션 30일 만료는 시간 경과 필요 |
| 33 | 메일 서비스의 사이트 대표→독립 전환 후 항목 유지 | 미수행 | 흐름 19 와 같은 외부 DNS 선행 조건 |
| 34 | 일시 중지·해지 예약·보존·삭제 단계의 표시 일치 | 미수행 | 시간 경과 필요(로컬 E2E 확인) |
흐름별 단계와 증거
1. 신규 고객 가입과 이메일 확인 — 실제 확인
실제 포털·실제 mailer 경로(포획 서버) — 외부 수신함 도착은 별도 1건으로 확인
- ✔ 가입 → 세션 발급(실제 포털 https://my.ariweb.net) — {"status":200}
- ✔ 확인 전 그룹 생성 차단(403 email_unverified) — "email_unverified"
- ✔ 확인 메일이 실제 발신 경로(mailer resend → 포획 서버)로 나감 · 토큰 추출 — {"subject":"[Ariweb] 이메일 주소를 확인해 주세요","from":"no-reply@ariweb.net","linkHost":"https://my.ariweb.net"}
- ✔ 이메일 확인(1회용) → 재사용 거부 — {"first":200,"second":"token_used"}
- ✔ 내 정보: 확인됨 · 개인 그룹 · owner — {"verifiedAt":"2026-10-26T14:31:15.078Z","group":"personal","role":"owner"}
- ✔ 중복 가입은 존재를 드러내지 않는 안내(409) — "signup_unavailable"
- ✔ 로그인 화면(로그인 상태면 302, 아니면 200)·기기(세션) 목록 — {"loggedIn":302,"anonymous":200,"sessions":"[redacted]"}
{
"verifiedAt": "2026-10-26T14:31:15.078Z",
"group": "personal",
"role": "owner"
}
2. 개인 사용자 그룹 생성과 다른 사용자 초대 — 실제 확인
- ✔ 팀 그룹 만들기 → 현재 그룹 전환 — "g_01a1789f67b12a216acd1955fa"
- ✔ 이메일 초대 → 초대 메일(포획)에서 링크 — "upaCVcL43bFzzZaGTtGZi_tU2J64oJEA"
- ✔ 초대 수락(1회용) → member · 재사용 거부 — {"reuse":"invite_invalid"}
- ✔ 권한 없는 구성원의 변경 API → 403 — {"requiredRole":["owner","admin"],"yourRole":"member"}
3. 상품 주문, 결제 확인, 권리 활성화 — 실제 확인
- ✔ 상품 목록(공개 버전·가격·한도) — {"count":2,"id":"pv_01a178834fac072b5600ce1e60","name":"팀","price":49000,"sites":3}
- ✔ 주문 제출(수동 결제, 독립 메일 옵션 포함) → 결제 대기 — {"id":"o_01a1789f68c3298aec8ad337e8","group_id":"g_01a1789f67b12a216acd1955fa","order_no":"AW-20261026-0003","kind":"new","product_version_id":"pv_01a178834fac072b5600ce1e60","items_json":"[{"type":"product","id":"team","name":"팀","qty":1,"unit_price":49000,"amount":49000,"tax":4900,"target_type":"group","target_id":null,"grants":{"sites":3,"web_disk":21474836480,"
- ✔ 입금 확인 전 승인 거부(409) — "payment_not_confirmed"
- ✔ 운영자 입금 확인 → 승인 → 권리 활성화 — {"paid":"awaiting_approval","approved":"approved","granted":10}
- ✔ 고객 결제 화면: 활성 상품·권리·다음 청구일 — {"subs":1,"nextBilling":"2026-11-26T14:31:15.451Z"}
{
"orderNo": "AW-20261026-0003",
"bill": {
"subs": 1,
"nextBilling": "2026-11-26T14:31:15.451Z"
}
}
4. 초안 사이트 생성 — 실제 확인
실제 Webmaker 에 프로젝트 생성(내부 API 서명 호출)
- ✔ 사이트 생성(새 Webmaker 프로젝트 · 관리형) → 초안 — {"id":"s_01a1789f690cb9115f0330d2e8","group_id":"g_01a1789f67b12a216acd1955fa","name":"검증 사이트 mvpcu283","purpose":"실제 환경 검증","webmaker_project_id":"85e1859a8638022beb761f1ec4ccfc93","template":null,"lang":"ko","timezone":"Asia/Seoul","lifecycle":"draft","deploy_mode":"managed","primary_domain":null,"site_count_state":"none","site_count_reservation_id":null,"server_id":null,"external_agent_id":null
- ✔ 초안 목록·사용량(사이트 수 미소비) — {"drafts":1,"lifecycle":"draft","projectId":null}
5. Webmaker에서 페이지 제작 — 부분 확인
제작 화면 진입(SSO)은 실제 Webmaker 로 확인 · 페이지 제작(AI 생성·저장)은 사람이 Webmaker 화면에서 수행해야 하므로 미수행
- ✔ 제작 화면 열기: 포털 SSO 티켓 → 실제 Webmaker /api/auth/sso 302(1회용) — {"portal":302,"webmaker":302,"webmakerLocation":"/?site=85e1859a8638022beb761f1ec4ccfc93","reuse":403}
- ✔ 저장본 목록·배포 전 확인(실제 Webmaker 프로젝트) — {"versionsStatus":200,"versions":0,"precheck":true}
{
"sso": {
"portal": 302,
"webmaker": 302,
"webmakerLocation": "/?site=85e1859a8638022beb761f1ec4ccfc93",
"reuse": 403
},
"ver": {
"versionsStatus": 200,
"versions": 0,
"precheck": true
}
}
6. 관리형 배포 — 부분 확인
배포 요청이 거부됨: precheck_failed — 배포 전 확인에서 차단된 항목이 있습니다 (저장본이 없어 배포할 내용이 없음; 사람이 Webmaker 에서 페이지를 저장한 뒤 수행)
- ✔ 배포 요청(관리형) → HAL 작업·사이트 수 예약 — {"status":409,"error":"precheck_failed","message":"배포 전 확인에서 차단된 항목이 있습니다"}
9. 사이트 정보와 접속·사용량 통계 확인 — 부분 확인
화면 데이터 제공 확인 · 실제 접속 통계(awstats 로그 집계)는 공개 DNS 로 외부 방문이 생긴 뒤 확인 가능
- ✔ 사이트 정보·배포 이력·사용량 화면 — {"overviewKeys":["ok","overview","refreshJob"],"usageKeys":["ok","overview","allocations","samples"],"deployments":0}
{
"overviewKeys": [
"ok",
"overview",
"refreshJob"
],
"usageKeys": [
"ok",
"overview",
"allocations",
"samples"
],
"deployments": 0
}
10. 사이트 대표 메일과 메일함 생성 — 부분 확인
실제 AriMail 테넌트·메일함 생성 확인 · 활성화는 도메인 DNS(MX/SPF/DKIM) 반영이 필요해 외부 대기
- ✔ 사이트 연결 도메인 등록(검증 전용 이름, 소유 확인은 외부 대기) — {"id":"d_01a1789f6a07e57873e2f0c05f"}
- ✔ 사이트 대표 메일 생성 → 실제 AriMail 테넌트 준비 — {"id":"msv_01a1789f6a0d5f702a1581f2fd","status":"needs_setup","kind":"site_bound"}
- ✔ 메일함 생성(초기 비밀번호 1회 표시) → 재조회에 비밀번호 없음 · 실제 AriMail 계정 — {"id":"mb_01a1789f6e723ade68602baaf9","address":"kim@check-mvpcu283.ariweb.net","shownOnce":true,"leakedOnReload":false}
- ✔ DNS 확인(미반영 구분) → 활성화 작업은 외부 대기 — {"dnsOk":true,"items":[],"activate":200,"job":"queued","waitReason":""}
{
"d": {
"id": "d_01a1789f6a07e57873e2f0c05f"
},
"svc": {
"id": "msv_01a1789f6a0d5f702a1581f2fd",
"status": "needs_setup",
"kind": "site_bound"
},
"mb": {
"id": "mb_01a1789f6e723ade68602baaf9",
"address": "kim@check-mvpcu283.ariweb.net",
"shownOnce": true,
"leakedOnReload": false
},
"dns": {
"dnsOk": true,
"items": [],
"activate": 200,
"job": "queued",
"waitReason": ""
}
}
12. 독립 메일 서비스 생성 — 실제 확인
- ✔ 메일 전용 도메인 등록(purpose mail) — "d_01a1789f6e94cf197bdcb0cb81"
- ✔ 독립 메일 서비스 생성(독립 옵션 소비·사이트 수 미소비) — {"id":"msv_01a1789f6e9604bd5f49bb08e1","kind":"standalone","status":"needs_setup","usage":{}}
{
"id": "msv_01a1789f6e9604bd5f49bb08e1",
"kind": "standalone",
"status": "needs_setup",
"usage": {}
}
13. 백업 옵션 구매와 첫 백업 확인 — 부분 확인
백업 옵션 주문·승인·활성화는 실제 확인. 수동 백업 실행은 사이트가 초안(미배포)이라 정기 실행기가 옵션을 site_not_deployed 로 중지해 Agent 백업까지 가지 않음(설계대로) — Webmaker 에서 페이지를 저장·배포한 뒤 다시 수행. 판정은 검증기의 시간 초과를 운영자가 DB 상태(옵션 paused: site_not_deployed)로 확인해 부분 확인으로 정정
- ✔ 백업 옵션 주문(대상 사이트 지정) → 입금 확인 → 승인 — {"orderNo":"AW-20261026-0004","approved":"approved"}
- ✔ 백업 화면(옵션 보유 여부) — {}
- ✔ 옵션 활성화(확인 필수) → 첫 백업 예정 — {"status":"active"}
- ✘ 지금 백업 실행 → 실제 Agent 가 사이트 파일·데이터를 묶어 저장(완료 대기 120초) — 백업 완료 대기 시간 초과
{
"optionState": {
"status": "paused",
"paused_reason": "site_not_deployed",
"updated_at": "2026-10-26T14:32:11.943Z"
},
"siteLifecycle": "draft",
"lastJob": {
"status": "failed",
"error": "대상 서버 또는 Agent 가 필요합니다"
}
}
22. HAL 우선 배포 후 HAL을 통한 전체 모듈 배포 — 실제 확인
HAL 부트스트랩 → 첫 Agent → HAL 작업으로 portal·webmaker·arimail·agent 배포, 실제 버전 0.1.1·건강 ok
- ✔ HAL 릴리스·모듈 목표/실제 버전(배포 영수증) — {"running":{"complete":true,"firstInstall":false,"releaseVersion":"0.1.1","mainCommit":"[redacted]","artifactSha256":"[redacted]","halRunningVersion":"0.1.1","firstAgent":"[redacted]","manualInstallLocked":true},"targets":[{"module":"agent","target":"0.1.1","actual":"0.1.1","health":"ok"},{"module":"arimail","target":"0.1.1","actual":"0.1.1","health":"ok"},{"module":"backup","target":null,"actual"
- ✔ HAL 을 통한 모듈 배포 작업(module.deploy) 결과 — [{"label":"portal 0.1.1 배포","status":"done"},{"label":"hal 0.1.1 배포","status":"done"},{"label":"portal 0.1.1 배포","status":"done"},{"label":"portal 0.1.1 배포","status":"done"},{"label":"agent 0.1.1 배포","status":"done"},{"label":"arimail 0.1.1 배포","status":"done"},{"label":"hal 0.1.1 배포","status":"done"},{"label":"agent 0.1.1 배포","status":"done"},{"label":"arimail 0.1.1 배포","status":"failed"},{"label
{
"rel": {
"running": {
"complete": true,
"firstInstall": false,
"releaseVersion": "0.1.1",
"mainCommit": "[redacted]",
"artifactSha256": "[redacted]",
"halRunningVersion": "0.1.1",
"firstAgent": "[redacted]",
"manualInstallLocked": true
},
"targets": [
{
"module": "agent",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok"
},
{
"module": "arimail",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok"
},
{
"module": "backup",
"target": null,
"actual": "0.1.1",
"health": "ok"
},
{
"module": "hal",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok"
},
{
"module": "observability",
"target": null,
"actual": "0.1.1",
"health": "ok"
},
{
"module": "portal",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok"
},
{
"module": "webmaker",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok"
}
]
},
"jobs": [
{
"label": "portal 0.1.1 배포",
"status": "done"
},
{
"label": "hal 0.1.1 배포",
"status": "done"
},
{
"label": "portal 0.1.1 배포",
"status": "done"
},
{
"label": "portal 0.1.1 배포",
"status": "done"
},
{
"label": "agent 0.1.1 배포",
"status": "done"
},
{
"label": "arimail 0.1.1 배포",
"status": "done"
},
{
"label": "hal 0.1.1 배포",
"status": "done"
},
{
"label": "agent 0.1.1 배포",
"status": "done"
},
{
"label": "arimail 0.1.1 배포",
"status": "failed"
},
{
"label": "webmaker 0.1.1 배포",
"status": "done"
},
{
"label": "portal 0.1.1 배포",
"status": "done"
}
]
}
24. 운영자 승인, 감사 기록, 고객 알림의 일치 — 부분 확인
- ✔ 고객 감사 기록(order.approve) · 알림 · 운영자 주문 상태 일치 — {"auditEntries":0,"notifications":6,"status":"approved"}
- ✔ HAL 감사 기록(deploy.module) — 10
{
"a": {
"auditEntries": 0,
"notifications": 6,
"status": "approved"
},
"halDeployAudit": 10
}
26. 새로 고침, 재로그인, HAL 재시작 후 진행 작업 상태 유지 — 실제 확인
- ✔ HAL 재시작 전: 운영자 세션·작업 수·서버 등록 — {"jobs":23,"servers":1}
- ✔ systemctl restart ariweb-hal → 건강 회복 → 같은 세션으로 작업 수·서버 유지 — {"uptimeSec":1,"sessionKept":"[redacted]","jobs":23,"servers":1,"agentOnline":true}
- ✔ Agent 가 재접속(heartbeat) 해 서버 ready 유지 — [{"name":"srv1953374 (ariweb.net)","status":"ready","lastSeen":"2026-10-26T14:33:13.381Z"}]
{
"before": {
"jobs": 23,
"servers": 1
},
"after": {
"uptimeSec": 1,
"sessionKept": "[redacted]",
"jobs": 23,
"servers": 1,
"agentOnline": true
},
"ag": [
{
"name": "srv1953374 (ariweb.net)",
"status": "ready",
"lastSeen": "2026-10-26T14:33:13.381Z"
}
]
}
검증에 쓴 테스트 데이터(정리 대상)
- 고객 계정
alice-mvpcu283@check.ariweb.net(및 bob-, 이전 실행분 alice-/bob-*), 사이트s_01a1789f690cb9115f0330d2e8, 도메인check-mvpcu283.ariweb.net·solo-*.ariweb.net(AriMail 테넌트는 운영자 취소 → 보존 기간 뒤 삭제), 주문o_01a1789f68c3298aec8ad337e8. 모두@check.ariweb.net주소의 검증 전용 데이터다.
성공 선언 전 재검증(서버에서 읽은 값, 90-verify.sh)
### systemd
ariweb-hal active / enabled=enabled
ariweb-agent active / enabled=enabled
ariweb-portal active / enabled=enabled
webmaker active / enabled=enabled
webmaker-setup active / enabled=enabled
arihakdang-mail active / enabled=enabled
arihakdang-mail-haraka active / enabled=enabled
nginx active / enabled=enabled
### nginx
nginx: configuration file /etc/nginx/nginx.conf test is successful
ariweb-hal.conf
ariweb-portal.conf
webmail.ariweb.net.conf
webmaker.ariweb.net.conf
webmaker.ariweb.net.conf.bak-1.5.27
### HAL health (127.0.0.1:8900)
{"ok":true,"version":"0.1.1","uptimeSec":5,"db":true,"jobs":true,"bootstrap":{"complete":true,"firstInstall":false,"releaseVersion":"0.1.1","mainCommit":"3951be5836a753e60f11d6b363025059fcf6d448","artifactSha256":"e7741899cd7387b0155c9d3bf8ff14cc4026880db999c9d59347744390415e84","halRunningVersion":"0.1.1","firstAgent":"ag_01a178829f1c3d88381d2c0c75","manualInstallLocked":true},"instanceId":"hal_01a178a14a3deef408f7ddfa91"}
### HAL health via nginx https (resolve 127.0.0.1)
{"ok":true,"version":"0.1.1","db":true,"bootstrap":true}
### portal health
{"ok":true,"version":"0.1.1","db":true,"jobs":17,"time":"2026-10-26T14:33:23.567Z"}
{"ok":true,"version":"0.1.1"}
my.ariweb.net /login → 200
### ops console
/ops/ (127.0.0.1) → 200
/ops/ via nginx (외부 IP 흉내 X-Real-IP 8.8.8.8) → 200
### modules (HAL 기록)
{
"running": {
"complete": true,
"firstInstall": false,
"releaseVersion": "0.1.1",
"mainCommit": "3951be5836a753e60f11d6b363025059fcf6d448",
"artifactSha256": "e7741899cd7387b0155c9d3bf8ff14cc4026880db999c9d59347744390415e84",
"halRunningVersion": "0.1.1",
"firstAgent": "ag_01a178829f1c3d88381d2c0c75",
"manualInstallLocked": true
},
"releases": [
{
"v": "0.1.1",
"status": "approved",
"halDeployedAt": "2026-10-26T14:30:34.618Z"
}
],
"targets": [
{
"module": "agent",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "arimail",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "backup",
"target": null,
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "hal",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "observability",
"target": null,
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "portal",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
},
{
"module": "webmaker",
"target": "0.1.1",
"actual": "0.1.1",
"health": "ok",
"active": 1,
"checkedAt": "2026-10-26T14:33:13.381Z",
"err": null
}
]
}
### modules (디스크)
/srv/ariweb/hal current → /srv/ariweb/hal/releases/0.1.1 REVISION=0.1.1(상류 0.1.1) pkg=0.1.1
/srv/ariweb/portal current → /srv/ariweb/portal/releases/0.1.1 REVISION=0.1.1(상류 0.1.1) pkg=0.1.1
/srv/ariweb/agent current → /srv/ariweb/agent/releases/0.1.1 REVISION=0.1.1(상류 0.1.1) pkg=0.1.1
/srv/webmaker current → /srv/webmaker/releases/0.1.1 REVISION=0.1.1(상류 1.7.3) pkg=1.7.3
/srv/arihakdang-mail current → /srv/arihakdang-mail/releases/0.1.1 REVISION=0.1.1(상류 1.0.11) pkg=1.0.11
### 서비스 자체 보고 버전
{"ok":true,"version":"1.0.11","domains":6}
webmaker csrf → 401
webmaker.ariweb.net → 302
webmail.ariweb.net → 200
### 배포 영수증(감사 기록 deploy.*)
[
{
"at": "2026-10-26T14:30:45.633Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "portal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:30:35.618Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "hal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:23:37.819Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "portal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:16:46.605Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "portal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:16:41.094Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "agent",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:09:32.947Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "arimail",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:09:24.433Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "hal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:08:47.250Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "agent",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:00:26.918Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "webmaker",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
},
{
"at": "2026-10-26T14:00:17.400Z",
"actor": "op_01a178829b90905c15a3191caa",
"subject": "portal",
"detail": {
"version": "0.1.1",
"serverIds": [
"srv_01a178829d5848f93a15f93a17"
],
"overall": "done"
}
}
]
### 배포 작업
[
{
"id": "j_01a1789ee309d1bc1102a6d949",
"label": "portal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:30:45.633Z"
},
{
"id": "j_01a1789eba1aac59f8518c92b3",
"label": "hal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:30:35.618Z"
},
{
"id": "j_01a178985cf9fa2f2e76fa7735",
"label": "portal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:23:37.819Z"
},
{
"id": "j_01a17892166e8460c04de6a7d6",
"label": "portal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:16:46.605Z"
},
{
"id": "j_01a17892094ddcff01ba7b8002",
"label": "agent 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:16:41.094Z"
},
{
"id": "j_01a1788b794d0d3545ca8bedd0",
"label": "arimail 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:09:32.947Z"
},
{
"id": "j_01a1788b53ed98904ed1127166",
"label": "hal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:09:24.433Z"
},
{
"id": "j_01a1788acd103d85194bbb8bba",
"label": "agent 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:08:47.250Z"
},
{
"id": "j_01a17883416842d8acc7909136",
"label": "arimail 0.1.1 배포",
"status": "failed",
"ended": "2026-10-26T14:00:33.432Z"
},
{
"id": "j_01a178831b657e19aaed13d7d8",
"label": "webmaker 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:00:26.918Z"
},
{
"id": "j_01a178830202223b4852e6cb6a",
"label": "portal 0.1.1 배포",
"status": "done",
"ended": "2026-10-26T14:00:17.401Z"
}
]
### 서버·Agent
[
{
"id": "srv_01a178829d5848f93a15f93a17",
"name": "srv1953374 (ariweb.net)",
"role": "control",
"status": "ready",
"agent": "ag_01a178829f1c3d88381d2c0c75",
"agentVersion": "0.1.1",
"lastSeen": "2026-10-26T14:33:13.381Z",
"modules": {
"webmaker": {
"target": "0.1.1",
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"arimail": {
"target": "0.1.1",
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"hal": {
"target": "0.1.1",
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"agent": {
"target": "0.1.1",
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"observability": {
"target": null,
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"backup": {
"target": null,
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
},
"portal": {
"target": "0.1.1",
"actual": "0.1.1",
"drift": false,
"health": "ok",
"active": true,
"lastCheckAt": "2026-10-26T14:33:13.381Z",
"lastError": null
}
}
}
]
### 공개 DNS(참고)
hal.ariweb.net →
my.ariweb.net →