Jak uruchomić własny serwer relay RustDesk na VPS
Uruchom hbbs i hbbr RustDesk na własnym VPS. Sprawdź klucz Ed25519, przypinanie tagów obrazu, wymagane porty oraz rzeczywiste zużycie pasma relay.
Czym jest własny serwer przekaźnikowy RustDesk
Własny serwer przekaźnikowy RustDesk to dwa demony działające na jednym VPS. hbbs to serwer identyfikatorów i pośrednictwa (rendezvous): rejestruje każdy identyfikator klienta i nawiązuje połączenie między dwoma klientami. hbbr to serwer przekaźnikowy: przesyła bajty sesji, ale tylko w przypadku sesji, których nie udało się zestawić bezpośrednio. Większość poradników opisuje instalację obu komponentów, parowanie i na tym kończy. Poniżej znajduje się reszta niezbędnych czynności: klucz stanowiący kontrolę dostępu, porty, aktualizacja oraz przepustowość.
Oba demony są dostarczane w tym samym obrazie, rustdesk/rustdesk-server, a w poniższej konfiguracji oba odczytują tę samą parę kluczy Ed25519 z tego samego katalogu. Jest to element wymagający konfiguracji, a nie ustawienie domyślne: hbbs ładuje lub generuje parę samodzielnie, natomiast hbbr ignoruje klucze, dopóki nie zostanie z nimi uruchomiony. Ed25519 to schemat podpisu kluczem publicznym. Ta para kluczy decyduje, z którymi klientami serwer będzie się komunikował; nie istnieje za nią żadna baza danych użytkowników.
hbbs i hbbr: który daemon zużywa pasmo
Ruch hbbs jest mały i stały: rejestracja identyfikatorów, sygnały heartbeat oraz krótka wymiana informacji potrzebna do połączenia dwóch peerów. Usługa działa przez cały dzień i zużywa niemal niezauważalną ilość pasma.
Ruch hbbr to sama sesja. Obrazy ekranu są przesyłane w jedną stronę, zdarzenia klawiatury i myszy w drugą, a każdy przekazywany bajt dociera do VPS i ponownie z niego wychodzi. Jeśli dostawca rozlicza wyłącznie ruch wychodzący, sesja przekazywana przez relay kosztuje około tyle, ile wynosi szybkość transmisji sesji. Jeśli rozlicza całkowity transfer, koszt wynosi około dwukrotność tej wartości.
Relay jest mechanizmem awaryjnym, a nie standardową ścieżką. Najpierw hbbs próbuje połączyć oba klienty bezpośrednio, wykorzystując hole punching przez dowolny NAT (network address translation) znajdujący się przed każdym z nich. Jeśli to zadziała, sesja nigdy nie przechodzi przez hbbr, a limit transferu pozostaje nienaruszony. Jeśli jedna ze stron znajduje się za NAT-em, który przydziela nowy port dla każdego celu, albo za zaporą odrzucającą połączenie utworzone przez hole punching, sesja przełącza się na hbbr i każda ramka przechodzi przez VPS.
Jedna zmienna środowiskowa usuwa ten wybór. ALWAYS_USE_RELAY=Y w hbbs wymusza przekazywanie każdej sesji przez hbbr. Dokumentacja RustDesk pokazuje ją w jednym z przykładów Compose, dlatego jest często kopiowana. Zapewnia bardziej przewidywalne połączenia, ale powoduje rzeczywiste zużycie ruchu wychodzącego. Należy ją ustawić tylko wtedy, gdy jest to zamierzone, a nie dlatego, że została skopiowana z przykładu.
Jakie porty wymaga serwer RustDesk hostowany samodzielnie
Poniższe numery portów zostały zweryfikowane zgodnie z dokumentacją serwera RustDesk oraz repozytorium rustdesk-server w dniu 10 października 2026.
- TCP 21115, na hbbs: test typu NAT.
- UDP 21116, na hbbs: rejestracja ID oraz sygnał heartbeat. Jest to ścieżka używana domyślnie przez klienta.
- TCP 21116, na hbbs: rejestracja ID dla klientów ustawionych wyłącznie na TCP, a także TCP hole punching oraz usługa połączeń.
- TCP 21117, na hbbr: przekaźnik (relay). Jest to port, przez który przesyłane są dane sesji, zatem generuje on zużycie transferu.
- TCP 21118 na hbbs oraz TCP 21119 na hbbr: WebSocket, używany przez klienta przeglądarkowego. Pozostaw oba porty zamknięte, jeśli nie korzystasz z tej funkcji.
- TCP 21114 to serwer HTTP API w wersji RustDesk Server Pro. Wersja open source nie nasłuchuje na tym porcie.
Instalacja hbbs i hbbr z przypiętą wersją obrazu
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 psObie usługi powinny odczytywać running. Przed konfiguracją firewalla należy potwierdzić, że nasłuchiwanie jest aktywne.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Powinny być widoczne gniazda TCP na portach 21115, 21116 oraz 21117, a także gniazdo UDP na porcie 21116. Brak linii UDP oznacza, że hbbs nie działa, ponieważ to właśnie ten proces otwiera wspomniany port przy starcie i to z nim domyślnie rejestrują się klienci.
Cztery elementy w tym pliku są zamierzone. Użyto tagu 1.1.16, który w październiku 2026 roku pozostaje aktualnym wydaniem (opublikowanym 20 lipca 2026), zamiast latest. Użycie latest oznacza pobranie najnowszej wersji, a docker compose pull za sześć miesięcy może skutkować wdrożeniem serwera, który nie był testowany. Opcja network_mode: "host" wiąże interfejsy hosta bezpośrednio, co jest zalecane w dokumentacji RustDesk i determinuje zachowanie firewalla. Parametr ./data:/root mapuje katalog roboczy obrazu na hosta, dzięki czemu para kluczy jest zapisywana w miejscu, które można archiwizować. Z kolei hbbr -k _ to jedyna zmiana względem oryginalnego przykładu, ponieważ ustawienia domyślne pozostawiają przekaźnik otwarty dla każdego. Jeśli Docker Compose jest nowym narzędziem, uruchamianie Docker Compose na VPS wyjaśnia format pliku oraz polecenia cyklu życia.
Jeśli hbbr zostanie przeniesiony na drugi serwer, hbbs musi otrzymać informację o nowej lokalizacji: należy przekazać flagę -r relay.example.com:21117 lub ustawić zmienną środowiskową RELAY-SERVERS. W przypadku pojedynczej maszyny konfiguracja ta nie jest wymagana.
Para Ed25519 jest mechanizmem kontroli dostępu
Przy pierwszym uruchomieniu hbbs tworzy id_ed25519 i id_ed25519.pub w swoim katalogu roboczym. Przy użyciu powyższego montowania oba pliki są dostępne na hoście.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub zawiera jeden ciąg base64. Ten ciąg należy wprowadzić w polu Key na każdym kliencie. id_ed25519 jest kluczem prywatnym i nigdy nie opuszcza serwera. Klucz publiczny nie jest tajny, ponieważ i tak jest kopiowany do konfiguracji każdego klienta. Klucz prywatny jest tajny: osoba, która go posiada, może uruchomić serwer, któremu klienci będą ufać.
Wykonaj teraz kopię zapasową obu plików, zanim skonfigurujesz dwudziestu klientów.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzSkopiuj to archiwum poza serwer. Oto dlaczego ma to większe znaczenie niż każdy inny krok. Usunięcie ~/rustdesk/data lub odtworzenie serwera na nowym VPS bez skopiowania tego pliku powoduje, że przy następnym uruchomieniu hbbs wygeneruje nową parę kluczy. Każdy klient nadal będzie zawierał stary klucz publiczny, dlatego hbbs odrzuci połączenie, a klient przejdzie w tryb offline. Uruchom sudo cat ~/rustdesk/data/id_ed25519.pub i porównaj wynik z polem Key na dowolnym kliencie: oba ciągi nie będą już zgodne, a ta niezgodność będzie przyczyną całego problemu. Naprawa wymaga ręcznej edycji ustawień na każdym komputerze, także na komputerach, do których planowano uzyskiwać dostęp za pomocą RustDesk.
Klucz nie jest hasłem sesji. Pomylenie tych wartości prowadzi do pominięcia jednej z nich. Klucz określa, z którymi klientami serwer będzie się komunikować. Stałe hasło lub kod jednorazowy na zarządzanym komputerze określa, kto może otworzyć sesję na tym komputerze. Potrzebne są obie wartości. Posiadanie jednej z nich nie kompensuje słabości drugiej.
Dlaczego niezauwierzytelniony przekaźnik stanowi problem
Domyślnie hbbr nie przeprowadza żadnej weryfikacji. Dokumentacja konfiguracji RustDesk stwierdza to wprost: pusty klucz pozwala klientom bez pasującego klucza na korzystanie z przekaźnika. Pusta wartość domyślna istnieje po to, aby nowi użytkownicy nie napotykali błędów niezgodności kluczy przy pierwszym uruchomieniu. Kosztem jest to, że każdy, kto znajdzie Twój adres na TCP 21117, może przesyłać swój ruch sesyjny przez Twój VPS, wykorzystując Twój limit transferu i Twój adres IP.
command: hbbr -k _ eliminuje ten problem. Argument _ nakazuje hbbr wczytanie pary kluczy z katalogu roboczego lub wygenerowanie jej, jeśli jeszcze nie istnieje. Ponieważ oba kontenery montują ten sam ./data, jest to ta sama para, której używa hbbs. Nic nie jest kopiowane ręcznie, więc nie ma ryzyka rozbieżności.
Współdzielony wolumen to element, w którym użytkownicy najczęściej popełniają błędy. Jeśli hbbr otrzyma własny katalog, wygeneruje inną parę kluczy. Wówczas hbbs i hbbr nie będą ze sobą współpracować, każda sesja przekaźnikowa zakończy się niepowodzeniem, a sesje bezpośrednie będą nadal działać. Objaw jest mylący: RustDesk łączy się z niektórymi węzłami, a z innymi nie, w zależności od tego, czy udało się nawiązać połączenie bezpośrednie (hole punching). Jedno ls -l ~/rustdesk/data/ pokazujące pojedynczą parę id_ed25519 wyklucza taką niezgodność. Nie dowodzi to jednak, że przekaźnik weryfikuje klucze, ponieważ hbbr ignoruje te pliki, dopóki nie zostanie uruchomiony z niepustym kluczem, dlatego należy również sprawdzić uruchomione polecenie:
ps -eo args | grep '[h]bbr'Powinno to wyświetlić hbbr -k _. Samo hbbr oznacza, że przekaźnik jest nadal otwarty, niezależnie od tego, co znajduje się w katalogu.
Skierowanie klientów na własny serwer
Na każdej maszynie otwórz RustDesk, przejdź do Settings, następnie Network, a potem ID/Relay Server.
- ID Server: nazwa hosta, na przykład
rustdesk.example.com. Klient używa portu 21116, chyba że zostanie podany inny. - Relay Server: pozostaw puste, gdy hbbr działa na tym samym hoście co hbbs.
- API Server: pozostaw puste. Wersja open source nie udostępnia tego interfejsu.
- Key: ciąg base64 z
id_ed25519.pub, wklejony dokładnie, bez spacji na końcu.
Główne okno powinno wskazać, że klient jest gotowy. Jeśli tak się nie dzieje, a klient działa na ustawieniach domyślnych, najczęstszą przyczyną jest brak dostępu do portu UDP 21116 na hbbs, ponieważ to tam domyślny klient rejestruje się i wysyła sygnał heartbeat. Stan offline ID sam w sobie tego nie dowodzi. Klient z ustawioną opcją disable-udp na Y rejestruje się przez TCP 21116 i nigdy nie używa UDP 21116, dlatego w przypadku takiego klienta należy w pierwszej kolejności sprawdzić port TCP 21116.
Ograniczenie portów, aby przekaźnik nie był otwartą usługą
Ponieważ kontenery korzystają z sieci hosta (host networking), przed nimi nie ma reguły Docker NAT, więc reguły ufw działają zgodnie z oczekiwaniami.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedDodaj 21118:21119/tcp tylko wtedy, gdy używasz klienta przeglądarkowego. Pozostaw otwartą drugą sesję SSH podczas włączania ufw, aby błąd w regule SSH nie spowodował utraty dostępu do serwera. Podstawy zapory sieciowej ufw dla VPS omawiają domyślne polityki oraz kolejność reguł.
A teraz pułapka. Jeśli przejdziesz na publikowanie portów za pomocą bloku ports:, co wykorzystuje wiele pojedynczych przykładów kontenerów RustDesk, Docker zapisuje własne reguły DNAT, a pakiety docierają do kontenera z pominięciem łańcucha, w którym znajdują się reguły ufw. Reguła ufw deny na porcie 21117 nie przynosi wtedy efektu, a przekaźnik jest otwarty na świat, mimo że ufw status twierdzi inaczej. Publikowanie portów w Dockerze omija ufw wyjaśnia kolejność łańcuchów. Sieć hosta całkowicie eliminuje ten problem. Jeśli publikujesz port, powiąż go z jednym adresem, jak w "127.0.0.1:21118:21118" za odwrotnym proxy.
Ograniczanie według adresu źródłowego działa tylko wtedy, gdy klienci mają stałe adresy.
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 udpLaptopy w sieciach hotelowych nie mają stałych adresów, dlatego klucz na hbbr wykonuje tutaj znacznie więcej realnej pracy niż zapora sieciowa.
Aktualizacja stosu zawierającego klucz
Klucz znajduje się w bind mount, a nie wewnątrz kontenera. Aktualizacja jest więc bezpieczna, o ile ./data pozostanie bez zmian.
- Najpierw wykonaj kopię zapasową katalogu danych:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Przeczytaj informacje o wydaniu dotyczącym nowego tagu na stronie wydań rustdesk-server.
- Edytuj
compose.ymli zmień oba wierszeimage:na nowy tag. - Uruchom
sudo docker compose pull, a następniesudo docker compose up -d. - Uruchom
sudo cat ~/rustdesk/data/id_ed25519.pubi potwierdź, że wyświetlony ciąg znaków jest taki sam jak ten zapisany już po stronie klientów.
Krok 5 jest najważniejszym sprawdzeniem. Zmieniony klucz nie powoduje jawnego błędu na serwerze, ale jednocześnie przerywa działanie wszystkich klientów. Wycofanie zmiany polega na przywróceniu starego tagu i ponownym uruchomieniu up -d. Działa to tylko dlatego, że tag został przypięty. W przypadku latest polecenie docker compose pull przeniosło nazwę na nowy obraz, więc nie pozostał żaden tag wskazujący stary obraz.
Najczęstszą przyczyną utraty klucza nie jest docker compose down, ponieważ to polecenie pozostawia bind mount bez zmian. Problem pojawia się podczas migracji na nowy VPS i skopiowania wyłącznie compose.yml. Należy skopiować razem z nim również ./data.
Monitorowanie ruchu wychodzącego w planie z limitem transferu
hbbr jest jedynym elementem tego stosu, który może zużywać limit transferu. FAQ RustDesk podaje, że jedno połączenie przekazywane przez relay na ekranie 1920x1080 zużywa od 30 KB/s do 3 MB/s, a zwykła praca biurowa około 100 KB/s. Są to opublikowane wartości dla jednej sesji, a nie pomiar wykonany w danej konfiguracji. Po przeliczeniu na sześćdziesiąt godzin w miesiącu, czyli dwie godziny dziennie, otrzymuje się następujące wartości.
Dane, na których opiera się ten wykres
[
{
"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
}
]Przy szybkości typowej dla pracy biurowej jedna sesja zużywa około 21.6 GB miesięcznie, więc żaden plan tego nie odczuje. Przy górnej wartości opublikowanego zakresu te same sześćdziesiąt godzin zużywa 648 GB, a dwie równoczesne sesje z taką szybkością przekraczają limit 1 TB w ciągu miesiąca. Dolna wartość to 6.5 GB. W tym wyliczeniu gigabajt oznacza 1000 MB, zgodnie ze sposobem, w jaki zwykle naliczane są limity transferu.
docker stats nie rozdzieli tego ruchu, ponieważ kontener korzystający z sieci hosta współdzieli przestrzeń nazw sieci z hostem, więc jego liczniki są licznikami hosta. Dwa inne narzędzia działają poprawnie. vnstat mierzy cały serwer:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -mCały serwer oznacza cały serwer: jeśli ten VPS uruchamia również coś, co przesyła rzeczywiste dane, na przykład jeden z serwerów zdjęć utrzymywanych samodzielnie, który co noc pobiera biblioteki z telefonów, jego wysyłanie jest uwzględniane w tym samym miesięcznym limicie co ruch relay. Serwer multimediów działa tak samo w przeciwnym kierunku. Na przykład Halcyon, który zmienia bibliotekę Jellyfin w przeglądalny sklep z filmami z lat 90., wysyła strumień do oglądających, a ten ruch wychodzący również korzysta z limitu zużywanego przez relay.
Licznik nftables mierzy konkretnie ruch 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 relaymeterTa reguła nie zawiera verdict, więc zlicza pakiety i bajty bez zmiany tego, co jest dozwolone. Znajduje się też we własnej tabeli, dzięki czemu nie zakłóca działania ufw. Nie jest trwała: aby przywrócić ją po restarcie, należy umieścić te same wiersze w /etc/nftables.conf. Licznik rośnie tylko wtedy, gdy sesja jest faktycznie przekazywana przez relay. Jeśli rośnie mimo braku połączeń z własnych komputerów, oznacza to, że ktoś znalazł relay. Temu przypadkowi ma zapobiegać hbbr -k _. Ponieważ nft list nie będzie sprawdzane każdego ranka, należy dodać do niego zadanie cron, które porówna liczbę bajtów z ustalonym progiem i wyśle powiadomienie push po jego przekroczeniu. Do tego celu można użyć własnego serwera ntfy.
hbbr ma również limity szybkości, które można obniżyć. SINGLE_BANDWIDTH domyślnie ma wartość 128 Mb/s dla każdego połączenia relay, a TOTAL_BANDWIDTH wartość 1024 Mb/s dla wszystkich połączeń łącznie. Ustawienie SINGLE_BANDWIDTH=8 ogranicza jedną sesję do około 1 MB/s. Ogranicza to szybkość, a nie miesięczną sumę transferu. Należy więc traktować to jako sposób na zapobieganie wysyceniu łącza przez jedną sesję, a nie jako mechanizm kontroli budżetu.
Gdy w ogóle nie jest potrzebny relay
W przypadku konfiguracji osobistej uczciwa odpowiedź brzmi: może nie być potrzebne żadne z tych rozwiązań. Należy umieścić oba komputery w mesh VPN i łączyć się bezpośrednio z adresem tunelu. Nie będzie potrzebny hbbs, hbbr ani ruch wychodzący przez relay. Nie będzie też potrzebny kontener na VPS wymagający aktualizacji.
Na komputerze, którym ma być sterowane, należy włączyć bezpośredni dostęp IP w ustawieniach zabezpieczeń RustDesk. Pole portu ma domyślnie wartość 21118. Przed próbą połączenia należy sprawdzić, czy usługa nasłuchuje:
ss -tlnp | grep 21118Następnie należy połączyć się z adresem VPN tego węzła zamiast z identyfikatorem. W FAQ RustDesk podano, że połączenie w tym trybie nie jest szyfrowane. Należy więc używać go wewnątrz tunelu i nigdy przez otwarty Internet. To tunel zapewnia szyfrowanie.
Wybór zależy od tego, do kogo należą komputery. Samodzielnie hostowane hbbs i hbbr sprawdzą się, gdy obsługiwane są komputery nienależące do użytkownika albo osoby, które nigdy nie zainstalują klienta VPN. Po ich stronie konfiguracja ogranicza się wtedy do identyfikatora i hasła. Mesh VPN z bezpośrednim dostępem IP sprawdzi się, gdy każdy komputer należy do użytkownika i może przechowywać klucz. WireGuard a Tailscale opisuje dwa typowe sposoby utworzenia takiej sieci, a uruchamianie zdalnego pulpitu na Linux VPS dotyczy drugiego przypadku, w którym komputer, do którego potrzebny jest dostęp do ekranu, jest samym serwerem.
FAQ
Czy każda sesja RustDesk przechodzi przez mój przekaźnik?
Nie. hbbs najpierw próbuje połączyć klientów bezpośrednio, wykorzystując technikę hole punching przez NAT znajdujący się przed każdym z nich. Tylko sesje, w których to się nie powiedzie, korzystają z hbbr i tylko one generują zużycie pasma. Wyjątkiem jest ALWAYS_USE_RELAY=Y w hbbs, która wymusza przesyłanie każdej sesji przez hbbr, niezależnie od dostępności bezpośredniej ścieżki. Jeśli ta zmienna jest ustawiona w pliku Compose, każdy bajt każdej sesji obciąża Twój limit transferu.
Gdzie przechowywany jest klucz serwera RustDesk i co się stanie, jeśli go zgubię?
hbbs generuje id_ed25519 oraz id_ed25519.pub w swoim katalogu roboczym przy pierwszym uruchomieniu. W oficjalnym obrazie katalogiem tym jest /root, więc przy użyciu powyższego montowania wolumenu pliki pojawią się w ./data na hoście. Wykonaj kopię zapasową obu plików poza serwerem. W przypadku ich utraty hbbs wygeneruje nową parę przy kolejnym starcie, a każdy klient posiadający stary klucz publiczny zostanie odrzucony. Nie ma innej możliwości odzyskania dostępu poza ręczną edycją pola Key na każdym kliencie.
Które porty muszę otworzyć dla własnego serwera RustDesk?
TCP 21115, 21116 oraz 21117, a także UDP 21116. hbbs używa portu 21115 do testu typu NAT, a 21116 do rejestracji ID i sygnału heartbeat przez UDP oraz do rejestracji i hole punching przez TCP. hbbr używa portu 21117 do przekaźnika. Porty TCP 21118 i 21119 to porty WebSocket dla klienta przeglądarkowego, więc pozostaw je zamknięte, jeśli z niego nie korzystasz. Port TCP 21114 należy do serwera Pro HTTP API i wersja open source go nie wymaga.
Czy osoby niepowołane mogą korzystać z mojego przekaźnika RustDesk?
Tak, jeśli uruchomisz hbbr z domyślną konfiguracją. Dokumentacja RustDesk wskazuje, że pusty klucz pozwala klientom bez pasującego klucza na korzystanie z przekaźnika, więc każdy, kto pozna Twój adres hosta i port 21117, może przesyłać ruch przez Twój serwer. Uruchom hbbr z -k _, aby wczytywał tę samą parę kluczy, której używa hbbs, ze współdzielonego wolumenu ./data. Po tym zabiegu tylko klienci skonfigurowani z Twoim kluczem publicznym będą mogli korzystać z przekaźnika.