Hiện tại, mình đang chuyển một số ứng dụng web từ VPS bên ngoài về LXC trong homelab ở nhà để tiện việc quản lý. Các ứng dụng web trong mạng nội bộ của mình đều được reverse proxy thông qua một máy chủ Caddy để quản lý truy cập từ internet.
Tuy nhiên, khi thiết lập reverse proxy cho Invoice Ninja, mình gặp phải tình huống là cấu hình cài đặt đã bao gồm sẵn 1 docker container chạy Caddy để làm reverse proxy cho ứng dụng, kết nối thông qua tên miền https://invoice.thuanbui.me
Máy chủ Caddy này sau khi đượ chuyển về homelab, sẽ nằm ở phía sau máy chủ Caddy chính, khiến việc cấu hình Reverse Proxy trở nên rắc rối hơn.
Mục Lục
1. Mô hình kết nối
Mô hình kết nối từ Internet đến Invoice Ninja sẽ như bên dưới
[Internet] → [Caddy Chính] → [Caddy Phụ] → [Invoice Ninja]
Code language: CSS (css)
- Caddy Chính (Máy chủ chính / Router)
- Chịu trách nhiệm nhận request từ internet.
- Quản lý chứng chỉ SSL từ Let’s Encrypt.
- Chuyển tiếp request đến Secondary Caddy trong mạng nội bộ.
- Caddy Phụ (LXC Container)
- Chạy Invoice Ninja.
- Không cần HTTPS vì HTTPS được xử lý bởi Primary Caddy.
Dưới đây là cách cấu hình kết nối Kết nối hai máy chủ Caddy để chạy ứng dụng web nội bộ qua HTTPS
2. Cấu hình Caddy chính
Chỉnh sửa lại Caddyfile trên máy chủ chính, bổ sung cấu hình cho tên miền dùng để truy cập Invoice Ninja
invoice.thuanbui.me {
reverse_proxy 192.168.1.120:80 {
header_up X-Forwarded-Proto https
}
}
Code language: YAML (yaml)
Giải thích:
192.168.1.120:80
là địa chỉ của LXC Container đang chạy Caddy phụ.header_up X-Forwarded-Proto https
thông báo cho Caddy phụ biết request ban đầu là HTTPS, tránh lỗi Mixed Content.
Sau đó, khởi động lại Caddy:
docker compose restart
Code language: Nginx (nginx)
3. Cấu hình Caddy phụ
Cấu hình ban đầu của Caddyfile
như sau
invoice.thuanbui.me
root * /var/www/app/public
php_fastcgi dockerfiles-app-1:9000
encode zstd gzip
file_server browse
}
Code language: PHP (php)
Mình phải sửa dòng invoice.thuanbui.me
thành http://invoice.thuanbui.me
, để Caddy phụ không tạo SSL nữa (có tạo cũng bị lỗi không xác thực được).
http://invoice.purna.vn {
root * /var/www/app/public
php_fastcgi dockerfiles-app-1:9000
encode zstd gzip
file_server browse
header {
Content-Security-Policy upgrade-insecure-requests
}
}
Code language: PHP (php)
Giải thích:
http://
Chạy trên giao thức HTTP vì HTTPS đã được xử lý bởi Caddy chính.Content-Security-Policy upgrade-insecure-requests
giúp trình duyệt tự động chuyển HTTP → HTTPS.
Sau đó, khởi động lại
docker compose restart
Code language: Nginx (nginx)
5. Kiểm tra & Hoàn tất
Truy cập lại vào Invoice Ninja thông qua tên miền.
Nếu mọi thứ hoạt động đúng, bạn đã hoàn thành việc thiết lập hai Caddy instance hoạt động cùng nhau trong mạng nội bộ!
6. Lời kết
Trong bài viết này, mình đã hướng dẫn cách sử dụng hai máy chủ Caddy để quản lý ứng dụng web nội bộ với Reverse Proxy. Điều này giúp bạn dễ dàng:
- Quản lý hệ thống linh hoạt hơn, tách biệt frontend / backend.
- Sử dụng HTTPS trên mọi ứng dụng, ngay cả khi chúng chạy trong mạng nội bộ.
- Dễ dàng mở rộng, chỉ cần chỉnh sửa Caddy chính để thêm dịch vụ mới.
Nếu bạn có thắc mắc, hãy để lại bình luận bên dưới nhé!
Hi anh, em gặp lỗi khi cố gắng cài Invoice Ninja với 2 Caddy như hướng dẫn ạ
invoiceninja | Error Output:
invoiceninja | ================
invoiceninja | mysql: Deprecated program name. It will be removed in a future release, use
invoiceninja | ‘/usr/bin/mariadb’ instead
invoiceninja | ERROR 2026 (HY000): TLS/SSL error: SSL is required, but the server does not
invoiceninja | support it
Cho em hỏi chỗ IP này là local IP của host mình cài Invoice lên nhỉ?
– “in5.localhost:192.168.0.124 ” #host and ip
Phần đó anh không chỉnh sửa gì cả. Để mặc định.
Rất tiếc cái này anh không rõ nhé. Em thử xóa hết làm lại xem sao. Nếu cần hỗ trợ riêng thì liên hệ đặt dịch vụ nhé.