운영 서비스 목록, 데이터 볼륨 위치, 노출 포트, 운영 중 적용한 hotfix(Mailu DNSSEC/MariaDB 11.8 등), Phase 별 이관 체크리스트. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 KiB
인프라 이관 가이드 (집 PC → IDC)
작성: 2026-05-12 / 대상 호스트:
chparkserver(183.99.177.40) 목적: 운영 중인 서비스 전부 IDC 서버로 옮길 때 필요한 정보와 절차 정리
1. 현재 호스트 사양 / 환경
| 항목 | 값 |
|---|---|
| Hostname | chparkserver |
| OS | Ubuntu 24.04.4 LTS (kernel 6.8) |
| Docker | 29.1.3 |
| K3s | v1.34.6+k3s1 |
| 디스크 | / 116G / /data 916G (사용 121G) |
| 외부 IP | 183.99.177.40 |
| 접속 | SSH (chpark@) |
디스크 사용량 분포 (/data):
51G containerd (K3s container runtime)
31G docker (docker engine data-root)
56G opt (docker compose 운영 파일들)
544M transfer
490M dumps
303M k3s
90M mailu
87M backups ← 이번 사고 대응으로 만든 백업
2. 운영 중인 서비스 전체 목록
2.1 Docker Compose 기반 (직접 운영)
| Project | 경로 | 도메인/포트 | 비고 |
|---|---|---|---|
| traefik | /data/opt/docker/traefik/ |
80, 443 | HTTPS reverse proxy (Let's Encrypt). 모든 도메인 입구 |
| mailufinal | /data/mailu/ |
mail.coa-soft.com (25/110/143/465/587/993/995) | Mailu 메일 서버 9개 컨테이너 |
| nextcloudfinal | /home/chpark/nextcloud/ |
cloud.junggomoa.com | Nextcloud + MariaDB 11.8 + Redis |
| gitea2 | /data/opt/docker/gitea/ |
git.junggomoa.com / 2222 (SSH) | Gitea + PostgreSQL |
| mattermost2 | /data/opt/docker/mattermost/ |
8065 | Mattermost + PostgreSQL |
| registry2 | /data/opt/docker/registry/ |
localhost:5000 | Docker registry (K3s 가 image pull 용) |
| source | /home/chpark/momo-erp/source/ |
momotogether.com | momo-erp |
| tradeing2 | /home/chpark/tradeing/ |
(도메인 확인) | Tradeing 서비스 + PostgreSQL |
| portainer | /data/opt/docker/portainer/ |
9000 (관리 UI) | Docker 관리 UI |
⚠️ stopped 상태로 남은 옛 프로젝트:
gitea,mailu,mattermost,nextcloud,registry,tradeing— 이전 버전. 이관 시 무시.
2.2 K3s 위에서 운영 (kubectl 로 관리)
| Namespace | 서비스 | 도메인 |
|---|---|---|
invyone |
frontend / backend-spring / backend-node | www.invyone.com / solution.invyone.com |
invyone-homepage |
homepage | (invyone homepage) |
insurance |
api / web / postgres-0 | (insurance 도메인) |
kubernetes-dashboard |
dashboard / metrics-scraper | (관리용) |
portainer |
portainer-agent | (관리용) |
kube-system |
coredns / metrics-server / local-path-provisioner | (인프라) |
K3s manifests:
/data/k8s-manifests/또는 Gitea 의 repo 확인.
3. 데이터 볼륨 (이관 시 반드시 옮길 것)
3.1 Docker Named Volumes
nextcloud_nextcloud_db ← Nextcloud DB (MariaDB 11.8)
nextcloud_nextcloud_data ← Nextcloud 사용자 파일
insurance_postgres_data ← Insurance K3s PostgreSQL
insurance_uploads ← Insurance 업로드 파일
invyone-db-data ← Invyone PostgreSQL
source_momo_data_storage ← Momo ERP 데이터
호스트 경로: /data/docker/volumes/<volume_name>/_data/
3.2 Bind Mount 경로
/data/mailu/ ← Mailu compose + env + 인증서
/mailu/ ← Mailu data (메일함 실제 저장 위치, /mailu/data)
/data/opt/docker/ ← 각 서비스의 compose 디렉토리
/home/chpark/nextcloud/ ← Nextcloud compose
/home/chpark/momo-erp/ ← Momo ERP compose + source
/home/chpark/tradeing/ ← Tradeing compose
3.3 K3s/containerd
/data/containerd/ ← K3s container runtime data (이관 비추, K3s 새로 설치 + manifest 재배포 권장)
/data/k3s/ ← K3s state
/data/k8s-manifests/ ← K8s manifest 파일들 (직접 이관)
4. 외부 노출 포트 (방화벽 규칙)
| 포트 | 프로토콜 | 용도 |
|---|---|---|
| 80, 443 | TCP | Traefik (HTTPS 리버스 프록시) |
| 25 | TCP | SMTP (메일 수신) |
| 465 | TCP | SMTPS (메일 송신 TLS) |
| 587 | TCP | SMTP Submission |
| 993 | TCP | IMAPS |
| 995 | TCP | POP3S |
| 110, 143 | TCP | POP3/IMAP plain (보안상 disable 권장) |
| 2222 | TCP | Gitea SSH |
| 8065 | TCP | Mattermost |
| 5432 | TCP | ⚠️ invyone-db PostgreSQL 외부 노출 — IDC 이관 시 내부 IP 만 허용하도록 변경 권장 |
5. 운영 중 적용된 Hotfix 내역 (이관 시 그대로 가져가야 함)
이관 시 단순히 compose 파일만 복사하면 안 됨. 아래는 컨테이너/네트워크 quirk 대응으로 추가한 패치.
5.1 Mailu (/data/mailu/docker-compose.yml)
-
admin / front / antispam 의
entrypointoverride:entrypoint: - /bin/sh - -c - | echo "nameserver 127.0.0.11" > /etc/resolv.conf echo "nameserver 192.168.203.2" >> /etc/resolv.conf echo "search ." >> /etc/resolv.conf echo "options edns0 trust-ad ndots:0" >> /etc/resolv.conf exec /start.py -
admin / front / antispam 에
extra_hosts(mailu 내부 service IP 직접 박음):extra_hosts: - "redis:192.168.203.4" - "imap:192.168.203.9" - "smtp:192.168.203.6" - "antispam:192.168.203.8" - "webmail:192.168.203.10" - "front:192.168.203.3" - "resolver:192.168.203.2"이유: docker user-defined bridge network 에서 admin 만 DNSSEC AD flag 강제. embedded DNS(127.0.0.11) 가 DNSSEC 안 함 → admin 시작 실패. mailu unbound resolver(192.168.203.2) 가 DNSSEC capable 이라 그쪽으로 박았고, internal service hostname 은
extra_hosts로 박아 NXDOMAIN 방지. -
resolver service 의
ipv4_address: 192.168.203.254제거됨 (자동 할당).이유: 192.168.203.254 IP 가 packet drop 되는 docker bridge quirk 발견. 자동 할당으로 .2 받음.
-
/data/mailu/mailu.env에 추가:WEBROOT_REDIRECT=/webmail/이유: 로그인 후 admin 계정이라 가끔 admin UI 로 redirect 됨. 항상 webmail 로 일관시킴.
5.2 Nextcloud (/home/chpark/nextcloud/docker-compose.yml)
- DB 컨테이너 image:
mariadb:10.5→mariadb:11.8(원본 데이터 버전 일치) command:라인 중복 제거 (이전엔 두 줄이라 첫 번째가 덮어써짐)- 백업 위치:
/data/backups/nextcloud_db_20260512_080401.tgz(87MB) - 추가 mariadb-dump:
/data/backups/nc_db_*.sql
5.3 Docker daemon (/etc/docker/daemon.json)
- 사용자가 이전에 추가한
"dns": ["8.8.8.8", "1.1.1.1"]가 모든 컨테이너 dns 옵션과 합쳐져 충돌. 이관 시 daemon.json 의 dns 키는 빼는 게 안전 (Mailu 가 의존하는 docker embedded DNS 만 사용하도록).
5.4 cron
*/5 * * * * /mailu/sync-certs.sh
0 4 * * * /usr/bin/docker builder prune -af --filter until=72h
5 4 * * * /usr/bin/docker image prune -af --filter until=168h
이관 시 root crontab 그대로 복사. sync-certs.sh 는 traefik 발급 인증서를 Mailu 형식으로 변환하는 스크립트.
6. 이관 절차 (체크리스트)
Phase 1 — 신규 IDC 호스트 준비
- Ubuntu 24.04 LTS 설치 (현재와 동일 버전 권장)
- Docker 29.x + Docker Compose v2 설치
- K3s 설치 (
curl -sfL https://get.k3s.io | sh -) - 디스크 파티션:
/(시스템) +/data(운영 데이터, 916G 이상 권장) - systemd:
docker,k3s,containerd자동 시작 enable
Phase 2 — 데이터 백업 (현재 호스트)
# 1. 모든 docker compose 정지 (downtime 시작)
for proj in mailufinal nextcloudfinal gitea2 mattermost2 registry2 source tradeing2 traefik portainer; do
docker compose -p $proj down
done
# 2. K3s 도 정지 (시작 시 컨테이너 자동 stop)
sudo systemctl stop k3s
# 3. volume + 운영 디렉토리 통째로 백업
sudo tar -czf /data/backups/all_volumes_$(date +%Y%m%d).tgz \
/data/docker/volumes \
/data/mailu \
/data/opt \
/data/k8s-manifests \
/home/chpark/nextcloud \
/home/chpark/momo-erp \
/home/chpark/tradeing \
/mailu
# 4. crontab 백업
sudo crontab -l > /data/backups/root_crontab.txt
# 5. daemon.json 백업
sudo cp /etc/docker/daemon.json /data/backups/daemon.json
Phase 3 — IDC 로 전송
# rsync 권장 (재시도 가능)
rsync -avzP --partial --append-verify \
/data/backups/all_volumes_*.tgz \
user@idc-host:/data/backups/
Phase 4 — IDC 에서 복원
cd /
sudo tar -xzf /data/backups/all_volumes_*.tgz
# crontab 복원
sudo crontab /data/backups/root_crontab.txt
# 각 서비스 기동
for path in /data/opt/docker/traefik /data/mailu /home/chpark/nextcloud /data/opt/docker/gitea /data/opt/docker/mattermost /data/opt/docker/registry /home/chpark/momo-erp/source /home/chpark/tradeing /data/opt/docker/portainer; do
cd "$path" && docker compose up -d
done
# K3s manifest 재적용
kubectl apply -f /data/k8s-manifests/
Phase 5 — DNS 변경
- 도메인 A 레코드를 새 IDC IP 로 변경 (TTL 짧게 미리 줄여놓으면 좋음)
mail.coa-soft.comcloud.junggomoa.comgit.junggomoa.commomotogether.comwww.invyone.com/solution.invyone.com- 기타
- Mailu MX 레코드도 새 IP 로
Phase 6 — 검증
# 컨테이너 상태
docker ps --filter "name=mailufinal\|nextcloud\|traefik\|gitea" --format "{{.Names}} {{.Status}}"
# HTTP 확인
for url in https://mail.coa-soft.com/ https://cloud.junggomoa.com/ https://git.junggomoa.com/ https://momotogether.com/; do
curl -ksS -o /dev/null -w "$url -> %{http_code}\n" "$url"
done
# SMTP banner
echo "QUIT" | nc -w 3 새IDC_IP 25
7. 이관 후 정리할 것 (선택)
- 옛 compose project (gitea/mailu/mattermost/nextcloud/registry/tradeing) 삭제 —
docker compose -p <이름> down --remove-orphans - dangling image 정리 — 이미 cron 으로 자동화됨
/data/backups/의 오래된 tarball 정리daemon.json의"dns"키 제거 (Mailu admin DNS 충돌 방지)- Mailu admin/front/antispam 의 entrypoint override 가 더 이상 필요한지 재확인 (IDC 의 docker network 환경에서는 안 필요할 수도)
8. 핵심 비밀번호 / 인증 정보
⚠️ 이 문서에는 비밀번호 직접 안 박는다. 아래 위치에서 확인:
- Mailu 계정:
/data/mailu/mailu.env(SECRET_KEY, DB_PW 등) - Nextcloud DB:
/home/chpark/nextcloud/docker-compose.yml(MYSQL_ROOT_PASSWORD) - 각 서비스 admin 계정: 해당 compose 의 environment 또는 env_file
- Traefik basic auth:
/data/opt/docker/traefik/안 설정 - SSH 비밀번호: 운영 PC 관리자가 보관
이관 시 새 IDC 에서 비밀번호 모두 회전(rotation) 권장.
9. 알려진 이슈 / 주의사항
-
Mailu resolver 192.168.203.254 IP 회피: 이번 사고에서 .254 IP 가 packet drop 되는 docker bridge quirk 발견. IDC 에서도 발생할 수 있으니 resolver 는 자동 할당으로 두는 게 안전.
-
MariaDB 버전 일치: Nextcloud DB 는 11.8.x. 이관 시 절대 다운그레이드 금지 (이번에 10.5 로 갔다가 plugin load fail 로 사고남).
-
K3s 와 docker 의 iptables/nftables 공존: K3s 의 kube-router 가 FORWARD chain 에 끼어들어서 docker bridge 통신에 영향을 줄 수 있음. mailu 의 192.168.203.0/24 subnet 이 다른 서비스의 K3s pod CIDR 와 안 겹치는지 확인.
-
메일 데이터 위치: 사용자 메일함 파일은
/mailu/data/(호스트 root)./data/mailu/와 다른 위치. 이관 시 둘 다 옮겨야 함. -
인증서: Let's Encrypt 인증서는 Traefik 이 자동 발급. 이관 후 도메인 가리키면 자동 재발급. 단 rate limit 주의 (도메인당 주 5건).
10. 빠른 참조 — 자주 쓰는 명령
# 전체 컨테이너 상태
docker ps --format "{{.Names}}\t{{.Status}}" | sort
# 특정 서비스 로그
docker logs --tail 50 mailufinal-admin-1
# 한 서비스만 재기동
cd /data/mailu && docker compose up -d --force-recreate admin
# Mailu 계정 추가 (admin 컨테이너 안)
docker exec mailufinal-admin-1 flask mailu user $USER $DOMAIN $PASSWORD
# Nextcloud occ
docker exec -u www-data nextcloud-app-new php occ status
# K3s pod 상태
kubectl get pods -A