본문으로 이동

도움말:S3 연구 메모리/백업과 복원: 두 판 사이의 차이

S3 연구 메모리
S3 연구 메모리 저장소 문서 게시
 
S3 연구 메모리 저장소 문서 동기화
 
93번째 줄: 93번째 줄:
* 분기마다 격리 복원 시험
* 분기마다 격리 복원 시험
실제 복구 시점 목표는 운영 상황에 맞게 정합니다. 스케줄러 종료 상태와 디스크 여유 공간을 확인하세요. 오류 알림이 없는 예약 명령만으로는 충분하지 않습니다. 새 복원을 확인하기 전에 가장 최근의 정상 백업을 지우지 마세요.
실제 복구 시점 목표는 운영 상황에 맞게 정합니다. 스케줄러 종료 상태와 디스크 여유 공간을 확인하세요. 오류 알림이 없는 예약 명령만으로는 충분하지 않습니다. 새 복원을 확인하기 전에 가장 최근의 정상 백업을 지우지 마세요.
==== Cloudflare R2 자동 백업 ====
이 서버는 다음 비공개 R2 bucket의 <code><nowiki>restic</nowiki></code> prefix를 원격 백업 저장소로 사용합니다.
<pre><nowiki>
https://96f01030a087d07d906bff299d260155.r2.cloudflarestorage.com/s3rm-backups
</nowiki></pre>
백업 데이터는 <code><nowiki>restic</nowiki></code>이 서버에서 먼저 암호화한 뒤 전송합니다. R2 Access Key, Secret Key와 restic 암호는 Git이나 프로젝트 <code><nowiki>.env</nowiki></code>에 넣지 않습니다.
서버에 <code><nowiki>restic</nowiki></code>을 설치한 뒤 root 권한으로 설정 파일을 준비합니다.
<pre><nowiki>
sudo install -d -m 0700 /etc/s3-research-memory /srv/s3rm-backups
sudo install -m 0600 config/remote-backup.env.example \
  /etc/s3-research-memory/remote-backup.env
sudo sh -c 'umask 077; openssl rand -base64 48 > /etc/s3-research-memory/restic-password'
sudoedit /etc/s3-research-memory/remote-backup.env
</nowiki></pre>
R2에서 <code><nowiki>s3rm-backups</nowiki></code> bucket에만 목록 조회·읽기·쓰기·삭제가 가능한 S3 API 자격 증명을 만들고 설정 파일의 두 placeholder를 바꿉니다. 삭제 권한은 오래된 restic snapshot과 pack을 보존 정책에 맞게 정리할 때 필요합니다. restic 암호 파일은 서버 장애 때도 찾을 수 있도록 서버 밖의 비밀번호 관리자에 따로 보관합니다. 이 암호를 잃으면 R2의 백업을 복구할 수 없습니다.
초기 운영에서는 R2 bucket lock이나 별도 lifecycle 삭제 규칙을 켜지 않습니다. 두 기능은 restic의 <code><nowiki>forget</nowiki></code>·<code><nowiki>prune</nowiki></code>과 충돌할 수 있습니다. 첫 원격 복원 시험을 마친 뒤 별도 삭제 방지 정책을 설계합니다.
원격 저장소는 한 번만 초기화합니다.
<pre><nowiki>
sudo bash -c '
  set -a
  source /etc/s3-research-memory/remote-backup.env
  set +a
  exec /home/mrcha033/Projects/s3wiki/scripts/init-remote-backup.sh
'
</nowiki></pre>
systemd 단위를 설치하고 첫 백업을 수동으로 확인합니다.
<pre><nowiki>
sudo install -m 0644 deploy/systemd/s3rm-remote-backup.service \
  /etc/systemd/system/s3rm-remote-backup.service
sudo install -m 0644 deploy/systemd/s3rm-remote-backup.timer \
  /etc/systemd/system/s3rm-remote-backup.timer
sudo systemctl daemon-reload
sudo systemctl start s3rm-remote-backup.service
sudo systemctl status s3rm-remote-backup.service
sudo systemctl enable --now s3rm-remote-backup.timer
systemctl list-timers s3rm-remote-backup.timer
</nowiki></pre>
작업은 매일 서울 시각 03:15 이후 45분 안에 실행합니다. 성공한 원격 snapshot은 일간 14개와 주간 8개를 보존하고, 원격 pack 정리는 일요일에 실행합니다. 전송이나 검증이 실패하면 로컬 복구 세트를 지우지 않습니다. 성공하면 R2에 이미 암호화된 snapshot을 확인한 뒤 <code><nowiki>/srv/s3rm-backups</nowiki></code>의 해당 임시 세트를 정리합니다.
상태와 최근 로그를 정기적으로 확인합니다.
<pre><nowiki>
systemctl status s3rm-remote-backup.timer
sudo journalctl -u s3rm-remote-backup.service --since '2 days ago'
</nowiki></pre>
원격 snapshot을 복구할 때는 빈 root 전용 디렉터리에 먼저 내려받고 기존 복원 스크립트로 넘깁니다.
<pre><nowiki>
sudo install -d -m 0700 /srv/s3rm-remote-restore
sudo bash -c '
  set -a
  source /etc/s3-research-memory/remote-backup.env
  set +a
  restic snapshots --tag s3rm-recovery-set
  restic restore latest --tag s3rm-recovery-set --target /srv/s3rm-remote-restore
'
sudo find /srv/s3rm-remote-restore -maxdepth 2 -type f -name SHA256SUMS -print
</nowiki></pre>
출력된 <code><nowiki>SHA256SUMS</nowiki></code>의 상위 디렉터리가 한 개이고 원하는 시각의 복구 세트인지 확인한 뒤 <code><nowiki>scripts/restore.sh &lt;그 디렉터리&gt; --yes</nowiki></code>를 사용합니다. 운영 서버를 덮어쓰기 전에 격리 복원 시험을 먼저 수행합니다.


=== 복원 전 주의 ===
=== 복원 전 주의 ===

2026년 7월 16일 (목) 23:32 기준 최신판

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

Semantic MediaWiki가 유일한 Lesson 저장소입니다. 복구 지점에는 같은 시점의 MariaDB 덤프, 업로드 파일, 생성된 위키 설정이 모두 있어야 합니다. 공용 mcp-http는 상태를 저장하지 않는 전송·검증 어댑터입니다. Lesson 볼륨, 토큰 DB, 별도 기준 데이터가 없으므로 백업하지 않습니다. 이미지와 설정은 저장소와 .env에서 다시 만듭니다.

Caddy는 [1][2]의 HTTPS 진입점이며 지식을 저장하지 않습니다.

복구 스크립트는 Bash 4 이상, GNU coreutils(stat, sha256sum), GNU tar, gzip이 있는 GNU/Linux Docker 호스트에서 지원합니다. 필요한 명령이 없으면 바로 실패합니다. macOS와 Windows Docker Desktop에서는 이 Compose 프로젝트를 소유한 Linux VM 또는 Linux 호스트에서 실행하세요. BSD 명령 옵션이 같다고 가정하지 마세요.

영구 데이터

Compose 볼륨 내용 복구 때 역할
db_data MediaWiki 페이지, 의미 데이터, 사용자, 변경 이력, 로그, 호환 필드 기준 데이터베이스
mediawiki_images 업로드한 근거 파일과 MediaWiki 업로드 메타데이터 DB 덤프와 같은 시점이어야 함
mediawiki_config 생성된 LocalSettings.php와 MediaWiki 비밀 키 위키 식별·설정 보존에 필요
caddy_data 발급된 TLS 인증서, 개인 키, Caddy 실행 상태 평소 보존하되 Lesson 기준 데이터는 아님
caddy_config Caddy 실행 설정 저장소와 공개 hostname으로 다시 생성 가능

백업 스크립트는 앞의 세 볼륨만 저장합니다. 이 세 항목이 Lesson 복구 세트입니다. caddy_datacaddy_config는 평소 재시작 때 남겨 두되, 버전이 있는 위키 백업에 섞지 않습니다. 이 볼륨이 없어지면 DNS와 외부 80/443이 정상일 때 Caddy가 인증서를 다시 받을 수 있습니다. 일반 운영에서는 docker compose down --volumes를 쓰지 마세요.

저장소에는 다시 만들 수 있는 코드, 템플릿, 양식이 있습니다. 자격 증명이 든 .env는 추적하지 않으며 일반 백업 아카이브에도 넣지 않습니다. 서버 담당자가 복구용 사본을 따로 보관하되 Git이나 공개 아카이브에는 넣지 마세요.

서버 .env에는 MCP 쓰기 토큰의 해시만 있습니다. 전달용 원문 토큰이 든 mode 0600 ~/.config/s3-research-memory/client.env도 최소 한 곳에 보관하세요. 원문 토큰을 모두 잃었다면 ./scripts/configure-mcp-token.sh --rotate로 새 토큰을 만들고 쓰기 클라이언트에 다시 전달합니다. 이 작업 중에도 공개 조회는 계속됩니다.

백업

저장소 밖의 절대 경로를 사용합니다. 가능하면 Docker 호스트와 다른 디스크를 선택하고, 서버 담당자만 읽고 쓸 수 있게 만듭니다.

install -d -m 0700 /srv/s3rm-backups
docker compose stop mcp-http
./scripts/backup.sh /srv/s3rm-backups
docker compose up -d mcp-http

먼저 mcp-http를 멈추면 에이전트 변경 경로가 닫힙니다. 백업 스크립트는 DB를 기다린 뒤 mediawiki와 실행 중인 bootstrap을 멈춰 브라우저 변경도 막습니다. 이어서 MariaDB 논리 덤프를 만들고 업로드·설정 볼륨을 묶습니다. 실패해도 exit trap이 스크립트가 관리한 서비스를 백업 전 상태로 돌립니다. mcp-http는 명시적으로 멈췄으므로 성공하거나 원인을 확인한 실패 뒤에도 마지막 up 명령을 실행해야 합니다.

모든 파일의 형식과 checksum을 확인한 뒤에만 시각이 붙은 최종 디렉터리를 공개합니다. 덤프나 근거 아카이브를 저장소에 넣지 않습니다. 끝에 출력되는 복구 디렉터리의 정확한 경로를 기록하세요.

복구 디렉터리는 다음 파일을 한 세트로 가집니다.

파일 내용
database.sql.gz 설정된 MediaWiki DB 전체 논리 덤프
mediawiki-images.tar.gz 업로드·근거 볼륨의 numeric-owner 아카이브
mediawiki-config.tar.gz 생성된 설정과 위키 키의 numeric-owner 아카이브
metadata.txt 형식 버전, DB 이름, 페이지·revision 수, 소스 revision, 이미지 참조, Compose 파일 해시
SHA256SUMS 앞의 네 payload checksum

기본 대상, 각 복구 디렉터리, 모든 파일의 권한은 0700 또는 0600입니다. 기존 대상에 group/other 접근 비트가 하나라도 있으면 스크립트가 거부하며 권한을 임의로 바꾸지 않습니다. 백업할 때 db는 실행 중이어야 합니다. 위키가 원래 정지 상태였다면 그대로 두고, 실행 중이었다면 API가 다시 healthy가 될 때까지 기다린 뒤 성공을 알립니다. 복원도 소스 디렉터리에 같은 권한 검사를 합니다.

기본 로컬 대상에 저장하려면 경로를 생략합니다.

docker compose stop mcp-http
./scripts/backup.sh
docker compose up -d mcp-http

기본 로컬 경로만 장기 보관에 사용하지 마세요. 완료된 디렉터리 전체를 접근이 제한된 외부 저장소에 복사합니다. 공개 메모가 주 내용이더라도 백업에는 사용자 정보, 삭제·이전 revision, 생성된 비밀 키가 있으므로 공개하지 않습니다.

백업 확인

스크립트가 실패하면 그 백업은 사용할 수 없습니다. 성공한 뒤에도 다음을 확인합니다.

  1. DB 덤프, 설정·이미지 아카이브, 메타데이터, checksum 파일이 모두 있는지 확인합니다.
  2. 스크립트가 출력한 checksum 명령을 실행합니다. ```bash (cd /ABS/PATH/TO/BACKUP-DIRECTORY && \ sha256sum --check --strict SHA256SUMS) ```
  3. 빈 파일이 없는지, 시각과 소스 버전이 맞는지 확인합니다.
  4. 디렉터리 전체를 한 단위로 복사합니다. 서로 다른 시각의 파일을 섞지 마세요.
  5. 아래의 격리 복원 시험을 정기적으로 실행합니다. checksum은 전송 무결성만 확인하며 실제 복원 가능성을 보장하지 않습니다.

MediaWiki 백업 안내도 DB와 파일을 함께 보관하도록 안내합니다. XML 페이지 내보내기는 보조 이동본으로 쓸 수 있지만 사용자 계정, 모든 로그, 업로드 메타데이터, 사이트 전체 상태를 담지 않으므로 이 복구 세트를 대신할 수 없습니다.

권장 주기

파일럿에서는 다음 주기로 시작합니다.

  • 매일 백업, 14일 보관
  • 매주 백업, 8주 보관
  • 이미지·의존성 업데이트나 자격 증명 변경 전 백업
  • 분기마다 격리 복원 시험

실제 복구 시점 목표는 운영 상황에 맞게 정합니다. 스케줄러 종료 상태와 디스크 여유 공간을 확인하세요. 오류 알림이 없는 예약 명령만으로는 충분하지 않습니다. 새 복원을 확인하기 전에 가장 최근의 정상 백업을 지우지 마세요.

Cloudflare R2 자동 백업

이 서버는 다음 비공개 R2 bucket의 restic prefix를 원격 백업 저장소로 사용합니다.

https://96f01030a087d07d906bff299d260155.r2.cloudflarestorage.com/s3rm-backups

백업 데이터는 restic이 서버에서 먼저 암호화한 뒤 전송합니다. R2 Access Key, Secret Key와 restic 암호는 Git이나 프로젝트 .env에 넣지 않습니다.

서버에 restic을 설치한 뒤 root 권한으로 설정 파일을 준비합니다.

sudo install -d -m 0700 /etc/s3-research-memory /srv/s3rm-backups
sudo install -m 0600 config/remote-backup.env.example \
  /etc/s3-research-memory/remote-backup.env
sudo sh -c 'umask 077; openssl rand -base64 48 > /etc/s3-research-memory/restic-password'
sudoedit /etc/s3-research-memory/remote-backup.env

R2에서 s3rm-backups bucket에만 목록 조회·읽기·쓰기·삭제가 가능한 S3 API 자격 증명을 만들고 설정 파일의 두 placeholder를 바꿉니다. 삭제 권한은 오래된 restic snapshot과 pack을 보존 정책에 맞게 정리할 때 필요합니다. restic 암호 파일은 서버 장애 때도 찾을 수 있도록 서버 밖의 비밀번호 관리자에 따로 보관합니다. 이 암호를 잃으면 R2의 백업을 복구할 수 없습니다.

초기 운영에서는 R2 bucket lock이나 별도 lifecycle 삭제 규칙을 켜지 않습니다. 두 기능은 restic의 forget·prune과 충돌할 수 있습니다. 첫 원격 복원 시험을 마친 뒤 별도 삭제 방지 정책을 설계합니다.

원격 저장소는 한 번만 초기화합니다.

sudo bash -c '
  set -a
  source /etc/s3-research-memory/remote-backup.env
  set +a
  exec /home/mrcha033/Projects/s3wiki/scripts/init-remote-backup.sh
'

systemd 단위를 설치하고 첫 백업을 수동으로 확인합니다.

sudo install -m 0644 deploy/systemd/s3rm-remote-backup.service \
  /etc/systemd/system/s3rm-remote-backup.service
sudo install -m 0644 deploy/systemd/s3rm-remote-backup.timer \
  /etc/systemd/system/s3rm-remote-backup.timer
sudo systemctl daemon-reload
sudo systemctl start s3rm-remote-backup.service
sudo systemctl status s3rm-remote-backup.service
sudo systemctl enable --now s3rm-remote-backup.timer
systemctl list-timers s3rm-remote-backup.timer

작업은 매일 서울 시각 03:15 이후 45분 안에 실행합니다. 성공한 원격 snapshot은 일간 14개와 주간 8개를 보존하고, 원격 pack 정리는 일요일에 실행합니다. 전송이나 검증이 실패하면 로컬 복구 세트를 지우지 않습니다. 성공하면 R2에 이미 암호화된 snapshot을 확인한 뒤 /srv/s3rm-backups의 해당 임시 세트를 정리합니다.

상태와 최근 로그를 정기적으로 확인합니다.

systemctl status s3rm-remote-backup.timer
sudo journalctl -u s3rm-remote-backup.service --since '2 days ago'

원격 snapshot을 복구할 때는 빈 root 전용 디렉터리에 먼저 내려받고 기존 복원 스크립트로 넘깁니다.

sudo install -d -m 0700 /srv/s3rm-remote-restore
sudo bash -c '
  set -a
  source /etc/s3-research-memory/remote-backup.env
  set +a
  restic snapshots --tag s3rm-recovery-set
  restic restore latest --tag s3rm-recovery-set --target /srv/s3rm-remote-restore
'
sudo find /srv/s3rm-remote-restore -maxdepth 2 -type f -name SHA256SUMS -print

출력된 SHA256SUMS의 상위 디렉터리가 한 개이고 원하는 시각의 복구 세트인지 확인한 뒤 scripts/restore.sh <그 디렉터리> --yes를 사용합니다. 운영 서버를 덮어쓰기 전에 격리 복원 시험을 먼저 수행합니다.

복원 전 주의

scripts/restore.sh는 현재 DB, 업로드, 생성된 위키 설정을 교체합니다. 명시적인 --yes가 필요하며, 공지한 점검 시간에만 실행합니다. 병합이나 페이지 가져오기 도구가 아닙니다.

복원 전에 다음을 확인합니다.

  • 정확한 백업 디렉터리를 정하고 모든 checksum을 확인합니다.
  • 백업의 MediaWiki·애플리케이션 버전이 현재 checkout과 호환되는지 확인합니다. 새 DB를 더 오래된 코드에 복원할 수 없습니다.
  • 점검 시간을 알리고 mcp-http를 멈춘 뒤 브라우저 편집도 중단합니다.
  • 현재 상태를 읽을 수 있으면 복원 직전 백업을 하나 더 만듭니다.
  • .env에 복원할 인스턴스와 맞는 자격 증명이 있는지 확인합니다.
  • 복원을 결정한 사람과 이유를 기록합니다.

현재 서버 복원

백업을 만든 것과 같은 저장소 버전에서 실행합니다.

docker compose stop mcp-http
./scripts/restore.sh /ABS/PATH/TO/BACKUP-DIRECTORY --yes

스크립트는 checksum manifest, 백업 형식 버전, 압축 stream, 모든 아카이브 member의 경로와 종류를 먼저 확인합니다. 백업의 DB 이름과 MARIADB_DATABASE도 같아야 합니다. 다르면 덤프를 편집하지 말고 복구용 .env를 맞춥니다. 이 검증과 이미지 빌드 사전 확인이 모두 끝난 뒤에만 애플리케이션을 멈추고 세 영구 항목을 교체합니다.

mediawiki 시작 때 MediaWiki·확장 기능 마이그레이션을 적용하고, 이어서 반복 실행이 가능한 bootstrap을 실행합니다. 교체 경고가 나온 뒤에는 중단하지 마세요. 오류가 나오면 클라이언트를 멈춘 상태로 로그와 소스 백업을 보존합니다. 실패한 상태 위에 부분 SQL이나 일부 볼륨을 임의로 덮어쓰지 마세요.

완료 뒤 상태를 확인합니다.

docker compose ps -a
docker compose logs mediawiki bootstrap

아래 MediaWiki 복구 확인을 마칠 때까지 mcp-http를 멈춰 둡니다. 확인 뒤 현재 설정으로 공용 어댑터를 다시 만들고, 공개 조회와 토큰 기반 변경을 모두 시험합니다.

docker compose up -d --force-recreate mcp-http
docker compose ps mcp-http
docker compose logs --tail=100 mcp-http

격리 복원 시험

실제 서버를 덮어쓰지 말고 별도 Compose 프로젝트와 사용하지 않는 포트에서 시험합니다. 별도 checkout을 사용하고, 복구 디렉터리는 이동하지 말고 복사합니다. Compose 프로젝트와 볼륨 이름을 고유하게 지정하세요. 최상위 이름은 COMPOSE_PROJECT_NAME으로 바꿀 수 있으며 두 스크립트가 이 값을 사용합니다. COMPOSE 환경 변수에는 docker compose --ansi never처럼 고정 접두사를 넣을 수 있습니다. 설치, 백업, 복원에 같은 값을 사용하세요.

Docker가 설치된 일회용 VM에서는 다음 순서가 안전합니다.

  1. 백업과 정확히 같은 저장소 revision, 복구 디렉터리, 복구용 .env를 VM에 복사합니다.
  2. COMPOSE_PROFILES=로 실제 hostname과 80/443을 사용하지 않게 합니다. 겹치지 않는 S3RM_HTTP_PORT와 맞는 로컬 MW_SERVER_URL을 설정합니다. 별도 loopback S3RM_MCP_HTTP_PORT·S3RM_MCP_PUBLIC_URL과 일회용 MCP 토큰도 사용합니다. 실제 MCP URL이나 토큰을 복원 시험에 쓰지 마세요.
  3. VM에서 scripts/restore.sh <backup-directory> --yes를 실행합니다.
  4. 아래 복구 확인을 모두 수행합니다.
  5. 결과를 기록한 뒤 VM을 지웁니다. 원본 복구 세트는 그대로 둡니다.

docker compose configdocker volume ls에서 볼륨 이름이 다른지 보기 전에는 COMPOSE_PROJECT_NAME만 바꿨다고 격리된 것으로 보지 마세요.

복구 완료 확인

다음 항목을 모두 통과해야 복원이 끝납니다.

  1. dbmediawiki가 healthy이고 bootstrap이 코드 0으로 종료되었습니다.
  2. Special:Version에 예상한 MediaWiki, Semantic MediaWiki, Page Forms, S3 Research Memory 버전이 표시됩니다.
  3. Lesson 페이지 수와 최근 revision 수가 백업 기록과 맞습니다.
  4. 복원된 Lesson의 필드, 근거, 관계, 출처, 호환 필드, 시간이 정상 표시됩니다.
  5. 역사 보기에서 이전 revision 하나 이상이 열립니다.
  6. 업로드한 근거가 열리고, 외부 checksum을 기록했다면 값이 맞습니다.
  7. 전문 검색이 알려진 제목과 본문 단어를 찾습니다.
  8. 격리한 복원 시험 환경에서만 일반 브라우저 계정으로 Lesson 양식을 열고 복구 확인용 메모를 저장합니다. 바로 검색되는지 본 뒤 격리 환경과 함께 폐기합니다.
  9. 다시 만든 mcp-http가 healthy입니다. 토큰 없이 초기화·도구 목록· search_lessons를 실행하면 짧은 인용 결과가 나옵니다. 쓰기 토큰을 넣은 클라이언트는 같은 격리 환경에 확인용 메모를 만들 수 있습니다. 운영 위키에는 확인용 데이터를 만들지 않습니다.
  10. 따로 설정한 두 번째 클라이언트가 같은 Lesson을 조회합니다. 두 클라이언트가 로컬 데이터가 아닌 복원된 위키 하나를 보고 있어야 합니다.
  11. MCP 계정은 여전히 삭제, 이동, 보호, 관리 기능을 사용할 수 없습니다.

복구 디렉터리, 소요 시간, 애플리케이션 revision, 결과, 실행자, 필요했던 조치를 기록합니다. 하나라도 실패하면 점검 상태를 유지합니다.

평소 상태 확인

상태와 제한된 길이의 로그를 확인합니다.

docker compose ps -a
docker compose logs --tail=200 db mediawiki bootstrap mcp-http caddy

로컬 프로세스 경로와 두 공개 경로를 차례로 확인합니다. 로컬 확인만으로 다른 PC의 HTTPS 접속을 대신할 수 없습니다.

curl --fail --silent --show-error \
  'http://localhost:8080/api.php?action=query&meta=siteinfo&format=json' \
  >/dev/null
curl --fail --silent --show-error \
  'http://127.0.0.1:8765/healthz' \
  >/dev/null
curl --fail --silent --show-error \
  'https://s3wiki.yonsei.ac.kr/api.php?action=query&meta=siteinfo&format=json' \
  >/dev/null

S3RM0의 토큰 없는 MCP 초기화도 https://s3wiki.yonsei.ac.kr/mcp에서 실행합니다. 단순 GET /mcp는 streaming 연결을 계속 열어 둘 수 있으므로 상태 확인이 아닙니다.

같은 서버에서 위 확인을 한 번에 실행하려면 make verify-domain을 사용합니다. 이 결과만으로 학교 밖 인바운드 경로까지 확인되지는 않습니다.

MediaWiki 작업 queue가 늘어나면 한가한 시간에 제한된 수만 실행합니다.

docker compose exec mediawiki \
  php maintenance/run.php runJobs --maxjobs 100

Special:RecentChanges, 계정 그룹, 로그인 실패, MCP 쓰기 인증 실패와 403/421, 디스크 여유 공간, 백업 시각, 복원 시험 상태를 확인합니다. bootstrap이 관리하는 스키마·양식 페이지가 반복해서 달라지면 원인을 찾으세요. 일반 Lesson revision은 bootstrap이 바꾸지 않습니다.

공용 MCP 운영

mcp-http에는 영구 지식이 없습니다. 정지하거나 다시 만들면 진행 중인 도구 호출이 끊기고 클라이언트가 재연결해야 하지만 Lesson이나 revision은 없어지지 않습니다.

docker compose stop mcp-http
docker compose up -d mcp-http
docker compose up -d --force-recreate mcp-http
docker compose ps mcp-http

일시적인 프로세스 오류에는 restart를 사용합니다. 토큰 해시, 공개 URL, bind·port, allowlist, 위키 자격 증명, 이미지를 바꿨다면 --force-recreate를 사용합니다. 공개 mcp-http 복제본을 여러 개 띄우지 마세요. 현재 서비스에는 load balancer나 session 공유 설계가 없습니다. 읽기 요청은 재연결 뒤 다시 시도해도 됩니다. 시간이 초과된 변경 요청은 결과를 먼저 확인한 뒤 다시 보내세요.

공개 HTTPS

Caddy는 Compose domain 프로필에서 실행하며 공개 포트를 사용합니다.

docker compose ps caddy
docker compose logs --tail=200 caddy
docker compose up -d --force-recreate caddy
make verify-domain

S3RM_PUBLIC_HOST나 저장소의 Caddyfile을 바꾼 뒤 Caddy를 다시 만듭니다. 인증서 발급을 다시 시도하려고 caddy_data를 지우지 마세요. 먼저 s3wiki.yonsei.ac.kr165.132.118.220을 가리키는지, 다른 프로세스가 80/443을 쓰는지, 두 포트가 외부에서 서버까지 들어오는지 확인합니다. Caddy는 원래 Host 헤더를 보존하며 MCP는 이를 S3RM_MCP_PUBLIC_URL=https://s3wiki.yonsei.ac.kr/mcp와 대조합니다. 학교 밖 네트워크의 브라우저 확인도 별도로 해야 합니다.

공용 MCP 토큰 교체

이 파일럿은 토큰 해시 하나만 받으므로 교체 시 모든 쓰기 클라이언트의 기존 토큰이 한 번에 무효가 됩니다. 공개 조회는 계속됩니다. 변경이 잠시 끊긴다고 알리고 새 서비스 확인이 끝날 때까지 기존 client.env를 보관하세요.

  1. 원문을 출력하지 않고 새 토큰과 해시를 만듭니다. ```bash ./scripts/configure-mcp-token.sh --rotate ``` 스크립트는 .env의 해시만 바꾸고, 원문 토큰과 URL은 mode 0600 ~/.config/s3-research-memory/client.env에 씁니다. --rotate가 없으면 기존 토큰과 해시가 맞는지 확인하고 그대로 둡니다.
  2. 공용 어댑터만 다시 만듭니다. ```bash docker compose up -d --force-recreate mcp-http docker compose ps mcp-http docker compose logs --tail=100 mcp-http ```
  3. 토큰 없이 초기화, 도구 목록, search_lessons(limit=1)을 확인합니다. 이어서 신뢰하는 셸에서 새 비공개 파일을 불러오고 S3RM0의 쓰기 확인을 실행합니다.
  4. 새 원문 토큰 또는 클라이언트 환경을 쓰기 클라이언트에 전달하고 재연결합니다. 공개 조회 클라이언트는 바꿀 것이 없습니다. DB·위키 비밀번호와 쓸 수 없는 토큰 해시가 든 서버 .env는 전달하지 마세요.

새 서비스를 확인하기 전에 문제가 생겼다면 이전 해시와 그에 맞는 비공개 토큰을 복구하고 mcp-http를 다시 만듭니다. 변경 인증을 끄는 방식으로 되돌리지 마세요.

애플리케이션 업데이트와 되돌리기

업데이트 전에 이름을 붙인 백업을 만들고 복원을 시험합니다. 새 이미지를 빌드하고 DB 마이그레이션과 bootstrap을 완료한 뒤 복구 완료 항목을 확인합니다. 새 release가 DB를 마이그레이션했다면 이미지만 낮춰서는 안 됩니다. 이전 저장소 revision과 함께 업데이트 전 DB, 업로드, 설정을 한 세트로 복원해야 합니다.

기본 제약은 MediaWiki 복원 안내업그레이드 안내를 참고하세요.