Hướng dẫn tự host RustDesk relay server trên VPS
Tự host hbbs và hbbr trên VPS với Docker. Hướng dẫn cấu hình key Ed25519, cố định image tag, mở port firewall và tính toán băng thông thực tế cho relay server của bạn.
RustDesk relay server tự host là gì
RustDesk relay server tự host bao gồm hai daemon chạy trên một VPS. hbbs là server ID và rendezvous: nó đăng ký ID của mọi client và kết nối hai client với nhau. hbbr là relay server: nó truyền tải dữ liệu phiên làm việc, nhưng chỉ dành cho các phiên không thể kết nối trực tiếp. Hầu hết các hướng dẫn chỉ cài đặt cả hai, giúp bạn kết nối thành công rồi dừng lại. Phần dưới đây là các công việc còn lại: key dùng để kiểm soát truy cập, các cổng, nâng cấp và băng thông.
Cả hai daemon đều nằm trong cùng một image, rustdesk/rustdesk-server, và cùng đọc cặp key Ed25519 từ một thư mục. Ed25519 là một cơ chế chữ ký khóa công khai. Cặp key đó quyết định client nào được phép giao tiếp với server của bạn, và không có cơ sở dữ liệu người dùng nào phía sau nó.
hbbs và hbbr: daemon nào tiêu tốn băng thông của bạn
Lưu lượng của hbbs nhỏ và ổn định: bao gồm đăng ký ID, tín hiệu heartbeat và quá trình trao đổi ngắn để kết nối hai peer. Nó chạy cả ngày nhưng hầu như không tốn tài nguyên.
Lưu lượng của hbbr chính là phiên làm việc. Các khung hình màn hình truyền theo một hướng, tín hiệu bàn phím và chuột truyền theo hướng ngược lại, và mọi byte được relay đều đi vào VPS của bạn rồi lại đi ra. Nếu nhà cung cấp tính phí dựa trên lưu lượng egress, một phiên relay sẽ tiêu tốn đúng bằng dung lượng phiên đó. Nếu họ tính tổng lưu lượng truyền tải, chi phí sẽ gấp đôi.
Relay là phương án dự phòng, không phải đường truyền mặc định. hbbs trước tiên cố gắng kết nối trực tiếp hai client bằng cách sử dụng hole punching qua bất kỳ NAT (network address translation) nào nằm trước chúng. Khi thành công, phiên làm việc không bao giờ chạm tới hbbr và hạn mức truyền tải của bạn vẫn nguyên vẹn. Khi một phía nằm sau NAT gán cổng mới cho mỗi đích đến, hoặc firewall chặn đường truyền đã punch, phiên làm việc sẽ fallback về hbbr và mọi khung hình sẽ đi qua VPS của bạn.
Một biến môi trường sẽ loại bỏ sự lựa chọn này. ALWAYS_USE_RELAY=Y trên hbbs buộc mọi phiên làm việc phải đi qua hbbr. Tài liệu của RustDesk hiển thị nó trong một ví dụ Compose, nên nó thường bị sao chép. Nó làm cho các kết nối trở nên dễ dự đoán hơn và làm cho lưu lượng egress của bạn trở thành thực tế. Hãy thiết lập nó vì bạn đã quyết định như vậy, không phải vì bạn đã copy-paste nó.
Các cổng cần mở cho RustDesk server tự host
Các số cổng dưới đây đã được kiểm tra dựa trên tài liệu của RustDesk server và repository rustdesk-server vào ngày 17 tháng 8 năm 2026.
- TCP 21115, trên hbbs: kiểm tra loại NAT.
- UDP 21116, trên hbbs: đăng ký ID và heartbeat. Nếu không có cổng này, client sẽ không bao giờ online, bất kể các cổng khác có mở hay không.
- TCP 21116, trên hbbs: TCP hole punching và dịch vụ kết nối.
- TCP 21117, trên hbbr: relay. Đây là cổng truyền tải dữ liệu phiên làm việc, do đó đây là cổng tiêu tốn băng thông của bạn.
- TCP 21118 trên hbbs và TCP 21119 trên hbbr: WebSocket, được sử dụng bởi trình duyệt client. Hãy để cả hai cổng này đóng nếu bạn không sử dụng tính năng đó.
- TCP 21114 là web console trong RustDesk Server Pro. Bản mã nguồn mở không lắng nghe trên cổng này.
Cài đặt hbbs và hbbr với image tag cố định
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:1.1.16
command: hbbs
volumes:
- ./data:/root
network_mode: "host"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:1.1.16
command: hbbr -k _
volumes:
- ./data:/root
network_mode: "host"
restart: unless-stoppedmkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose psCả hai dịch vụ đều phải đọc running. Hãy xác nhận các listener đã tồn tại trước khi bạn đụng đến firewall.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Bạn sẽ thấy các TCP listener trên cổng 21115, 21116 và 21117, cùng một UDP listener trên cổng 21116. Nếu thiếu dòng UDP, nghĩa là hbbs không chạy, vì đó là listener mà các client dùng để đăng ký.
Có bốn điểm trong file đó là cố ý. Tag được dùng là 1.1.16, bản release hiện tại tính đến tháng 8 năm 2026, được phát hành ngày 20 tháng 7 năm 2026, thay vì dùng latest, bởi vì latest có nghĩa là bất cứ thứ gì được đẩy lên gần nhất và một docker compose pull vào sáu tháng tới có thể đưa cho bạn một server mà bạn chưa từng kiểm thử. network_mode: "host" bind trực tiếp vào các interface của host, đây là điều mà tài liệu RustDesk khuyến nghị và nó quyết định cách firewall của bạn hoạt động. ./data:/root map thư mục làm việc của image ra host, để cặp key nằm ở nơi bạn có thể backup. Và hbbr -k _ là thay đổi duy nhất so với ví dụ gốc, vì cấu hình mặc định sẽ để relay của bạn mở cho bất kỳ ai. Nếu bạn mới làm quen với Compose, chạy Docker Compose trên VPS sẽ bao gồm định dạng file và các lệnh quản lý vòng đời.
Nếu hbbr chuyển sang server thứ hai, hbbs cần được chỉ định nơi nó đã chuyển đến: hãy truyền -r relay.example.com:21117, hoặc thiết lập biến môi trường RELAY-SERVERS. Trên một máy đơn lẻ, bạn không cần làm điều này.
Cặp khóa Ed25519 là cơ chế kiểm soát truy cập
Trong lần khởi động đầu tiên, hbbs tạo ra id_ed25519 và id_ed25519.pub trong thư mục làm việc của nó. Với mount ở trên, cả hai file này đều xuất hiện trên host.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub chứa một chuỗi base64. Chuỗi đó được nhập vào trường Key trên mọi client. id_ed25519 là phần khóa bí mật và không bao giờ được rời khỏi server. Khóa công khai không phải là bí mật, vì dù sao nó cũng được sao chép vào cấu hình của mọi client. Khóa bí mật là thông tin nhạy cảm: bất kỳ ai nắm giữ nó đều có thể dựng lên một server mà các client của bạn sẽ tin tưởng.
Hãy sao lưu cả hai file ngay bây giờ, trước khi bạn có hai mươi client được cấu hình.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzSao chép bản lưu trữ đó ra khỏi máy chủ. Đây là lý do tại sao bước này quan trọng hơn bất kỳ bước nào khác. Nếu bạn xóa ~/rustdesk/data, hoặc rebuild trên một VPS mới mà không sao chép file này, hbbs sẽ tạo ra một cặp khóa mới trong lần khởi động tiếp theo. Mọi client vẫn giữ khóa công khai cũ, vì vậy hbbs sẽ từ chối kết nối và client sẽ bị offline. Chạy sudo cat ~/rustdesk/data/id_ed25519.pub và so sánh nó với trường Key trên bất kỳ client nào: hai chuỗi này không còn khớp nhau, và sự không khớp đó chính là nguyên nhân gây lỗi. Để khắc phục, bạn phải chỉnh sửa cài đặt trên từng máy theo cách thủ công, bao gồm cả những máy mà bạn đang dựa vào RustDesk để truy cập.
Khóa này không phải là mật khẩu phiên làm việc, và việc nhầm lẫn giữa hai thứ này khiến nhiều người bỏ qua một trong hai. Khóa quyết định client nào sẽ được phép giao tiếp với server của bạn. Mật khẩu cố định hoặc mã dùng một lần trên máy được điều khiển quyết định ai có thể mở phiên làm việc trên máy đó. Bạn cần cả hai, và việc có một cái không thể bù đắp cho sự yếu kém của cái còn lại.
Tại sao relay không xác thực lại là một vấn đề
Theo mặc định, hbbr không kiểm tra bất cứ thứ gì. Tài liệu cấu hình RustDesk đã nêu rõ: một key trống cho phép các client không có key khớp vẫn có thể sử dụng relay. Mặc định trống này tồn tại để người dùng mới không gặp lỗi sai lệch key ngay lần chạy đầu tiên. Cái giá phải trả là bất kỳ ai tìm thấy địa chỉ của bạn trên TCP 21117 đều có thể đẩy lưu lượng phiên làm việc của họ qua VPS của bạn, sử dụng hạn mức truyền tải của bạn, từ địa chỉ IP của bạn.
command: hbbr -k _ giải quyết vấn đề đó. Tham số _ yêu cầu hbbr tải cặp key từ thư mục làm việc của nó, và vì cả hai container đều mount cùng một ./data, đó chính là cặp key mà hbbs đã tạo trước đó. Không có gì phải sao chép thủ công, nên không thể xảy ra sai lệch.
Volume dùng chung là phần mọi người thường làm sai. Nếu cấp cho hbbr một thư mục riêng, nó sẽ tạo ra một cặp key khác. Khi đó hbbs và hbbr không khớp nhau, mọi phiên relay đều thất bại, còn các phiên kết nối trực tiếp vẫn hoạt động. Triệu chứng này gây khó hiểu: RustDesk kết nối được với một số peer nhưng không kết nối được với các peer khác, tùy thuộc vào việc hole punching có thành công hay không. Một ls -l ~/rustdesk/data/ hiển thị một cặp id_ed25519 duy nhất sẽ loại trừ khả năng này.
Trỏ các client về server của bạn
Trên mỗi máy, mở RustDesk, sau đó vào Settings, chọn Network, rồi chọn ID/Relay Server.
- ID Server: hostname của bạn, ví dụ
rustdesk.example.com. Client sẽ sử dụng cổng 21116 trừ khi bạn chỉ định một cổng khác. - Relay Server: để trống nếu hbbr chạy trên cùng host với hbbs.
- API Server: để trống. Phiên bản mã nguồn mở không cung cấp tính năng này.
- Key: chuỗi base64 từ
id_ed25519.pub, dán chính xác, không có khoảng trắng ở cuối.
Cửa sổ chính sẽ thông báo client đã sẵn sàng. Nếu không, có nghĩa là UDP 21116 không tới được hbbs, vì quá trình đăng ký và heartbeat chạy qua UDP và không có cách nào khác để đưa ID lên trạng thái online.
Giới hạn các cổng để relay không trở thành dịch vụ mở
Vì các container sử dụng host networking, không có quy tắc Docker NAT nào đứng trước chúng, nên các quy tắc ufw sẽ áp dụng đúng như bạn mong đợi.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedChỉ thêm 21118:21119/tcp nếu bạn chạy client trình duyệt. Hãy giữ một phiên SSH thứ hai mở trong khi bạn bật ufw, để tránh việc sai sót trong quy tắc SSH khiến bạn bị khóa khỏi chính máy chủ của mình. Các kiến thức cơ bản về tường lửa ufw cho VPS bao gồm các chính sách mặc định và thứ tự ưu tiên của quy tắc.
Bây giờ là điểm cần lưu ý. Nếu bạn chuyển sang publish các cổng bằng khối ports:, như ví dụ về image RustDesk supervisor thay thế sử dụng, Docker sẽ tự ghi các quy tắc DNAT của riêng nó và các gói tin sẽ đến container mà không đi qua chuỗi quy tắc ufw của bạn. Khi đó, lệnh ufw deny trên cổng 21117 sẽ không có tác dụng, và relay vẫn mở ra internet trong khi ufw status lại báo ngược lại. Docker published ports bypass ufw giải thích về thứ tự của các chuỗi này. Host networking giúp tránh hoàn toàn vấn đề này. Nếu bạn thực sự cần publish một cổng, hãy bind nó vào một địa chỉ cụ thể, như trong "127.0.0.1:21118:21118" phía sau một reverse proxy.
Việc giới hạn theo địa chỉ nguồn chỉ hiệu quả khi các client của bạn có địa chỉ ổn định.
sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udpLaptop trên mạng khách sạn không có địa chỉ ổn định, đó chính là lý do tại sao key trên hbbr thực hiện công việc bảo mật thực tế ở đây nhiều hơn là tường lửa.
Upgrading a stack that holds your key
The key lives in the bind mount, not inside the container, so an upgrade is safe as long as you leave ./data alone.
- Back up the data directory first:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Read the release notes for the new tag on the rustdesk-server releases page.
- Edit
compose.ymland change bothimage:lines to the new tag. - Run
sudo docker compose pull, thensudo docker compose up -d. - Run
sudo cat ~/rustdesk/data/id_ed25519.puband confirm the string is the one your clients already hold.
Step 5 is the check that matters, because a changed key is silent on the server and breaks every client at the same moment. Rolling back is putting the old tag back and running up -d again, and that only works because you pinned it: with latest, docker compose pull moved the name onto the new image, so there is no tag left that names the old one.
The usual way to lose the key is not docker compose down, which leaves a bind mount alone. It is migrating to a new VPS and copying only compose.yml. Copy ./data with it.
Giám sát lưu lượng egress trên gói cước có giới hạn băng thông
hbbr là thành phần duy nhất trong stack này tiêu tốn hạn mức truyền tải dữ liệu. FAQ của RustDesk ước tính một kết nối relay trên màn hình 1920x1080 tiêu tốn từ 30 KB/s đến 3 MB/s, và công việc văn phòng thông thường rơi vào khoảng 100 KB/s. Đây là các con số công bố cho một phiên làm việc đơn lẻ, không phải số đo thực tế trên hệ thống của bạn. Nếu nhân lên với 60 giờ mỗi tháng, tương đương 2 giờ mỗi ngày, kết quả sẽ như sau.
The data behind this chart
[
{
"label": "Low end, 30 KB/s",
"gb_per_month": 6.5
},
{
"label": "Office work, 100 KB/s",
"gb_per_month": 21.6
},
{
"label": "High end, 3 MB/s",
"gb_per_month": 648
}
]Với tốc độ làm việc văn phòng, một phiên làm việc tiêu tốn khoảng 21.6 GB mỗi tháng, mức này không đáng kể với bất kỳ gói cước nào. Ở ngưỡng cao nhất theo công bố, 60 giờ đó tiêu tốn 648 GB, và hai phiên làm việc đồng thời ở tốc độ này sẽ dùng hết hạn mức 1 TB trong tháng. Mức thấp nhất là 6.5 GB. Gigabyte ở đây được tính là 1000 MB, đây là cách tính hạn mức truyền tải thông thường.
docker stats sẽ không phân tách dữ liệu này cho bạn, vì một container sử dụng host networking sẽ chia sẻ chung network namespace với host, do đó các bộ đếm của nó cũng chính là bộ đếm của host. Hai công cụ khác có thể thực hiện việc này. vnstat đo lường toàn bộ máy chủ:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -mToàn bộ máy chủ nghĩa là toàn bộ máy chủ: nếu VPS này còn chạy các dịch vụ truyền tải dữ liệu lớn khác, ví dụ như các photo server tự host đồng bộ thư viện ảnh từ điện thoại mỗi đêm, thì lưu lượng upload của chúng sẽ nằm chung trong bảng tính lưu lượng hàng tháng với traffic relay của bạn. Một media server cũng tương tự, vì các dịch vụ như Halcyon, công cụ biến thư viện Jellyfin thành cửa hàng băng đĩa thập niên 90 sẽ stream dữ liệu đến người xem, và lưu lượng egress đó sẽ dùng chung hạn mức với relay của bạn.
Một bộ đếm nftables có thể đo lường riêng cho relay:
sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeterRule này không đưa ra verdict nào, nên chỉ đếm packet và byte mà không thay đổi những gì được phép. Nó nằm trong một table riêng nên không ảnh hưởng đến ufw. Rule này không persistent: nếu muốn giữ lại sau reboot, hãy đặt các dòng tương tự vào /etc/nftables.conf. Counter chỉ tăng khi một session thực sự đang được relay. Nếu counter vẫn tăng trong khi không máy nào của bạn đang kết nối, nghĩa là đã có người khác phát hiện relay của bạn. Đây chính là trường hợp mà hbbr -k _ được tạo ra để ngăn chặn. Vì bạn sẽ không đọc nft list mỗi sáng, hãy tạo một cron job trên đó để so sánh số byte với một ngưỡng và gửi push alert khi vượt ngưỡng. Việc này phù hợp để thực hiện bằng ntfy server của riêng bạn.
hbbr cũng có các giới hạn tốc độ (rate limit) mà bạn có thể giảm xuống. SINGLE_BANDWIDTH mặc định là 128 Mb/s cho mỗi kết nối relay và TOTAL_BANDWIDTH là 1024 Mb/s cho tổng tất cả các kết nối. Thiết lập SINGLE_BANDWIDTH=8 sẽ giới hạn một phiên làm việc ở mức gần 1 MB/s. Việc này chỉ giới hạn tốc độ, không phải tổng lưu lượng hàng tháng, vì vậy hãy coi nó là cách để ngăn một phiên làm việc làm bão hòa đường truyền thay vì là công cụ kiểm soát ngân sách.
Khi bạn không cần relay
Đối với thiết lập cá nhân, câu trả lời thành thật là bạn có thể không cần bất kỳ thứ gì trong số này. Hãy đưa cả hai máy vào một mesh VPN và kết nối trực tiếp đến địa chỉ tunnel. Khi đó sẽ không có hbbs, không có hbbr, không có relay egress và không có container nào trên VPS cần phải nâng cấp.
Trên máy bạn muốn điều khiển, hãy bật quyền truy cập IP trực tiếp trong cài đặt bảo mật của RustDesk. Trường cổng mặc định là 21118. Hãy kiểm tra xem nó đã listening trước khi bạn thử kết nối:
ss -tlnp | grep 21118Sau đó, hãy kết nối đến địa chỉ VPN của peer đó thay vì dùng ID. FAQ của RustDesk cho biết ở chế độ này, kết nối sẽ không được mã hóa, vì vậy hãy chạy nó bên trong tunnel và tuyệt đối không chạy qua internet công cộng. Tunnel chính là thứ cung cấp lớp mã hóa.
Hãy lựa chọn dựa trên việc ai là chủ sở hữu các máy đó. Việc tự host hbbs và hbbr là phù hợp khi bạn hỗ trợ các máy không thuộc quyền sở hữu của bạn, hoặc những người sẽ không bao giờ cài đặt VPN client, vì phía thiết lập của họ chỉ cần ID và mật khẩu. Một mesh VPN với quyền truy cập IP trực tiếp là lựa chọn đúng đắn khi mọi máy đều thuộc về bạn và có thể cài đặt key. So sánh WireGuard với Tailscale bao gồm hai cách phổ biến để xây dựng mesh đó, và chạy remote desktop trên Linux VPS bao gồm trường hợp còn lại, nơi máy bạn muốn truy cập màn hình chính là bản thân máy chủ đó.
FAQ
Mọi phiên RustDesk có đi qua relay của tôi không?
Không. hbbs cố gắng kết nối trực tiếp hai client trước, sử dụng kỹ thuật hole punching xuyên qua NAT phía trước mỗi máy. Chỉ những phiên kết nối thất bại mới chuyển sang dùng hbbr, và chỉ những phiên đó mới tiêu tốn băng thông của bạn. Ngoại lệ là ALWAYS_USE_RELAY=Y trên hbbs, biến này ép mọi phiên phải đi qua hbbr bất kể có đường truyền trực tiếp hay không. Nếu biến này được thiết lập trong file Compose của bạn, mọi byte dữ liệu của mọi phiên đều sẽ tính vào hóa đơn truyền tải của bạn.
Key của RustDesk server được lưu ở đâu, và nếu mất thì sao?
hbbs tạo ra id_ed25519 và id_ed25519.pub trong thư mục làm việc của nó ngay lần khởi động đầu tiên. Thư mục đó là /root bên trong image chính thức, vì vậy với volume mount như đã hiển thị ở trên, các file này sẽ xuất hiện tại ./data trên host. Hãy sao lưu cả hai file này ra khỏi server. Nếu bị mất, hbbs sẽ tạo một cặp key mới vào lần khởi động kế tiếp, và mọi client vẫn giữ public key cũ sẽ bị từ chối kết nối. Không có cách khôi phục nào khác ngoài việc chỉnh sửa thủ công trường Key trên từng client.
Tôi cần mở những cổng nào cho RustDesk server tự host?
TCP 21115, 21116 và 21117, cùng với UDP 21116. hbbs dùng 21115 để kiểm tra loại NAT, và 21116 để đăng ký ID và heartbeat qua UDP cũng như cho hole punching qua TCP. hbbr dùng 21117 cho relay. TCP 21118 và 21119 là các cổng WebSocket cho client trên trình duyệt, vì vậy hãy đóng chúng lại nếu bạn không sử dụng. TCP 21114 thuộc về Pro web console và bản open source không cần dùng đến nó.
Người lạ có thể sử dụng relay RustDesk tự host của tôi không?
Có, nếu bạn chạy hbbr với cấu hình mặc định. Tài liệu của RustDesk nêu rõ rằng một key trống cho phép các client không có key khớp vẫn sử dụng được relay, vì vậy bất kỳ ai biết hostname và cổng 21117 của bạn đều có thể đẩy lưu lượng qua server của bạn. Hãy chạy hbbr với -k _ để nó load cùng cặp key mà hbbs đã tạo trong volume ./data dùng chung. Sau đó, chỉ những client được cấu hình với public key của bạn mới có thể relay qua server của bạn.