1. Cấu hình Backup tự động cho Database OpenZiti và IdP trên Proxmox
1.1. Backup cơ sở dữ liệu OpenZiti (PostgreSQL)
OpenZiti lưu trữ toàn bộ trạng thái định tuyến, chứng chỉ và cấu hình trong PostgreSQL. Mất dữ liệu này đồng nghĩa với việc mất toàn bộ kiến trúc Zero-Trust.
Tạo script backup tự động nén dữ liệu và đẩy về thư mục lưu trữ an toàn trên Proxmox. Script này sẽ chạy theo lệnh cron.
Đường dẫn: /opt/scripts/backup_ziti_db.sh
Nội dung script:
#!/bin/bash
# Cấu hình biến môi trường
DB_NAME="ziti"
DB_USER="ziti"
BACKUP_DIR="/var/backup/ziti/db"
DATE=$(date +%Y%m%d_%H%M%S)
RETENTION_DAYS=7
# Tạo thư mục backup nếu chưa tồn tại
mkdir -p $BACKUP_DIR
# Thực hiện dump database PostgreSQL
PGPASSWORD=$DB_PASS psql -U $DB_USER -d $DB_NAME -c "\q" 2>/dev/null
pg_dump -U $DB_USER -d $DB_NAME -Fc > $BACKUP_DIR/ziti_db_$DATE.dump
# Nén file dump để tiết kiệm dung lượng
gzip -f $BACKUP_DIR/ziti_db_$DATE.dump
# Xóa các bản backup cũ hơn $RETENTION_DAYS
find $BACKUP_DIR -name "ziti_db_*.dump.gz" -mtime +$RETENTION_DAYS -delete
# Kiểm tra kích thước file mới nhất
LATEST_FILE=$(ls -t $BACKUP_DIR/*.gz 2>/dev/null | head -1)
if [ -n "$LATEST_FILE" ]; then
echo "Backup thành công: $(stat -c%s $LATEST_FILE) bytes"
else
echo "Lỗi: Không tạo được file backup"
exit 1
fi
Kết quả mong đợi: File ziti_db_YYYYMMDD_HHMMSS.dump.gz xuất hiện trong thư mục /var/backup/ziti/db. Script in ra kích thước file.
1.2. Backup cấu hình IdP (Keycloak/Duo/Okta)
Giả sử bạn đang dùng Keycloak làm IdP nội bộ. Cần backup cả database và thư mục imports chứa cấu hình Realm.
Đường dẫn: /opt/scripts/backup_keycloak.sh
#!/bin/bash
KEYCLOAK_DB="keycloak"
KEYCLOAK_USER="keycloak"
BACKUP_DIR="/var/backup/ziti/idp"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
# Backup Database
pg_dump -U $KEYCLOAK_USER -d $KEYCLOAK_DB | gzip > $BACKUP_DIR/keycloak_db_$DATE.sql.gz
# Backup thư mục imports (nếu có custom realm)
if [ -d /opt/keycloak/data/import ]; then
tar -czf $BACKUP_DIR/keycloak_imports_$DATE.tar.gz /opt/keycloak/data/import
fi
echo "Backup IdP hoàn tất vào $BACKUP_DIR"
1.3. Cài đặt Cron Job trên Proxmox Host
Chạy backup tự động hàng ngày lúc 2 giờ sáng để giảm tải cho hệ thống.
Sửa file crontab của root trên Proxmox Host hoặc container chứa database.
crontab -e
Nội dung thêm vào file crontab:
0 2 * * * /opt/scripts/backup_ziti_db.sh >> /var/log/ziti_backup.log 2>&1
0 3 * * * /opt/scripts/backup_keycloak.sh >> /var/log/ziti_backup.log 2>&1
Verify: Chạy lệnh crontab -l để xác nhận job đã được thêm. Kiểm tra file log /var/log/ziti_backup.log sau khi script chạy xong.
2. Thiết lập kiến trúc High Availability (HA) cho OpenZiti Controller
2.1. Kiến trúc Multi-Controller với Shared Database
OpenZiti Controller không chạy HA cluster tự động như Kubernetes. Để đạt HA, ta cần triển khai nhiều instance Controller (ví dụ: 2 node) cùng trỏ vào một PostgreSQL duy nhất.
Yêu cầu: 2 VM chạy Controller, 1 VM chạy PostgreSQL (đã backup ở bước 1).
Cấu hình file controller.yml trên cả 2 node Controller phải giống hệt nhau, ngoại trừ địa chỉ IP quảng bá (advertise address).
Đường dẫn: /etc/ziti/controller/controller.yml (Trên Controller-1)
apiVersion: controller.v1
name: ziti-controller
database:
type: postgres
host: 192.168.1.50
port: 5432
name: ziti
user: ziti
password: YOUR_DB_PASSWORD
sslmode: require
sslcert: /etc/ziti/ssl/ziti-controller-ca.pem
sslkey: /etc/ziti/ssl/ziti-controller-key.pem
sslrootcert: /etc/ziti/ssl/ziti-controller-ca.pem
pool:
max: 50
min: 10
api:
listen: "0.0.0.0:1280"
caCertPath: /etc/ziti/ssl/ziti-controller-ca.pem
caKeyPath: /etc/ziti/ssl/ziti-controller-key.pem
certPath: /etc/ziti/ssl/ziti-controller.pem
keyPath: /etc/ziti/ssl/ziti-controller-key.pem
advertise: "192.168.1.10:1280"
edge:
listen: "0.0.0.0:1279"
caCertPath: /etc/ziti/ssl/ziti-controller-ca.pem
caKeyPath: /etc/ziti/ssl/ziti-controller-key.pem
certPath: /etc/ziti/ssl/ziti-controller.pem
keyPath: /etc/ziti/ssl/ziti-controller-key.pem
advertise: "192.168.1.10:1279"
Đường dẫn: /etc/ziti/controller/controller.yml (Trên Controller-2)
Lưu ý: Thay đổi phần advertise thành IP của Controller-2.
api:
advertise: "192.168.1.11:1280"
edge:
advertise: "192.168.1.11:1279"
Kết quả mong đợi: Khi khởi động, cả 2 Controller đều kết nối được vào DB và lắng nghe trên cổng 1280/1279. Không có lỗi database connection error.
2.2. Cấu hình Load Balancer (HAProxy) trước Controller
Để Edge Router và Client không cần biết IP cụ thể của Controller, ta dùng HAProxy để cân bằng tải.
Đường dẫn: /etc/haproxy/haproxy.cfg
global
log stdout format raw local0
maxconn 256000
defaults
log global
mode tcp
option tcplog
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
frontend ziti-api
bind *:1280
default_backend ziti-api-servers
frontend ziti-edge
bind *:1279
default_backend ziti-edge-servers
backend ziti-api-servers
balance roundrobin
server ziti-ctrl-1 192.168.1.10:1280 check
server ziti-ctrl-2 192.168.1.11:1280 check
backend ziti-edge-servers
balance roundrobin
server ziti-ctrl-1 192.168.1.10:1279 check
server ziti-ctrl-2 192.168.1.11:1279 check
Verify: Chạy lệnh telnet IP_HAProxy 1280 từ máy khác. Nếu cả 2 Controller đều sống, kết nối sẽ thành công. Tắt 1 Controller, kết nối vẫn duy trì.
3. Cấu hình HA cho Edge Router
3.1. Triển khai nhiều Edge Router
Edge Router đóng vai trò điểm cuối (endpoint) để Client kết nối. Cần ít nhất 2 Edge Router trên các VM khác nhau để tránh điểm chết (single point of failure).
Cấu hình file router.yml trên Edge Router-1 và Edge Router-2.
Đường dẫn: /etc/ziti/router/router.yml
apiVersion: router.v1
name: ziti-edge-router-1
identity:
path: /etc/ziti/router/ziti-edge-router-1.id
api:
listen: "0.0.0.0:1280"
caCertPath: /etc/ziti/ssl/ziti-ca.pem
caKeyPath: /etc/ziti/ssl/ziti-ca-key.pem
certPath: /etc/ziti/ssl/ziti-edge-router-1.pem
keyPath: /etc/ziti/ssl/ziti-edge-router-1-key.pem
advertise: "192.168.1.20:1280"
edge:
listen: "0.0.0.0:1279"
caCertPath: /etc/ziti/ssl/ziti-ca.pem
caKeyPath: /etc/ziti/ssl/ziti-ca-key.pem
certPath: /etc/ziti/ssl/ziti-edge-router-1.pem
keyPath: /etc/ziti/ssl/ziti-edge-router-1-key.pem
advertise: "192.168.1.20:1279"
transports:
- name: t1
type: tcp
bindAddr: "0.0.0.0:3020"
dialAddresses:
- "192.168.1.10:3020" # Connect to Controller LB
- "192.168.1.11:3020" # Fallback
advertise: "192.168.1.20:3020"
Lưu ý quan trọng: Phần dialAddresses trong transports phải trỏ về địa chỉ HAProxy (IP Controller LB) để đảm bảo nếu Controller bị lỗi, Edge Router vẫn có thể chuyển sang Controller dự phòng.
Trên Edge Router-2: Thay đổi name, identity, advertise và certPath tương ứng với IP 192.168.1.21.
Verify: Chạy lệnh ziti router status trên cả 2 Edge Router. Cả 2 phải hiển thị trạng thái running và connected đến Controller.
4. Lập kế hoạch khôi phục dữ liệu (Disaster Recovery)
4.1. Quy trình khôi phục từ Backup Database
Khi PostgreSQL bị hỏng hoàn toàn hoặc dữ liệu bị xóa, cần thực hiện khôi phục từ file .dump.gz đã tạo ở Phần 1.
Bước 1: Dừng dịch vụ OpenZiti. Không được phép chạy Controller khi đang restore DB để tránh xung đột dữ liệu.
systemctl stop ziti-controller
systemctl stop ziti-edge-router
systemctl stop postgresql
Bước 2: Khôi phục database. Sử dụng pg_restore cho định dạng custom (-Fc) hoặc psql cho SQL text.
# Giả sử file backup mới nhất là ziti_db_20231025_020000.dump.gz
gunzip /var/backup/ziti/db/ziti_db_20231025_020000.dump.gz
pg_restore -U ziti -d ziti -v /var/backup/ziti/db/ziti_db_20231025_020000.dump
Bước 3: Khởi động lại dịch vụ. Đảm bảo PostgreSQL chạy trước, sau đó mới chạy Controller.
systemctl start postgresql
sleep 5
systemctl start ziti-controller
systemctl start ziti-edge-router
Verify: Chạy lệnh ziti controller get entities. Nếu danh sách entities xuất hiện, việc khôi phục thành công.
4.2. Quy trình khôi phục IdP (Keycloak)
Khi IdP bị mất, cần khôi phục Realm để người dùng có thể xác thực lại.
gunzip /var/backup/ziti/idp/keycloak_db_20231025_030000.sql.gz
psql -U keycloak -d keycloak -f /var/backup/ziti/idp/keycloak_db_20231025_030000.sql
Nếu có file imports riêng, cần copy lại vào thư mục dữ liệu của Keycloak trước khi khởi động.
tar -xzf /var/backup/ziti/idp/keycloak_imports_20231025_030000.tar.gz -C /opt/keycloak/data/
systemctl start keycloak
5. Thực hành (Drill) khôi phục hệ thống
5.1. Kịch bản: Mất toàn bộ Controller và Database
Thực hiện bài tập giả lập mất dữ liệu để kiểm tra quy trình DR.
Bước 1: Chuẩn bị môi trường sạch. Tạo một VM mới (Proxmox VM mới) hoặc xóa sạch container Controller hiện tại.
Bước 2: Cài đặt lại phần mềm. Cài đặt PostgreSQL và OpenZiti Controller từ đầu (theo hướng dẫn Phần 1 và 3) nhưng chưa khởi động.
Bước 3: Khôi phục dữ liệu. Copy file backup từ máy lưu trữ sang VM mới và chạy lệnh restore (như mục 4.1).
# Trên VM mới
scp root@backup-server:/var/backup/ziti/db/ziti_db_latest.dump.gz /tmp/
gunzip /tmp/ziti_db_latest.dump.gz
pg_restore -U ziti -d ziti -v /tmp/ziti_db_latest.dump
Bước 4: Cập nhật cấu hình. Đảm bảo file controller.yml trên VM mới trỏ đúng đến database vừa restore (thường là localhost nếu DB chạy cùng VM).
Bước 5: Khôi phục Edge Router. Cấu hình Edge Router trỏ về IP mới của Controller (hoặc qua HAProxy mới).
Bước 6: Test kết nối. Sử dụng Client Zero-Trust (ziti-tunnel hoặc SDK) để kết nối vào dịch vụ được bảo vệ.
ziti tunnel list
ziti tunnel start --name test-tunnel
Kết quả mong đợi: Client kết nối thành công, đường hầm được thiết lập, truy cập được vào service nội bộ. Log không báo lỗi certificate expired hoặc entity not found.
5.2. Kịch bản: Mất Controller-1, Controller-2 nhận toàn bộ tải
Kiểm tra khả năng tự động chuyển đổi (failover) của HAProxy.
Bước 1: Dừng Controller-1.
systemctl stop ziti-controller
Bước 2: Kiểm tra HAProxy stats.
curl http://localhost:8404/stats
Bước 3: Test kết nối từ Client. Client vẫn phải kết nối được mà không bị ngắt quãng quá 5 giây.
Verify: Quan sát log của HAProxy, thấy thông báo server ziti-ctrl-1 chuyển sang trạng thái DOWN và traffic được chuyển hoàn toàn sang ziti-ctrl-2.
Điều hướng series:
Mục lục: Series: Series: Xây dựng nền tảng Zero-Trust Network cho doanh nghiệp với OpenZiti, Cloudflare Access và Identity-aware Proxy trên hạ tầng Proxmox
« Phần 7: Tích hợp log, giám sát và cảnh báo an ninh
Phần 9: Troubleshooting, tối ưu hiệu năng và mẹo nâng cao »