Khi chuyển khoảng 20 microservice nội bộ từ Docker Swarm sang Fedora Server chạy Podman, rào cản lớn nhất của mình là cấu hình Nginx. Cứ mỗi lần dựng container mới, quy trình lại lặp lại: mở nginx.conf, viết block upstream, reload service rồi chạy Certbot lấy SSL. Chỉ cần ai đó gõ nhầm một dấu chấm phẩy, cả cụm proxy gián đoạn. Traefik giải quyết dứt điểm sự cồng kềnh này: tự đọc event từ socket của Podman, định tuyến qua nhãn (labels) và xin chứng chỉ Let’s Encrypt tự động.
Fedora là môi trường lý tưởng cho Podman vì được Red Hat ưu tiên cập nhật kernel mới và tích hợp sâu cgroups v2. Kết hợp Traefik v3 với Podman trên Fedora 39/40 mang lại một cụm proxy nhẹ, chạy ổn định và tốn rất ít công bảo trì.
Quick start (triển khai trong 5 phút)
Chuẩn bị trước một tên miền đã trỏ bản ghi A/AAAA về IP máy chủ Fedora, đồng thời mở port 80 và 443 trên firewall:
sudo firewall-cmd --permanent --add-port={80,443}/tcp
sudo firewall-cmd --reload
1. Kích hoạt Podman System Socket
Traefik giao tiếp với Podman qua socket tương thích chuẩn Docker API. Hãy kích hoạt socket cấp systemd:
sudo systemctl enable --now podman.socket
# Kiểm tra socket đã hoạt động chưa
curl -s --unix-socket /run/podman/podman.sock http://d/v1.41/version | jq .Version
2. Tạo thư mục và file cấu hình cho Traefik
Tạo một thư mục riêng tại /opt/traefik để chứa cấu hình và file lưu chứng chỉ:
sudo mkdir -p /opt/traefik
cd /opt/traefik
sudo touch acme.json
sudo chmod 600 acme.json
Tạo file cấu hình tĩnh traefik.yml:
api:
dashboard: true
insecure: false
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to: websecure
scheme: https
websecure:
address: ":443"
providers:
docker:
endpoint: "unix:///var/run/docker.sock"
exposedByDefault: false
certificatesResolvers:
letsencrypt:
acme:
email: "[email protected]"
storage: "/acme.json"
httpChallenge:
entryPoint: web
Lưu ý: Thay [email protected] bằng email thật để nhận cảnh báo khi chứng chỉ sắp hết hạn.
3. Khởi chạy Traefik bằng Podman Compose
Tạo file /opt/traefik/compose.yml:
version: "3.8"
services:
traefik:
image: docker.io/library/traefik:v3.0
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
security_opt:
- label=disable
volumes:
- /run/podman/podman.sock:/var/run/docker.sock:ro
- /opt/traefik/traefik.yml:/traefik.yml:ro,z
- /opt/traefik/acme.json:/acme.json:z
networks:
- proxy-net
networks:
proxy-net:
name: proxy-net
Chạy container Traefik:
podman compose up -d
4. Dựng thử một ứng dụng test có SSL
Dựng một web server Nginx nhỏ để xác thực tính năng tự động cấp chứng chỉ:
podman run -d --name demo-web \
--network proxy-net \
--label "traefik.enable=true" \
--label "traefik.http.routers.demo.rule=Host(\`app.example.com\`)" \
--label "traefik.http.routers.demo.entrypoints=websecure" \
--label "traefik.http.routers.demo.tls.certresolver=letsencrypt" \
--label "traefik.http.services.demo.loadbalancer.server.port=80" \
docker.io/library/nginx:alpine
Truy cập https://app.example.com trên trình duyệt. Bạn sẽ thấy kết nối HTTPS hợp lệ ngay sau khoảng 3 đến 5 giây mà không cần cấu hình thêm bất kỳ dòng lệnh Nginx nào trên host.
Bản chất kỹ thuật cần nắm rõ
Cơ chế Provider và Docker API Compatibility
Traefik không polling container định kỳ. Thay vào đó, nó lắng nghe trực tiếp luồng event từ podman.socket.
Khi bạn gõ podman run hoặc tắt container, Traefik bắt được tín hiệu ngay tức khắc. Bảng định tuyến trong RAM được cập nhật lại sau chưa đầy 10 mili-giây. Toàn bộ quá trình diễn ra ngầm, không reload tiến trình và không làm rớt các kết nối TCP hiện có.
Nhờ Podman cung cấp API chuẩn Docker qua Unix socket, Traefik dùng thẳng provider docker có sẵn mà không cần cài thêm plugin ngoài.
Xử lý rào cản SELinux trên Fedora Server
Fedora bật SELinux ở chế độ Enforcing theo mặc định. Nếu mount file hoặc socket thiếu ngữ cảnh bảo mật, container sẽ dính lỗi Permission Denied ngay lập tức.
Các điểm mấu chốt cần lưu ý:
- Flag
:zở volume gán nhãn SELinux chia sẻ (shared contextcontainer_file_t) cho file cấu hìnhtraefik.ymlvàacme.json. - Tuyệt đối không dùng cờ
:zvới file socket hệ thống/run/podman/podman.sock. Việc relabel socket hệ thống có thể gây lỗi quyền cho systemd. Thay vào đó, hãy vô hiệu hóa hạn chế nhãn trên riêng container Traefik bằng tùy chọnsecurity_opt: ["label=disable"].
Vòng đời cấp phát SSL Let’s Encrypt
Khi request đầu tiên gửi tới domain app.example.com qua port 443:
- Traefik kiểm tra file
acme.json. - Nếu chưa có cert, Traefik kích hoạt ACME client gửi yêu cầu cấp mới đến Let’s Encrypt.
- Let’s Encrypt gửi challenge
HTTP-01về port 80. Traefik chặn riêng request này và trả về token xác thực hợp lệ. - Sau khi xác thực thành công, Let’s Encrypt gửi về cặp chứng chỉ cùng khóa riêng tư (private key).
- Traefik lưu thông tin vào
acme.jsonrồi nạp thẳng vào bộ nhớ. Khi hạn dùng của chứng chỉ còn dưới 30 ngày, Traefik sẽ tự động renew định kỳ.
Cấu hình nâng cao
1. Bảo vệ Dashboard của Traefik bằng Basic Auth
Dashboard mặc định đã tắt chế độ công khai (insecure: false). Để mở dashboard qua subdomain riêng (như traefik.example.com), ta kết nối router tới service nội bộ api@internal kèm middleware xác thực:
# Tạo hash mật khẩu (cài đặt: sudo dnf install -y httpd-tools)
htpasswd -nb admin MatKhauManh_2026@Secure
Khai báo thêm labels cho service Traefik trong compose.yml:
labels:
- "traefik.enable=true"
- "traefik.http.routers.dashboard.rule=Host(`traefik.example.com`)"
- "traefik.http.routers.dashboard.service=api@internal"
- "traefik.http.routers.dashboard.entrypoints=websecure"
- "traefik.http.routers.dashboard.tls.certresolver=letsencrypt"
- "traefik.http.routers.dashboard.middlewares=auth"
- "traefik.http.middlewares.auth.basicauth.users=admin:$$apr1$$xyz...chuoi_hash_o_tren"
Lưu ý: Trong file compose, mọi ký tự $ trong chuỗi mật khẩu hash phải được viết thành $$ để tránh bị hiểu nhầm là biến môi trường.
2. Cấp chứng chỉ Wildcard qua DNS-01 Challenge (Cloudflare)
Phương thức HTTP-01 bị giới hạn: không cấp được chứng chỉ wildcard dạng *.example.com và bắt buộc server phải mở port 80 ra Internet. Với các service nội bộ, DNS challenge là lựa chọn tối ưu:
# Bổ sung vào traefik.yml
certificatesResolvers:
dns-cloudflare:
acme:
email: "[email protected]"
storage: "/acme.json"
dnsChallenge:
provider: cloudflare
resolvers:
- "1.1.1.1:53"
- "8.8.8.8:53"
Thêm API token của Cloudflare vào biến môi trường trong file compose của Traefik:
environment:
- CF_DNS_API_TOKEN=vj98aX_example_cloudflare_token
Kinh nghiệm vận hành thực tế trên Production
Vài lưu ý quan trọng giúp bạn tránh sự cố khi vận hành hệ thống:
- Chế độ phân quyền của file
acme.json: Traefik sẽ lập tức dừng khởi động nếu file này có quyền khác600. Nếu bạn vô tình dùng lệnhchmodthành644hoặc copy đè từ máy khác sang, Traefik sẽ báo lỗipermissions 0644 for /acme.json are too open. - Cẩn thận với rate-limit của Let’s Encrypt: Khi thử nghiệm cấu hình, hãy trỏ tạm về staging server bằng cách thêm
caServer: "https://acme-staging-v02.api.letsencrypt.org/directory". Let’s Encrypt áp trần 5 lần thử thất bại mỗi giờ cho một account/hostname. Vượt ngưỡng này, IP của bạn sẽ bị tạm khóa cấp cert. - Bật Access Log dạng JSON để tiện trace lỗi: Thêm
accessLog: { format: json }vào file cấu hình. Định dạng JSON giúp bạn lọc và đẩy log trực tiếp qua Fluentbit/Promtail về Grafana Loki, hiển thị rõ thời gian phản hồi upstream và HTTP status của từng container. - Lỗi 404 do lệch Network: 90% trường hợp web báo lỗi 404 sau khi gắn label là do container ứng dụng chưa join vào network
proxy-netcùng Traefik. Bridge network mặc định của Podman không tự phân giải tên máy chủ giữa các container với nhau.

