diff --git a/AIRGAP_DEPLOY.md b/AIRGAP_DEPLOY.md new file mode 100644 index 0000000..04660b9 --- /dev/null +++ b/AIRGAP_DEPLOY.md @@ -0,0 +1,159 @@ +# 폐쇄망 반입·구동 가이드 (Python venv, 컨테이너 미사용) + +서버관리망이 컨테이너 없이 **Python 가상환경**으로 구동하는 환경일 때의 반입 절차. +핵심은 **소스 + wheelhouse(오프라인 .whl 묶음)** 를 매체로 들고 들어가 거기서 venv로 설치·실행하는 것. + +> 정적 자산(pico·htmx·Pretendard·JetBrains Mono)은 이미 `app/static/`에 동봉돼 있어 **런타임 인터넷 불필요**. +> 외부 의존은 Python 패키지(pip)뿐 → 이걸 wheelhouse로 해결한다. + +--- + +## 0. 사전 확인 (가장 중요) + +폐쇄망 **타깃 서버**에서 Python 버전·아키텍처를 확인한다. wheel은 이 값에 맞춰 받아야 한다. +```bash +python3 --version # 예: Python 3.12.x → cp312 +uname -m # 예: x86_64 +``` +- 타깃 Python이 **3.11/3.12** 등이면 wheelhouse도 그 버전으로 받아야 한다(컴파일 wheel: pydantic-core, psycopg 등). +- 가능하면 **타깃과 같은 OS/파이썬**(예: Rocky9 + python3.12)에서 wheelhouse를 만드는 게 가장 안전하다. + +--- + +## 1. 인터넷 되는 곳에서 산출물 준비 + +**(a) 소스** — git 메타·가상환경 제외하고 압축 +```bash +git archive --format=tar.gz -o pulp-console-src.tgz HEAD +# (또는 repo 폴더에서 .git/.venv/tests 빼고 zip) +``` + +**(b) wheelhouse** — 타깃 Python/플랫폼에 맞춰 다운로드 +```bash +# 타깃과 동일 환경(권장): +pip download -r requirements.txt -d vendor/ + +# 빌드 머신과 타깃이 다르면 플랫폼/버전 명시: +pip download -r requirements.txt -d vendor/ \ + --only-binary=:all: --implementation cp \ + --platform manylinux2014_x86_64 --python-version 312 +``` +`vendor/`에 모든 의존성 .whl이 모인다. (개수 확인: `ls vendor | wc -l`) + +> 참고: `uvicorn[standard]`는 uvloop/httptools/watchfiles 등 컴파일 wheel을 포함한다. 버전 매칭이 +> 까다로우면 `requirements.txt`의 `uvicorn[standard]`를 `uvicorn`(순정)으로 바꿔 wheel 세트를 줄일 수 있다 +> (운영은 `--reload` 안 쓰므로 watchfiles 불필요). + +--- + +## 2. 반입 매체에 담을 것 + +- `pulp-console-src.tgz` (소스 — 정적자산 포함) +- `vendor/` (wheelhouse) +- `boknet-ca.pem` (사내 HTTPS Pulp 검증용 CA) +- 환경변수 값 메모: `PULP_BASE_URL` / `PULP_USERNAME` / `PULP_PASSWORD` / `DATABASE_URL` + (비밀번호는 안전한 방법으로) + +--- + +## 3. 폐쇄망에서 설치·구동 + +```bash +mkdir -p /opt/pulp-console && cd /opt/pulp-console +tar xzf /media/pulp-console-src.tgz # 소스 풀기 +cp -r /media/vendor ./vendor # wheelhouse 복사 + +python3 -m venv .venv +.venv/bin/pip install --no-index --find-links vendor -r requirements.txt +``` + +환경변수(`.env` 또는 systemd) 설정 후 실행 — **운영은 `--reload` 금지**: +```bash +PULP_BASE_URL=https://repo.서버관리망:8080 \ +PULP_USERNAME=admin PULP_PASSWORD='***' \ +PULP_VERIFY_TLS=true PULP_CA_FILE=/opt/pulp-console/boknet-ca.pem \ +DATABASE_URL='postgresql://...' \ +.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 +``` + +--- + +## 4. 상시 구동 (systemd 예시) + +`/etc/systemd/system/pulp-console.service`: +```ini +[Unit] +Description=Pulp 패치 관리 콘솔 +After=network.target + +[Service] +WorkingDirectory=/opt/pulp-console +EnvironmentFile=/opt/pulp-console/.env +ExecStart=/opt/pulp-console/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port 8000 +Restart=on-failure +User=pulpconsole + +[Install] +WantedBy=multi-user.target +``` +```bash +sudo systemctl daemon-reload && sudo systemctl enable --now pulp-console +``` +`.env`(권한 600)에 `PULP_*`, `DATABASE_URL`, `PULP_CA_FILE` 등 기입. + +--- + +## 5. 구동 확인 + +```bash +curl 127.0.0.1:8000/healthz # {"ok": true} (앱 생존) +curl 127.0.0.1:8000/pulp-status # Pulp 연결 배지 (실패 시 사유) +``` +브라우저로 대시보드 접속 → 실제 저장소 목록 확인. 연동 검증은 `PULP_INTEGRATION.md §5` 체크리스트 참고. + +--- + +## 6. 업데이트(다음 버전 반입) + +- 소스만 바뀌면: 새 `pulp-console-src.tgz`만 반입해 교체 후 `systemctl restart pulp-console`. +- 의존성이 바뀌면(`requirements.txt` 변경): `vendor/`에 새 wheel도 함께 반입 후 `pip install --no-index --find-links vendor -r requirements.txt` 재실행. + +--- + +## venv / pip 가 없을 때 (대안) + +venv는 필수가 아니다. **필요한 건 Python 인터프리터 하나**뿐. 점점 더 미니멀한 순서: + +**① venv만 없음 — `pip --target` + PYTHONPATH** +```bash +python3 -m pip install --no-index --find-links vendor --target ./libs -r requirements.txt +PYTHONPATH=./libs python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8000 +``` + +**② pip도 없음 — pip wheel 부트스트랩** (반입물에 `pip-*.whl` 포함: `pip download pip -d vendor/`) +```bash +python3 vendor/pip-*.whl/pip install --no-index --find-links vendor --target ./libs -r requirements.txt +# wheel 은 zip 이라 설치 없이 바로 실행됨. (또는 python3 -m ensurepip) +``` + +**③ pip 자체가 불가 — wheel 압축해제 + PYTHONPATH** (pip 0개) +```bash +mkdir libs && cd libs +for w in ../vendor/*.whl; do unzip -oq "$w"; done # wheel=zip, 컴파일 .so 포함 +cd .. && PYTHONPATH=./libs python3 -m uvicorn app.main:app --host 0.0.0.0 --port 8000 +``` + +**④ Python 자체가 없음 — 독립 실행형 Python 반입** +- python-build-standalone(astral-sh) tarball을 풀어 그 안의 `bin/python3`로 ①~③ 수행. + 단, 그 Python 버전에 맞춰 wheelhouse를 받을 것(§0). + +systemd 로 상시 구동 시 `ExecStart`를 위 실행 커맨드로 바꾸면 된다 +(예: `Environment=PYTHONPATH=/opt/pulp-console/libs` + `ExecStart=/usr/bin/python3 -m uvicorn ...`). + +--- + +## 폐쇄망에 이미 있어야 하는 것 +- **Python 3.x** (타깃 버전 — §0). venv/pip 없어도 위 대안으로 가능. +- **Pulp 서버** (붙는 대상, 이미 존재) +- **Postgres** (감사 로그용; 없으면 배포는 되나 "감사 로그 기록 실패" 경고) +- **사내 CA(.pem)** (HTTPS Pulp 검증)