Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

172 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

BookOasis (뢁 μ˜€μ•„μ‹œμŠ€)

No Build Vanilla JS No Framework Native Python Zero Dependencies AGPLv3

English Version (README_EN.md)

뢁 μ˜€μ•„μ‹œμŠ€λŠ” ZIP/CBZ μ••μΆ• 파일 ν˜•νƒœμ˜ λ„μ„œ 및 λ§Œν™”μ±…μ„ μ›Ή ν™˜κ²½μ—μ„œ μ§€μ—° 없이 감상할 수 μžˆλ„λ‘ μ„€κ³„λœ μ΄ˆκ²½λŸ‰, κ³ μ„±λŠ₯ 개인 λ―Έλ””μ–΄ μ„œλ²„μž…λ‹ˆλ‹€.

μ„œλ“œνŒŒν‹° 쒅속성을 κ·Ήλ„λ‘œ μ΅œμ†Œν™”ν•˜κ³  파이썬 ν‘œμ€€ 라이브러리의 잠재λ ₯을 ν™œμš©ν•˜μ—¬ 가볍고 λΉ λ₯Έ ꡬ동 ν™˜κ²½μ„ μ œκ³΅ν•©λ‹ˆλ‹€.


μ£Όμš” νŠΉμ§•

  • 파일 λ¬΄ν•΄μ œ μ‹€μ‹œκ°„ 슀트리밍

    • λŒ€μš©λŸ‰ μ••μΆ• 파일(ZIP/CBZ)을 μ„œλ²„ 디렉터리에 미리 μ••μΆ• ν•΄μ œν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.
    • λ‚΄μž₯ zipfile λͺ¨λ“ˆμ„ μ œμ–΄ν•˜μ—¬ ν•„μš”ν•œ νŽ˜μ΄μ§€μ˜ 물리적 λ°”μ΄νŠΈ μ‹œμž‘ μ˜€ν”„μ…‹λ§Œ 읽어 슀트리밍 μ „μ†‘ν•˜λ―€λ‘œ λ””μŠ€ν¬ I/O와 CPU μ†Œλͺ¨λ₯Ό ν˜μ‹ μ μœΌλ‘œ μ ˆκ°ν•©λ‹ˆλ‹€.
  • λ―Έλ‹ˆλ©€ν•œ 쒅속성

    • Flask ν”„λ ˆμž„μ›Œν¬ 외에 무거운 ORMμ΄λ‚˜ μ„œλ“œνŒŒν‹° λͺ¨λ“ˆμ„ λ°°μ œν–ˆμŠ΅λ‹ˆλ‹€.
    • λ‚΄μž₯ SQLite λͺ¨λ“ˆμ— κ³ μ„±λŠ₯ 컀λ„₯μ…˜ 풀링과 μ •λ°€ 쿼리λ₯Ό μž…ν˜€ μ„±λŠ₯ μ €ν•˜ μ—†λŠ” μ΄ˆκ²½λŸ‰ μ•„ν‚€ν…μ²˜λ₯Ό μ‹€ν˜„ν–ˆμŠ΅λ‹ˆλ‹€.
  • μ΅œμ ν™”λœ ν”„λ‘ νŠΈμ—”λ“œ νŒŒμ΄ν”„λΌμΈ

    • 뷰포트 λ‚΄ μΉ΄λ“œλ§Œ λ‘œλ“œν•˜λŠ” μ§€μ—° λ‘œλ”©(Lazy Loading) 및 λ‹€μŒ νŽ˜μ΄μ§€ ν”„λ¦¬λ‘œλ”©(Preloading)을 μ§€μ›ν•˜μ—¬ λŠκΉ€ μ—†λŠ” λ…μ„œ κ²½ν—˜μ„ 보μž₯ν•©λ‹ˆλ‹€.
  • μœ μ—°ν•œ 메타데이터 ν”ŒλŸ¬κ·ΈμΈ

    • ν”ŒλŸ¬κ·ΈμΈ μ•„ν‚€ν…μ²˜λ₯Ό λ‚΄μž₯ν•˜μ—¬ κ΅­λ‚΄ ν™˜κ²½μ— νŠΉν™”λœ μ•ŒλΌλ”˜ Open API λ“±μ˜ μ™ΈλΆ€ 정보 μˆ˜κΈ‰ 채널을 ν”ŒλŸ¬κ·ΈμΈ ν˜•νƒœλ‘œ μ œμ–΄ν•©λ‹ˆλ‹€.
    • μ±… μ†Œκ°œκΈ€, μž‘κ°€ 정보, κ³ ν™”μ§ˆ 컀버λ₯Ό μ›ν΄λ¦­μœΌλ‘œ 톡합 λ°˜μ˜ν•˜λ©° μˆ˜λ™ 메타데이터 νŽΈμ§‘κΈ° 및 ν‘œμ§€ ꡐ체λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
  • λͺ¨λ°”일 λ·°μ–΄ ν˜Έν™˜

    • μ™ΈλΆ€ λ·°μ–΄ μ• ν”Œλ¦¬μΌ€μ΄μ…˜ 연동을 μœ„ν•œ OPDS κ·œκ²©μ„ μ§€μ›ν•˜λ©°, λ°μ΄ν„°λ² μ΄μŠ€ 인증정보 기반의 Basic Authentication λ³΄μ•ˆ 처리λ₯Ό μ μš©ν–ˆμŠ΅λ‹ˆλ‹€.

🎨 4μ»· λ§Œν™”λ‘œ λ³΄λŠ” BookOasis ꡬ동 원리

BookOasisκ°€ λŒ€μš©λŸ‰(10만 ꢌ 이상) ν™˜κ²½μ—μ„œλ„ λ²„λ²…μž„ 없이 μ΄ˆκ΄‘μ†μœΌλ‘œ λ™μž‘ν•˜λŠ” λΉ„λ°€μž…λ‹ˆλ‹€!

BookOasis ꡬ동 원리

  • μ΄ˆκ³ μ† μŠ€μΊλ„ˆ: λ„μ„œμ˜ μ••μΆ•νŒŒμΌμ„ ν•΄μ œν•˜μ§€ μ•Šκ³  μ΅œμ†Œ μ˜€ν”„μ…‹λ§Œ 읽어 μˆœμ‹κ°„μ— 메타데이터λ₯Ό μΆ”μΆœν•΄ DB에 μ‹œλ”©ν•©λ‹ˆλ‹€.
  • μ§€μ—°(Lazy) μŠ€μΊλ„ˆ: μš©λŸ‰μ΄ 큰 λ§Œν™”μ±… ZIP 파일 등은 λ¬΄λ¦¬ν•˜κ²Œ μ¦‰μ‹œ νŒŒμ‹±ν•˜μ§€ μ•Šκ³  λ°±κ·ΈλΌμš΄λ“œμ—μ„œ λ‚˜λ₯Έν•˜κ²Œ 비동기 μ²˜λ¦¬ν•˜μ—¬ 메인 λ™μž‘μ˜ 렉을 μ°¨λ‹¨ν•©λ‹ˆλ‹€.

λŒ€μ‹œλ³΄λ“œ ν™”λ©΄

BookOasis Dashboard


μ‹œμž‘ν•˜κΈ°

μƒμ„Έν•œ ν™˜κ²½ ꡬ성 및 μ„€μΉ˜ 방법은 기술 λ¬Έμ„œλ₯Ό μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.

이벀트 μ›Ήν›…(book.new, book.read, book.finish)은 포맷별 μ§„ν–‰λ₯  μ œμ•½μ„ λ°˜μ˜ν•©λ‹ˆλ‹€. EPUB/TXTλŠ” 물리 νŽ˜μ΄μ§€κ°€ κ³ μ •λ˜μ§€ μ•Šμ•„ totalPagesκ°€ null일 수 있으며, μˆ˜μ‹  μΈ‘μ—μ„œλŠ” progress(0~100)λ₯Ό μš°μ„  μ²˜λ¦¬ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

κ°„νŽΈ ꡬ동 (Docker)

  1. μ„€μ • ν…œν”Œλ¦Ώ 볡사 둜컬 ν™˜κ²½ 고유 섀정을 μœ„ν•΄ μ œκ³΅λ˜λŠ” μ˜€λ²„λΌμ΄λ“œ ν…œν”Œλ¦Ώ νŒŒμΌμ„ λ³΅μ‚¬ν•©λ‹ˆλ‹€.

    cp docker-compose.override.example.yml docker-compose.override.yml
  2. λ³Όλ₯¨ 경둜 μˆ˜μ • μƒμ„±λœ docker-compose.override.yml νŒŒμΌμ„ μ—΄μ–΄ 본인의 μ‹€μ œ μ±…/λ§Œν™”μ±… 라이브러리 디렉토리 경둜둜 μˆ˜μ •ν•©λ‹ˆλ‹€.

    services:
      bookoasis:
        volumes:
          - /μ‹€μ œ/μ±…/μ €μž₯/경둜:/data/comics:ro
  3. μ»¨ν…Œμ΄λ„ˆ μ‹€ν–‰

    docker compose up -d --build

Tip: docker-compose.override.yml은 .gitignore에 λ“±λ‘λ˜μ–΄ μžˆμœΌλ―€λ‘œ ν–₯ν›„ ν”„λ‘œμ νŠΈ μ†ŒμŠ€κ°€ μ—…λ°μ΄νŠΈλ˜μ–΄ git pull을 받아도 μ‚¬μš©μžμ˜ 개인 경둜 μ„€μ • 파일이 μΆ©λŒμ„ μΌμœΌν‚€κ±°λ‚˜ μœ μ‹€λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

λ³΄μ•ˆ 정책에 따라 운영자용 배포/μ—…λ°μ΄νŠΈ μ ˆμ°¨λŠ” λΉ„κ³΅κ°œ λ‚΄λΆ€ λ¬Έμ„œλ‘œ κ΄€λ¦¬ν•©λ‹ˆλ‹€.

직접 ꡬ동 (Native Python)

🐧 Linux / macOS ν™˜κ²½

# κ°€μƒν™˜κ²½ ν™œμ„±ν™” 및 쒅속성 μ„€μΉ˜
python -m venv venv
source venv/bin/activate
pip install -r requirements.txt

# μ„€μ • 파일 ꡬ성
# .env λ‚΄ SECRET_KEY ν•­λͺ©μ— μžμ‹ λ§Œμ˜ μž„μ˜μ˜ κΈ΄ λ¬Έμžμ—΄μ„ μž…λ ₯ν•˜μ—¬ λ³΄μ•ˆ κ³ μ • ν‚€λ₯Ό μƒμ„±ν•©λ‹ˆλ‹€.
# 이 ν‚€λ₯Ό κ³ μ •ν•΄ μ£Όμ‹œλ©΄ μ„œλ²„ 기동 ν”„λ‘œμ„ΈμŠ€κ°€ μž¬μ‹œμž‘λ˜λ”λΌλ„ μ‚¬μš©μž μ„Έμ…˜(둜그인 μƒνƒœ)이 풀리지 μ•Šκ³  μ•ˆμ „ν•˜κ²Œ μœ μ§€λ©λ‹ˆλ‹€.

# μ„œλ²„ 기동
python core.py
  • κΈ°λ³Έ λ™μž‘: 도컀 μ™Έ ν™˜κ²½μ—μ„œλŠ” μŠ€μΊλ„ˆ μ›Œμ»€κ°€ μžλ™μœΌλ‘œ ν•¨κ»˜ κΈ°λ™λ˜μ–΄ 큐 λŒ€κΈ°μ—΄(pending)을 μ²˜λ¦¬ν•©λ‹ˆλ‹€.
  • ν•„μš” μ‹œ λΉ„ν™œμ„±ν™”: BOOKOASIS_ENABLE_EMBEDDED_WORKER=0 python core.py

πŸͺŸ Windows ν™˜κ²½

μœˆλ„μš° ν™˜κ²½μ—μ„œλŠ” 마우슀 더블클릭 ν•œ 번으둜 ꡬ동 디렉토리 생성 및 νŒ¨ν‚€μ§€ μ„€μΉ˜λΆ€ν„° ν”„λ‘œλ•μ…˜ μˆ˜μ€€μ˜ μ›Ή μ„œλ²„(waitress) μ‹€ν–‰κΉŒμ§€ μžλ™μœΌλ‘œ 원클릭 μ…‹μ—…ν•΄ μ£ΌλŠ” 배치 νŒŒμΌμ„ μ œκ³΅ν•©λ‹ˆλ‹€.

  1. .env.example νŒŒμΌμ„ λ³΅μ‚¬ν•˜μ—¬ .env 파일둜 이름 λ³€κ²½ ν›„ ν•„μš”ν•œ μ„€μ • μž…λ ₯.(SECURITY_KEY)
  2. ν”„λ‘œμ νŠΈ 루트의 run_windows.bat νŒŒμΌμ„ 마우슀 λ”λΈ”ν΄λ¦­ν•˜μ—¬ 기동.
  • run_windows.batλŠ” μ›Ή μ„œλ²„μ™€ μŠ€μΊλ„ˆ μ›Œμ»€λ₯Ό ν•¨κ»˜ κΈ°λ™ν•˜λ„λ‘ κ΅¬μ„±λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

  • 둜컬 포트: http://localhost:5930


πŸ’Ύ Redis μΊμ‹œ 연동 및 μ„±λŠ₯ κ°€μ΄λ“œ (선택 및 ꢌμž₯)

BookOasisλŠ” μ‹€μ‹œκ°„ λ…μ„œ 진행도 μ €μž₯ μ‹œ SQLite νŒŒμΌμ— λ°”λ‘œ μ ‘κ·Όν•˜μ§€ μ•Šκ³  인메λͺ¨λ¦¬(RAM) μΊμ‹œλ‘œ μ™„μΆ©ν•΄ μ£ΌλŠ” Redis ν•˜μ΄λΈŒλ¦¬λ“œ μΊμ‹œ λͺ¨λ“œλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€. 이λ₯Ό 톡해 λ””μŠ€ν¬ μ“°κΈ° 병λͺ©μ΄ κ²©κ°ν•˜κ³  μŠ€μΊ” μ€‘μ˜ DB 손상(Malformed) ν˜„μƒμ΄ μ™„λ²½νžˆ λ°©μ§€λ©λ‹ˆλ‹€.

🐳 Docker μ‚¬μš©μžμ˜ 경우 (μ™„μ „ μžλ™)

  • docker-compose.yml ν…œν”Œλ¦Ώμ— redis:7-alpine 이미지 연동이 λ‚΄μž₯λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.
  • .env νŒŒμΌμ„ μˆ˜μ •ν•  ν•„μš” 없이 docker compose up -d λͺ…λ Ήμ–΄ ν•˜λ‚˜λ‘œ μ „μš© λ ˆλ””μŠ€κ°€ μΌœμ§€κ³  격리 λ„€νŠΈμ›Œν¬ μƒμ—μ„œ μ™„μ „νžˆ μžλ™μœΌλ‘œ 톡합 μ—°λ™λ©λ‹ˆλ‹€.
  • μ»¨ν…Œμ΄λ„ˆ μ’…λ£Œ μ‹œ μΊμ‹œκ°€ μœ μ‹€λ˜μ§€ μ•Šλ„λ‘ stop_grace_period이 1m(1λΆ„)으둜 상ν–₯ μ§€μ •λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

πŸ–₯️ Native Python (Linux / Windows) μ‚¬μš©μžμ˜ 경우

  1. 호슀트 OS에 λ ˆλ””μŠ€ μ„œλ²„λ₯Ό μ„€μΉ˜ 및 κΈ°λ™ν•©λ‹ˆλ‹€. (Ubuntu μ˜ˆμ‹œ: sudo apt install redis-server -y)
  2. .env 파일 ν•˜λ‹¨μ— 접속 URL을 κΈ°μž¬ν•΄ μ€λ‹ˆλ‹€.
    REDIS_URL=redis://127.0.0.1:6379/9
    • Tip: λ‹€λ₯Έ κΈ°μ‘΄ μ„œλΉ„μŠ€μ™€ λ ˆλ””μŠ€λ₯Ό κ³΅μœ ν•˜λŠ” 경우, DB 번호λ₯Ό /9번 λ“± λ‹€λ₯Έ 인덱슀둜 μ§€μ •ν•˜λ©΄ 좩돌이 μ „ν˜€ μ—†μŠ΅λ‹ˆλ‹€. λͺ¨λ“  데이터 ν‚€ μ•žμ— bookoasis: λ„€μž„μŠ€νŽ˜μ΄μŠ€κ°€ κ°•μ œ μ§€μ •λ©λ‹ˆλ‹€.
  3. λ ˆλ””μŠ€κ°€ μ€€λΉ„λ˜μ§€ μ•Šμ•˜κ±°λ‚˜ 접속에 μ‹€νŒ¨ν•˜λ©΄ μžλ™μœΌλ‘œ 기쑴의 SQLite 직접 μ“°κΈ° λͺ¨λ“œλ‘œ 우회(Fallback) ν•˜λ―€λ‘œ μ•ˆμ‹¬ν•˜κ³  μ‚¬μš©ν•˜μ…”λ„ λ©λ‹ˆλ‹€.

πŸ”‘ 초기 둜그인 및 계정 정보

  • 졜초 μ„œλ²„ ꡬ동 ν›„ 둜그인 μ‹œ μ•„λž˜μ˜ κ΄€λ¦¬μž 계정을 μ‚¬μš©ν•˜μ—¬ 접속할 수 μžˆμŠ΅λ‹ˆλ‹€.
    • μ‚¬μš©μž 이름(ID): admin
    • λΉ„λ°€λ²ˆν˜Έ: admin
  • λ³΄μ•ˆ ꢌμž₯: 첫 둜그인 ν›„ μ¦‰μ‹œ [μ„€μ •] > [계정 관리] νƒ­μ—μ„œ κ΄€λ¦¬μž λΉ„λ°€λ²ˆν˜Έλ₯Ό λ³€κ²½ν•΄ μ£Όμ„Έμš”.

πŸ›‘οΈ ν”„λ‘μ‹œ 헀더 인증 (Proxy Header Auth / SSO) κ°€μ΄λ“œ

ν•΄μ™Έ ν™ˆλž© μœ μ € 및 OIDC 연동을 μœ„ν•΄ Proxy Header Auth (λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ μžλ™ 둜그인) κΈ°λŠ₯을 μ§€μ›ν•©λ‹ˆλ‹€. Authelia, Authentik λ“± μ•žλ‹¨μ˜ λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ 인증 μ„œλ²„κ°€ 검증을 마치고 μ „λ‹¬ν•˜λŠ” HTTP 헀더(Remote-User λ˜λŠ” X-Forwarded-User) 값을 μ‹ λ’°ν•˜μ—¬ μžλ™μœΌλ‘œ BookOasis에 둜그인(SSO)μ‹œν‚¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

Caution

μ‹¬κ°ν•œ λ³΄μ•ˆ κ²½κ³  이 κΈ°λŠ₯은 λ°˜λ“œμ‹œ Nginx, Authelia λ“± λ¦¬λ²„μŠ€ ν”„λ‘μ‹œκ°€ 헀더λ₯Ό λ³€μ‘° 및 λ³΄ν˜Έν•˜λŠ” 폐쇄망 ν™˜κ²½μ—μ„œλ§Œ ν™œμ„±ν™”ν•΄μ•Ό ν•©λ‹ˆλ‹€! ν”„λ‘μ‹œ 없이 인터넷에 개방된 μƒνƒœμ—μ„œ 이 μ˜΅μ…˜μ„ μΌ€ 경우, μ•…μ˜μ μΈ μ‚¬μš©μžκ°€ 헀더 μ‘°μž‘(예: Remote-User: admin)만으둜 κ΄€λ¦¬μž κΆŒν•œμ„ νƒˆμ·¨ν•  수 μžˆλŠ” μ‹¬κ°ν•œ 취약점이 λ©λ‹ˆλ‹€. μœ„ν—˜μ„±μ„ μΆ©λΆ„νžˆ μΈμ§€ν•œ λΆ„λ§Œ μ‚¬μš©ν•˜μ„Έμš”.

μ„€μ • 방법:

  1. μ–΄λ“œλ―Ό κ³„μ •μœΌλ‘œ 둜그인 ν›„ 일반 μ„€μ • 메뉴에 μ§„μž…ν•©λ‹ˆλ‹€.
  2. μŠ€ν¬λ‘€μ„ λ‚΄λ € Proxy Header Auth (λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ μžλ™ 둜그인) ν•­λͺ©μ„ μ°Ύμ•„ ν† κΈ€ν•©λ‹ˆλ‹€.
  3. 섀정을 μ €μž₯ν•œ λ’€, μ•žλ‹¨μ˜ Nginx/ν”„λ‘μ‹œ μ„œλ²„κ°€ μ˜¬λ°”λ₯Έ μ‚¬μš©μžλͺ… 헀더λ₯Ό BookOasis 둜 λ„˜κ²¨μ£Όλ„λ‘ κ΅¬μ„±ν•˜μ‹­μ‹œμ˜€.

선택 λ³΄μ•ˆ μ˜΅μ…˜ (ꢌμž₯):

  • PROXY_HEADER_TRUSTED_IPS: ν”„λ‘μ‹œ 원본 IP/CIDR ν™”μ΄νŠΈλ¦¬μŠ€νŠΈ (예: 127.0.0.1,10.0.0.0/8,192.168.0.0/16)
    • 이 값이 μ„€μ •λ˜λ©΄, ν™”μ΄νŠΈλ¦¬μŠ€νŠΈμ— μ—†λŠ” μ†ŒμŠ€ IPμ—μ„œ μ „λ‹¬λœ Remote-User/X-Forwarded-User ν—€λ”λŠ” λ¬΄μ‹œλ©λ‹ˆλ‹€.
  • PROXY_HEADER_DENY_DIRECT: 1둜 μ„€μ • μ‹œ, ν”„λ‘μ‹œ 헀더가 μ—†λŠ” 직접 접속을 κ±°λΆ€ (reverse proxy 경유 κ°•μ œ)

μœ„ μ˜΅μ…˜μ€ DB μ„€μ •(settings ν…Œμ΄λΈ”) λ˜λŠ” ν™˜κ²½λ³€μˆ˜(.env)둜 μ„€μ •ν•  수 μžˆμŠ΅λ‹ˆλ‹€. DB 섀정값이 μš°μ„  μ μš©λ©λ‹ˆλ‹€.


Nginx μ„€μ • κ°€μ΄λ“œ

  1. μ „μ—­ μ„€μ • (nginx.conf) μ—…λ°μ΄νŠΈ Cloudflareλ₯Ό ν†΅ν•˜λŠ” μš”μ²­μ€ 일반적인 μš”μ²­λ³΄λ‹€ 헀더 크기(μΏ ν‚€, 인증 토큰, ν”„λ‘μ‹œ 헀더 λ“±)κ°€ 훨씬 λΉ„λŒ€ν•©λ‹ˆλ‹€. Nginx의 κΈ°λ³Έ 헀더 버퍼 크기가 μž‘μœΌλ©΄ μ„œλ²„κ°€ μš”μ²­μ„ κ±°λΆ€ν•˜κ³  400 Bad Request λ˜λŠ” 414 Request-URI Too Large μ—λŸ¬λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

이λ₯Ό λ°©μ§€ν•˜κΈ° μœ„ν•΄ /etc/nginx/nginx.conf 파일의 http { ... } 블둝 내뢀에 μ•„λž˜ 섀정을 λ°˜λ“œμ‹œ μΆ”κ°€ν•˜κ±°λ‚˜ ν™•μž₯ν•΄ μ£Όμ„Έμš”.

http {
    # ------------------------------------------------------------------
    # [Cloudflare 및 λŒ€μš©λŸ‰ 헀더 λŒ€μ‘] 버퍼 크기 λŒ€ν­ ν™•μž₯
    # μΏ ν‚€ 및 인증 헀더가 κΈΈμ–΄μ§ˆ λ•Œ λ°œμƒν•˜λŠ” 4XX μ—λŸ¬λ₯Ό μ›μ²œ μ°¨λ‹¨ν•©λ‹ˆλ‹€.
    # ------------------------------------------------------------------
    client_header_buffer_size 16k;
    large_client_header_buffers 4 64k;

    # ------------------------------------------------------------------
    # ν”„λ‘μ‹œ 헀더 ν•΄μ‹œ 크기 μ΅œμ ν™”
    # λ‹€μˆ˜μ˜ λ³΅μž‘ν•œ X-Forwarded-* 헀더가 μœ μž…λ˜μ–΄λ„ ν•΄μ‹œ ν…Œμ΄λΈ” μ˜€λ²„ν”Œλ‘œμš°κ°€ λ‚˜μ§€ μ•Šλ„λ‘ ν•©λ‹ˆλ‹€.
    # ------------------------------------------------------------------
    proxy_headers_hash_max_size 1024;
    proxy_headers_hash_bucket_size 128;

    # (기쑴의 λ‹€λ₯Έ μ„€μ •λ“€...)
}
  1. BookOasis 가상 호슀트 μ„€μ • (sites-available) /etc/nginx/sites-available/default 파일(λ˜λŠ” 가상 호슀트 μ„€μ • 블둝)에 μ•„λž˜ λ‚΄μš©μ„ μž‘μ„±ν•˜κ³ , sites-enabled에 심볼릭 링크λ₯Ό κ±Έμ–΄ μ μš©ν•©λ‹ˆλ‹€.
# ------------------------------------------------------------------
# λ°±μ—”λ“œ 영ꡬ 컀λ„₯μ…˜ ν’€ μ„€μ • (μ†ŒμΌ“ 생성 μ§€μ—° 0ms)
# ------------------------------------------------------------------
upstream bookoasis_backend {
    server 127.0.0.1:5930;
    keepalive 64; # 64개 λ°±μ—”λ“œ 컀λ„₯μ…˜μ„ 영ꡬ μœ μ§€ν•˜μ—¬ μ—°κ²° μ†Œλͺ¨ λ°©μ§€
}

server {
    listen 80;
    server_name your-domain.com; # <== 본인의 λ„λ©”μΈμœΌλ‘œ λ³€κ²½ν•˜μ„Έμš”.

    # HTTP둜 λ“€μ–΄μ˜€λŠ” μš”μ²­μ„ HTTPS둜 κ°•μ œ λ¦¬λ‹€μ΄λ ‰νŠΈ (λ³΄μ•ˆ)
    if ($http_x_forwarded_proto = "http") {
        return 301 https://$host$request_uri/;
    }

    # ------------------------------------------------------------------
    # Gzip ν…μŠ€νŠΈ 및 SVG μ••μΆ• μ„€μ • (UI 및 JSON API 가속)
    # ------------------------------------------------------------------
    gzip on;
    gzip_disable "msie6";
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;

    # 메타데이터 ν”ŒλŸ¬κ·ΈμΈ 및 λŒ€μš©λŸ‰ 파일 μ—…λ‘œλ“œλ₯Ό κ³ λ €ν•œ λ°”λ”” 크기 μ œν•œ
    client_max_body_size 100M;

    # ------------------------------------------------------------------
    # λ³΄μ•ˆ 헀더 μ£Όμž…
    # ------------------------------------------------------------------
    add_header X-Frame-Options "SAMEORIGIN" always;         # ν΄λ¦­μž¬ν‚Ή λ°©μ§€
    add_header X-Content-Type-Options "nosniff" always;     # MIME μŠ€λ‹ˆν•‘ λ°©μ§€
    add_header Referrer-Policy "no-referrer-when-downgrade" always;

    # ------------------------------------------------------------------
    # 1. 컀버 이미지 λΌμš°νŒ… μ΅œμ ν™”
    # ------------------------------------------------------------------
    # 1-1. 동적 SVG 컀버 생성 API (λ°±μ—”λ“œ 파이썬으둜 전달)
    location /covers/fallback {
        proxy_pass http://bookoasis_backend;
        proxy_set_header Host $http_host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;
    }

    # 1-2. 컀버 이미지 정적 μ„œλΉ™ μ΅œμ ν™” (파이썬 우회 λ‹€μ΄λ ‰νŠΈ 0ms μ„œλΉ™)
    location /covers/ {
        alias /path/to/media_server/covers/; # <== 본인의 μ„€μΉ˜ 경둜/covers/ 둜 λ³€κ²½ν•˜μ„Έμš”.
        expires 1d;
        add_header Cache-Control "public, max-age=86400";
        sendfile on;
        tcp_nopush on;
    }

    # ------------------------------------------------------------------
    # 2. 일반 API 및 메인 μ›Ή μ„œλΉ„μŠ€ (WebSocket 지원)
    # ------------------------------------------------------------------
    location / {
        proxy_pass http://bookoasis_backend/;

        # [κΈ°λ³Έ ν”„λ‘μ‹œ 헀더 μ„€μ •]
        proxy_set_header Host $http_host; 
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $http_x_forwarded_proto;

        # [WebSocket 및 HTTP/1.1 ν”„λ‘œν† μ½œ μ—…κ·Έλ ˆμ΄λ“œ 지원]
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";

        # [CRITICAL] λŒ€μš©λŸ‰ 파일 전솑 μ΅œμ ν™” (ν”„λ‘μ‹œ 버퍼링 끔)
        proxy_buffering off;

        # [νƒ€μž„μ•„μ›ƒ ν™•μž₯] λŒ€μš©λŸ‰ μŠ€μΊ” ν”„λ‘œμ„ΈμŠ€ 및 μž₯μ‹œκ°„ μž‘μ—… λŒ€μ‘
        proxy_read_timeout 300;
        proxy_connect_timeout 300;
        proxy_send_timeout 300;
    }
}

Caddy μ„€μ • κ°€μ΄λ“œ

Nginx λŒ€μ‹  Caddyλ₯Ό λ¦¬λ²„μŠ€ ν”„λ‘μ‹œλ‘œ μ‚¬μš©ν•˜λŠ” 경우 μ•„λž˜μ™€ 같이 Caddyfile을 κ΅¬μ„±ν•˜μ—¬ μ΅œμ ν™” 및 연동을 μ§„ν–‰ν•  수 μžˆμŠ΅λ‹ˆλ‹€. CaddyλŠ” μžλ™μœΌλ‘œ SSL μΈμ¦μ„œ(HTTPS)λ₯Ό λ°œκΈ‰ 및 관리해주며, WebSocketκ³Ό λ¦¬λ²„μŠ€ ν”„λ‘μ‹œ 헀더 처리λ₯Ό κΈ°λ³Έ λ‚΄μž₯ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

/etc/caddy/Caddyfile νŒŒμΌμ— 본인의 도메인을 λ§€ν•‘ν•˜μ—¬ λ‹€μŒκ³Ό 같이 λ‚΄μš©μ„ κ΅¬μ„±ν•©λ‹ˆλ‹€.

your-domain.com { # <== 본인의 λ„λ©”μΈμœΌλ‘œ λ³€κ²½ν•˜μ„Έμš”.
    # ------------------------------------------------------------------
    # Gzip 및 Zstd ν…μŠ€νŠΈ μ••μΆ• μ„€μ • (UI 및 JSON API 가속)
    # ------------------------------------------------------------------
    encode gzip zstd

    # ------------------------------------------------------------------
    # μ΅œλŒ€ λ°”λ”” 크기 μ œν•œ (Nginx client_max_body_size 100M λŒ€μ‘)
    # μ•ŒλΌλ”˜ 메타데이터 ν”ŒλŸ¬κ·ΈμΈ λ“± 컀버 이미지 μ—…λ‘œλ“œλ₯Ό κ³ λ €ν•œ ν•œλ„μž…λ‹ˆλ‹€.
    # ------------------------------------------------------------------
    request_body {
        max_size 100mb
    }

    # ------------------------------------------------------------------
    # 메인 μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜ ν”„λ‘μ‹œ λΌμš°νŒ…
    # ------------------------------------------------------------------
    reverse_proxy 127.0.0.1:5930 {
        # [CRITICAL] λŒ€μš©λŸ‰ 파일 전솑 μ΅œμ ν™” (ν”„λ‘μ‹œ 버퍼링 λΉ„ν™œμ„±ν™”)
        # BookOasis의 핡심 κΈ°λŠ₯인 'μ˜€ν”„μ…‹ 기반 μ‹€μ‹œκ°„ 슀트리밍'이 ν”„λ‘μ‹œ 버퍼에
        # κ°€λ‘œλ§‰νžˆμ§€ μ•Šκ³  μ¦‰μ‹œ μ „μ†‘λ˜λ„λ‘ μ„€μ •ν•©λ‹ˆλ‹€.
        flush_interval -1
    }
}

λ³€κ²½ μ™„λ£Œ ν›„ sudo systemctl reload caddy λͺ…령을 톡해 Caddy 섀정을 κ°±μ‹ ν•©λ‹ˆλ‹€.

λΌμ΄μ„ μŠ€ 및 μƒν‘œκΆŒ 정보

  • μ˜€ν”ˆμ†ŒμŠ€ λΌμ΄μ„ μŠ€: λ³Έ ν”„λ‘œμ νŠΈλŠ” GNU AGPLv3 (Affero General Public License v3.0) κ·œκ²©μ„ λ”°λ¦…λ‹ˆλ‹€. λˆ„κ΅¬λ‚˜ μ†ŒμŠ€ μ½”λ“œλ₯Ό μ—΄λžŒ, μˆ˜μ •, 배포할 수 있으며, 이 μ†Œν”„νŠΈμ›¨μ–΄λ₯Ό 기반으둜 ν•œ μ„œλΉ„μŠ€(λ„€νŠΈμ›Œν¬λ₯Ό ν†΅ν•œ μ„œλΉ„μŠ€ 포함)λ₯Ό μ œκ³΅ν•  경우 λ°˜λ“œμ‹œ μˆ˜μ •λœ μ†ŒμŠ€ μ½”λ“œλ₯Ό λ™μΌν•œ AGPLv3 λΌμ΄μ„ μŠ€λ‘œ κ³΅κ°œν•΄μ•Ό ν•©λ‹ˆλ‹€. μžμ„Έν•œ 약관은 LICENSE νŒŒμΌμ„ μ°Έμ‘°ν•˜μ‹­μ‹œμ˜€.
  • μƒν‘œκΆŒ 보호 κ°€μ΄λ“œλΌμΈ: "BookOasis" λͺ…μΉ­ 및 κ΄€λ ¨ 곡식 둜고 μ΄λ―Έμ§€λŠ” μ›μž‘μžμ˜ 고유 식별 μƒν‘œ(Trademark)둜 λ³΄ν˜Έλ©λ‹ˆλ‹€. λ³Έ ν”„λ‘œκ·Έλž¨μ„ 포크(Fork) 및 λ³€κ²½ν•˜μ—¬ 재배포 μ‹œ 원본 μ†ŒμŠ€μ½”λ“œμ˜ μ €μž‘κΆŒ ν‘œκΈ°λŠ” μ„±μ‹€νžˆ μ€€μˆ˜ν•˜λ˜, λ™μΌν•œ λͺ…μΉ­("BookOasis")κ³Ό 곡식 둜고λ₯Ό μ œν’ˆλͺ…에 μ‚¬μš©ν•˜μ—¬ μž¬λ°°ν¬ν•  수 μ—†μœΌλ©° λ°˜λ“œμ‹œ 이름을 λ‹€λ₯΄κ²Œ λ³€κ²½ν•˜μ—¬ μ‹λ³„λ˜λ„λ‘ ν•΄μ•Ό ν•©λ‹ˆλ‹€.

Copyright Β© 2026 leeyj (Carls, leeyj78@gmail.com). All rights reserved.

About

A lightweight, high-performance alternative to Kavita, Komga, and Stump for streaming books and comics (ZIP/CBZ/EPUB/PDF) directly from remote storage

Topics

Resources

Stars

Watchers

Forks

Releases

Sponsor this project

Packages

Contributors

Languages