도움말:S3 연구 메모리/설치와 검증: 두 판 사이의 차이
S3 연구 메모리 저장소 문서 동기화 |
S3 연구 메모리 저장소 문서 동기화 |
||
| 131번째 줄: | 131번째 줄: | ||
|- | |- | ||
| <code><nowiki>S3RM_WIKI_REVISION_HMAC_KEY</nowiki></code> || 예 || MCP와 MediaWiki 저장 훅만 공유하는 43~256자 URL-safe 서명 키 | | <code><nowiki>S3RM_WIKI_REVISION_HMAC_KEY</nowiki></code> || 예 || MCP와 MediaWiki 저장 훅만 공유하는 43~256자 URL-safe 서명 키 | ||
|- | |||
| <code><nowiki>S3RM_AGENT_EDITS_PER_MINUTE</nowiki></code> || 아니요 || <code><nowiki>600</nowiki></code>; 공유 <code><nowiki>agent</nowiki></code> 계정의 편집 한도 91~6000회/분. 일반 계정과 편집 이외 작업에는 적용하지 않음 | |||
|- | |- | ||
| <code><nowiki>S3RM_HTTP_PORT</nowiki></code> || 아니요 || <code><nowiki>8080</nowiki></code>; MediaWiki 80번 포트에 연결한 호스트 진단 포트 | | <code><nowiki>S3RM_HTTP_PORT</nowiki></code> || 아니요 || <code><nowiki>8080</nowiki></code>; MediaWiki 80번 포트에 연결한 호스트 진단 포트 | ||
| 178번째 줄: | 180번째 줄: | ||
| <code><nowiki>S3RM_WIKI_TIMEOUT_SECONDS</nowiki></code> || 아니요 || <code><nowiki>20</nowiki></code>; MediaWiki 요청 제한 1~120초 | | <code><nowiki>S3RM_WIKI_TIMEOUT_SECONDS</nowiki></code> || 아니요 || <code><nowiki>20</nowiki></code>; MediaWiki 요청 제한 1~120초 | ||
|} | |} | ||
<code><nowiki>S3RM_AGENT_EDITS_PER_MINUTE</nowiki></code>를 바꾼 뒤에는 <code><nowiki>restart</nowiki></code>가 아니라 MediaWiki 컨테이너를 다시 만들어야 새 환경 변수가 들어갑니다. | |||
<pre><nowiki> | |||
docker compose up -d --force-recreate mediawiki | |||
</nowiki></pre> | |||
저장소의 <code><nowiki>LocalSettings.s3.php</nowiki></code>도 함께 바뀐 배포에서는 이미지를 먼저 다시 만듭니다. | |||
<pre><nowiki> | |||
docker compose up -d --build --force-recreate mediawiki | |||
</nowiki></pre> | |||
Compose의 <code><nowiki>mcp-http</nowiki></code>는 내부 <code><nowiki>http://mediawiki/api.php</nowiki></code>만 사용합니다. 이 주소와 위키 비밀번호는 클라이언트에 전달하지 않습니다. | Compose의 <code><nowiki>mcp-http</nowiki></code>는 내부 <code><nowiki>http://mediawiki/api.php</nowiki></code>만 사용합니다. 이 주소와 위키 비밀번호는 클라이언트에 전달하지 않습니다. | ||
2026년 7월 18일 (토) 15:49 판
이 페이지는 저장소 문서에서 자동으로 동기화됩니다. 위키에서 직접 편집하지 마세요.
한 대의 서버에서 위키와 공용 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_AGENT_EDITS_PER_MINUTE |
아니요 | 600; 공유 agent 계정의 편집 한도 91~6000회/분. 일반 계정과 편집 이외 작업에는 적용하지 않음
|
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초
|
S3RM_AGENT_EDITS_PER_MINUTE를 바꾼 뒤에는 restart가 아니라 MediaWiki 컨테이너를 다시 만들어야 새 환경 변수가 들어갑니다.
docker compose up -d --force-recreate mediawiki
저장소의 LocalSettings.s3.php도 함께 바뀐 배포에서는 이미지를 먼저 다시 만듭니다.
docker compose up -d --build --force-recreate mediawiki
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 GGUF와 llama.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_analogies에 retrieval_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)만 계정을 만들 수 있습니다. 새 설치에서는 다음 순서로 일반 편집 계정을 만드세요.
MW_ADMIN_USERNAME과MW_ADMIN_PASSWORD로 로그인합니다./index.php/Special:CreateAccount를 엽니다.- 사용할 사람의 이름을 알 수 있는 사용자 이름과 새 임시 비밀번호를 입력합니다.
- 계정을 만든 뒤
/index.php/Special:ListUsers에서 확인합니다. sysop,bureaucrat,agent그룹은 추가하지 않습니다. 로그인한 일반 계정은 자동으로user권한을 받아 양식으로 메모를 작성·편집할 수 있습니다.- 새 계정으로 로그인해 비밀번호를 바꾸고 메모 양식이 열리는지 확인합니다.
관리자 계정이나 S3RM_WIKI_USERNAME 계정을 일상 편집에 함께 쓰지 마세요. 계정과 권한 기준은 security.md에 정리되어 있습니다.
설치 확인
로컬 테스트와 Compose 검사를 실행합니다.
make test make check-compose
make test는 Compose 없이 메모리 내 위키 어댑터로 스키마, 에이전트 권한, 관계, 페이지네이션, 직렬화 출력 제한을 확인합니다. make check-compose는 테스트용 필수 값을 넣은 뒤 Compose 배포 모델을 확인합니다.
브라우저에서는 다음을 확인합니다.
- 로그아웃 상태에서
Special:Version, 검색, Lesson 페이지가 열리고, 작성·편집은 로그인을 요구하는지 확인합니다. - 새 설치라면 Lesson 네임스페이스의
Special:AllPages가 비어 있어도 정상입니다. - 로그인한 일반 계정으로
/index.php/연구_메모리#create-a-lesson을 열고 작성 양식이 보이는지 확인합니다. 확인용 가짜 메모는 저장하지 않습니다. - 첫 실제 메모를 저장할 때 검색에 바로 나오는지, 필드와 근거 인용이 보이는지, 역사 보기에 변경 이력이 생겼는지 확인합니다.
클라이언트를 연결하기 전 공용 MCP 확인
.env의 S3RM_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에 넣고mediawiki와mcp-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 이미지는 호환 태그를 사용합니다.
- MediaWiki, Semantic MediaWiki, Page Forms, MariaDB, MCP 의존성의 릴리스 안내와 호환표를 확인합니다.
operations.md에 따라 전체 백업을 만들고 확인합니다.- 버전 고정을 추적 가능한 커밋에서 바꿉니다. 실제 서버에서 검증하지 않은 floating 버전을 쓰지 마세요.
make test와make check-compose를 실행합니다.- 별도 볼륨에 빌드하고 복원 시험을 합니다.
- 확인 뒤 실제 서버 이미지를 다시 만들고
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 업그레이드 안내를 기준으로 확인합니다.