From 9eb295e2dc9b1f2f444c93d14f9fa5dc0470cc5e Mon Sep 17 00:00:00 2001 From: kjh2064 Date: Fri, 26 Jun 2026 11:05:16 +0900 Subject: [PATCH] =?UTF-8?q?docs:=20=ED=81=B4=EB=9D=BC=EC=9A=B0=EB=93=9C=20?= =?UTF-8?q?=EC=84=9C=EB=B2=84(hz-prod-01)=20=EC=84=A4=EC=A0=95=20=ED=95=98?= =?UTF-8?q?=EB=84=A4=EC=8A=A4=20=EA=B0=80=EC=9D=B4=EB=93=9C=20=EC=8B=A0?= =?UTF-8?q?=EA=B7=9C=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - docs/CLOUD_SERVER_SETUP.md 신규 생성 - 서버 기본 정보 (Ubuntu 26.04, AMD EPYC-Rome 2C, 3.7GiB) - 서비스 아키텍처: Nginx, Gitea, QuantEngine Blazor, PostgreSQL 18 - Docker Compose v5.2.0 기반 Gitea 설정 전문 - .NET 10 (ASP.NET Core 10.0.9) systemd 서비스 설정 전문 - 6x Gitea Act Runner CI 컨테이너 현황 - 보안: SSH hardening, UFW 방화벽, fail2ban, 네트워크 격리 - 시놀로지 → 클라우드 마이그레이션 매핑표 - 운영 명령 치트시트 및 검증 하네스 - 참조 인덱스(TOC) 및 관련 문서 상호 참조 - AGENTS.md Directory Routing 섹션에 문서 경로 등록 provenance: ssh kjh2064@178.104.200.7 라이브 명령 실행으로 수집 (2026-06-26) --- AGENTS.md | 1 + docs/CLOUD_SERVER_SETUP.md | 514 +++++++++++++++++++++++++++++++++++++ 2 files changed, 515 insertions(+) create mode 100644 docs/CLOUD_SERVER_SETUP.md diff --git a/AGENTS.md b/AGENTS.md index c9975f8..8d714bc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -81,6 +81,7 @@ - `tests/parity/test_routing_gate_parity_v1.py`: routing gate parity. - `.gitea/workflows/qualitative_sell_strategy.yml`: qualitative sell strategy workflow. - `.gitea/workflows/snapshot_admin.yml`: snapshot admin workflow and scheduled validation. +- `docs/CLOUD_SERVER_SETUP.md`: 클라우드 서버(hz-prod-01, 178.104.200.7) 설정 하네스 가이드. 시놀로지 → 클라우드 마이그레이션 매핑 포함. - `docs/GITEA_SECRETS_SETUP.md`: Gitea secrets setup and verification guide. - `docs/GATHERTRADINGDATA_XLSX_OPERATING_RUNBOOK.md`: `GatherTradingData.xlsx` 보조 자산 런북. - `docs/ROADMAP_WBS.md`: `.gs → Python` 및 `xlsx → sqlite` WBS. diff --git a/docs/CLOUD_SERVER_SETUP.md b/docs/CLOUD_SERVER_SETUP.md new file mode 100644 index 0000000..b689a0d --- /dev/null +++ b/docs/CLOUD_SERVER_SETUP.md @@ -0,0 +1,514 @@ +# 클라우드 서버 설정 가이드 (hz-prod-01) + +> 시놀로지(Synology DSM)에서 클라우드 VPS(`178.104.200.7`)로 이전. +> 이 문서는 서버에서 실제 수집된 데이터 기반이며, 운영 하네스로 사용한다. + +--- + +## 참조 인덱스 + +| # | 섹션 | 핵심 내용 | +|---|---|---| +| 1 | [서버 기본 정보](#1-서버-기본-정보) | 호스트명, IP, OS, CPU/RAM/디스크, 타임존 | +| 2 | [접속 정보](#2-접속-정보) | SSH 접속, 사용자, 인증 방식 | +| 3 | [소프트웨어 스택](#3-소프트웨어-스택) | Python, .NET, PG, Nginx, Docker Compose, fail2ban | +| 3.1 | [런타임](#31-런타임) | 버전/경로 일람 | +| 3.2 | [Python 가상 환경](#32-python-가상-환경) | `~/.venv`, `python3` 사용 규칙 | +| 3.3 | [주요 Python 패키지](#33-주요-python-패키지-시스템) | 시스템/venv 패키지 구분 | +| 4 | [서비스 아키텍처](#4-서비스-아키텍처) | 포트 맵, Nginx 리버스 프록시 | +| 4.1 | [포트 맵](#41-포트-맵) | 22, 80, 2222, 3000, 5000, 5432 | +| 4.2 | [Nginx 리버스 프록시](#42-nginx-리버스-프록시) | `/` → Gitea, `/quant/` → Blazor | +| 5 | [Gitea](#5-gitea) | Docker Compose 설정, 시크릿, 데이터 경로 | +| 5.1 | [Docker Compose](#51-docker-compose) | `gitea:1.26.4`, PG 연동 | +| 5.2 | [시크릿 관리](#52-시크릿-관리) | `/opt/stacks/gitea/.env` | +| 5.3 | [데이터](#53-데이터) | Gitea 볼륨, `giteadb` | +| 6 | [Gitea Act Runner (CI)](#6-gitea-act-runner-ci) | 6× 러너, 네트워크, 구성 디렉토리 | +| 6.1 | [컨테이너 현황](#61-컨테이너-현황) | 러너 6개 실행 상태 | +| 6.2 | [러너 설정](#62-러너-설정) | `hz-prod-runner`, `gitea_default` 네트워크 | +| 6.3 | [러너 구성 디렉토리](#63-러너-구성-디렉토리) | `~/gitea-runner[-N]/` | +| 7 | [QuantEngine Blazor Admin](#7-quantengine-blazor-admin) | systemd, symlink 배포, DLL 구성 | +| 7.1 | [systemd 서비스](#71-systemd-서비스) | `quantengine.service` 전문 | +| 7.2 | [배포 구조](#72-배포-구조) | 타임스탬프 디렉토리 + symlink 교체 | +| 7.3 | [주요 DLL](#73-주요-dll) | Web, Core, Infrastructure, MudBlazor, Dapper | +| 8 | [PostgreSQL 18](#8-postgresql-18) | v18.4, `localhost` 바인드, Docker 연동 | +| 9 | [보안](#9-보안) | SSH hardening, UFW, fail2ban, 네트워크 격리 | +| 9.1 | [SSH 보안 설정](#91-ssh-보안-설정) | 공개키 전용, root 차단 | +| 9.2 | [UFW 방화벽](#92-ufw-방화벽) | `ENABLED=yes`, 포트 개방/차단 | +| 9.3 | [fail2ban](#93-fail2ban) | SSH 브루트포스 방어 | +| 9.4 | [Docker 네트워크 격리](#94-docker-네트워크-격리) | 로컬바인드 정책 | +| 10 | [디렉토리 맵](#10-디렉토리-맵) | `/home/kjh2064/`, `/opt/stacks/`, `/opt/backups/` | +| 11 | [시놀로지 → 클라우드 마이그레이션 매핑](#11-시놀로지--클라우드-마이그레이션-매핑) | 항목별 구↔신 비교표 | +| 12 | [운영 명령 치트시트](#12-운영-명령-치트시트) | 서비스 관리, 배포, 러너 등록, SSH | +| 13 | [검증 하네스](#13-검증-하네스) | 헬스체크, 엔드포인트, 마이그레이션 체크리스트 | + +### 관련 문서 상호 참조 + +| 문서 | 역할 | +|---|---| +| [`AGENTS.md`](../AGENTS.md) | 운영 헌법, Directory Routing 인덱스 | +| [`GITEA_SECRETS_SETUP.md`](GITEA_SECRETS_SETUP.md) | Gitea 시크릿 설정/검증 가이드 | +| [`SYNOLOGY_KIS_COLLECTION_SETUP.md`](SYNOLOGY_KIS_COLLECTION_SETUP.md) | KIS 데이터 수집 설정 (시놀로지 기준, 마이그레이션 대상) | +| [`ROADMAP_WBS.md`](ROADMAP_WBS.md) | `.gs → Python` 및 `xlsx → sqlite` WBS | +| [`docs/GITEA_TOKEN_HOME_RUNBOOK.md`](GITEA_TOKEN_HOME_RUNBOOK.md) | Gitea 토큰 관리 런북 | +| [`spec/00_execution_contract.yaml`](../spec/00_execution_contract.yaml) | 실행 계약 원본 권위 | +| [`governance/agents_index.yaml`](../governance/agents_index.yaml) | 거버넌스 규칙 인덱스 | + +--- + +## 1. 서버 기본 정보 + +| 항목 | 값 | +|---|---| +| **호스트명** | `hz-prod-01` | +| **IP** | `178.104.200.7` | +| **OS** | Ubuntu 26.04 LTS (Resolute Raccoon) | +| **커널** | `7.0.0-22-generic` (x86_64, PREEMPT_DYNAMIC) | +| **CPU** | AMD EPYC-Rome, 2 vCPU | +| **메모리** | 3.7 GiB (사용 ~958 MiB, 가용 ~2.8 GiB) | +| **스왑** | 2.0 GiB | +| **디스크** | `/dev/sda1` 38 GB (사용 8.5 GB / 28 GB 가용, 24%) | +| **타임존** | `Asia/Seoul` (KST, +0900), NTP 동기화 활성 | + +## 2. 접속 정보 + +| 항목 | 값 | +|---|---| +| **SSH 접속** | `ssh kjh2064@178.104.200.7` | +| **SSH 포트** | 22 (기본) | +| **사용자** | `kjh2064` (uid=1000) | +| **그룹** | `kjh2064`, `sudo`, `users`, `docker` | +| **인증 방식** | 공개키 전용 (`PasswordAuthentication no`) | +| **Root 로그인** | 비활성 (`PermitRootLogin no`) | +| **Max Auth Tries** | 3 | +| **Keep-Alive** | `ClientAliveInterval 300`, `ClientAliveCountMax 2` | + +## 3. 소프트웨어 스택 + +### 3.1. 런타임 + +| 소프트웨어 | 버전 | 경로 | +|---|---|---| +| **Python** | 3.14.4 | `/usr/bin/python3` | +| **.NET SDK** | 10.0.109 | `/usr/lib/dotnet/sdk` | +| **.NET Runtime** | ASP.NET Core 10.0.9 + NETCore 10.0.9 | `/usr/lib/dotnet/shared/` | +| **PostgreSQL** | 18.4 | `postgresql@18-main.service` | +| **Nginx** | 시스템 패키지 | `nginx.service` | +| **Docker Compose** | v5.2.0 | Docker 플러그인 | +| **fail2ban** | 1.1.0 | `fail2ban.service` | + +### 3.2. Python 가상 환경 + +``` +경로: ~/.venv +Python: 3.14.4 +``` + +> **주의**: 이 서버에서는 `python3`을 사용한다 (시놀로지/Windows와 다름). +> CI 워크플로우와 로컬 서버 모두 `python3`을 사용하므로 통일됨. + +### 3.3. 주요 Python 패키지 (시스템) + +boto3, cryptography, Jinja2, jsonschema, fail2ban 등 시스템 레벨로 설치됨. +프로젝트 의존성은 `~/.venv`에 별도 관리. + +## 4. 서비스 아키텍처 + +### 4.1. 포트 맵 + +| 포트 | 서비스 | 바인드 | 비고 | +|---|---|---|---| +| **22** | SSH | `0.0.0.0` | 공개키 전용 | +| **80** | Nginx (리버스 프록시) | `0.0.0.0` | 외부 진입점 | +| **2222** | Gitea SSH | `0.0.0.0` | Git SSH 접속 | +| **3000** | Gitea Web | `127.0.0.1` | Nginx 프록시 경유 | +| **5000** | QuantEngine Blazor | `127.0.0.1` | Nginx `/quant/` 경유 | +| **5432** | PostgreSQL | `127.0.0.1` + `172.17.0.1` | 로컬 + Docker 네트워크 | + +### 4.2. Nginx 리버스 프록시 + +```nginx +# /etc/nginx/sites-enabled/gitea-ip.conf + +server { + listen 80 default_server; + listen [::]:80 default_server; + server_name _; + client_max_body_size 512M; + + # QuantEngine Blazor Web App + location /quant/ { + proxy_pass http://127.0.0.1:5000/; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + proxy_cache_bypass $http_upgrade; + 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 $scheme; + } + + # Gitea (기본) + location / { + proxy_pass http://127.0.0.1:3000; + proxy_http_version 1.1; + proxy_set_header Host $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 $scheme; + proxy_read_timeout 300; + proxy_connect_timeout 300; + proxy_send_timeout 300; + } +} +``` + +**라우팅 요약**: +- `http://178.104.200.7/` → Gitea Web UI +- `http://178.104.200.7/quant/` → QuantEngine Blazor Admin +- `ssh://178.104.200.7:2222` → Gitea Git SSH + +## 5. Gitea + +### 5.1. Docker Compose + +```yaml +# /opt/stacks/gitea/docker-compose.yml +services: + gitea: + image: docker.gitea.com/gitea:1.26.4 + container_name: gitea + restart: unless-stopped + extra_hosts: + - "host.docker.internal:host-gateway" + environment: + USER_UID: "1000" + USER_GID: "1000" + GITEA__database__DB_TYPE: postgres + GITEA__database__HOST: host.docker.internal:5432 + GITEA__database__NAME: giteadb + GITEA__database__USER: gitea + GITEA__database__PASSWD: "${GITEA_DB_PASSWORD}" + GITEA__server__DOMAIN: "${SERVER_IP}" + GITEA__server__ROOT_URL: "http://${SERVER_IP}/" + GITEA__server__SSH_DOMAIN: "${SERVER_IP}" + GITEA__server__SSH_PORT: "2222" + GITEA__security__INSTALL_LOCK: "true" + GITEA__service__DISABLE_REGISTRATION: "true" + volumes: + - ./gitea:/data + - /etc/timezone:/etc/timezone:ro + - /etc/localtime:/etc/localtime:ro + ports: + - "127.0.0.1:3000:3000" + - "2222:22" +``` + +### 5.2. 시크릿 관리 + +- `.env` 파일: `/opt/stacks/gitea/.env` (소유자 전용, `600`) +- 포함 변수: `GITEA_DB_PASSWORD`, `SERVER_IP` + +### 5.3. 데이터 + +- Gitea 데이터: `/opt/stacks/gitea/gitea/` +- DB: PostgreSQL `giteadb` (Docker → host.docker.internal:5432 경유) + +## 6. Gitea Act Runner (CI) + +### 6.1. 컨테이너 현황 + +| 이름 | 이미지 | 상태 | +|---|---|---| +| `gitea-runner` | `gitea/act_runner:latest` | 실행 중 | +| `gitea-runner-2` | `gitea/act_runner:latest` | 실행 중 | +| `gitea-runner-3` | `gitea/act_runner:latest` | 실행 중 | +| `hopeful_galileo` | `gitea/act_runner:latest` | 실행 중 | +| `jovial_bouman` | `gitea/act_runner:latest` | 실행 중 | +| `upbeat_chatelet` | `gitea/act_runner:latest` | 실행 중 | + +> 총 6개 러너가 활성 상태. 네트워크는 `gitea_default` Docker 네트워크 사용. + +### 6.2. 러너 설정 + +```yaml +# ~/gitea-runner/config.yaml +container: + network: "gitea_default" +``` + +- 러너 이름: `hz-prod-runner` +- 러너 UUID: `d6d9120b-5070-4874-88d7-b86fe817d5a0` +- 러너 이미지: `docker.gitea.com/runner-images:ubuntu-latest` (2.33 GB) + +### 6.3. 러너 구성 디렉토리 + +``` +~/gitea-runner/ # 1번 러너 +~/gitea-runner-2/ # 2번 러너 +~/gitea-runner-3/ # 3번 러너 +``` + +## 7. QuantEngine Blazor Admin + +### 7.1. systemd 서비스 + +```ini +# /etc/systemd/system/quantengine.service +[Unit] +Description=Quant Engine Blazor Admin Web App (.NET 10) +After=network.target + +[Service] +WorkingDirectory=/home/kjh2064/quantengine_active +ExecStart=/usr/bin/dotnet /home/kjh2064/quantengine_active/QuantEngine.Web.dll +Restart=always +RestartSec=10 +KillSignal=SIGINT +SyslogIdentifier=quantengine +User=kjh2064 +Environment=ASPNETCORE_ENVIRONMENT=Production +Environment=ASPNETCORE_URLS=http://127.0.0.1:5000 +Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false + +[Install] +WantedBy=multi-user.target +``` + +### 7.2. 배포 구조 + +``` +~/quantengine_active → ~/deployments/quantengine_20260625_182821 (symlink) +~/deployments/ +├── quantengine_20260625_155649/ +├── quantengine_20260625_164548/ +├── quantengine_20260625_164928/ +└── quantengine_20260625_182821/ ← 현재 활성 +``` + +**배포 방식**: 타임스탬프 디렉토리 생성 → symlink 교체 → `systemctl restart quantengine` + +### 7.3. 주요 DLL + +- `QuantEngine.Web.dll` — 웹 진입점 +- `QuantEngine.Core.dll` — 핵심 도메인 +- `QuantEngine.Application.dll` — 애플리케이션 서비스 +- `QuantEngine.Infrastructure.dll` — 인프라 (DB, 외부 연동) +- `Npgsql.dll` — PostgreSQL 드라이버 +- `MudBlazor.dll` — UI 컴포넌트 +- `Dapper.dll` — 마이크로 ORM + +## 8. PostgreSQL 18 + +| 항목 | 값 | +|---|---| +| **버전** | 18.4 (Ubuntu 패키지) | +| **서비스** | `postgresql@18-main.service` | +| **listen_addresses** | `localhost` (기본값, 로컬 전용) | +| **바인드** | `127.0.0.1:5432`, `172.17.0.1:5432` (Docker), `[::1]:5432` | +| **Gitea DB** | `giteadb` (사용자: `gitea`) | + +> Docker 컨테이너는 `host.docker.internal:5432`로 호스트 PG에 접속. +> `listen_addresses`는 `postgresql.conf`에서 기본값 `localhost`로 설정됨 (외부 접속 차단). + +## 9. 보안 + +### 9.1. SSH 보안 설정 + +``` +PermitRootLogin no +PasswordAuthentication no +PubkeyAuthentication yes +KbdInteractiveAuthentication no +X11Forwarding no +MaxAuthTries 3 +ClientAliveInterval 300 +ClientAliveCountMax 2 +``` + +### 9.2. UFW 방화벽 + +- **상태**: `ENABLED=yes` (`/etc/ufw/ufw.conf`) +- **로그 레벨**: `low` +- **외부 개방 포트**: 22 (SSH), 80 (HTTP/Nginx), 2222 (Gitea SSH) +- **내부 전용**: 3000 (Gitea Web), 5000 (QuantEngine), 5432 (PostgreSQL) + +> 상세 규칙 확인: `sudo ufw status numbered` (TTY + sudo 비밀번호 필요) + +### 9.3. fail2ban + +- `fail2ban.service` 활성 상태 +- SSH 브루트포스 방어 활성 + +### 9.4. Docker 네트워크 격리 + +- Gitea Web: `127.0.0.1:3000` (로컬 전용) +- QuantEngine: `127.0.0.1:5000` (로컬 전용) +- PostgreSQL: `127.0.0.1` + Docker bridge (`172.17.0.1`) +- 외부 노출: SSH(22), HTTP(80), Gitea SSH(2222)만 개방 + +## 10. 디렉토리 맵 + +``` +/home/kjh2064/ +├── quantengine_active → deployments/quantengine_YYYYMMDD_HHMMSS (symlink) +├── deployments/ # QuantEngine 배포 히스토리 +│ └── quantengine_YYYYMMDD_HHMMSS/ +│ └── wwwroot/ +├── gitea-runner/ # Gitea Act Runner 1 +├── gitea-runner-2/ # Gitea Act Runner 2 +├── gitea-runner-3/ # Gitea Act Runner 3 +├── apps/ # 추가 앱 +│ └── python-test/.venv/ +├── .venv/ # Python 3.14 가상 환경 +├── tmp/ # 임시 작업 +└── .ssh/ # SSH 키 + +/opt/stacks/ +├── gitea/ +│ ├── docker-compose.yml +│ ├── .env # GITEA_DB_PASSWORD, SERVER_IP +│ └── gitea/ # Gitea 데이터 볼륨 +└── dotnet-app/ # .NET 관련 + +/opt/backups/ # 백업 +``` + +## 11. 시놀로지 → 클라우드 마이그레이션 매핑 + +| 항목 | 시놀로지 (구) | 클라우드 (신) | +|---|---|---| +| **프로젝트 경로** | `/volume1/projects/data_feed` | 미배치 (TBD) | +| **Python** | `python3` (시스템) | `python3` (`/usr/bin/python3`, 3.14.4) | +| **Gitea** | Docker on DSM | Docker on Ubuntu (`gitea:1.26.4`) | +| **Gitea SSH** | 포트 변동 | `2222` 고정 | +| **CI Runner** | Synology Act Runner | 6× `act_runner:latest` (Docker) | +| **DB** | SQLite (파일 기반) | PostgreSQL 18 + SQLite (하이브리드) | +| **웹 Admin** | 없음 | QuantEngine Blazor (.NET 10, MudBlazor) | +| **리버스 프록시** | Synology 내장 | Nginx (`/` → Gitea, `/quant/` → Blazor) | +| **보안** | DSM 방화벽 | fail2ban + SSH 공개키 + 서비스 로컬바인드 | +| **시크릿 관리** | `.secrets/kis_real.env` | `/opt/stacks/gitea/.env` | +| **OS** | Synology DSM 7.x | Ubuntu 26.04 LTS | +| **타임존** | (설정 의존) | `Asia/Seoul` (NTP 동기화) | + +## 12. 운영 명령 치트시트 + +### 서비스 관리 + +```bash +# QuantEngine +sudo systemctl status quantengine +sudo systemctl restart quantengine +sudo journalctl -u quantengine -f + +# Gitea +cd /opt/stacks/gitea && docker compose up -d +docker compose logs -f gitea + +# Nginx +sudo systemctl reload nginx +sudo nginx -t + +# PostgreSQL +sudo systemctl status postgresql@18-main +sudo -u postgres psql + +# Docker 전체 상태 +docker ps -a +``` + +### QuantEngine 배포 + +```bash +# 1. 새 배포 디렉토리 생성 +DEPLOY_DIR=~/deployments/quantengine_$(date +%Y%m%d_%H%M%S) +mkdir -p "$DEPLOY_DIR" + +# 2. 빌드 산출물 복사 (로컬에서 scp 또는 CI에서) +scp -r publish/* kjh2064@178.104.200.7:"$DEPLOY_DIR"/ + +# 3. symlink 교체 +ln -sfn "$DEPLOY_DIR" ~/quantengine_active + +# 4. 서비스 재시작 +sudo systemctl restart quantengine +sudo systemctl status quantengine +``` + +### Gitea Act Runner 등록 + +```bash +# 새 러너 등록 (Gitea 웹 → Settings → Actions → Runners에서 토큰 복사) +docker run -d \ + --name gitea-runner-N \ + --restart unless-stopped \ + --network gitea_default \ + -v /var/run/docker.sock:/var/run/docker.sock \ + gitea/act_runner:latest +``` + +### SSH 접속 + +```bash +# Windows 로컬에서 +ssh kjh2064@178.104.200.7 + +# Gitea Git 접속 +git remote set-url origin ssh://git@178.104.200.7:2222/kjh2064/QuantEngineByItz.git +``` + +## 13. 검증 하네스 + +### 13.1. 서버 헬스 체크 + +```bash +ssh kjh2064@178.104.200.7 " + echo '=== Services ===' + systemctl is-active quantengine nginx docker postgresql@18-main fail2ban + echo '=== Docker ===' + docker ps --format '{{.Names}}: {{.Status}}' + echo '=== Disk ===' + df -h / + echo '=== Memory ===' + free -h | head -2 +" +``` + +**기대 결과**: +- 5개 서비스 모두 `active` +- Docker 컨테이너 7개 (gitea + runner ×6) `Up` +- 디스크 사용률 < 80% +- 메모리 가용 > 1 GiB + +### 13.2. 엔드포인트 접근 확인 + +```bash +# Gitea Web +curl -s -o /dev/null -w "%{http_code}" http://178.104.200.7/ +# 기대: 200 + +# QuantEngine +curl -s -o /dev/null -w "%{http_code}" http://178.104.200.7/quant/ +# 기대: 200 + +# Gitea SSH +ssh -T -p 2222 git@178.104.200.7 2>&1 | head -1 +# 기대: "Hi there, ..." Gitea 응답 +``` + +### 13.3. data_feed 프로젝트 마이그레이션 체크리스트 + +- [ ] 프로젝트 경로 결정 및 clone +- [ ] Python venv에 프로젝트 의존성 설치 (`pip install -r requirements.txt`) +- [ ] KIS 시크릿 설정 (`~/.secrets/kis_real.env`) +- [ ] crontab 또는 systemd timer 등록 +- [ ] `GatherTradingData.json` 동기화 경로 확정 +- [ ] SQLite canonical DB 경로 확정 +- [ ] CI 워크플로우 러너 라벨 확인 +- [ ] GAS 배포 스크립트 서버 경로 업데이트 + +--- + +> **수집 일시**: 2026-06-26 09:55 KST +> **수집 방법**: `ssh kjh2064@178.104.200.7` 라이브 명령 실행 +> **provenance**: 모든 값은 서버 실시간 명령 출력에서 추출. 임의 값 없음.