기록 84편을 계약 에이전트로 다시 썼다. 기존 71편(kss 25 · virt 46)과, 계약에만 있고 안 쓰여 있던 새 글감 13편이다. 원장 84개를 열어 단계마다 스킬 영수증과 관문 종료 코드를 적었고 verify-pipeline-run.py 가 error 0 으로 닫는다. SSOT 결함 둘을 고쳤다. - kss 의 `약 58일` 이 반입 중 `약 59일` 로 바뀌어 있었다. 원 증거 파일이 「남은 일수: 88일 … 실제 갱신까지 약 58일」로 산수를 직접 적는다. D-4a 쪽 `약 59일` 은 강제 갱신 뒤(`VALID: 89 days`)라 맞는 값이라 그대로 뒀다. - virt §198 의 `11.6GB` 는 §178 의 원 측정 `Mem: 11648`(MiB)과 어긋나는데 원 가이드의 표기 그대로라 고치지 않고 쓰이는 자리에 대조를 적었다. 기록의 수치 오류 셋을 고쳤다 — CASE 요약의 「게스트 셋에 8240MB」(5120+3120 은 둘이다), k3s 편이 같은 것을 여섯·일곱·여덟로 세던 것, no-docker 편의 「셋을 더 든다」(§281 의 표는 네 행이고 디스크 행이 빠져 있었다). 계약을 셋 고쳤다. - kss 의 sourceRepository 리비전이 cdac9b8 이었는데 그 커밋에는 docs/guides/** 28개가 아예 없다. 9465582b 로 바꾸고, 반입한 바이트가 어느 커밋과도 같지 않다는 것을 측정값과 함께 적었다 — 반입은 커밋이 아니라 그 시점의 작업 트리에서 떠 온 것이다(kss 297/306 · virt 12/14 가 작업 트리와 같고, 200 커밋을 거슬러 전수 대조했을 때 가장 가까운 커밋도 28개가 어긋났다). - virt 계약이 「2026-09-11 재배분」이라고 적는데 SSOT 는 재배분 날짜를 적지 않고 재배분 뒤 값은 이미 2026-09-10 측정에 찍혀 있다. - kss 후보 대장이 지나친 절 아홉에 처분을 적었다(warn 9 → 0). 새 글감은 0건이고 넷은 앵커가 h3 슬러그의 접두가 아니라 중간 토막이라 검사기가 못 본 것이었다. style_profile.mjs 의 결함 둘을 고쳤다 — frontmatter 가 문장으로 세어져 (실측 398자짜리 「문장」 하나) 평균 길이를 기준 안으로 밀어 올리고 있었고, engPerSent 의 분자는 목록을 포함한 글에서, 분모는 목록을 걷어낸 글에서 세고 있었다(Question 기록에서 11.94 → 3.86). verify-pipeline.py 전 항목 PASS · error 0 · unittest 334건 OK. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
8.2 KiB
kind, slug, title, topic, topicName, project, status, sourceRevision, source
| kind | slug | title | topic | topicName | project | status | sourceRevision | source | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| REFERENCE | a-config-file-does-not-mean-the-same-thing-on-two-distros | 같은 설정 파일이 두 배포판에서 같은 뜻이 아니다 — 옮기기 전에 세 가지를 본다 | lab-environment-build | 실험대 환경 구성 | virtualization | 게시 전 | 9465582b5d1630eb4ae7c4e078021486919bf6b6 |
|
같은 설정 파일이 두 배포판에서 같은 뜻이 아니다 — 옮기기 전에 세 가지를 본다
설정 파일을 배포판이 다른 기계로 옮기기 전에 셋을 본다. 그 지시어가 대상의 판올림에 있는가, 패키지가 기본으로 켜 둔 것과 충돌하지 않는가, 그 배포판이 그 관례를 갖고 있는가. 이 실험대의 함정 셋이 전부 여기 걸렸다.
관계
- 단계별 구축 문서는 작성 시점이 아니라 실행 순서로 검증한다 그 기준은 순서와 위치를 보고 이 기준은 대상 기계를 본다. 그 기록이 자기 예외 절에서 배포판 차이를 이쪽으로 넘긴다.
- 엣지 게스트에 nginx 를 세우고 호스트 DNAT 으로 밖에서 들어오는 길을 연다 Arch 호스트에서 쓰던 nginx 설정이 Debian 12 게스트로 건너가는 절차가 그 기록에 있다.
- cloud-init 시드로 게스트 세 대를 만들고 SSH 가 키로 붙게 한다 부트 시점 설정이 게스트 판올림의 검사기를 통과해야 하는 대목이 그 절차 안에 있다.
- cloud-init 이 안 도는 원인은 넷인데 증상은 「SSH 가 안 붙는다」 하나였다 원인이 옮긴 파일 안에 없을 때 증상이 어떻게 보이는지를 그 기록이 보여 준다.
- 가까운 층부터 한 층씩 건너뛰며 확인한다 — 층마다 성공 신호가 다르다 증상이 난 층부터 좁혀 오는 절차이고, 이 기준은 그 층에 닿은 뒤 파일을 의심할지 기계를 의심할지를 가른다.
목적
이 기준이 막는 것은 원인이 파일 안에 없는 두 증상이다. 하나는 설정 전체가 뜨지 않는 것이고, 다른 하나는 파일을 제자리에 놓았는데 아무 일도 일어나지 않는 것이다. 둘 다 파일을 아무리 읽어도 나오지 않는다.
§203 이 실측으로 드러난 함정 셋을 적었는데 셋 다 배포판 차이였다. 이 실험대는 호스트가 Arch(nginx 1.30.4)이고 엣지 게스트가 Debian 12(nginx 1.22.1)라 같은 설정이 두 판올림 사이를 오갔다.
규칙
1. 그 지시어가 대상의 판올림에 있는가
http2 on; 은 nginx 1.25.1 이상이다. Arch 에서 쓰던 설정을 Debian 12 게스트로 그대로 옮기면 unknown directive "http2" 가 나면서 설정 전체가 죽는다.
없다는 것을 확인하는 데서 멈추면 규칙이 답을 내지 않는다. 양쪽에서 도는 형태가 무엇인지까지 찾는다. listen 443 ssl http2; 형태는 1.22 와 1.30 양쪽에서 다 돈다.
설정 정본 deploy/lab/edge/nginx-keycloak-lab.conf 의 주석이 그 형태를 고른 까닭을 파일 안에 적어 두었다. 따로 떼어 쓰는 지시어 쪽은 nginx 1.25.1 이상을 요구하는데 엣지 게스트는 nginx 1.22 를 쓰는 Debian 12 다. listen 의 인자로 쓰는 형태는 양쪽에서 다 돌고, 이 실험대가 실제로 돌리는 것도 그쪽이다.
2. 패키지가 기본으로 켜 둔 것과 충돌하지 않는가
Debian 계열은 /etc/nginx/sites-enabled/default 가 처음부터 붙어 있고 :80 에 default_server 로 선언돼 있어서, 실험대 설정의 listen 80 default_server 와 충돌한다. 심볼릭 링크를 걸 때 그 기본 사이트를 같이 지운다.
3. 그 배포판이 그 관례를 갖고 있는가
sites-available 과 sites-enabled 는 nginx 의 기능이 아니라 Debian/Ubuntu 패키지 메인테이너가 만든 관례다. nginx 가 아는 것은 include 지시어 하나뿐이고 나머지는 패키지가 미리 깔아 둔 디렉터리 구조다.
Arch 는 /etc/nginx/nginx.conf 한 파일이 전부이고 include 줄도 없다. http { } 안에 include /etc/nginx/sites-enabled/*; 를 직접 넣어야 이 파일이 효력을 갖는다. 넣지 않으면 아무 일도 일어나지 않고 오류조차 나지 않는다. 최종 병합된 설정에 내 파일이 들어갔는지는 nginx -T 로 확인한다.
2번과 3번은 같은 관례의 양면이다. 한쪽은 있어서 충돌하고 한쪽은 없어서 손으로 넣어야 한다.
적용 조건
한 기계에서 쓰던 설정 파일을 다른 배포판이나 다른 판올림의 기계로 옮기는 모든 곳에 적용한다. 이 실험대에서는 호스트 Arch 와 게스트 Debian 12 사이, 그리고 운영과 실험대 사이다.
특히 자주 걸리는 것 : 데몬 설정(nginx · systemd 유닛)과 부트 시점 설정(cloud-init)
이 기준은 파일을 옮길 때 한 번 도는 검사이지 막히는 것마다 꺼내 드는 설명이 아니다. §212 가 적었듯 낯선 것의 대부분은 배포판 때문이 아니다. 클라우드가 대신 해 주던 일(KVM · libvirt · cloud-init · DHCP 예약)과 이미 누가 해 두었던 일(nginx upstream · certbot · k3s 설치)이 대부분이고, 진짜 배포판 고유는 얼마 되지 않는다 — 이 실험대에서는 conf.d include 부재, 롤링 업그레이드, libvirtd.socket, 패키지명이다.
같은 구성을 Ubuntu 에서 해도 가상화와 네트워크 층은 명령 이름만 조금 바뀐다.
예외
같은 계열 안에서도 판올림이 다르면 1번이 그대로 걸린다. Debian 과 Ubuntu 는 apt 와 dpkg 와 systemd 와 디렉터리 구조가 같은 계열인데 패키지 판올림이 달라서다.
배포판이 같으면 안 걸리는 것도 아니다. Arch 는 롤링 릴리스이고 부분 업그레이드를 지원하지 않아서, pacman -Sy 패키지 로 DB 만 갱신하고 일부만 설치하면 같은 기계 안에서도 공유 라이브러리 판이 어긋난다.
순서와 위치 문제는 이 축에서 안 잡힌다. 「단계별 구축 문서는 작성 시점이 아니라 실행 순서로 검증한다」가 그쪽을 맡고, 그 기록이 자기 예외 절에서 이쪽을 가리킨다. 두 기준이 서로의 사각을 덮는다.
1번은 문서로 판올림을 대조해 예측할 수 있다. 2번과 3번은 그 배포판에 실제로 깔아 봐야 드러난다 — 기본으로 붙어 있는 사이트가 무엇인지와 그 배포판이 어떤 include 관례를 갖는지는 패키지 메인테이너가 정한다.
배포판 차이가 아닌 것을 이 기준으로 설명하지 않는다. SELinux 와 AppArmor 가 Arch 에 기본 활성이 아닌 것은 이 기준이 잡는 종류이지만, RHEL 계열에서 k3s 에 정책 패키지가 필요한 것은 옮긴 설정의 문제가 아니라 그 배포판의 보안 모듈 문제다.
예시
http2 on; 을 쓴 설정을 Debian 12 의 nginx 1.22.1 로 옮기자 unknown directive "http2" 로 설정 검사가 실패했다.
Debian 기본 사이트를 지우지 않은 채 실험대 설정을 켜자 :80 의 default_server 가 두 번 선언됐다.
Arch 에 sites-enabled 디렉터리를 만들어 파일을 넣었는데 include 줄이 없어 오류 없이 무시됐다.
게스트의 cloud-init 22.4.2 스키마 검사기가 sudo 를 리스트로 적은 형태를 거부했다. 어느 키가 걸렸는지는 알려 주지 않고 users.0 블록을 통째로 찍은 뒤 어느 스키마에도 안 맞는다고만 한다. 그 형태로도 부팅은 됐고 NOPASSWD sudo 도 멀쩡히 돌았다.
certbot DNS 플러그인의 패키지 이름이 Arch 에서 certbot-dns-cloudflare 이고 Debian/Ubuntu 에서 python3-certbot-dns-cloudflare 다.