bioreport.hyooni.io 운영 가이드
바이오텍 백테스트 리서치 사이트. 폰/데스크탑에서 위키식으로 리포트를 열람하기 위한 자체 호스팅.
Summary
- URL: https://bioreport.hyooni.io
- 빌더: Quartz v4 (Obsidian vault → 정적 사이트)
- 호스팅: Cloudflare Pages (Direct Upload 모드, GitHub 연동 없음)
- 접근 제어: Cloudflare Access — Email OTP + 3명 allowlist
- 세션: 90일 (2160h). 1년까지도 가능하지만 일단 3달.
- 비용: 0원
아키텍처
projects/biolode-backtest/ (원본 리포트 — 절대 건드리지 않음)
│
▼ build-content.sh (매핑)
quartz/content/ (재배치된 사이트용 구조)
│
▼ npx quartz build
quartz/public/ (정적 HTML + 차트 + CSS)
│
▼ wrangler pages deploy
Cloudflare Pages (bioreport)
│
▼ custom domain + SSL + Access
https://bioreport.hyooni.io
배포
wiki 또는 리포트 업데이트 후:
bash /Users/martian/agents/offclaw-lucky/quartz/deploy.sh내부 동작:
build-content.sh— 원본을quartz/content/에 재배치npx quartz build— markdown → HTMLnpx wrangler pages deploy public— Cloudflare 에 업로드
배포 시간 15초. 업로드 후 cache warm 까지 약 1030초.
콘텐츠 매핑
quartz/build-content.sh 가 원본 → 사이트 구조 매핑 담당.
현재 매핑 (요약):
| 축 | 원본 | 사이트 경로 |
|---|---|---|
| 시간축 | biotech/results/v{N}/, docs/plans/v{N}-plan.md | /versions/v{N}/ |
| 시간축 | biotech/results/v51_*/, docs/reports/v51-*.md | /versions/v5.1/ |
| 주제축 | biotech/results/research_{topic}/, docs/studies/{topic}.md | /research/{topic}/ |
| 주제축 | biotech/results/grid_search_v{N}/ | /research/grid-search/v{N}/ |
| IR | docs/ir/, biotech/results/ir_report*/, notion_exports/backtest_reports_db/ | /ir/ |
| 메타 | docs/review/, docs/plans/catalyst-*, docs/ops/ | /meta/ |
제외: run_*/, auto_pipeline/ (재현 run — 시끄러움).
새 연구 추가 시
- 원본 파일을
projects/biolode-backtest/의 적절한 위치에 드롭 build-content.sh에copy한 줄 추가 (src → dest)bash deploy.sh실행
Cloudflare 설정
계정/도메인
- Account:
Gusdbs.lee@gmail.com's Account(ID:f036e01a34bc671f4fb61d19787d7e09) - Zone:
hyooni.io(ID:270a06e7a6f60d55ae40b42d451acded) - Registrar: GoDaddy (DNS 는 Cloudflare 에 위임됨)
Pages 프로젝트
- 이름:
bioreport - Mode: Direct Upload (GitHub 연동 없음)
- Default subdomain: https://bioreport.pages.dev
- Custom domain: bioreport.hyooni.io (CNAME → bioreport.pages.dev, proxied)
- SSL: 자동 (Google CA)
Access Application
- 이름:
bioreport - App ID:
66c7085c-7a6c-4a17-87fa-a27d223e0d5d - Type: self_hosted
- Domain: bioreport.hyooni.io
- Session duration:
2160h(90일) - IdP: Email OTP (
onetimepin, account default)
Allowlist 정책
martian.danoff@gmail.comgusdbs.lee@gmail.comh8627h@gmail.com
이 3개 외 이메일은 OTP 코드 받아도 거부됨.
Allowlist 변경
# Access policy 조회
source /Users/martian/agents/offclaw-lucky/.env
curl -s "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/access/apps/66c7085c-7a6c-4a17-87fa-a27d223e0d5d/policies" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" | python3 -m json.tool추가/제거는 Cloudflare Zero Trust UI 에서 하는 게 실수 적음 (Zero Trust → Access → Applications → bioreport → Policies).
Secrets
API Token 은 /Users/martian/agents/offclaw-lucky/.env 에 저장. gitignored.
CLOUDFLARE_API_TOKEN=...
CLOUDFLARE_ACCOUNT_ID=f036e01a34bc671f4fb61d19787d7e09
CLOUDFLARE_ZONE_ID_HYOONI=270a06e7a6f60d55ae40b42d451acded
토큰 scope: Pages:Edit + Access Apps and Policies:Edit + Zone.DNS:Edit + Zone:Read.
토큰 재발급은 https://dash.cloudflare.com/profile/api-tokens .
로컬 개발
실시간 미리보기 (로컬):
cd /Users/martian/agents/offclaw-lucky/quartz
bash build-content.sh
npx quartz build --serve --directory contenthttp://localhost:8080 에서 핫 리로드.
트러블슈팅
Quartz 가 Found 0 input files 로 잡음
원인: .gitignore 에 quartz/content/ 가 들어있으면 Quartz 가 discovery 에서 스킵. quartz/content/ 는 ignore 하면 안 됨.
YAML frontmatter 파싱 에러 (bad indentation of a mapping entry)
원인: related: [[a]], [[b]] 같은 Obsidian 전용 wikilink-in-YAML 은 엄격 YAML 파서가 거부. 해결: list 형식으로.
related:
- "[[a]]"
- "[[b]]"Obsidian 은 둘 다 인식함.
배포 후 폰에서 로그인 무한 루프
Cloudflare Access 쿠키 CF_AppSession 이 도메인에 맞게 설정됐는지 확인. Safari 의 사이트 간 추적 방지가 쿠키 막을 수 있음 — 개인정보 설정에서 bioreport.hyooni.io 허용.
SSL cert 발급 지연
custom domain 추가 후 CF Universal SSL 발급에 보통 1~5분, 최대 24시간. DNS 전파 + Let’s Encrypt/Google 인증 순서. 그 동안 default subdomain (bioreport.pages.dev) 은 바로 사용 가능.
한계 / 단점
- 자동 rebuild 없음 (Direct Upload 모드의 대가). 원본 수정 후
deploy.sh수동 실행 필요 .xlsx파일은 인라인 뷰 불가 — 다운로드만 가능. Quartz 가 markdown → HTML 정적 변환기라 xlsx 렌더러 없음- Obsidian Charts 플러그인 (chartjs) 미지원 — 차트는 PNG/SVG 로 export 해서 넣으면 됨
- 검색 인덱스는 build 시점 snapshot — hot-reload 안 됨
재구축 (필요시)
만약 Pages project 날리고 재생성해야 한다면:
source /Users/martian/agents/offclaw-lucky/.env
# Pages 프로젝트 생성
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"bioreport","production_branch":"main"}'
# Custom domain 연결
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/pages/projects/bioreport/domains" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" \
-d '{"name":"bioreport.hyooni.io"}'
# DNS CNAME
curl -X POST "https://api.cloudflare.com/client/v4/zones/$CLOUDFLARE_ZONE_ID_HYOONI/dns_records" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" \
-d '{"type":"CNAME","name":"bioreport","content":"bioreport.pages.dev","proxied":true,"ttl":1}'
# Access Application (allowlist + OTP)
curl -X POST "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/access/apps" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" -H "Content-Type: application/json" \
-d '{
"name":"bioreport","domain":"bioreport.hyooni.io","type":"self_hosted",
"session_duration":"2160h","auto_redirect_to_identity":false,
"policies":[{"name":"allowlist","decision":"allow","include":[
{"email":{"email":"martian.danoff@gmail.com"}},
{"email":{"email":"gusdbs.lee@gmail.com"}},
{"email":{"email":"h8627h@gmail.com"}}
]}]
}'
# 첫 배포
cd /Users/martian/agents/offclaw-lucky/quartz
bash deploy.sh관련 파일
quartz/quartz.config.ts— 사이트 메타 (타이틀, baseUrl, 테마)quartz/build-content.sh— 원본 → 사이트 구조 매핑quartz/deploy.sh— build + deploy 오케스트레이터/Users/martian/agents/offclaw-lucky/.env— Cloudflare API token (gitignored)projects/biolode-backtest/docs/ops/bioreport-site.md— 이 문서
참고 링크
- Quartz: https://quartz.jzhao.xyz
- Cloudflare Pages: https://developers.cloudflare.com/pages
- Cloudflare Access: https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/self-hosted-public-app/
- Wrangler CLI: https://developers.cloudflare.com/workers/wrangler/commands/#pages