NPM (Nginx Proxy Manager) hiện đang là ứng dụng Reverse Proxy mình sử dụng cho các dịch vụ mạng đang cài đặt trong nhà.
Các bước cài đặt Reverse Proxy thông thường khi dùng NPM sẽ như sau:
- Tạo Proxy Host mới
- Chọn tên miền trong mục Domain Names
- Trỏ về địa chỉ IP và Port của máy chủ đang cài đặt dịch vụ.
- Cài đặt chứng chỉ SSL.
- Xong! Reverse Proxy đã sẵn sàng phục vụ.
Ví dụ như dưới đây là cách tạo Reversey Proxy cho Portainer.
Trong thực tế, đa số các dịch vụ mạng mình sử dụng đều được cài đặt bằng Docker và đều nằm chung trên 1 máy chủ đang chạy Nginx Proxy Manager.
Để tối ưu bảo mật, mình sẽ tận dụng tính năng mạng riêng của Docker để tạo Reverse Proxy cho dịch vụ mà không cần phải mở port kết nối ra bên ngoài. Nhờ đó chặn được hết các kết nối trực tiếp vào dịch vụ thông qua địa chỉ http://<IP-Address>:<Port>
. Chỉ có các kết nối bằng tên miền thông qua NPM mới được chuyển hướng đến dịch vụ.
Mình đã từng hướng dẫn phương pháp này trong hướng dẫn cấu hình NPM làm Reverse Proxy cho OpenLiteSpeed + MariaDB + Docker. Bài viết hôm nay sẽ tóm tắt gọn lại để có thể áp dụng cho mọi Docker container khác.
Mục Lục
1. Tạo Docker network
Đầu tiên, mình sẽ tạo 1 mạng Docker ảo. Tất cả các dịch vụ mạng được kích hoạt bằng Docker trên cùng máy chủ sẽ được kết nối vào mạng ảo này.
Bằng các thiết lập mạng riêng, chúng ta không cần publish các cổng mạng của dịch vụ ra ngoài. Chỉ duy nhất cổng 80 và 443 của NPM được truy cập từ bên ngoài.
docker network create thuanbuidepchai
Code language: Nginx (nginx)
2. Cập nhật thông số
Mình sẽ ví dụ bằng cách tạo Reverse Proxy cho Paperless-ngx.
Truy cập vào thư mục cài đặt dịch vụ mạng cần được tạo Reverse Proxy và thay đổi file cấu hình docker-compose.yml
.
- Thêm dấu # vào trước các phần cấu hình port để vô hiệu hoá.
- Thêm thông số mạng vào dưới cùng như sau
networks:
default:
external:
name: thuanbuidepchai
Code language: YAML (yaml)
Sau khi thay đổi, file docker-compose.yml
của mình sẽ như dưới đây
version: "2.1"
services:
paperless-ngx:
image: lscr.io/linuxserver/paperless-ngx:latest
container_name: paperless-ngx
environment:
- PUID=1000
- PGID=1000
- TZ=Asia/Ho_Chi_Minh
- PAPERLESS_URL=https://paperless.thuanbui.me
#- REDIS_URL= #optional
volumes:
- ./config:/config
- ./data:/data
#ports:
# - 8000:8000
restart: unless-stopped
networks:
default:
external:
name: thuanbuidepchai
Code language: YAML (yaml)
Chú ý dòng 5: container_name
(paperless-ngx). Chúng ta sẽ cần thông số này cho bước tạo Proxy Host.
3. Cập nhật cấu hình NPM
Truy cập vào thư mục cài NPM và chỉnh lại docker-compose.yml
: thêm vào thông số network tương tự như ở trên
version: '3'
services:
app:
image: 'jc21/nginx-proxy-manager:latest'
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
environment:
DB_MYSQL_HOST: "db"
DB_MYSQL_PORT: 3306
DB_MYSQL_USER: "npm"
DB_MYSQL_PASSWORD: "npm"
DB_MYSQL_NAME: "npm"
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
db:
image: 'jc21/mariadb-aria:latest'
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: 'npm'
MYSQL_DATABASE: 'npm'
MYSQL_USER: 'npm'
MYSQL_PASSWORD: 'npm'
volumes:
- ./data/mysql:/var/lib/mysql
networks:
default:
external:
name: thuanbuidepchai
Code language: YAML (yaml)
Kích hoạt lại NPM
docker-compose up -d
Mở trình duyệt web, truy cập vào địa chỉ IP của máy chủ, nếu hiện ra trang web như sau nghĩa là bạn đang đi đúng hướng: NPM đang đóng vai trò làm Reverse Proxy cho máy chủ.
Kiểm tra lại network thuanbuidepchai
bằng lệnh docker network inspect thuanbuidepchai
, sẽ thấy Nginx Proxy Manager và Paperless-ngx đang cùng kết nối vào mạng này.
"Containers": {
"2fd5b65ce7302cf1fce6c68bb7fc78183a31885eab862fc861ce26bc21f94ffc": {
"Name": "paperless-ngx",
"EndpointID": "bd6bcfe5c4c426a304e7b16ac1d5fd8a56a004ad7171d28596caae689aefd9e8",
"MacAddress": "02:42:ac:14:00:05",
"IPv4Address": "172.20.0.5/16",
"IPv6Address": ""
},
"750a3bbc428746ab647b32af96d5d207db5cb38c8faa312011fb56ae57c9300c": {
"Name": "nginxproxymanager_app_1",
"EndpointID": "8fda668e72e00a151a999a40b9cca1e7eb7b93e6ebe2b796715948f5c7cabb8b",
"MacAddress": "02:42:ac:14:00:04",
"IPv4Address": "172.20.0.4/16",
"IPv6Address": ""
},
"cce31506dca30c10f2a26926b0e676cc44134a02cd5db5b3c7625708235aee03": {
"Name": "nginxproxymanager_db_1",
"EndpointID": "60a1ce468bb72b820da6b030c6dcb1c50ca488f1f381597ba3d9501f8da0143b",
"MacAddress": "02:42:ac:14:00:03",
"IPv4Address": "172.20.0.3/16",
"IPv6Address": ""
}
},
Code language: JavaScript (javascript)
4. Tạo Proxy Host
Mình sẽ cấu hình tên miền document.thuanbui.me
để sử dụng cho Paperless-ngx.
Truy cập vào NPM, tạo Proxy Host mới với thông số như sau
- Domain Names: nhập vào tên miền
document.thuanbui.me
- Scheme: chọn http
- Forward Hostname / IP: nhập vào
paperless-ngx
là tên của container đang chạy Paperless-ngx. - Forward Port: 8000
Do cả NPM và Paparless-ngx đang cùng nằm trong mạng Docker thuanbuidepchai
nên có thể kết nối trực tiếp với nhau bằng Hostname và Port. Nhờ vậy chúng ta không cần phải nhập địa chỉ IP của máy chủ vào mục Forward Hostname / IP và cũng không cần phải mở truy cập port 8000
của Paperless-ngx ra bên ngoài.
Bấm tiếp vào tab SSL để tạo chứng chỉ bảo mật nếu cần thiết. Sau đó bấm Save để hoàn tất.
Vậy là xong. Nếu muốn tăng bảo mật, mình có thể chỉnh thêm tính năng Access List để hạn chế truy cập hoặc yêu cầu nhập tài khoản / mật khẩu mỗi khi truy cập vào tên miền.
Chúc bạn thực hiện thành công!
Bạn cho mình hỏi portainer mình cài qua docker run mình không thấy có file docker-compose.yml thì giờ phải cấu hình như thế nào nhỉ?
Cám ơn bạn!
Bạn cần phải tắt portainer bằng lênh
docker stop portainer
, sau đó tạo lại file docker-compose.yml để kích hoạt Portainer. Bạn xem lại bài này, mình đã cập nhật cách cài bằng Docker-Compose: https://thuanbui.me/quan-ly-docker-truc-quan-va-hieu-qua-hon-voi-portainer/Mình cấu hình như trên thì bị lỗi 502 bad gateway, không biết là lỗi nà vì đâu vậy bạn?
Cám ơn bạn!
Bạn paste cái file docker-compose.yml vô đây để mình xem thử: https://pastebin.com/ , chứ hỏi không vậy thì không biết lỗi gì.
Mình đang dùng https://github.com/sdr-enthusiasts/docker-reversewebproxy chạy cũng khá ổn. Nay ham cái UI đẹp của em NPM nà cài xong cũng bị 502 bad gate way.
docker-compose.yml đây https://pastebin.com/Fp1rSD6d
Cảm ơn bạn.
Bạn thử cài lại theo cách hướng dẫn ở đây xem: https://nginxproxymanager.com/setup/
Hiện tại không còn cần dùng MariaDB container nữa. CHỉ 1 container nginx proxy manager là đủ.
Mình đang cài npm lên Rasberypi ở nhà để dùng như bài hướng dẫn này nhưng đang bị một vấn đề là. Router của nhà mạng (trường hợp của mình là Viettel) không cho mở port 80 và 443. Nên khi truy cập domain đã tạo trong npm sẽ không được vì khi truy cập vào domain thì mặc định là domain đó đang chạy trên cổng 80 hoặc 443.
Không biết bạn có cách nào để khắc phục vấn đề này không nhỉ?
Bạn kiểm tra xem Public IP (check ở https://ifconfig.me) và WAN IP trong Router nhà mạng có giống nhau không?
Bạn cho mình hỏi với các container không nằm chung subnet với NPM thì mình cấu hình NPM như thế nào để chạy được nhỉ? Cám ơn bạn
Nếu bạn muốn kết nối các container trên nhiều host vào chung 1 network thì phải cấu hình overlay network. Cái này mình chưa nghiên cứu bao giờ, bạn có thể tham khảo ở đây: https://gdevillele.github.io/engine/userguide/networking/get-started-overlay/
Cách đơn giản mình thường xài là cấu hình Reverse Proxy của NPM trỏ tới IP của host khác kèm theo port của docker container.
Có cách nào để mình cấu hình 1 container chạy trên nhiều subnet được không nhỉ bạn? Mình thấy trong portainer cho phép chỉnh container vào nhiều mạng khác nhau. Nhưng không biết cấu hình bằng docker compose được không?
Bạn có thể cấu hình trong file docker compose theo hướng dẫn này: https://docs.docker.com/compose/networking/
Còn nếu muốn kết nối container đang chạy vào 1 subnet đang có sẵn thì dùng lệnh
docker network connect network_name container_name
. Để xem network_name thì dùng lệnhdocker network ls
. Để xem container_name thì dùng lệnhdocker ps
Bạn xem thêm tham khảo hướng dẫn ở dây: https://docs.docker.com/engine/reference/commandline/network_connect/
Bạn cho mình hỏi khi mình tạo 1 mạng riêng cho NPM thì khi mình trỏ NPM về 1 container khác ở khác lớp mạng bằng IP và port của container ở lớp mạng khác thì thấy không chạy được. Lý do là sao vậy nhỉ?
Theo mình biết thì các subnet của Docker không liên lạc được với nhau vì lý do bảo mật nhé.
Bạn cho mình hỏi thêm mình có tạo wgeasy và một vài container khác trên cùng một vps và sử dụng nginx reverse proxy để truy cập thông qua tên miền. nhưng khi mình kết nối đến vps bằng wgeasy thì sẽ bị tình trạng là không truy cập được các container khác trên cùng vps qua tên miền được nữa. Có cách nào để khi kết nối bằng wireguard mà vẫn truy cập được thông qua tên miền không nhỉ?
Mình thường xuyên truy cập vào wg-easy thiết lập tại nhà. Sau đó vẫn truy cập được các container khác được cài đặt ở nhà thông qua tên miền. Có lẽ bạn cấu hình sai gì đó thôi.
Có thể do ở nhà bạn có hairpin nat cho mạng nội bộ. Cái này mình đang chạy trên vps nên không được thì phải
Trên VPS của mình cũng chạy ngon lành nhé. Vì VPS nào mình cũng có 1 cái WireGuard chạy ở đó. Và luôn có nhiều ứng dụng khác chạy cùng. Đã thử kết nối vào wg-easy, sau đó truy cập các container trên cùng VPS đó, tất cả chạy bình thường.
Dùng chung cùng 1 docker với wirehole-ui như trong bài của bác thì có cần lưu ý gì về phần network ko bác