Skip to content
Version
Proxmox VE 9.1
Status
Active
Level
Intermediate
Updated
2026. 04. 16.
Tags
proxmoxvirtualboxlvmsshaptnetworkingapi-tokenpostfix

환경 정보 ​

항목내용
Proxmox VE9.1-1 (Debian Bookworm 기반)
가상화 플랫폼Oracle VirtualBox 7.1.14 (r170994)
네트워크 모드NAT → NAT Network (클러스터 확장 시 변경)
호스트 OSWindows
디스크64GB (단일 가상 디스크)
RAM약 8GB
호스트명pve-nodeA.proxmox.internal.example
NICenp0s3 (VirtualBox 가상 NIC)

이 문서는 단일 노드 기준의 초기 설치 과정을 다룬다. 클러스터 구성은 02-cluster-setup.md에서 다룬다.


1. Proxmox VE 설치 ​

ISO 부팅 후 Installer에서 아래 값을 입력한다. 나머지 항목은 기본값 유지.

항목입력값
Management Interfaceenp0s3 (VirtualBox 가상 NIC)
Hostname (FQDN)pve-nodeA.proxmox.internal.example
IP Address (CIDR)10.0.2.15/24
Gateway10.0.2.2
DNS Server10.0.2.3

2. OS 초기 설정 ​

2.1 APT 저장소 전환 ​

Proxmox 기본 설치 시 Enterprise 구독 저장소(pve-enterprise)가 활성화된다. 구독 키가 없는 상태에서 apt update를 실행하면 401 Unauthorized 에러가 발생한다. No-Subscription 저장소로 교체해야 한다.

bash
# Enterprise repo 비활성화 (삭제 대신 백업 처리)
mv /etc/apt/sources.list.d/pve-enterprise.list \
   /etc/apt/sources.list.d/pve-enterprise.list.bak

# No-Subscription repo 등록
echo "deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription" \
  > /etc/apt/sources.list.d/pve-no-subscription.list

# Ceph repo가 존재하면 동일하게 처리
if [ -f /etc/apt/sources.list.d/ceph.list ]; then
  sed -i 's/enterprise/no-subscription/g' /etc/apt/sources.list.d/ceph.list
fi

apt update && apt full-upgrade -y

No-Subscription 빌드는 공식 릴리스보다 약간 앞선 스테이징(Staging) 채널이다. 학습·테스트 환경에서는 문제없지만, 프로덕션에서는 Enterprise 구독을 사용해야 한다.

.list는 옛날 방식이다. deb822 대로라면 source 파일만 있을 것이다.

bash
# Enterprise repo 비활성화
sed -i '1i Enabled: no' /etc/apt/sources.list.d/pve-enterprise.sources
sed -i '1i Enabled: no' /etc/apt/sources.list.d/ceph.sources

# (deb822 방식) No-subscription repo 추가
## 예전 방식인 .list 가이드가 인터넷에 많은데, 이렇게 섞어쓰면 pveversion GUI에서 경고 아이콘이 뜬다.
cat > /etc/apt/sources.list.d/pve-no-subscription.sources << 'EOF'
Types: deb
URIs: http://download.proxmox.com/debian/pve
Suites: trixie
Components: pve-no-subscription
Signed-By: /usr/share/keyrings/proxmox-archive-keyring.gpg
EOF

# Subscription Nag 제거
(1)서드파티 설치 (free-pmx-no-subscription)
(2)dpkg post-invoke hook으로 영속화

VirtualBox의 Enable Nested VT-x/AMD-V 체크박스는 GUI 상에서 조작 불가하게 막혀있다.

powershell
& "C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" modifyvm "Proxmos-9.1-1" --nested-hw-virt on

2.2 기본 패키지 설치 ​

bash
apt install -y vim htop curl wget net-tools dnsutils lsof tmux bash-completion

2.3 타임존 및 로케일 ​

bash
timedatectl set-timezone Asia/Seoul
dpkg-reconfigure locales  # en_US.UTF-8 선택

2.4 구독 팝업 제거 (학습 환경 전용) ​

Web UI 접속 시 표시되는 "No valid subscription" 팝업을 제거한다.

bash
sed -Ei.bak "s/NotFound/Active/g" \
  /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
systemctl restart pveproxy

apt full-upgrade 이후 proxmox-widget-toolkit 패키지가 갱신되면 이 패치가 초기화된다. 업그레이드 후 재적용이 필요하다.


3. 네트워크 설정 ​

3.1 Linux 브릿지와 VM 네트워크의 관계 ​

Proxmox는 VM 네트워크 연결에 Linux 브릿지(Bridge) 를 사용한다. 브릿지는 L2(데이터 링크 계층) 스위치와 동일하게 동작하며, 물리 NIC과 가상 NIC(tap 디바이스)을 같은 L2 도메인에 묶는다.

이 구조에서 물리 NIC(enp0s3)에 직접 IP를 부여해서는 안 된다. 물리 NIC은 브릿지의 업링크(bridge-ports)로만 사용하고, IP는 브릿지 인터페이스(vmbr0)에 부여한다. 그래야 호스트와 VM이 동일한 브릿지 인터페이스를 통해 같은 네트워크 세그먼트에 존재할 수 있다.

VM의 가상 NIC(tap)이 브릿지에 연결되면, VM은 마치 물리 스위치의 포트에 직접 연결된 것처럼 네트워크에 참여한다. Proxmox 호스트가 라우터가 아닌 스위치 역할을 하는 셈이다.

3.2 VirtualBox 네트워크 모드 비교 ​

항목NATNAT Network
게이트웨이10.0.2.210.0.2.1
VM 간 통신불가가능
DHCP 범위10.0.2.15~10.0.2.4~
클러스터 구성불가 (노드 간 통신 차단)가능

단일 노드 초기 설치에는 NAT로도 충분하다. 그러나 이후 3노드 클러스터를 구성할 때 노드 간 Corosync 통신이 필요하므로 NAT Network로 전환해야 한다. 전환 과정은 02-cluster-setup.md에서 다룬다.

3.3 네트워크 인터페이스 설정 ​

/etc/network/interfaces ​

bash
auto lo
iface lo inet loopback

# 물리 NIC은 manual 모드 — IP 없이 브릿지 슬레이브로만 사용
iface enp0s3 inet manual

# 외부 통신용 브릿지 (NAT 경유)
auto vmbr0
iface vmbr0 inet static
    address 10.0.2.15/24
    gateway 10.0.2.2
    bridge-ports enp0s3
    bridge-stp off
    bridge-fd 0

# 내부 VM 격리 네트워크 (브릿지 포트 없음 = 호스트-VM 간 전용)
auto vmbr1
iface vmbr1 inet static
    address 192.168.10.1/24
    bridge-ports none
    bridge-stp off
    bridge-fd 0
    post-up echo 1 > /proc/sys/net/ipv4/ip_forward
    post-up   iptables -t nat -A POSTROUTING -s '192.168.10.0/24' -o vmbr0 -j MASQUERADE
    post-down iptables -t nat -D POSTROUTING -s '192.168.10.0/24' -o vmbr0 -j MASQUERADE

source /etc/network/interfaces.d/*
브릿지IPbridge-ports용도
vmbr010.0.2.15/24enp0s3외부 통신 (NAT 경유)
vmbr1192.168.10.1/24none내부 VM 전용 격리 네트워크

vmbr1의 bridge-ports none은 이 브릿지가 물리 인터페이스와 연결되지 않음을 의미한다. VM들끼리만, 또는 VM과 호스트 간에만 통신하는 격리된 사설 네트워크를 만드는 표준 패턴이다. iptables MASQUERADE 규칙을 통해 이 대역의 VM들이 vmbr0을 경유해 외부로 나갈 수 있도록 NAT를 구성한다.

/etc/resolv.conf ​

bash
search proxmox.internal.example
nameserver 8.8.8.8
nameserver 1.1.1.1

3.4 VirtualBox 포트포워딩 ​

VirtualBox NAT 모드에서는 게스트에 직접 접근할 수 없으므로 포트포워딩이 필요하다.

VM 설정 → 네트워크 → 어댑터1 → 고급 → 포트 포워딩:

이름프로토콜호스트 IP호스트 포트게스트 IP게스트 포트
SSHTCP127.0.0.12210.0.2.1522
WebUITCP127.0.0.1800610.0.2.158006

4. SSH 설정 ​

4.1 키 생성 (Windows 호스트) ​

powershell
ssh-keygen -t ed25519 -C "proxmox-lab"
# 키 파일: C:\Users\<username>\.ssh\id_ed25519 (비밀키)
#          C:\Users\<username>\.ssh\id_ed25519.pub (공개키)

ed25519는 타원곡선(Elliptic Curve) 기반 알고리즘으로, RSA-4096 대비 키 길이가 짧고 서명 연산이 빠르다. passphrase를 설정하면 비밀키 파일이 유출되더라도 passphrase 없이는 사용할 수 없다.

4.2 공개키 전송 (Windows → Proxmox) ​

Windows에는 ssh-copy-id가 없으므로 PowerShell에서 파이프로 전송한다.

powershell
type $env:USERPROFILE\.ssh\id_ed25519.pub | `
  ssh -p 2222 root@127.0.0.1 `
  "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys"

초회 접속 시에만 패스워드를 묻는다. 이후는 키 인증으로 접속한다.

powershell
# 접속 테스트
ssh -p 2222 root@127.0.0.1

4.3 SSH 강화 ​

/etc/ssh/sshd_config:

bash
Port 2222
PermitRootLogin prohibit-password   # 키 인증 root 로그인만 허용, 패스워드 로그인 차단
PasswordAuthentication no            # 패스워드 인증 전면 차단
MaxAuthTries 3
ClientAliveInterval 300
ClientAliveCountMax 2

적용 시 주의순서:

  1. 공개키 등록 완료 확인 후 PasswordAuthentication no 적용
  2. 기존 세션을 유지한 채 새 터미널에서 키 인증 접속 테스트
  3. 실패 시 기존 세션에서 즉시 롤백
bash
systemctl reload sshd

# 롤백 (필요 시)
cp /etc/ssh/sshd_config.bak /etc/ssh/sshd_config
systemctl reload sshd

5. 스토리지 구성 ​

5.1 Proxmox 기본 파티션 구조 ​

markdown
sda (64GB)
├─ sda1        BIOS boot (1007K)
├─ sda2        EFI System (512M)
└─ sda3        LVM PV (63.5G)
    ├─ pve-swap       5.8G    [SWAP]
    ├─ pve-root      26.4G    /  (ext4)
    └─ pve-data      21.4G    VM 디스크 영역 (LVM-thin pool)
    └─ (미할당)        7.88G

5.2 LVM-thin Pool의 의미 ​

pve-data는 일반 LVM Logical Volume이 아니라 LVM-thin Pool이다. 일반 LV는 생성 시 선언한 용량을 즉시 물리 공간에서 예약하지만, thin pool은 씬 프로비저닝(Thin Provisioning) 방식으로 동작한다.

씬 프로비저닝의 핵심은 오버 커밋(Over-commit) 허용이다. 물리 공간 29GB인 pool에 20GB짜리 VM 디스크를 3개 만들어도(논리적 합계 60GB > 물리 29GB) 실제 쓰기가 일어나기 전까지는 공간을 차지하지 않는다. VM 디스크가 실제로 데이터를 쓸 때 비로소 pool에서 블록을 할당한다.

스냅샷도 thin pool의 CoW(Copy-on-Write) 메커니즘을 활용한다. 스냅샷 생성 시점에 데이터를 복사하지 않고, 원본 블록에 변경이 생길 때만 변경 전 데이터를 별도 공간에 기록한다. 이 때문에 스냅샷 생성이 즉각적이고 초기 용량을 거의 소모하지 않는다.

Proxmox가 VM 디스크 스토리지로 LVM-thin을 기본값으로 채택한 이유가 바로 이것이다. LVM-Thin의 스냅샷 동작 원리는 04-storage/01-lvm-disk.md에서 더 깊이 다룬다.

5.3 미할당 공간 처리 ​

VG에 7.88G의 미할당 공간이 남아있다. 두 가지 선택지:

옵션명령어적합 상황
A. data(thin pool) 확장lvextend -l +100%FREE pve/dataVM 여러 개 생성 (채택)
B. root 확장lvextend -l +100%FREE pve/root && resize2fs /dev/pve/rootISO·템플릿 다수 보관
bash
# A안 적용
lvextend -l +100%FREE pve/data

A안 채택 근거: pve/root 26G는 Proxmox OS, ISO 이미지, 컨테이너 템플릿용으로 충분하다. 실습에서 VM 디스크 공간이 먼저 부족해지므로 data pool 확장이 우선이다.

최종 LV 구성:

LV크기용도
pve/root26.43GOS, ISO 이미지, 컨테이너 템플릿
pve/data29.29GVM/CT 디스크 (LVM-thin pool)
pve/swap5.79G스왑

6. 관리 인터페이스 ​

6.1 Web UI 접속 ​

markdown
https://127.0.0.1:8006
  • ID: root
  • Realm: PAM (Linux PAM 인증, 로컬 시스템 계정과 동일한 자격증명 사용)

6.2 관리 계정 생성 ​

root@pam 계정을 자동화 작업에 직접 사용하는 것은 보안상 좋지 않다. 권한이 제한된 전용 관리 계정을 별도로 만든다.

Datacenter → Permissions → Users → Add:

  • User name: admin
  • Realm: PVE (Proxmox 자체 인증) 또는 PAM (리눅스 계정 연동)

PVE Realm은 /etc/passwd와 독립된 Proxmox 내부 사용자 DB를 사용한다. PAM Realm은 리눅스 로컬 계정과 동기화된다. 자동화 계정은 PVE Realm이 관리가 편하다.

6.3 API 토큰 발급 ​

Datacenter → Permissions → Users → (계정 선택) → API Tokens → Add:

  • Token ID: 영소문자·숫자·하이픈·언더스코어만 허용
  • Token 식별자 형식: 유저명@realm!토큰ID (예: admin@pve!cmp-token)

토큰 비밀값(UUID)은 생성 직후 한 번만 표시된다. 반드시 즉시 복사해둘 것.

6.4 토큰 권한 부여 ​

Datacenter → Permissions → Add → API Token Permission:

  • Path: /
  • API Token: 드롭다운에서 생성한 토큰 선택
  • Role: PVEAdmin

6.5 Privilege Separation (권한 분리) ​

API 토큰 생성 시 Privilege Separation 체크박스가 있다. 이 설정이 토큰의 실효 권한을 결정하는 핵심이다.

모드privsep동작 방식
Privilege Separation 해제0토큰 권한 = 소유자 계정 권한. 소유자가 할 수 있는 모든 것이 가능
Privilege Separation 활성1토큰에 별도 ACL을 추가로 부여해야 동작. 소유자 권한과 토큰 ACL의 **교집합(Intersection)**이 실효 권한이 됨

privsep=1 모드에서는 소유자 계정에 PVEAdmin이 있더라도, 토큰에 명시적으로 ACL을 부여하지 않으면 아무 권한도 없다. 용도별로 최소 권한만 부여하는 것이 보안 원칙에 부합한다.

bash
# CLI로 토큰 생성 (privsep=1)
pveum user token add admin@pve cmp-token --privsep 1

# 토큰에 최소 권한 부여 (예: VM 관리만)
pveum acl modify / --token 'admin@pve!cmp-token' --role PVEVMAdmin

CMP 백엔드에서 Proxmox와의 상시 연결에는 API Token 방식을 사용해야 한다. Ticket(PVEAuthCookie) 방식은 유효기간이 2시간이라 갱신 로직이 필요하고 불필요한 상태 관리 복잡도가 생긴다.

6.6 시행착오: Key IDs 필드 혼동 ​

User 메뉴의 Key IDs 필드에 API 토큰 값을 입력 시도 → regex 에러 발생:

log
Parameter verification failed. (400)
keys: value does not match the regex pattern

원인: Key IDs 필드는 SSH 공개키 등록 전용이다. API 토큰은 생성 시 자동으로 계정에 귀속되며, 권한은 Datacenter → Permissions에서 별도 부여한다. 서로 다른 개념이다.


7. 알림 설정 (Postfix + Daum 메일) ​

Proxmox Datacenter 알림을 이메일로 수신하려면 Postfix를 SMTP 릴레이로 구성해야 한다.

7.1 CA 인증서 갱신 ​

bash
apt install -y ca-certificates
update-ca-certificates -f
ls -l /etc/ssl/certs/ca-certificates.crt   # 파일 존재 확인

7.2 Postfix 설정 ​

/etc/postfix/main.cf를 직접 편집하는 대신 postconf -e로 개별 항목을 적용한다. postconf -e는 해당 키가 없으면 추가하고, 있으면 덮어쓰므로 멱등적(Idempotent)으로 실행할 수 있다.

bash
postconf -e "relayhost = [smtp.daum.net]:465"
postconf -e "smtp_tls_wrappermode = yes"          # 465 포트 래퍼 모드 강제
postconf -e "smtp_tls_security_level = encrypt"
postconf -e "smtp_sasl_auth_enable = yes"
postconf -e "smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd"
postconf -e "smtp_sasl_security_options = noanonymous"
postconf -e "smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt"
postconf -e "smtp_generic_maps = hash:/etc/postfix/generic"
postconf -e "sender_canonical_maps = hash:/etc/postfix/sender_canonical"
postconf -e "myorigin = internal.example"
postconf -e "myhostname = pve-nodeA.proxmox.internal.example"
postconf -e "smtputf8_enable = no"               # Daum SMTP의 UTF-8 엔벨로프 미지원 대응

smtp_tls_wrappermode = yes의 의미: 표준 STARTTLS(포트 587)는 평문 연결로 시작한 뒤 STARTTLS 명령으로 암호화를 협상한다. 래퍼(Wrapper) 모드는 TCP 연결 즉시 TLS 핸드셰이크를 수행하는 방식으로, 포트 465(SMTPS)가 이 방식을 사용한다. Daum SMTP는 465 포트에서 래퍼 모드만 허용하므로 이 옵션이 없으면 연결이 실패한다.

smtputf8_enable = no의 의미: RFC 6531(SMTPUTF8) 확장을 비활성화한다. Postfix 일부 버전에서 기본값이 yes인데, Daum SMTP가 이 확장을 지원하지 않아 501 5.5.4 에러가 발생하는 경우가 있다.

7.3 인증 정보 등록 ​

bash
# /etc/postfix/sasl_passwd — Daum 앱 비밀번호 사용 (계정 패스워드 아님)
echo "[smtp.daum.net]:465 your_id@daum.net:<앱-비밀번호>" > /etc/postfix/sasl_passwd

# /etc/postfix/generic — 시스템 내부 주소를 외부 발신 주소로 리라이팅
cat > /etc/postfix/generic << 'EOF'
@pve-nodeA.proxmox.internal.example  your_id@daum.net
root                         your_id@daum.net
MAILER-DAEMON                your_id@daum.net
EOF

7.4 발신자 주소(From) 덮어쓰기 ​

generic 맵은 수신자(Recipient) 측 주소는 건드리지 않는다. Postfix가 메일을 발송할 때 사용하는 엔벨로프 발신자(Envelope Sender)와 From: 헤더가 Daum 인증 계정과 일치하지 않으면 릴레이 서버가 거부하는 경우가 있다. sender_canonical로 발신자 주소를 명시적으로 덮어쓴다.

bash
cat > /etc/postfix/sender_canonical << 'EOF'
root    your_id@daum.net
pve-nodeA your_id@daum.net
EOF

7.5 권한 설정 및 반영 ​

bash
postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/generic
postmap /etc/postfix/sender_canonical

chmod 600 /etc/postfix/sasl_passwd     /etc/postfix/sasl_passwd.db
chmod 600 /etc/postfix/generic         /etc/postfix/generic.db
chmod 600 /etc/postfix/sender_canonical /etc/postfix/sender_canonical.db

systemctl restart postfix

postmap은 텍스트 파일을 Postfix가 읽는 Berkeley DB(.db) 해시 파일로 변환한다. 텍스트 파일을 수정할 때마다 postmap을 다시 실행해야 변경이 반영된다.

7.6 발송 큐 초기화 및 진단 ​

설정 변경 전 실패했던 메일이 큐에 남아있으면 이전 설정으로 재시도를 계속 시도한다. 큐를 비운 뒤 재시작해야 깨끗하게 적용된다.

bash
# 현재 큐 상태 확인
mailq

# 전체 큐 삭제 (이전 실패 메일 일괄 제거)
postsuper -d ALL

# 설정 재적용
systemctl restart postfix
postmap /etc/postfix/sasl_passwd

# SMTP 세션 로그 실시간 확인
journalctl -t postfix/smtp -f

# Postfix 전체 유닛 로그 (최근 20줄)
journalctl -u postfix -u "postfix@*" -n 20 --no-pager

# SMTP 로그 끝에서부터 확인
journalctl -t postfix/smtp -e --no-pager

Proxmox가 발송하는 알림 메일의 내용은 단순하다. 백업 성공/실패, HA 상태 변경, 업데이트 알림 정도만 포함된다. 실용적인 모니터링이 목적이라면 Alertmanager나 PagerDuty 같은 전용 알림 시스템과 연동하는 편이 낫다.


8. 트러블슈팅 ​

`rrdcached` 에러 / 기타 초기 설정 트러블슈팅 notes/linux/proxmox/06-references/07-troubleshooting#_8-1-rrdcached-rrd-update-error

부록: 검증 체크리스트 ​

bash
# 네트워크
ip a                       # enp0s3 UP, vmbr0에 10.0.2.15 확인
ping -c 2 10.0.2.2         # 게이트웨이 응답 확인
ping -c 2 8.8.8.8          # 외부 통신 확인
ping -c 2 google.com       # DNS 해석 확인

# APT
apt update                 # 에러 없이 패키지 목록 갱신

# SSH (호스트에서)
ssh -p 2222 root@127.0.0.1 # 키 인증으로 패스워드 없이 접속

# 스토리지
lvs                        # data ~29G, root ~26G, swap ~5.8G 확인

# API 토큰 인증 테스트
curl -k -H "Authorization: PVEAPIToken=admin@pve!cmp-token=<UUID>" \
  https://127.0.0.1:8006/api2/json/version
# → data.version 반환 확인