본문으로 이동

도움말:S3 연구 메모리/설치와 검증: 두 판 사이의 차이

S3 연구 메모리
S3 연구 메모리 저장소 문서 동기화
S3 연구 메모리 저장소 문서 동기화
170번째 줄: 170번째 줄:
| <code><nowiki>S3RM_PUBLIC_HTTPS_PORT</nowiki></code> || 아니요 || <code><nowiki>443</nowiki></code>; 공개 HTTPS 포트
| <code><nowiki>S3RM_PUBLIC_HTTPS_PORT</nowiki></code> || 아니요 || <code><nowiki>443</nowiki></code>; 공개 HTTPS 포트
|-
|-
| <code><nowiki>COMPOSE_PROFILES</nowiki></code> || 아니요 || <code><nowiki>domain</nowiki></code>을 넣으면 Caddy를 실행. 도메인 스크립트가 추가
| <code><nowiki>COMPOSE_PROFILES</nowiki></code> || 아니요 || <code><nowiki>domain</nowiki></code>은 Caddy, <code><nowiki>embedding</nowiki></code>은 내부 GPU 임베딩 서비스를 실행. 쉼표로 함께 지정 가능
|-
|-
| <code><nowiki>S3RM_MAX_OUTPUT_BYTES</nowiki></code> || 아니요 || <code><nowiki>32768</nowiki></code>; 도구 결과 제한 2048~65536바이트. 전체 JSON-RPC 응답은 별도 212992바이트 제한
| <code><nowiki>S3RM_MAX_OUTPUT_BYTES</nowiki></code> || 아니요 || <code><nowiki>32768</nowiki></code>; 도구 결과 제한 2048~65536바이트. 전체 JSON-RPC 응답은 별도 212992바이트 제한
183번째 줄: 183번째 줄:
==== 선택적 의미 검색 ====
==== 선택적 의미 검색 ====


기본 <code><nowiki>S3RM_EMBEDDING_PROVIDER=disabled</nowiki></code>는 임베딩 요청을 보내지 않고 기존 전체 텍스트와 관계 검색을 사용합니다. 의미 검색을 켜려면 OpenAI 호환 <code><nowiki>/embeddings</nowiki></code> API를 준비하고 아래 값을 <code><nowiki>.env</nowiki></code>에 설정한 뒤 <code><nowiki>mcp-http</nowiki></code>를 다시 만듭니다.
기본 <code><nowiki>S3RM_EMBEDDING_PROVIDER=disabled</nowiki></code>는 모델을 실행하지 않고 기존 전체 텍스트와 관계 검색을 사용합니다. 이 저장소에는 이 서버의 AMD Vega GPU에 맞춘 비공개 <code><nowiki>llama.cpp</nowiki></code> Vulkan 서비스가 포함되어 있습니다. 모델은 <code><nowiki>Qwen/Qwen3-Embedding-0.6B</nowiki></code> F16이며, 결과는 1024차원입니다. [https://huggingface.co/Qwen/Qwen3-Embedding-0.6B-GGUF 공식 Qwen GGUF]와 [https://github.com/ggml-org/llama.cpp/tree/master/tools/server llama.cpp 서버]를 고정된 revision과 이미지 digest로 사용합니다.
 
다음 두 값만 바꾸면 <code><nowiki>.env.example</nowiki></code>의 고정 모델 설정을 그대로 사용할 수 있습니다.


<pre><nowiki>
<pre><nowiki>
S3RM_EMBEDDING_PROVIDER=openai-compatible
S3RM_EMBEDDING_PROVIDER=openai-compatible
S3RM_EMBEDDING_API_URL=https://embedding.example/v1/embeddings
COMPOSE_PROFILES=domain,embedding
S3RM_EMBEDDING_API_KEY=서버에만-보관할-키
</nowiki></pre>
S3RM_EMBEDDING_MODEL=multilingual-embedding-model
 
S3RM_EMBEDDING_MODEL_REVISION=endpoint에서-고정한-revision-식별자
고정 모델을 확인하고 서비스를 시작합니다. 첫 실행은 약 1.2GB 모델을 받습니다.
S3RM_EMBEDDING_DIMENSIONS=768
 
<pre><nowiki>
make embedding-up
</nowiki></pre>
 
<code><nowiki>embedding-model-init</nowiki></code>만 인터넷에 연결됩니다. 이 작업은 모델 저장소 commit, 파일 크기와 SHA-256을 모두 확인한 뒤 <code><nowiki>embedding_models</nowiki></code> 볼륨에 원자적으로 게시합니다. 실제 <code><nowiki>embedding</nowiki></code> 서비스는 호스트 포트를 열지 않으며 <code><nowiki>mcp-http</nowiki></code>와만 공유하는 내부 <code><nowiki>embedding-backend</nowiki></code> 네트워크를 사용합니다. Vega의 render node 하나만 컨테이너에 전달합니다.
 
실행 중인 모델, 차원과 MCP 연결 설정을 다시 확인할 수 있습니다.
 
<pre><nowiki>
make verify-embedding
</nowiki></pre>
</nowiki></pre>


모델 이름과 차원은 제공자 응답과 정확히 맞아야 합니다. <code><nowiki>MODEL_REVISION</nowiki></code>은 generation 식별 메타데이터이며 upstream 모델을 직접 고정하지 않습니다. 운영자가 endpoint나 모델 alias를 실제 immutable revision에 고정한 뒤 같은 식별자를 적습니다. API key는 제공자에 따라 선택입니다. 외부 API를 사용하면 Lesson의 의미 검색 필드와 아직 저장하지 않은 검색 query가 해당 제공자에게 전송됩니다. 전송·보존·학습 사용·region·비용 조건을 확인한 뒤 켜세요.
<code><nowiki>s3rm-qwen3-retrieval-v1</nowiki></code> profile은 모델 artifact digest, 1024차원, last pooling, 16K token 입력 계약과 세 facet의 query instruction을 한 generation으로 묶습니다. document에는 instruction을 붙이지 않습니다. 희귀 CJK의 byte fallback도 16K를 넘지 않도록 각 document facet은 보수적으로 4,000자에서 자릅니다. 이 값 중 하나를 바꾸면 새 exact index를 처음부터 만듭니다. 서로 다른 generation의 벡터는 섞지 않습니다.


{| class="wikitable"
{| class="wikitable"
200번째 줄: 212번째 줄:
|-
|-
| <code><nowiki>S3RM_EMBEDDING_PROVIDER</nowiki></code> || 아니요 || <code><nowiki>disabled</nowiki></code>; <code><nowiki>disabled</nowiki></code>, <code><nowiki>openai-compatible</nowiki></code> 중 하나
| <code><nowiki>S3RM_EMBEDDING_PROVIDER</nowiki></code> || 아니요 || <code><nowiki>disabled</nowiki></code>; <code><nowiki>disabled</nowiki></code>, <code><nowiki>openai-compatible</nowiki></code> 중 하나
|-
| <code><nowiki>S3RM_EMBEDDING_PROFILE</nowiki></code> || 사용 시 || 번들 모델은 <code><nowiki>s3rm-qwen3-retrieval-v1</nowiki></code>; 기존 제공자는 <code><nowiki>legacy-v1</nowiki></code>
|-
|-
| <code><nowiki>S3RM_EMBEDDING_API_URL</nowiki></code> || 임베딩 사용 시 || 자격 증명·query·fragment가 없는 HTTP(S) embeddings endpoint
| <code><nowiki>S3RM_EMBEDDING_API_URL</nowiki></code> || 임베딩 사용 시 || 자격 증명·query·fragment가 없는 HTTP(S) embeddings endpoint
207번째 줄: 221번째 줄:
| <code><nowiki>S3RM_EMBEDDING_MODEL</nowiki></code> || 임베딩 사용 시 || 제공자의 고정 모델 식별자
| <code><nowiki>S3RM_EMBEDDING_MODEL</nowiki></code> || 임베딩 사용 시 || 제공자의 고정 모델 식별자
|-
|-
| <code><nowiki>S3RM_EMBEDDING_MODEL_REVISION</nowiki></code> || 아니요 || endpoint에서 실제 고정한 revision의 generation 식별 메타데이터
| <code><nowiki>S3RM_EMBEDDING_MODEL_REVISION</nowiki></code> || profile에 따라 || generation에 넣는 immutable revision. 번들 모델은 <code><nowiki>sha256:&lt;GGUF digest&gt;</nowiki></code>
|-
|-
| <code><nowiki>S3RM_EMBEDDING_DIMENSIONS</nowiki></code> || 임베딩 사용 시 || 벡터 차원 1~4096
| <code><nowiki>S3RM_EMBEDDING_DIMENSIONS</nowiki></code> || 임베딩 사용 시 || 벡터 차원 1~4096
|-
|-
| <code><nowiki>S3RM_EMBEDDING_TIMEOUT_SECONDS</nowiki></code> || 아니요 || <code><nowiki>10</nowiki></code>; 0.5~120초
| <code><nowiki>S3RM_EMBEDDING_MODEL_SOURCE_REVISION</nowiki></code> || 번들 모델 || downloader가 사용하는 40자리 Hugging Face commit
|-
|-
| <code><nowiki>S3RM_EMBEDDING_BATCH_SIZE</nowiki></code> || 아니요 || <code><nowiki>16</nowiki></code>; 요청 한 번에 1~128개
| <code><nowiki>S3RM_EMBEDDING_MODEL_SHA256</nowiki></code> || 번들 모델 || 내려받은 GGUF의 64자리 SHA-256
|-
|-
| <code><nowiki>S3RM_EMBEDDING_MAX_CONCURRENCY</nowiki></code> || 아니요 || <code><nowiki>2</nowiki></code>; 동시 요청 1~16개
| <code><nowiki>S3RM_EMBEDDING_MODEL_SIZE_BYTES</nowiki></code> || 번들 모델 || 내려받은 GGUF의 정확한 바이트 수
|-
| <code><nowiki>S3RM_EMBEDDING_DRI_DEVICE</nowiki></code> || 번들 모델 || 이 서버의 외장 Vega render node <code><nowiki>/dev/dri/renderD128</nowiki></code>
|-
| <code><nowiki>S3RM_EMBEDDING_GPU_DEVICE</nowiki></code> || 번들 모델 || 컨테이너에서 보이는 장치 <code><nowiki>Vulkan0</nowiki></code>
|-
| <code><nowiki>S3RM_RENDER_GID</nowiki></code> || 번들 모델 || render node의 group ID. 이 서버는 <code><nowiki>987</nowiki></code>
|-
| <code><nowiki>S3RM_EMBEDDING_TIMEOUT_SECONDS</nowiki></code> || 아니요 || 번들 모델은 <code><nowiki>60</nowiki></code>; 허용 범위 0.5~120초
|-
| <code><nowiki>S3RM_EMBEDDING_BATCH_SIZE</nowiki></code> || 아니요 || 번들 모델은 <code><nowiki>6</nowiki></code>; 요청 한 번에 1~128개
|-
| <code><nowiki>S3RM_EMBEDDING_MAX_CONCURRENCY</nowiki></code> || 아니요 || 번들 모델은 <code><nowiki>1</nowiki></code>; 동시 요청 1~16개
|-
|-
| <code><nowiki>S3RM_EMBEDDING_QUEUE_LIMIT</nowiki></code> || 아니요 || <code><nowiki>32</nowiki></code>; 대기 요청 1~1000개
| <code><nowiki>S3RM_EMBEDDING_QUEUE_LIMIT</nowiki></code> || 아니요 || <code><nowiki>32</nowiki></code>; 대기 요청 1~1000개
221번째 줄: 247번째 줄:
| <code><nowiki>S3RM_EMBEDDING_QUEUE_TIMEOUT_SECONDS</nowiki></code> || 아니요 || <code><nowiki>1</nowiki></code>; 대기 제한 0.05~30초
| <code><nowiki>S3RM_EMBEDDING_QUEUE_TIMEOUT_SECONDS</nowiki></code> || 아니요 || <code><nowiki>1</nowiki></code>; 대기 제한 0.05~30초
|-
|-
| <code><nowiki>S3RM_EMBEDDING_ALLOW_INSECURE_HTTP</nowiki></code> || 아니요 || <code><nowiki>false</nowiki></code>; -loopback HTTP를 명시적으로 허용할 때만 <code><nowiki>true</nowiki></code>
| <code><nowiki>S3RM_EMBEDDING_ALLOW_INSECURE_HTTP</nowiki></code> || 아니요 || 번들 내부 HTTP는 <code><nowiki>true</nowiki></code>; 외부 endpoint는 HTTPS 사용
|-
| <code><nowiki>S3RM_EMBEDDING_INSECURE_HTTP_HOSTS</nowiki></code> || 내부 HTTP 사용 시 || 허용할 정확한 Host 목록. 번들 서비스는 <code><nowiki>embedding:8080</nowiki></code>
|-
|-
| <code><nowiki>S3RM_SEMANTIC_CANDIDATE_LIMIT</nowiki></code> || 아니요 || <code><nowiki>50</nowiki></code>; facet별 후보 5~100개
| <code><nowiki>S3RM_SEMANTIC_CANDIDATE_LIMIT</nowiki></code> || 아니요 || <code><nowiki>50</nowiki></code>; facet별 후보 5~100개
228번째 줄: 256번째 줄:
|}
|}


의미 인덱스는 <code><nowiki>mcp-http</nowiki></code> 메모리의 파생 후보 인덱스입니다. Semantic MediaWiki가 계속 기준 저장소이며, 제공자나 인덱스가 실패하면 제한된 기존 검색으로 대체합니다. <code><nowiki>S3RM_SEARCH_SCAN_LIMIT × 3 × S3RM_EMBEDDING_DIMENSIONS</nowiki></code>는 3,000,000개 벡터 구성요소를 넘을 수 없습니다. 이 조합 검사는 exact index의 메모리 사용을 제한합니다. 비-loopback HTTP 제공자는 기본적으로 거부합니다. 내부 HTTP가 불가피할 때만 위험을 확인하고 <code><nowiki>S3RM_EMBEDDING_ALLOW_INSECURE_HTTP=true</nowiki></code>를 사용하세요.
의미 인덱스는 <code><nowiki>mcp-http</nowiki></code> 메모리의 파생 후보 인덱스입니다. Semantic MediaWiki가 계속 기준 저장소이며, 제공자나 인덱스가 실패하면 제한된 기존 검색으로 대체합니다. <code><nowiki>S3RM_SEARCH_SCAN_LIMIT × 3 × S3RM_EMBEDDING_DIMENSIONS</nowiki></code>는 3,000,000개 벡터 구성요소를 넘을 수 없습니다. 이 조합 검사는 exact index의 메모리 사용을 제한합니다. 외부 OpenAI 호환 API를 대신 사용할 수도 있습니다. 이 경우 <code><nowiki>legacy-v1</nowiki></code> 또는 별도로 검증한 profile을 사용하고 HTTPS endpoint를 설정합니다. Lesson 의미 검색 필드와 아직 저장하지 않은 query가 외부로 전송되므로 보존·학습 사용·region·비용 조건을 확인한 뒤 켜세요. 로컬 서비스 장애가 외부 API로 자동 전환되지는 않습니다.


설정만으로 기본 검색 순서는 바뀌지 않습니다. 클라이언트가 <code><nowiki>search_lessons</nowiki></code> 또는 <code><nowiki>find_analogies</nowiki></code>에 <code><nowiki>retrieval_mode=hybrid_v1</nowiki></code>을 명시해야 합니다. <code><nowiki>mcp-http</nowiki></code>는 시작할 때 단 하나의 백그라운드 작업으로 전체 Lesson exact index를 프리웜합니다. hybrid 요청은 이 작업을 기다리지 않습니다. 아직 snapshot이 없으면 <code><nowiki>effective_mode=legacy</nowiki></code>, <code><nowiki>semantic_status=building</nowiki></code>으로 즉시 대체하고, 구축에 실패해 사용할 snapshot도 없으면 <code><nowiki>unavailable</nowiki></code>을 표시합니다.
설정만으로 기본 검색 순서는 바뀌지 않습니다. 클라이언트가 <code><nowiki>search_lessons</nowiki></code> 또는 <code><nowiki>find_analogies</nowiki></code>에 <code><nowiki>retrieval_mode=hybrid_v1</nowiki></code>을 명시해야 합니다. <code><nowiki>mcp-http</nowiki></code>는 시작할 때 단 하나의 백그라운드 작업으로 전체 Lesson exact index를 프리웜합니다. hybrid 요청은 이 작업을 기다리지 않습니다. 아직 snapshot이 없으면 <code><nowiki>effective_mode=legacy</nowiki></code>, <code><nowiki>semantic_status=building</nowiki></code>으로 즉시 대체하고, 구축에 실패해 사용할 snapshot도 없으면 <code><nowiki>unavailable</nowiki></code>을 표시합니다.
288번째 줄: 316번째 줄:
* <code><nowiki>mediawiki</nowiki></code>: Apache/PHP, Semantic MediaWiki, Page Forms, 생성된 <code><nowiki>LocalSettings.php</nowiki></code>, <code><nowiki>mediawiki_config</nowiki></code>·<code><nowiki>mediawiki_images</nowiki></code> 볼륨
* <code><nowiki>mediawiki</nowiki></code>: Apache/PHP, Semantic MediaWiki, Page Forms, 생성된 <code><nowiki>LocalSettings.php</nowiki></code>, <code><nowiki>mediawiki_config</nowiki></code>·<code><nowiki>mediawiki_images</nowiki></code> 볼륨
* <code><nowiki>bootstrap</nowiki></code>: 스키마·양식 페이지를 맞추고 MCP 계정과 그룹을 만드는 일회성 작업
* <code><nowiki>bootstrap</nowiki></code>: 스키마·양식 페이지를 맞추고 MCP 계정과 그룹을 만드는 일회성 작업
* <code><nowiki>embedding-model-init</nowiki></code>: 고정한 GGUF를 받아 크기와 SHA-256을 확인하는 일회성 작업
* <code><nowiki>embedding</nowiki></code>: 선택적 Vulkan 임베딩 런타임. 호스트 포트와 영구 벡터 저장소는 없음
* <code><nowiki>mcp-http</nowiki></code>: 공개 조회와 토큰 기반 변경을 제공하는 공용 Streamable HTTP 어댑터. Lesson DB나 영구 볼륨은 없음
* <code><nowiki>mcp-http</nowiki></code>: 공개 조회와 토큰 기반 변경을 제공하는 공용 Streamable HTTP 어댑터. Lesson DB나 영구 볼륨은 없음
* <code><nowiki>caddy</nowiki></code>: 위키와 MCP의 공개 HTTPS 진입점
* <code><nowiki>caddy</nowiki></code>: 위키와 MCP의 공개 HTTPS 진입점

2026년 7월 18일 (토) 13:04 판

이 페이지는 저장소 문서에서 자동으로 동기화됩니다. 위키에서 직접 편집하지 마세요.

한 대의 서버에서 위키와 공용 MCP를 함께 실행합니다. 브라우저는 [1]에 접속하고, 모든 에이전트는 [2]에 연결합니다. 두 주소는 하나의 Semantic MediaWiki를 사용합니다. 클라이언트 PC에는 이 저장소, Docker 권한, MediaWiki 에이전트 비밀번호가 필요하지 않습니다.

데이터베이스, 생성된 위키 설정, 업로드 파일은 Docker 볼륨에 저장합니다. 저장소에는 데이터, 자격 증명, 생성된 LocalSettings.php를 넣지 않습니다.

준비 사항

  • Docker Engine 24 이상과 Docker Compose v2 플러그인 또는 최신 Docker Desktop
  • Python 3.11 이상과 uv
  • 메모리 4 GiB 이상, 디스크 여유 공간 8 GiB 이상
  • Bash, make, openssl
  • 백업·복원용 GNU/Linux 호스트: Bash 4 이상, GNU coreutils(stat, sha256sum), GNU tar, gzip, 일반 파일 권한 지원
  • s3wiki.yonsei.ac.kr이 서버의 165.132.118.220으로 연결된 DNS
  • 서버까지 들어오는 TCP 80, 443

macOS와 Windows의 Docker Desktop은 화면 확인에 사용할 수 있습니다. 백업·복원 스크립트는 이 Compose 프로젝트를 실행하는 Linux VM이나 Linux Docker 호스트에서 실행하세요. uv가 없다면 공식 설치 안내를 따릅니다.

필수 명령을 확인합니다.

docker version
docker compose version
make --version
bash --version
sha256sum --version
uv --version

docker version이 클라이언트 버전만 출력하지 않고 Docker 데몬에도 연결되어야 합니다. 이 확인 전에 도메인 설정 스크립트를 실행하지 마세요. 첫 빌드에서는 이미지와 고정된 PHP·Python 의존성을 내려받으므로 인터넷 연결이 필요합니다.

일반 운영 경로는 위 HTTPS 도메인 하나입니다. 읽기와 검색은 공개됩니다. S3RM_MCP_WRITE_AUTH_MODE=token이면 생성·관계·근거 추가와 기존 Lesson의 조건부 수정에 같은 공용 Bearer 토큰이 필요합니다. open은 네 변경 도구를 인증 없이 허용합니다. github는 GitHub 로그인을 거쳐 MCP용 access·refresh token을 발급하며 이 모드에서는 MCP 연결 전체가 OAuth 인증 대상입니다. Caddy는 TLS를 종료하고 /mcp와 OAuth 경로를 MCP 서비스로 보냅니다. 나머지 경로는 MediaWiki로 보냅니다.

기본값은 token입니다. 짧은 공개 시험에서만 .env에 다음 값을 넣고 mcp-http를 다시 만드세요.

S3RM_MCP_WRITE_AUTH_MODE=open

다시 잠그려면 값을 token으로 바꿉니다. 기존 S3RM_MCP_TOKEN_SHA256은 지우지 않아도 되며 open 모드에서는 쓰기에 사용하지 않습니다. 사용자 연결은 Linux, macOS, Windows 문서에 있고 제품별 제약은 mcp-clients.md에 있습니다.

GitHub OAuth 모드 준비

GitHub의 Settings → Developer settings → OAuth Apps에서 앱을 만들고 callback URL을 정확히 다음 값으로 등록합니다.

https://s3wiki.yonsei.ac.kr/oauth/github/callback

그다음 .env를 설정합니다.

S3RM_MCP_WRITE_AUTH_MODE=github
S3RM_GITHUB_CLIENT_ID=발급받은-client-id
S3RM_GITHUB_CLIENT_SECRET=발급받은-client-secret
S3RM_GITHUB_ALLOWED_USERS=허용할-github-사용자
S3RM_GITHUB_ALLOWED_ORGS=
S3RM_GITHUB_ALLOW_ANY_USER=false

사용자 또는 조직 allowlist 중 하나는 설정해야 합니다. 정말 모든 GitHub 사용자를 허용할 때만 S3RM_GITHUB_ALLOW_ANY_USER=true를 사용하세요. GitHub 모드는 저장소 권한을 요청하지 않습니다. 조직 allowlist를 사용할 때만 조직 확인을 위해 read:org scope를 요청합니다. mcp:write scope는 생성, 관계, 근거와 조건부 수정에 함께 적용됩니다.

현재 OAuth client와 token 상태는 mcp-http 프로세스 메모리에만 있습니다. 서비스를 다시 만들면 기존 OAuth 연결이 무효가 되므로 ChatGPT 앱을 다시 인증하거나 다시 만들어야 합니다.

환경 설정

저장소 루트에서 실행합니다.

cp .env.example .env
chmod 600 .env

비밀번호의 change-me 값을 모두 바꿉니다. S3RM_MCP_TOKEN_SHA256=change-me-...는 다음 단계의 토큰 스크립트가 바꾸므로 그대로 둡니다. 비밀번호마다 새 값을 만드세요.

openssl rand -base64 36

공용 MCP 설정

.env의 비밀번호를 바꾼 뒤 등록된 도메인을 설정합니다.

./scripts/configure-public-domain.sh s3wiki.yonsei.ac.kr \
  --expected-ip 165.132.118.220

스크립트는 DNS를 확인하고 위키 URL, MCP URL, loopback 바인딩, HTTPS 설정, Compose domain 프로필을 맞춥니다. 공용 쓰기 토큰은 화면에 출력하지 않습니다. 서버의 mode 0600 .env에는 SHA-256 해시만 저장하고, 원문 토큰과 S3RM_MCP_URL은 mode 0600 ~/.config/s3-research-memory/client.env에 저장합니다. 두 파일의 값이 이미 일치하면 토큰을 바꾸지 않습니다.

모든 클라이언트에 같은 MCP URL을 설정합니다. 조회만 할 때는 토큰이 필요하지 않습니다. 메모를 생성·수정하거나 관계·근거를 추가할 에이전트에만 공용 토큰을 전달합니다. 이 토큰으로 페이지 삭제나 위키 관리를 할 수는 없습니다. 위키 관리자·DB 비밀번호를 토큰으로 재사용하지 마세요.

서버에서 쓰기 연결을 시험할 때는 값을 출력하지 않고 불러옵니다.

set -a
source "$HOME/.config/s3-research-memory/client.env"
set +a

원문 토큰은 필요한 사람에게 비공개 채널로 전달합니다. Git, 공개 이슈, 프롬프트, 스크린샷에는 넣지 마세요. 공용 토큰을 바꾸면 쓰기 클라이언트를 함께 갱신해야 합니다. 공개 조회에는 영향이 없습니다.

설정 스크립트는 비어 있는 S3RM_WIKI_REVISION_HMAC_KEY에 URL-safe 무작위 32바이트 값을 만들고 이후 실행과 토큰 교체에서는 보존합니다. 스크립트를 쓰지 않는 설정은 openssl rand -hex 32로 직접 만들 수 있습니다. 이 키는 mcp-http와 MediaWiki 저장 훅만 공유하며 클라이언트에는 전달하지 않습니다. 공용 토큰이나 위키 비밀번호와 같은 값을 쓰지 마세요. 키가 없거나 형식이 맞지 않으면 MCP가 시작을 거부합니다.

Compose는 현재 프로젝트 디렉터리 또는 --project-directory가 가리키는 곳의 .env를 읽습니다. 자세한 동작은 Docker의 환경 변수 보간 안내를 참고하세요. .env는 추적하지 않습니다. docker compose config는 비밀번호와 토큰 해시를 출력하므로 일반 확인에는 docker compose config --quiet를 사용합니다.

환경 변수

변수 필수 기본값·용도
MARIADB_DATABASE 아니요 s3_research_memory; 위키 데이터베이스 이름
MARIADB_USER 아니요 s3wiki; MediaWiki DB 계정
MARIADB_PASSWORD 제한된 MediaWiki DB 계정 비밀번호
MARIADB_ROOT_PASSWORD 초기화·복구 때만 쓰는 MariaDB 관리자 비밀번호
MW_SITE_NAME 아니요 S3 연구 메모리; 브라우저에 표시할 이름
MW_SERVER_URL 아니요 https://s3wiki.yonsei.ac.kr; 끝에 /가 없는 외부 주소
MW_ADMIN_USERNAME 아니요 S3Admin; 처음 만드는 관리자 계정 이름
MW_ADMIN_PASSWORD 처음 만드는 관리자 비밀번호
S3RM_WIKI_USERNAME 아니요 S3ResearchAgent; MCP 전용 최소 권한 위키 계정
S3RM_WIKI_PASSWORD MCP 어댑터만 쓰는 위키 비밀번호
S3RM_WIKI_REVISION_HMAC_KEY MCP와 MediaWiki 저장 훅만 공유하는 43~256자 URL-safe 서명 키
S3RM_HTTP_PORT 아니요 8080; MediaWiki 80번 포트에 연결한 호스트 진단 포트
S3RM_WIKI_BIND_ADDRESS 아니요 127.0.0.1; 진단 포트를 외부에 열지 않음
S3RM_WIKI_DIRECT_URL 아니요 비워 두면 직접 주소를 사용하지 않음. 외부 HTTP 화면을 명시적으로 열 때만 http://SERVER_IP:8080처럼 전체 주소를 입력하고 bind를 0.0.0.0으로 설정
S3RM_MCP_PUBLIC_URL 클라이언트 주소 https://s3wiki.yonsei.ac.kr/mcp
S3RM_MCP_WRITE_AUTH_MODE 아니요 token; open, token, github 중 하나
S3RM_MCP_TOKEN_SHA256 token 모드 쓰기 토큰의 64자리 16진수 SHA-256 해시. 원문은 저장하지 않음
S3RM_GITHUB_CLIENT_ID github 모드 GitHub OAuth App의 client ID
S3RM_GITHUB_CLIENT_SECRET github 모드 GitHub OAuth App의 client secret. 커밋하지 않음
S3RM_GITHUB_ALLOWED_USERS 선택 허용할 GitHub 사용자명. 쉼표로 구분
S3RM_GITHUB_ALLOWED_ORGS 선택 허용할 GitHub 조직명. 쉼표로 구분
S3RM_GITHUB_ALLOW_ANY_USER 아니요 false; true면 모든 GitHub 계정을 허용
S3RM_MCP_BIND_ADDRESS 아니요 도메인 프로필에서는 127.0.0.1. 공개 진입점은 Caddy
S3RM_MCP_HTTP_PORT 아니요 8765; MCP 컨테이너 8000번 포트에 연결한 loopback 진단 포트
S3RM_MCP_ALLOWED_HOSTS 아니요 쉼표로 나눈 추가 Host 값. 공개 URL의 host는 자동 허용
S3RM_MCP_ALLOWED_ORIGINS 아니요 쉼표로 나눈 추가 HTTP(S) Origin. 공개 URL의 origin은 자동 허용
S3RM_MCP_ALLOW_INSECURE_HTTP 아니요 false; 클라이언트 주소는 HTTPS만 사용
S3RM_PUBLIC_HOST 아니요 s3wiki.yonsei.ac.kr; Caddy 주소
S3RM_PUBLIC_HTTP_PORT 아니요 80; 리디렉션과 인증서 발급용 공개 HTTP 포트
S3RM_PUBLIC_HTTPS_PORT 아니요 443; 공개 HTTPS 포트
COMPOSE_PROFILES 아니요 domain은 Caddy, embedding은 내부 GPU 임베딩 서비스를 실행. 쉼표로 함께 지정 가능
S3RM_MAX_OUTPUT_BYTES 아니요 32768; 도구 결과 제한 2048~65536바이트. 전체 JSON-RPC 응답은 별도 212992바이트 제한
S3RM_SEARCH_SCAN_LIMIT 아니요 200; 후보 스캔 제한 20~1000페이지
S3RM_WIKI_TIMEOUT_SECONDS 아니요 20; MediaWiki 요청 제한 1~120초

Compose의 mcp-http는 내부 http://mediawiki/api.php만 사용합니다. 이 주소와 위키 비밀번호는 클라이언트에 전달하지 않습니다.

선택적 의미 검색

기본 S3RM_EMBEDDING_PROVIDER=disabled는 모델을 실행하지 않고 기존 전체 텍스트와 관계 검색을 사용합니다. 이 저장소에는 이 서버의 AMD Vega GPU에 맞춘 비공개 llama.cpp Vulkan 서비스가 포함되어 있습니다. 모델은 Qwen/Qwen3-Embedding-0.6B F16이며, 결과는 1024차원입니다. 공식 Qwen GGUFllama.cpp 서버를 고정된 revision과 이미지 digest로 사용합니다.

다음 두 값만 바꾸면 .env.example의 고정 모델 설정을 그대로 사용할 수 있습니다.

S3RM_EMBEDDING_PROVIDER=openai-compatible
COMPOSE_PROFILES=domain,embedding

고정 모델을 확인하고 서비스를 시작합니다. 첫 실행은 약 1.2GB 모델을 받습니다.

make embedding-up

embedding-model-init만 인터넷에 연결됩니다. 이 작업은 모델 저장소 commit, 파일 크기와 SHA-256을 모두 확인한 뒤 embedding_models 볼륨에 원자적으로 게시합니다. 실제 embedding 서비스는 호스트 포트를 열지 않으며 mcp-http와만 공유하는 내부 embedding-backend 네트워크를 사용합니다. Vega의 render node 하나만 컨테이너에 전달합니다.

실행 중인 모델, 차원과 MCP 연결 설정을 다시 확인할 수 있습니다.

make verify-embedding

s3rm-qwen3-retrieval-v1 profile은 모델 artifact digest, 1024차원, last pooling, 16K token 입력 계약과 세 facet의 query instruction을 한 generation으로 묶습니다. document에는 instruction을 붙이지 않습니다. 희귀 CJK의 byte fallback도 16K를 넘지 않도록 각 document facet은 보수적으로 4,000자에서 자릅니다. 이 값 중 하나를 바꾸면 새 exact index를 처음부터 만듭니다. 서로 다른 generation의 벡터는 섞지 않습니다.

변수 필수 기본값·범위
S3RM_EMBEDDING_PROVIDER 아니요 disabled; disabled, openai-compatible 중 하나
S3RM_EMBEDDING_PROFILE 사용 시 번들 모델은 s3rm-qwen3-retrieval-v1; 기존 제공자는 legacy-v1
S3RM_EMBEDDING_API_URL 임베딩 사용 시 자격 증명·query·fragment가 없는 HTTP(S) embeddings endpoint
S3RM_EMBEDDING_API_KEY 제공자에 따라 요청에만 쓰는 secret. 커밋하지 않음
S3RM_EMBEDDING_MODEL 임베딩 사용 시 제공자의 고정 모델 식별자
S3RM_EMBEDDING_MODEL_REVISION profile에 따라 generation에 넣는 immutable revision. 번들 모델은 sha256:<GGUF digest>
S3RM_EMBEDDING_DIMENSIONS 임베딩 사용 시 벡터 차원 1~4096
S3RM_EMBEDDING_MODEL_SOURCE_REVISION 번들 모델 downloader가 사용하는 40자리 Hugging Face commit
S3RM_EMBEDDING_MODEL_SHA256 번들 모델 내려받은 GGUF의 64자리 SHA-256
S3RM_EMBEDDING_MODEL_SIZE_BYTES 번들 모델 내려받은 GGUF의 정확한 바이트 수
S3RM_EMBEDDING_DRI_DEVICE 번들 모델 이 서버의 외장 Vega render node /dev/dri/renderD128
S3RM_EMBEDDING_GPU_DEVICE 번들 모델 컨테이너에서 보이는 장치 Vulkan0
S3RM_RENDER_GID 번들 모델 render node의 group ID. 이 서버는 987
S3RM_EMBEDDING_TIMEOUT_SECONDS 아니요 번들 모델은 60; 허용 범위 0.5~120초
S3RM_EMBEDDING_BATCH_SIZE 아니요 번들 모델은 6; 요청 한 번에 1~128개
S3RM_EMBEDDING_MAX_CONCURRENCY 아니요 번들 모델은 1; 동시 요청 1~16개
S3RM_EMBEDDING_QUEUE_LIMIT 아니요 32; 대기 요청 1~1000개
S3RM_EMBEDDING_QUEUE_TIMEOUT_SECONDS 아니요 1; 대기 제한 0.05~30초
S3RM_EMBEDDING_ALLOW_INSECURE_HTTP 아니요 번들 내부 HTTP는 true; 외부 endpoint는 HTTPS 사용
S3RM_EMBEDDING_INSECURE_HTTP_HOSTS 내부 HTTP 사용 시 허용할 정확한 Host 목록. 번들 서비스는 embedding:8080
S3RM_SEMANTIC_CANDIDATE_LIMIT 아니요 50; facet별 후보 5~100개
S3RM_SEMANTIC_REFRESH_SECONDS 아니요 300; 주기 대조와 실패 후 재시도 간격 10~86400초. dirty hint는 즉시 갱신

의미 인덱스는 mcp-http 메모리의 파생 후보 인덱스입니다. Semantic MediaWiki가 계속 기준 저장소이며, 제공자나 인덱스가 실패하면 제한된 기존 검색으로 대체합니다. S3RM_SEARCH_SCAN_LIMIT × 3 × S3RM_EMBEDDING_DIMENSIONS는 3,000,000개 벡터 구성요소를 넘을 수 없습니다. 이 조합 검사는 exact index의 메모리 사용을 제한합니다. 외부 OpenAI 호환 API를 대신 사용할 수도 있습니다. 이 경우 legacy-v1 또는 별도로 검증한 profile을 사용하고 HTTPS endpoint를 설정합니다. Lesson 의미 검색 필드와 아직 저장하지 않은 query가 외부로 전송되므로 보존·학습 사용·region·비용 조건을 확인한 뒤 켜세요. 로컬 서비스 장애가 외부 API로 자동 전환되지는 않습니다.

설정만으로 기본 검색 순서는 바뀌지 않습니다. 클라이언트가 search_lessons 또는 find_analogiesretrieval_mode=hybrid_v1을 명시해야 합니다. mcp-http는 시작할 때 단 하나의 백그라운드 작업으로 전체 Lesson exact index를 프리웜합니다. hybrid 요청은 이 작업을 기다리지 않습니다. 아직 snapshot이 없으면 effective_mode=legacy, semantic_status=building으로 즉시 대체하고, 구축에 실패해 사용할 snapshot도 없으면 unavailable을 표시합니다.

인덱스가 준비된 뒤에는 Lesson 저장 dirty hint가 즉시 같은 단일 백그라운드 갱신을 시작합니다. S3RM_SEMANTIC_REFRESH_SECONDS가 지나면 다음 hybrid 요청이 브라우저 편집까지 포함한 전체 대조를 시작합니다. 요청은 기존 snapshot을 계속 사용하며 갱신 중에는 stale, 갱신 실패 뒤에는 degraded가 될 수 있습니다. 확인할 때는 작은 요청을 다시 보내 effective_mode=hybrid_v1, semantic_status=ready인지 봅니다.

search_lessons(query="단편화", retrieval_mode="hybrid_v1", limit=1)

직접 HTTP 화면을 함께 열어야 한다면 다음 두 값을 같이 설정합니다. MediaWiki는 정확히 이 Host로 들어온 요청에만 직접 주소를 사용합니다. 임의의 Host 헤더를 신뢰하지 않으며 정식 주소와 MCP 주소는 HTTPS 도메인으로 유지합니다.

S3RM_WIKI_BIND_ADDRESS=0.0.0.0
S3RM_WIKI_DIRECT_URL=http://165.132.118.220:8080

이 설정은 Docker의 호스트 리스너만 엽니다. 학교 경계 보안정책에서 TCP 8080이 차단되어 있으면 외부 접속은 계속 timeout입니다. 직접 주소는 위키 화면에만 쓰며 MCP URL로 등록하지 않습니다.

진단 포트만 바꿀 때는 외부 브라우저 주소를 그대로 둡니다.

S3RM_HTTP_PORT=8090
MW_SERVER_URL=https://s3wiki.yonsei.ac.kr

도메인과 Caddy 프로필

도메인 스크립트는 여러 번 실행해도 됩니다. Docker를 시작하지 않으며, 기존 토큰과 해시가 일치하면 토큰을 바꾸지 않습니다.

./scripts/configure-public-domain.sh s3wiki.yonsei.ac.kr \
  --expected-ip 165.132.118.220

domain 프로필은 Caddy 컨테이너 하나를 시작합니다. Caddy는 TLS 인증서를 발급·갱신하고, HTTP를 HTTPS로 돌립니다. /mcp/mcp/*mcp-http로 보내고 나머지 경로는 MediaWiki로 보냅니다. MCP 경로를 다시 쓰거나 Lesson을 저장하지 않습니다. 동작 원리는 Caddy의 자동 HTTPS 안내리버스 프록시 안내를 참고하세요.

정적 Authorization 헤더를 보낼 수 있는 클라이언트는 공용 Bearer 토큰으로 변경 도구 네 개를 사용할 수 있습니다. 호스팅형 ChatGPT와 Claude 커넥터는 같은 URL에서 공개 조회 도구를 사용할 수 있습니다. 이 제품에서 변경 도구를 쓰려면 OAuth 진입점이 추가로 필요합니다. OAuth를 붙이더라도 MCP나 위키를 하나 더 만들지 않습니다.

시작

필수 변수와 Compose 모델을 출력 없이 확인합니다.

docker compose config --quiet

이미지를 빌드하고 서비스를 시작합니다. 아래 명령은 HTTPS 위키 API와 /mcp도 확인합니다.

make domain-up

이 확인은 명령을 실행한 서버 기준입니다. 학교 밖에서 80/443이 열렸는지는 다른 네트워크의 브라우저에서도 확인해야 합니다. 이미 실행 중인 서버의 HTTPS와 MCP만 다시 확인할 때는 make verify-domain을 사용합니다.

서비스 역할은 다음과 같습니다.

  • db: MariaDB와 db_data 볼륨
  • mediawiki: Apache/PHP, Semantic MediaWiki, Page Forms, 생성된 LocalSettings.php, mediawiki_config·mediawiki_images 볼륨
  • bootstrap: 스키마·양식 페이지를 맞추고 MCP 계정과 그룹을 만드는 일회성 작업
  • embedding-model-init: 고정한 GGUF를 받아 크기와 SHA-256을 확인하는 일회성 작업
  • embedding: 선택적 Vulkan 임베딩 런타임. 호스트 포트와 영구 벡터 저장소는 없음
  • mcp-http: 공개 조회와 토큰 기반 변경을 제공하는 공용 Streamable HTTP 어댑터. Lesson DB나 영구 볼륨은 없음
  • caddy: 위키와 MCP의 공개 HTTPS 진입점

첫 시작 상태를 확인합니다.

docker compose ps -a
docker compose logs -f mediawiki bootstrap mcp-http caddy

db, mediawiki, mcp-http, caddy가 실행 또는 healthy 상태이고, bootstrap이 코드 0으로 종료되면 정상입니다. Caddy 인증서도 발급되어야 합니다. bootstrap은 일회성 작업이므로 종료 상태가 정상입니다. docker compose up -d를 다시 실행해도 관리 스키마와 양식을 맞추며 일반 Lesson과 변경 이력은 보존합니다. 새 설치에는 Lesson 페이지가 없습니다. 첫 메모를 저장하기 전에는 최근 목록과 검색 결과가 비어 있어도 정상입니다.

<!-- Contract marker: There is no browser installation step. --> 브라우저 설치 단계는 없습니다. 저장된 LocalSettings.php가 없으면 mediawiki entrypoint가 Apache를 시작하기 전에 MediaWiki CLI 설치를 실행하고 DB 마이그레이션을 적용합니다. /mw-config/에 접속하거나, 브라우저 설치를 다시 시작하거나, 생성된 LocalSettings.php를 컨테이너에 복사하지 마세요. 설치 화면이 나오거나 세션 만료 오류가 보이면 문제 해결 안내를 따릅니다.

[3]를 엽니다. 읽기와 검색은 로그인 없이 할 수 있습니다. 작성과 편집에는 이름이 있는 위키 계정이 필요합니다.

  • /index.php/Special:Version: Semantic MediaWiki, Page Forms, S3 Research Memory 확장 기능 확인
  • /index.php/연구_메모리#create-a-lesson: 문서 ID를 정하고 Lesson: 메모 작성
  • /index.php/Special:Search: MediaWiki 전문 검색
  • /index.php/Special:AllPages?namespace=3000: 모든 Lesson: 페이지

브라우저 계정 만들기

자기 가입은 꺼져 있습니다. 설정에서 익명 그룹(*)의 createaccount 권한을 제거했고, 관리자 그룹(sysop)만 계정을 만들 수 있습니다. 새 설치에서는 다음 순서로 일반 편집 계정을 만드세요.

  1. MW_ADMIN_USERNAMEMW_ADMIN_PASSWORD로 로그인합니다.
  2. /index.php/Special:CreateAccount를 엽니다.
  3. 사용할 사람의 이름을 알 수 있는 사용자 이름과 새 임시 비밀번호를 입력합니다.
  4. 계정을 만든 뒤 /index.php/Special:ListUsers에서 확인합니다.
  5. sysop, bureaucrat, agent 그룹은 추가하지 않습니다. 로그인한 일반 계정은 자동으로 user 권한을 받아 양식으로 메모를 작성·편집할 수 있습니다.
  6. 새 계정으로 로그인해 비밀번호를 바꾸고 메모 양식이 열리는지 확인합니다.

관리자 계정이나 S3RM_WIKI_USERNAME 계정을 일상 편집에 함께 쓰지 마세요. 계정과 권한 기준은 security.md에 정리되어 있습니다.

설치 확인

로컬 테스트와 Compose 검사를 실행합니다.

make test
make check-compose

make test는 Compose 없이 메모리 내 위키 어댑터로 스키마, 에이전트 권한, 관계, 페이지네이션, 직렬화 출력 제한을 확인합니다. make check-compose는 테스트용 필수 값을 넣은 뒤 Compose 배포 모델을 확인합니다.

브라우저에서는 다음을 확인합니다.

  1. 로그아웃 상태에서 Special:Version, 검색, Lesson 페이지가 열리고, 작성·편집은 로그인을 요구하는지 확인합니다.
  2. 새 설치라면 Lesson 네임스페이스의 Special:AllPages가 비어 있어도 정상입니다.
  3. 로그인한 일반 계정으로 /index.php/연구_메모리#create-a-lesson을 열고 작성 양식이 보이는지 확인합니다. 확인용 가짜 메모는 저장하지 않습니다.
  4. 첫 실제 메모를 저장할 때 검색에 바로 나오는지, 필드와 근거 인용이 보이는지, 역사 보기에 변경 이력이 생겼는지 확인합니다.

클라이언트를 연결하기 전 공용 MCP 확인

.envS3RM_MCP_PUBLIC_URL과 같은 주소를 설정합니다.

export S3RM_MCP_URL='https://s3wiki.yonsei.ac.kr/mcp'

서버에서 프로세스 상태를 먼저 확인합니다. S3RM_MCP_HTTP_PORT를 바꿨다면 8765도 같이 바꿉니다. 이 경로는 프로세스 상태만 반환하며 위키 데이터나 인증이 없습니다.

curl --fail --silent --show-error http://127.0.0.1:8765/healthz

이어서 토큰 없이 MCP 초기화를 보냅니다. HTTP나 JSON 오류가 있으면 0이 아닌 코드로 끝납니다.

python3 - <<'PY'
import json
import os
import urllib.request

payload = json.dumps({
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
        "protocolVersion": "2025-11-25",
        "capabilities": {},
        "clientInfo": {"name": "s3rm-setup-smoke", "version": "1"},
    },
}).encode()
request = urllib.request.Request(
    os.environ["S3RM_MCP_URL"],
    data=payload,
    headers={
        "Accept": "application/json, text/event-stream",
        "Content-Type": "application/json",
    },
    method="POST",
)
with urllib.request.urlopen(request, timeout=20) as response:
    result = json.load(response)
assert result.get("result", {}).get("serverInfo", {}).get("name") == "S3 Research Memory"
print("anonymous MCP initialize: ok")
PY

토큰이 없는 클라이언트도 초기화, 도구 목록, search_lessons, get_lesson, audit_lessons, find_related_lessons, find_analogies를 사용할 수 있습니다. mcp-clients.md에 따라 연결하고 search_lessons(limit=1)을 실행합니다. 다른 PC의 클라이언트에서도 같은 결과가 나오는지 확인하세요.

변경 도구가 필요한 클라이언트에는 플랫폼 설정으로 공용 토큰을 불러옵니다. 이 토큰으로 생성, 관계, 근거와 조건부 수정을 모두 호출합니다. 연결 확인만 하려고 가짜 메모를 만들지 않습니다. 쓰기 권한 경계는 make test로 확인하고, 실제 첫 메모를 남길 때 MediaWiki 이력, audit_lessons와 검색 결과를 확인합니다.

평소 시작과 종료

설치가 끝난 서비스를 시작합니다.

docker compose up -d
docker compose ps -a
make verify-domain

마지막 명령은 서버에서 본 HTTPS 위키와 MCP를 확인합니다. 다른 PC에서 접속되는지는 그 PC의 브라우저나 MCP 클라이언트로 따로 확인합니다.

볼륨을 남기고 종료합니다.

docker compose down

MediaWiki만 다시 시작합니다.

docker compose restart mediawiki

공용 MCP 프로세스만 다시 시작합니다.

docker compose restart mcp-http
docker compose ps mcp-http

의도적으로 설정을 바꾼 뒤 스키마·계정을 다시 맞춥니다.

docker compose up -d --force-recreate bootstrap
docker compose logs bootstrap

일반 운영 중에는 docker compose down --volumes, docker volume rm, 수동 SQL 삭제를 실행하지 마세요. 위키의 기준 데이터가 사라집니다.

자격 증명 변경

.env 값만 바꿔도 MariaDB나 MediaWiki에 이미 저장된 자격 증명은 바뀌지 않습니다. 해당 제품의 계정 관리 절차로 먼저 바꾸고, 같은 작업 시간에 .env와 관련 서비스를 함께 갱신합니다.

  • 공용 MCP 토큰: ./scripts/configure-mcp-token.sh --rotate를 실행하고 mcp-http를 다시 만듭니다. 변경 경로를 확인한 뒤 새 handoff를 전달하고 클라이언트를 재연결합니다. --rotate가 없으면 일치하는 기존 토큰을 보존합니다. 공개 조회는 계속되지만 이전·새 쓰기 토큰을 동시에 받을 수는 없습니다.
  • revision HMAC 키: 새 URL-safe 키를 .env에 넣고 mediawikimcp-http를 같은 작업 시간에 다시 만듭니다. 둘 중 하나만 이전 키를 쓰는 동안에는 revision을 실행하지 않습니다. 이 키는 어떤 클라이언트에도 전달하지 않습니다.
  • MCP 위키 계정: S3RM_WIKI_PASSWORD를 바꾸고 bootstrap을 다시 실행한 뒤 mcp-http를 다시 만듭니다. bootstrap은 전용 계정과 agent 그룹을 맞추고 높은 권한을 제거합니다.
  • 일반 위키 계정: MediaWiki 화면에서 비밀번호를 바꿉니다. DB 테이블을 직접 편집하지 마세요.
  • MariaDB 계정: MariaDB 공식 계정 관리 절차로 서버 계정을 바꾼 뒤, 같은 작업 시간에 .env를 갱신합니다.

먼저 백업하고, 변경 뒤 조회를 확인합니다. 공용 토큰 절차는 operations.md에 있습니다.

업데이트

MediaWiki 기본 이미지는 정확한 버전으로 고정되어 있습니다. PHP 의존성은 docker/mediawiki/composer.lock, Python 의존성은 mcp/uv.lock을 사용합니다. MariaDB 이미지는 호환 태그를 사용합니다.

  1. MediaWiki, Semantic MediaWiki, Page Forms, MariaDB, MCP 의존성의 릴리스 안내와 호환표를 확인합니다.
  2. operations.md에 따라 전체 백업을 만들고 확인합니다.
  3. 버전 고정을 추적 가능한 커밋에서 바꿉니다. 실제 서버에서 검증하지 않은 floating 버전을 쓰지 마세요.
  4. make testmake check-compose를 실행합니다.
  5. 별도 볼륨에 빌드하고 복원 시험을 합니다.
  6. 확인 뒤 실제 서버 이미지를 다시 만들고 bootstrap의 마이그레이션·동기화를 완료합니다.
docker compose build --pull mediawiki mcp-http
docker compose up -d
docker compose logs mediawiki bootstrap mcp-http caddy

새 MediaWiki에서 만든 DB를 더 오래된 MediaWiki로 복원하지 마세요. 호환성은 Semantic MediaWiki 설치 안내, Page Forms 설치 안내, MediaWiki 업그레이드 안내를 기준으로 확인합니다.