세션 요약

이사장님과 함께 가비아 클라우드 서버(sakyowon-server)를 신청부터 DNS 전환까지 하루 만에 구축 완료했다. 이제 sakyowon.co.kr의 모든 정적 사이트와 신청·문의 API가 지미(본부 GCP)·GitHub Pages 없이 사교원 자체 서버에서 서빙된다. 같은 날 앞서 망남마을학교를 세대별 3교실(연두=청소년 스킴보드캠프 / 파란=청년 / 푸른=장년 강사양성)로 재편하고 신청폼을 자체 서버 API로 연결했다.

1. 가비아 자체 서버 (핵심 성과)

서버 정보

  • 가비아 클라우드 콘솔: console.gabiacloud.com — 그룹 “사회혁신교육원 사회적협동조합의 클라우드” → 프로젝트 Project
  • 서버: sakyowon-server, Ubuntu 22.04.5 LTS, Standard 2vCore/8GB/50GB, 월 74,250원(VAT별도)
  • 공인 IP: 1.201.116.225 / 접속: ssh root@1.201.116.225 (비밀번호는 이사장님 보관, 채팅 노출분은 전부 교체 완료)
  • 보안 그룹: 인바운드 22(SSH)·80(HTTP)·443(HTTPS)만 개방, 3389 삭제함

서버 구성 (설치 완료·검증 통과)

Caddy(443/80, HTTPS 자동인증서)
 ├─ /api/*  → FastAPI(127.0.0.1:8787, systemd: sakyowon-api) → SQLite(/opt/sakyowon/data/sakyowon.db)
 └─ 그 외   → 정적 파일(/opt/sakyowon/www)
  • /opt/sakyowon/: server(FastAPI)·data(DB)·www(정적)·www-home(본진용, 아직 빈 폴더)·apps(Node용, 아직 빈 폴더)·src(배포 레포 클론)
  • 관리자 키: 서버 /etc/sakyowon-api.envSAKYOWON_ADMIN_KEY (setup.sh가 자동 생성)
  • 신청 조회: https://sakyowon.co.kr/api/applications.csv?key=관리자키 (CSV 다운로드)

배포 레포 (서버가 pull 받는 곳)

  • deka2026/sakyowon-server (공개): app.py, setup.sh(API 설치), deploy-www.sh(정적 일괄배치), setup-caddy.sh(Caddy 설치), Caddyfile, systemd 유닛들, README/MIGRATION
  • 캐노니컬 원본은 haeory-cyber/sakyowon-site의 server/ 폴더. 양쪽에 같은 내용 유지 필요 (수정 시 둘 다 푸시)

DNS (가비아 DNS 관리)

  • @·www A레코드 → 1.201.116.225 (TTL 600). 기존 GitHub Pages A(185.199.x)·CNAME 삭제
  • 하이웍스 메일(MX 2개·TXT SPF)은 그대로 유지 — 절대 건드리지 말 것

운영 명령 (서버 root에서)

  • 사이트 내용 갱신: bash /opt/sakyowon/src/deploy-www.sh (공개 레포들 다시 클론해 www 갱신)
  • 배포 스크립트 갱신: git -C /opt/sakyowon/src pull
  • API 상태: systemctl status sakyowon-api / 로그: journalctl -u sakyowon-api -n 30
  • 헬스: curl -s http://127.0.0.1:8787/api/health

최종 검증 결과 (2026-08-19 19:20 KST)

  • 허브·mangnam-coop(3교실 포함)·hometown-love·academy·teamlearning·sakyowon-wiki 전부 200
  • HTTPS 인증서 자동 발급 확인, www도 200
  • 신청 API 저장 성공: 테스트 신청 APP-260819-192036-434 (이름 “데카테스트” — 실데이터 아님, 삭제 대상)

2. 망남마을학교 3교실 재편 (mangnam-coop)

  • /village-school = 3교실 안내 허브, 사이드바·홈 카드 반영
  • 연두교실(/teen, lime): 청소년 스킴보드 캠프 2박3일 — 첨부 hwpx 기반
  • 파란교실(/youth, sea): 기존 청년 프로그램 이전. 화~금 3박4일, 1기 20명, 첫날 오후3시 망남리 집결(교통편 삭제), 고립·은둔→청년 일반화
  • 푸른교실(/senior, teal): 스킴보드 강사양성 1박2일 — 첨부 PDF 기반. 운영예산표는 대외 비공개 처리함
  • 신청폼 3종 모두 같은 출처 /api/applications로 전송 (site=mangnam-coop, program=teen/youth/senior). 관리자 페이지는 GET /api/applications?key= 조회로 전환
  • Apps Script 백엔드는 폐기(레포에 파일은 남아있으나 미사용). 지미 앞 재배포 요청도 취소 편지로 정리함
  • gh-pages 배포는 유지 중(main 푸시 후 수동으로 out/→gh-pages). 단 이제 실서빙은 가비아이므로 앞으로는 deploy-www.sh 재실행이 본선

3. 서버 코드 (app.py) 기능

  • POST /api/applications (신청, name·phone 필수, 나머지 자유 — raw JSON 보존)
  • GET /api/applications?key=[&program=&site=] / .csv 내보내기
  • POST/GET /api/inquiries (사교원 본진 문의폼 호환)
  • POST/GET /api/feedback
  • AI 재구현: /api/ai(Anthropic 메시지 프록시·스트리밍), /api/ai/chat, /api/translateSAKYOWON_ANTHROPIC_KEY env 넣으면 활성, 없으면 안내/폴백으로 무장애
  • 텔레그램 알림(선택): SAKYOWON_TG_TOKEN/SAKYOWON_TG_CHAT

레슨

  1. 가비아 서버 생성 시 함정: 공인 IP 기본값이 “미할당”이고, “할당”을 눌러도 “보유 IP 없음”이면 IP가 안 붙는다 — “신규 IP 생성”까지 선택해야 한다. 보안그룹에 HTTP 80이 기본으로 없다(443·22·3389만).
  2. 서버 생성 직후 SSH가 Connection closed로 끊기면 초기화가 덜 끝난 것 — 몇 분 기다리면 된다. root 비번은 이메일로 온다.
  3. apt upgrade 중 openssh-server 설정 질문이 나오면 반드시 “keep the local version” — maintainer’s version을 고르면 비밀번호 SSH 로그인이 막힐 수 있다.
  4. needrestart 대화창 때문에 스크립트가 10분+ 멈출 수 있다NEEDRESTART_MODE=a DEBIAN_FRONTEND=noninteractive를 앞에 붙여 재실행하면 뚫린다.
  5. 비공개 레포는 서버에서 clone 불가 — 서버에 자격증명을 넣지 말고, 서버 코드·정적 산출물을 공개 레포(deka2026/sakyowon-server, sakyowon-wiki-site)로 미러링하는 방식을 썼다.
  6. root가 sakyowon 소유 폴더의 git을 만지면 dubious ownershipgit config --global --add safe.directory <경로>로 해결.
  7. DNS 전환 직후 HTTPS가 TLS internal error면 인증서 발급 중이라는 뜻 — 80/443이 열려 있으면 1~2분 내 자동 해결된다.
  8. 초보자와 SSH 작업 시: 비밀번호는 password: 프롬프트에서만 입력(PowerShell 프롬프트에 붙이면 명령으로 실행됨), 여러 줄 붙여넣기는 ^M 찌꺼기를 만드니 한 줄씩.

미완료 (다음 세션)

  1. 테스트 신청 삭제 (데카): DB의 APP-260819-192036-434 행 — 서버에서 sqlite3 /opt/sakyowon/data/sakyowon.db "DELETE FROM applications WHERE id='APP-260819-192036-434';" (sqlite3 미설치면 apt install -y sqlite3 먼저) 또는 관리자 조회에서 무시.
  2. 서버 재부팅 1회 (이사장님, 한가할 때): 새 커널(5.15.0-190) 적용 — reboot 한 줄, 서비스는 자동 복구.
  3. 2단계 — Node 앱 2개 (데카 안내 + 이사장님 실행): mangnam-vitality(:3100)·bid-helper(:3200)를 vitality./bid.sakyowon.co.kr 서브도메인으로. Node LTS 설치→빌드→systemd→Caddy 블록 추가→DNS A레코드 2개 추가. bid는 비공개 레포라 미러 전략 필요 + G2B 공공데이터 키 별도. 데이터(app.db) 스냅샷은 지미에게 인계 요청 필요.
  4. 3단계 — 사교원 본진home.sakyowon.co.kr로: sakyowon-site 정적 HTML을 www-home에 배치(Caddyfile 블록은 이미 준비됨, DNS home A레코드 추가). AI 활성화하려면 사교원 Anthropic 키를 /etc/sakyowon-api.envSAKYOWON_ANTHROPIC_KEY에 추가systemctl restart sakyowon-api.
  5. 지미에게 알림 편지 (데카): sakyowon.co.kr DNS가 가비아로 전환됨 — 본부 서빙이전 로드맵(CF 네임서버 이전 등) 재조정 필요. hometown-love 정기갱신 크론도 이제 가비아 서버 crontab에 걸 수 있음(지미 등록 대기 건 대체 가능).
  6. 위키 갱신 자동화 검토 (데카): sakyowon-wiki 내용 갱신 시 현재는 데카 빌드→sakyowon-wiki-site 푸시→서버 deploy-www.sh 재실행 3단계. 서버 crontab으로 자동화 가능.
  7. 백업 루틴 (데카 제안): /opt/sakyowon/data/sakyowon.db 정기 백업(crontab) 설정.