최재영의 개발 일지
GitHubLinkedIn

Caddy로 리버스 프록시 구성하기

기타1분 읽기

배경

개인 서버를 그대로 네트워크에 노출하는 것은 위험하기 때문에 하나 더 남은 데스크탑으로 VPS 역할을 하는 리버스 프록시를 만드려고 했다. 여기에도 웹 서버를 띄워야 하는데, Caddy가 간편하면서도 인증서도 자동으로 설정해준다고 해서 Caddy를 사용해보기로 했다. 또한, Caddy는 로컬 환경에 설치하지 않고 도커로 띄우기로 했다.

디렉토리 구조

/opt/caddy에 필요한 파일을 모아두고 이 디렉토리만 사용한다.

/opt/caddy
├── config/     ← 설정 캐시
├── data/       ← 인증서 저장소
├── logs/       ← 로그
├── Caddyfile
└── docker-compose.yml

Caddyfile

Caddy 설정의 가장 핵심 부분이다. 설정한 도메인으로 들어오는 모든 요청을 172.30.1.87:80으로 보낸다.

{
  # ACME 설정 (Let's Encrypt)
  acme_ca https://acme-v02.api.letsencrypt.org/directory

  # 이메일 주소 (인증서 만료 알림용)
  email jayyoungchoi22@gmail.com

  # 로그 설정
  log default {
    output file /var/log/caddy/access.log
    format json
  }
}

biswine.duckdns.org, *.biswine.duckdns.org {

  reverse_proxy http://172.30.1.87:80 {
    header_up X-Forwarded-For {http.client_ip}
    header_up X-Forwarded-Proto https
  }

  header X-Frame-Options SAMEORIGIN
  header X-Content-Type-Options nosniff
  header X-XSS-Protection "1; mode=block"
  header Referrer-Policy strict-origin-when-cross-origin
}

Docker Compose

Caddy는 도커로 띄울 것이기 때문에 다음의 파일을 작성한다.

# docker-compose.yml

services:
  caddy:
    image: caddy:latest
    container_name: caddy-reverse-proxy
    restart: unless-stopped

    ports:
      - "80:80"
      - "443:443"
      - "443:443/udp"

    volumes:
      # Caddyfile 마운트 (읽기 전용)
      - ./Caddyfile:/etc/caddy/Caddyfile:ro

      # 인증서 저장소 - 호스트에 유지
      - ./data:/data

      # Caddy 설정 캐시 - 호스트에 유지
      - ./config:/config

      # (선택) 로그 저장
      - ./logs:/var/log/caddy

    environment:
      # Let's Encrypt 자동 동의
      - ACME_AGREE=true

      # (선택) 이메일 알림
      - ADMIN_EMAIL=jayyoungchoi22@gmail.com

    networks:
      - caddy-network

    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

networks:
  caddy-network:
    driver: bridge

Caddy 실행

cd /opt/caddy
docker compose up -d