Files
portfolio-hub/docs/technical/deployment-and-operations.md
T

4.3 KiB

Deployment and Operations

  • Related REQ: N/A

목표

PortfolioHub를 Linux 환경에서 안정적으로 배포하고 HTTPS 종단, 프로세스 복구, 기본 점검 경로를 표준화한다.

사전 조건

  • public IP를 가진 Linux/Ubuntu 서버
  • 해당 IP를 가리키는 도메인 DNS A record
  • 방화벽에서 80, 443 포트 개방

권장 배포 토폴로지

  • App: uvicorn app.main:app
  • Reverse proxy/TLS: Caddy
  • Process manager: systemd
  • 선택: Docker Compose + Caddy sidecar

Linux Direct Run 기준

  1. Python 가상환경 생성 후 패키지를 설치한다.
  2. 환경 변수 또는 .env를 구성한다.
  3. uvicorn app.main:app --host 127.0.0.1 --port 8000 --workers 2를 실행한다.
  4. GET /health를 확인한다.

Caddy 설치와 구성

Ubuntu/Debian 설치 예시:

sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https curl
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
	| sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
	| sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy

설치 검증:

caddy version

기본 Caddyfile:

your-domain.com {
		reverse_proxy localhost:8000
}

동작 기준:

  • TLS 인증서 자동 발급/갱신
  • 80에서 443으로 HTTP redirect
  • 외부 요청을 내부 uvicorn 프로세스(127.0.0.1:8000)로 전달

적용 후 reload:

sudo systemctl reload caddy

systemd 운영 기준

  • 서비스 계정 권한 최소화
  • Restart=on-failure
  • 로그 수집 경로(journalctl 또는 외부 수집기) 확보

예시 unit 파일:

[Unit]
Description=PortfolioHub API
After=network.target

[Service]
User=www-data
WorkingDirectory=/opt/portfoliohub
EnvironmentFile=/opt/portfoliohub/.env
ExecStart=/opt/portfoliohub/.venv/bin/uvicorn app.main:app \
		--host 127.0.0.1 --port 8000 --workers 2
Restart=on-failure

[Install]
WantedBy=multi-user.target

등록/기동:

sudo systemctl daemon-reload
sudo systemctl enable portfoliohub
sudo systemctl start portfoliohub

HTTPS/Caddy 운영 기준

  • 도메인 DNS가 서버 IP를 가리켜야 한다.
  • 포트 80/443을 개방한다.
  • Caddyfile에서 앱을 reverse_proxy로 연결한다.
  • 브라우저 기반 frontend가 있으면 PORTFOLIOHUB_ALLOWED_ORIGINS에 정확한 HTTPS origin을 지정한다.

예시:

PORTFOLIOHUB_ALLOWED_ORIGINS=https://app.example.com,https://www.example.com

Docker Compose 운영 기준

  • 앱 컨테이너는 내부 포트만 expose하고 외부 종단은 Caddy가 담당한다.
  • caddy_data, caddy_config 볼륨을 유지해 인증서 상태를 보존한다.
  • 배포 후 docker compose ps, curl /health로 기본 상태를 확인한다.

예시 compose:

services:
	app:
		build: .
		expose:
			- "8000"
		environment:
			- PORTFOLIOHUB_ALLOWED_ORIGINS=https://your-domain.com
		restart: unless-stopped

	caddy:
		image: caddy:2-alpine
		ports:
			- "80:80"
			- "443:443"
		volumes:
			- ./Caddyfile:/etc/caddy/Caddyfile:ro
			- caddy_data:/data
			- caddy_config:/config
		depends_on:
			- app
		restart: unless-stopped

volumes:
	caddy_data:
	caddy_config:

compose 네트워크 안에서는 reverse_proxy app:8000을 사용한다.

기동:

docker compose up -d

방화벽 설정

UFW:

sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw reload

firewalld:

sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload

배포 검증

HTTPS health check:

curl https://your-domain.com/health

운영 상태 확인:

sudo systemctl status caddy
sudo journalctl -u caddy -f

Validation Notes

  • HTTPS 엔드포인트에서 /health, /docs 접근이 가능해야 한다.
  • DB 사용 배포에서는 마이그레이션 적용 후 앱을 기동한다.
  • CORS 오리진 설정과 실제 프론트엔드 도메인이 일치해야 한다.

Open Implementation Points

  • blue/green 또는 rolling update 같은 무중단 배포 전략 도입 여부를 확정한다.
  • Loki/metrics 통합 운영 절차를 별도 런북으로 분리할지 결정한다.