-
hanyul released this
2026-10-11 14:43:52 +09:00 LINKS 1.0.2
이 patch 릴리스는 이전 릴리스 1.0.1(
9cdd56ca4e)부터 최종 소스4c4a5d3715까지를 묶었습니다. 루트 패키지는 1.0.2이고 ARCA pin은 exact 0.1.18로 그대로입니다. NAS 갱신은 이제sh update.sh한 명령입니다. 이 명령이 최신 release를 찾고, 배포 파일을 받아 대조하고, image 버전을 확인합니다. package coordinator의 정지·기동과 readiness 확인도 함께 합니다. package coordinator는 Compose service가 되어 재부팅 뒤 자동으로 기동합니다. schema는 바뀌지 않았으므로 DB 초기화와 migration이 필요 없습니다.업그레이드 주의: 1.0.1 → 1.0.2는 한 번만 수동으로 전환합니다(초기화 없음)
- 1회 수동 전환: 1.0.1의
update.sh는 자동 갱신을 모르므로 이번에만 아래 순서를 따릅니다.- 실행 중인 host coordinator(
sh ops/runtime-package-coordinator.sh …)를 종료합니다. foreground면 그 터미널에서Ctrl+C를 누르고, background면ps로 PID를 찾아kill <PID>를 실행합니다. .runtime-package-coordinator.lock파일은 지우지 않습니다. lock은 프로세스가 끝나면 풀립니다. coordinator가 아직 lock을 잡고 있으면 새update.sh가 아무것도 바꾸지 않고A host package coordinator is running; ...으로 멈춥니다.- Task Scheduler 작업을 만들었다면 중지하고 삭제합니다. 작업을 삭제해도 이미 실행 중인 프로세스는 끝나지 않습니다.
- 새
update.sh를 받아 실행합니다(아래 명령). 이후 갱신은sh update.sh한 줄입니다.
- 실행 중인 host coordinator(
- coordinator Compose service: coordinator는 Compose service
runtime-package-coordinator로 실행됩니다. 구성은docker:24.0.9-cli, networknone, 재시작 정책unless-stopped이며 배포 디렉터리를 read-only로 mount합니다. Docker socket을 mount하므로 이 service는 host root와 같은 권한을 가집니다. NAS 재부팅 뒤에는 Docker가 자동으로 기동하므로 Task Scheduler 작업이 필요 없습니다. 로그는docker compose --env-file .env.production logs runtime-package-coordinator로 봅니다. - shell override 거부:
update.sh와reset.sh는 Compose 값(compose.yaml이 interpolation하는 변수와COMPOSE_PROJECT_NAME·COMPOSE_FILE·COMPOSE_PROFILES·COMPOSE_ENV_FILES)이 shell에 설정돼 있으면 빈 값이어도 아무것도 바꾸지 않고Shell override is not supported: <NAME>. Set it in .env.production.으로 멈춥니다. 모든 값은.env.production에 literal 값으로 둡니다.${HOME}같은 host shell 참조는 쓰지 않습니다. host와 coordinator container의 환경이 달라 서로 다른 값으로 풀리기 때문입니다. LINKS_REGISTRY_TAG: 평소에는 비우거나latest로 둡니다. rollback 때만<tag>@sha256:<digest>pin을 넣습니다. digest 없는 버전 tag는update.sh가 거부합니다.- HTTPS와 manifest:
update.sh는 최초 URL과 redirect 모두 HTTPS만 사용합니다. release assetdeploy-files.sha256과 7개 배포 파일의 SHA-256을 자동으로 대조하고, 하나라도 다르면 아무것도 바꾸지 않습니다. 이 대조는 무결성 확인이며 서명 인증이 아닙니다. - NAS host Compose 2.20.1: NAS의 host Compose는
v2.20.1(Synology build)입니다. 릴리스 전에 공식 Docker Compose v2.20.1 binary(SHA-256 대조)로 바꾼 격리docker:24.0.2-dind에서 이 릴리스의 배포 파일을 검증했습니다. reset → update, 재-update, container 재생성 update 세 시나리오 모두 성공했습니다. 12개 service의 network 연결은 선언과 모두 일치했고 package·runtime readiness는 종료 코드 0이었습니다. Synology build의 자체 패치와 공식 binary는 다를 수 있으므로 실제 NAS 결과는 확인 전입니다. - DB 초기화 불필요: 기준 schema checksum은
14481d17c5947342be029bf6f850d2f862372b988dcbc1809360cdd7b333c918(infra/migrations/base.sha256)로 1.0.1과 같고 migration은 0개입니다.reset.sh를 실행하지 않습니다.
NAS 절차(1.0.1에서 한 번):
cd /volume1/docker/links # host coordinator를 Ctrl+C 또는 kill로 종료한 뒤(lock 파일 삭제 금지, Task Scheduler 작업이 있으면 삭제) curl -fL --proto '=https' https://git.2ex.dev/hanyul/LINKS/raw/tag/1.0.2/ops/deploy-registry.sh -o update.sh sh update.sh성공하면 단계 표시 6줄 뒤에
Updated to 1.0.2 (catalog f1c3cf7014ad), runtime.package ready.가 출력됩니다. 실패하면 원인 한 줄을 출력하고 nonzero로 끝납니다. 이후 갱신은cd /volume1/docker/links && sh update.sh입니다.원본 game library는 읽기 전용으로 유지합니다. 이번 게시 작업에서 개발·운영 DB 초기화나 NAS 배포는 실행하지 않았습니다.
sh update.sh한 명령 배포- 1단계 release 파일: Gitea
releases/latest에서 tag를 읽고 assetdeploy-files.sha256을 받습니다. manifest는 정확히 7개 경로를 한 번씩 담아야 하며, 각 줄은 64자리 hex와 두 칸 구분 형식이어야 합니다. 그다음 7개 파일을<이름>.tmp로 받아 대조합니다. asset이 없는 release(1.0.1 이하)에서는Release <tag> does not support automatic updates; ...로 멈춥니다. - 자기 교체: 받은
update.sh가 실행 중인 script와 다르면 대조를 마친 새 script를 한 번 실행하고, 이후 단계는 새 release의 규칙으로 진행합니다. 받은 파일은 5단계 직전에 설치합니다. 그 전의 실패와 처리 가능한 중단 signal(HUP·INT·TERM)은 받은 파일을 지우고 끝냅니다. 이전 실행이 남긴.tmp는 시작할 때 지웁니다. - image 버전 확인: pull한 image의 root version이 release tag와 같아야 진행합니다. 다르면
The registry image is version <v>, not release <tag>; try again later.로 멈춥니다. - coordinator: pull 전에 coordinator를 정지합니다. 다른 service를
up --wait로 갱신하고 catalog의 package 기능을 확인한 뒤 coordinator를 단독으로 기동합니다. 이번 기동의Package coordinator ready (...)줄을 최대 5분 기다립니다. 같은 container·StartedAt·RestartCount=0인지 확인해 ready 뒤 재시작이나 종료를 감지하고, 마지막으로 전체 readiness를 확인합니다. - 최초 설치:
compose.yaml이 없는 디렉터리에서는 파일만 설치하고sh reset.sh→sh update.sh를 안내합니다. - 거부: 인자, digest 없는
LINKS_REGISTRY_TAG, 실행 중인 host coordinator(lock), HTTPS가 아닌 저장소 URL, shell override는 아무것도 바꾸기 전에 거부합니다.
package coordinator Compose service
compose.yaml에runtime-package-coordinatorservice를 추가했습니다. 구성은docker:24.0.9-cli,init, read-only rootfs,cap_drop: ALL+DAC_READ_SEARCH,no-new-privileges, networknone,/tmptmpfs 256 MB,stop_grace_period60초,restart: unless-stopped입니다.- coordinator는 자기 mount에서 배포 디렉터리의 host 경로를 읽어 Compose의 project directory로 씁니다. 그래서 상대 bind 경로와 project 이름이 host Compose와 같게 해석됩니다.
- 시작 준비가 끝나면
Package coordinator ready (ARCA <version>, builder <image ID 앞 12자>), 대기에 들어가면Waiting for package jobs.를 출력합니다. 정지 요청을 받으면 실행 중인 Builder container를 바로 정지합니다. - Docker socket mount는 보안 정책에 예외로 기록했습니다. 개발 Windows에서는 이 service를 쓰지 않고 기존 host coordinator를 유지합니다.
shell override 거부와 정리
update.sh와reset.sh가 같은 규칙으로 Compose 값의 shell override를 거부합니다. 값은 출력하지 않습니다.update.sh는 이전 실행의.tmp를 설치하지 않으며, 중단 signal을 받으면 받은 파일을 지우고 129·130·143으로 끝납니다.
문서
- 운영 가이드: NAS 배포 두 줄,
update.sh단계·실패 메시지·되돌리기, 최초 설치와 1.0.1에서의 전환, release asset 첨부 절차, coordinator service 운영. - 보안 정책(Docker socket 예외), 아키텍처, 런타임 계약, 완료 기준선, 개발 계획, tests/README, README도 갱신했습니다.
알려진 제한(후속 과제)
- Docker 24 graphdriver에서는 Builder config digest를 pin과 직접 대조하지 않습니다. 이를 강화하려면 ARCA가 config digest를 공개 API로 제공해야 합니다(ARCA 후속).
- 3단계 이후 실패하면 coordinator는 정지된 채 남습니다. 원인을 고친 뒤 다음
sh update.sh가 다시 기동합니다. - 1.0과 같은 제한:
- Player 세이브 관리 listener(3005)는 catalog caller token으로만 보호되며
edgenetwork에서 TCP로 닿을 수 있습니다. - catalog·Player의 일반 egress를 network가 제한하지 않습니다.
update.sh는 opt-in profile container(translation-import등)를 갱신하지 않습니다. 갱신 뒤 직접 다시 기동합니다.
- Player 세이브 관리 listener(3005)는 catalog caller token으로만 보호되며
검증과 남은 범위
- PASS: one-command-update 브랜치(병합
ede4c1b)에서 통과한 검사update.sh기록기 98/98,reset.sh기록기 30/30, coordinator unit 31/31- 전체 unit 149 files / 1,135 tests, static, 문서 검사, Compose config 3개 조합, BusyBox
sh -n, 격리 foundation - HTTPS dind e2e(Docker 24.0.2): 최초 설치·자기 교체, reset, 배포, HTTPS만 허용, ready 뒤 종료 감지, 재부팅
- 리뷰 최종 판정: 병합 가능
- PASS: 릴리스 gate(Compose v2.20.1)
- 환경: 격리
docker:24.0.2-dind(overlay2, BusyBox ash). host Compose는 공식 v2.20.1 linux-x86_64 binary로 바꿨습니다(SHA-256804aa825c58b375901ba9dc9d0aa1648ce305d903a58f2a5c42bb5c6873b02bf, release의.sha256·checksums.txt와 일치). - 입력: 이 릴리스와 byte가 같은 7개 배포 파일을 합성 HTTPS release로 제공하고, 실제 registry image를 익명으로 pull했습니다.
- 최초 설치(자기 교체) →
reset.sh→update.sh: 118초, exit 0 - 재-update: exit 0
- container 재생성 update(catalog·player 포함 8개 재생성): exit 0
- 매 시나리오 뒤 12개 service의 network가 선언과 일치(누락 0)했고, unhealthy는 0이었으며 package·runtime readiness는 exit 0이었습니다.
- 환경: 격리
- PASS: 최종 1.0.2 소스. 릴리스 커밋 두 개(root version, 완료 기준선의 version 문구) 뒤 다음을 다시 통과했습니다.
- 문서 검사(756개 파일 / Markdown 32개)
- static(Prettier·ESLint·typecheck·docs-static)
git diff --check
- 게시 이미지: 같은 최종 소스에서 build했습니다. image 안에서 root version 1.0.2, ARCA pin·설치본 0.1.18,
base.sha256을 확인했습니다. - PARTIAL: 전체 UI/제품 acceptance. 화면·fixture·package/build 성공을 실제 browser play PASS로 기록하지 않습니다.
- NOT RUN:
- Synology NAS 실제 환경(Compose v2.20.1 Synology build, Docker 24 btrfs)에서의 1.0.1 → 1.0.2 전환과
sh update.sh - Docker 24에서 Builder
package전체 실행 - 실제 library/private game과 실제 scan
- 입력·오디오·save/reload의 실제 게임 acceptance
- live provider
- 개발 rebuild
- Synology NAS 실제 환경(Compose v2.20.1 Synology build, Docker 24 btrfs)에서의 1.0.1 → 1.0.2 전환과
배포 이미지와 파일
- Git annotated tag는 1.0.2이고 최종 소스는
4c4a5d3715입니다. - 단일 linux/amd64 이미지:
git.2ex.dev/hanyul/links:1.0.2=git.2ex.dev/hanyul/links:latest - 원격 digest:
sha256:f1c3cf7014ad65aa00dd3895bc1d3c964c852ecbf4995420bb973b05fcebdcfb - release asset
deploy-files.sha256(아래 7줄)을 첨부했습니다.update.sh가 이 asset으로 배포 파일을 자동 대조합니다. - 아래 SHA-256은 checkout의 CRLF 변환본이 아니라 1.0.2 태그의 Git blob 원본 byte로 계산했습니다.
- NAS 배포 목록은 7개입니다(
update.sh=ops/deploy-registry.sh,reset.sh=ops/reset-registry.sh,backup.sh=ops/backup-registry.sh).
SHA-256 파일 1.0.1 대비 c7b480fab3238bbefc008501bf2e65ab50b95c985dba2b8896f85af6e262caeccompose.yaml변경 ( runtime-package-coordinatorservice)6e1fd3f2f73faee52abca28c8552cde417f496d86fc3d78c7001dec480e171a3infra/docker/Caddyfile동일 39a4c55050e76043c8ca70f11f59dbdf08fff7ef38c1f1ec878f96194988d9d8ops/backup-verify.compose.yaml동일 9671a00c1a13723cf16b0eced336241f25299f45bbed5ca4044af23f9d81ac72ops/deploy-registry.sh변경 (한 명령 자동 갱신) cf6169a8ffa577d40b70ea476e10b662fc898a68ebfc28b43c513cf9c1b7bf33ops/reset-registry.sh변경 (shell override 거부) 89375a986b3cb64cf74145541701b32c6a0e983a72ca46be21a8bcfad7beaa3dops/backup-registry.sh동일 6ba741a66e9744c0cd01ce8e3df81b94a55ae3f7d41b6f1d05200eedc5dccdb9ops/runtime-package-coordinator.sh변경 (Compose service 모드·상태 줄·Builder 즉시 정지) c7b480fab3238bbefc008501bf2e65ab50b95c985dba2b8896f85af6e262caec compose.yaml 6e1fd3f2f73faee52abca28c8552cde417f496d86fc3d78c7001dec480e171a3 infra/docker/Caddyfile 39a4c55050e76043c8ca70f11f59dbdf08fff7ef38c1f1ec878f96194988d9d8 ops/backup-verify.compose.yaml 9671a00c1a13723cf16b0eced336241f25299f45bbed5ca4044af23f9d81ac72 ops/deploy-registry.sh cf6169a8ffa577d40b70ea476e10b662fc898a68ebfc28b43c513cf9c1b7bf33 ops/reset-registry.sh 89375a986b3cb64cf74145541701b32c6a0e983a72ca46be21a8bcfad7beaa3d ops/backup-registry.sh 6ba741a66e9744c0cd01ce8e3df81b94a55ae3f7d41b6f1d05200eedc5dccdb9 ops/runtime-package-coordinator.shDownloads 3
-
deploy-files.sha256
5
632 B
2026-10-11 14:46:49 +09:00 -
Source code (zip)
0
2026-10-11 14:43:52 +09:00 -
Source code (tar.gz)
0
2026-10-11 14:43:52 +09:00
- 1회 수동 전환: 1.0.1의