# Sao lưu với PBS (Simple)

<span style="white-space: pre-wrap;">Sao lưu PVE sẽ chia làm 2 phần. </span>

- Sao lưu VM/CTs: Được PBS hỗ trợ nên có thể thực hiện đơn giản trên GUI
- Sao lưu cấu hình PVE: Phần này phải sử dụng script

### Sao lưu cấu hình PVE

<span style="white-space: pre-wrap;">Vì PVE không có chức năng backup cấu hình nên chúng ta sẽ cần sử dụng script và dùng </span>**systemd timer**<span style="white-space: pre-wrap;"> để lên lịch backup tự động. </span>

#### Backup script

Trước khi bắt đầu với script chúng ta cần chuẩn bị 2 thứ là PBS API Token và Fingerprint

- Fingerprint
    - PBS Web &gt; Dashboard &gt; Show fingerprint
- API Token
    - <span style="white-space: pre-wrap;">PBS Web &gt; Configuration &gt; Access Control &gt; API Token </span>
    - <span style="white-space: pre-wrap;">Nếu chưa có hãy thêm mới. Sau khi nhấn </span>**Add**<span style="white-space: pre-wrap;"> bạn sẽ nhận được Token ID và Sceret. Hãy lưu lại để dùng ở bước tiếp theo.</span>  
        [![image.png](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/scaled-1680-/image.png)](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/image.png)

<span style="white-space: pre-wrap;">Tạo script backup bằng lệnh </span>`<span class="editor-theme-code">nano /usr/local/bin/pve-host-backup.sh</span>`<span style="white-space: pre-wrap;"> với nội dung sau. Điền thông tin đã chuẩn bị vào phần Cấu hình.</span>

```sh
#!/usr/bin/env bash
set -euo pipefail

########################################
# CẤU HÌNH PBS
########################################
# IP/FQDN PBS và Datastore
PBS_HOST='PBS IP'
PBS_DATASTORE='Datastore'

PBS_USER_TOKEN='Token ID'
PBS_TOKEN_SECRET='API Token Sceret'
PBS_FINGERPRINT='Fingerprint'

########################################
# TUỲ CHỌN CHUNG
########################################
BACKUP_ID="${BACKUP_ID:-"$(hostname)-hostcfg"}"
DRY_RUN="${DRY_RUN:-0}"

export PBS_REPOSITORY="${PBS_USER_TOKEN}@${PBS_HOST}:${PBS_DATASTORE}"
export PBS_PASSWORD="${PBS_TOKEN_SECRET}"
export PBS_FINGERPRINT="${PBS_FINGERPRINT}"

########################################
# NGUỒN BACKUP (CHỈ THƯ MỤC, KHÔNG FILE LẺ)
########################################
SOURCES=(
  "pve-etc.pxar:/etc"                           # Bao trọn: pve, network, hosts, resolv.conf, hostname, apt, ssh, default, kernel, modules, modprobe.d, sysc>
  "pve-cron.pxar:/etc/cron.d"                   # Cron.d
  "pve-crontabs.pxar:/var/spool/cron/crontabs"  # Tất cả crontab user (bao gồm root)
  "pve-root-home.pxar:/root"                    # Script & key quản trị (cân nhắc exclude bớt)
  "pve-usrlocal.pxar:/usr/local"                # Script/service tự thêm (nếu có)
)

# Loại trừ cho nhẹ (tuỳ bạn chỉnh)
EXCLUDES=(
  "--exclude=/root/*.iso"
  "--exclude=/root/*.img"
  "--exclude=/root/.cache"
)

########################################
# TIỀN KIỂM TRA
########################################
echo "[*] Checking PBS login..."
proxmox-backup-client login --repository "${PBS_REPOSITORY}"

########################################
# THỰC HIỆN BACKUP
########################################
echo "[*] Starting host-config backup (backup-id=${BACKUP_ID})"
CMD=(proxmox-backup-client backup)
CMD+=("${SOURCES[@]}")
CMD+=("${EXCLUDES[@]}")
CMD+=(--backup-id "${BACKUP_ID}")
CMD+=(--backup-type host)

if [[ "${DRY_RUN}" == "1" ]]; then
  CMD+=(--dry-run)
  echo "[*] DRY RUN enabled"
fi

# In câu lệnh (ẩn secret) rồi chạy
echo "[*] Running: ${CMD[*]/${PBS_TOKEN_SECRET}/***SECRET***}"
"${CMD[@]}"

echo "[✓] Backup finished"

# Dọn biến nhạy cảm
unset PBS_PASSWORD
```

<span style="white-space: pre-wrap;">Cấp quyền thực thi cho script </span>`<span class="editor-theme-code">chmod +x /usr/local/bin/pve-host-backup.sh</span>`

<span style="white-space: pre-wrap;">Dùng lệnh </span>`<span class="editor-theme-code">DRY_RUN=1 /usr/local/bin/pve-host-backup.sh</span>`<span style="white-space: pre-wrap;"> để kiểm tra. Nếu kết thúc bằng </span>`<span class="editor-theme-code">[✓] Backup finished</span>`<span style="white-space: pre-wrap;"> tức là thành công.</span>

<span style="white-space: pre-wrap;">Dùng lệnh </span>`<span class="editor-theme-code">/usr/local/bin/pve-host-backup.sh</span>`<span style="white-space: pre-wrap;"> để chạy script</span>

#### Lập lịch tự động

Thực hiện trên console hoặc ssh của PVE

- <span style="white-space: pre-wrap;">Tạo file </span>`<span class="editor-theme-code">.service.</span>`<span style="white-space: pre-wrap;"> Đây là hành vi sẽ được thực hiện bởi </span>`<span class="editor-theme-code">.timer</span>`
    - `<span class="editor-theme-code">nano /etc/systemd/system/pve-host-backup.service</span>`
    - Sử dụng nội dung sau  
        `<span class="editor-theme-code">[Unit]</span>`  
        `<span class="editor-theme-code">Description=Backup PVE host configuration to PBS</span>`  
        `<span class="editor-theme-code">After=network-online.target</span>`  
        `<span class="editor-theme-code">[Service]</span>`  
        `<span class="editor-theme-code">Type=oneshot</span>`  
        `<span class="editor-theme-code">ExecStart=/usr/local/bin/pve-host-backup.sh</span>`
- <span style="white-space: pre-wrap;">Tạo file </span>`<span class="editor-theme-code">.timer</span>`<span style="white-space: pre-wrap;">. Nó sẽ thực thi </span>`<span class="editor-theme-code">.service</span>`<span style="white-space: pre-wrap;"> theo thời gian được chỉ định.</span>
    - `<span class="editor-theme-code">nano /etc/systemd/system/pve-host-backup.timer</span>`
    - Sử dụng nội dung sau  
        `<span class="editor-theme-code">[Unit]</span>`  
        `<span class="editor-theme-code">Description=Schedule PVE host config backup (Tue, Thu, Sat at 2:00)</span>`  
        `<span class="editor-theme-code">[Timer]</span>`  
        `<span class="editor-theme-code">OnCalendar=Tue,Thu,Sat 2:00</span>`  
        `<span class="editor-theme-code">Persistent=true</span>`  
        `<span class="editor-theme-code">AccuracySec=1min</span>`  
        `<span class="editor-theme-code">[Install]</span>`  
        `<span class="editor-theme-code">WantedBy=timers.target</span>`
- Kích hoạt timer
    - <span style="white-space: pre-wrap;">Reload systemd </span>`<span class="editor-theme-code">systemctl daemon-reload</span>`
    - <span style="white-space: pre-wrap;">Kích hoạt timer </span>`<span class="editor-theme-code">systemctl enable --now pve-host-backup.timer</span>`
- <span style="white-space: pre-wrap;">Kiểm tra </span>
    - `<span class="editor-theme-code">systemctl list-timers | grep backup</span>`
    - `<span class="editor-theme-code">systemctl status pve-host-backup.timer</span>`
    - Kết quả tương tự như hình sau  
        [![image.png](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/scaled-1680-/rNpimage.png)](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/rNpimage.png)

Kết quả kiểm tra  
`<span class="editor-theme-code">Mon 2025-11-10 00:00:00 +07 20h Sun 2025-11-09 00:00:43 +07 3h 47min ago dpkg-db-backup.timer dpkg-db-backup.service</span>`  
`<span class="editor-theme-code">Tue 2025-11-11 02:00:00 +07 1 day 22h - - backup.timer backup.service</span>`

#### Tự động Verify sau khi backup

Chuẩn bị ssh key trên PVE

- <span style="white-space: pre-wrap;">Tạo </span>**cặp khóa SSH (public/private key)**<span style="white-space: pre-wrap;"> cho tài khoản </span>`<span class="editor-theme-code">root</span>`<span style="white-space: pre-wrap;"> trên máy PVE</span>  
    `<span class="editor-theme-code">ssh-keygen -t ed25519 -N "" -f /root/.ssh/id_ed25519</span>`
- <span style="white-space: pre-wrap;">Sao chép public key (file .pub) từ máy PVE sang máy PBS, để PBS cho phép </span>`<span class="editor-theme-code">root@PVE</span>`<span style="white-space: pre-wrap;"> đăng nhập mà không cần mật khẩu.</span>  
    `<span class="editor-theme-code">ssh-copy-id -i /root/.ssh/id_ed25519.pub root@192.168.1.104</span>`  
    Lần đầu chạy sẽ yêu cầu nhập đúng mật khẩu.
- <span style="white-space: pre-wrap;">Để kiểm tra hãy thử truy cập </span>`<span class="editor-theme-code">ssh root@192.168.1.104</span>`<span style="white-space: pre-wrap;"> nếu không yêu cầu mật khẩu là thành công.</span>

<span style="white-space: pre-wrap;">Thêm code </span>`<span class="editor-theme-code">post-verify</span>`<span style="white-space: pre-wrap;"> vào cuối script backup trên.</span>

```sh
# ==== POST: VERIFY DATASTORE TRÊN PBS SAU KHI BACKUP THÀNH CÔNG ====
if [[ "${DRY_RUN}" != "1" ]]; then
  echo "[*] Trigger verify on PBS for datastore '${PBS_DATASTORE}' ..."
  # Chạy verify toàn datastore. Mặc định --ignore-verified=true nên chỉ verify snapshot mới/chưa verified
  # hoặc snapshot đã quá hạn theo --outdated-after
  ssh -o BatchMode=yes root@"${PBS_HOST}" \
    "proxmox-backup-manager verify '${PBS_DATASTORE}' --ignore-verified true --outdated-after 7" \
    && echo '[✓] Verify job started on PBS' \
    || echo '[!] Failed to start verify job on PBS'
fi
```

### Sao lưu VM/CTs

Mục tiêu là lên lịch để PVE tự động chạy backup mỗi thứ 3, 5, 7 vào lúc 4h và thực hiện verify sau đó vào lúc 5h

#### Lên lịch backup

- PVE web &gt; Datacenter &gt; Backup &gt; Add
    - Storage: Chọn PBS đã thêm ở bước cài đặt
    - <span style="white-space: pre-wrap;">Schedule: Điền </span>**tue,thu,sat 04:00** để chọn thứ 3, 5, 7 vào lúc 4h. Thay đổi tùy ý
    - Selection mode: All (hoặc các lựa chọn khác nếu muốn)
    - Mode: Snapshot
    - Enable: true
    - **Add**
- [![image.png](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/scaled-1680-/dhaimage.png)](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/dhaimage.png)

#### Lên lịch verify

- PBS web &gt; Datastore &gt; Verify Jobs &gt; Add
    - Local Datastore: chọn datastore đã tạo khi cài đặt
    - <span style="white-space: pre-wrap;">Schedule: </span>**tue,thu,sat 05:00** để lên lịch verify lúc 5h, sau khi backup
    - Skip Verified: chọn để bỏ qua những file đã verified. tiết kiệm tài nguyên
    - Re-Verify After: 7 ngày. Verify lại những file đã verify quá 7 ngày
    - **Add**
- [![image.png](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/scaled-1680-/rRhimage.png)](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/rRhimage.png)

### Lưu ý

<span style="white-space: pre-wrap;">Với task backup cho DSM. PVE sẽ thực hiện backup tất cả các ổ đĩa được passthrough cho DSM nên dung lượng cần backup là </span>**rất lớn**<span style="white-space: pre-wrap;">, và điều này cũng là </span>**không cần thiết**<span style="white-space: pre-wrap;"> vì DSM đã sử dụng Hyper Backup.</span>

Để tắt backup cho 2 ổ cứng này PVE Web &gt; pve &gt; VM DSM &gt; Hardware &gt; Disk. Tick chọn Advanced &gt; Bỏ tích Backup

[![image.png](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/scaled-1680-/OL4image.png)](https://knowledge.thanhdv.com/uploads/images/gallery/2025-11/OL4image.png)