SSD Nodes Learn Hosting plans →
Guias Matt ConnorPor Matt Connor

Como hospedar seu próprio relay RustDesk

Execute hbbs e hbbr no VPS com chave Ed25519, tags de imagem fixas e portas restritas. Calcule a largura de banda do relay antes de contratar o plano.

O que é um servidor relay RustDesk autoalojado

Um servidor relay RustDesk autoalojado é composto por dois daemons num único VPS. hbbs é o servidor de ID e rendezvous: regista o ID de cada cliente e apresenta os dois clientes um ao outro. hbbr é o servidor relay: transporta os bytes da sessão, mas apenas nas sessões que não conseguiram comunicar diretamente. A maioria dos guias instala ambos, estabelece a ligação entre eles e termina aí. O que se segue é o restante trabalho: a chave que controla o acesso, as portas, a atualização e a largura de banda.

Ambos os daemons são distribuídos na mesma imagem, rustdesk/rustdesk-server, e, na configuração abaixo, ambos leem o mesmo par de chaves Ed25519 a partir do mesmo diretório. Isto é algo que tem de configurar, não um comportamento predefinido: hbbs carrega ou gera o par por conta própria, mas hbbr ignora as chaves, exceto se for iniciado com uma. Ed25519 é um esquema de assinatura com chave pública. Esse par de chaves determina com que clientes o seu servidor irá comunicar, e não existe uma base de dados de utilizadores por trás dele.

hbbs e hbbr: qual daemon consome a sua largura de banda

O tráfego do hbbs é pequeno e constante: registo de IDs e heartbeats, além da breve troca que apresenta dois peers. O serviço funciona todo o dia e quase não gera custos.

O tráfego do hbbr é a própria sessão. Os frames do ecrã seguem num sentido, o teclado e o rato seguem no outro, e cada byte retransmitido chega ao seu VPS e sai novamente. Se o seu fornecedor contabilizar apenas o tráfego de saída, uma sessão retransmitida custa aproximadamente à taxa da sessão. Se contabilizar a transferência total, o custo é aproximadamente o dobro.

O relay é um caminho alternativo, não o caminho normal. O hbbs tenta primeiro ligar diretamente os dois clientes, usando hole punching através do NAT (network address translation) que estiver à frente de cada um. Quando isso funciona, a sessão nunca passa pelo hbbr e o seu limite de transferência não é consumido. Quando um dos lados está atrás de um NAT que atribui uma porta nova por destino, ou de uma firewall que bloqueia o caminho criado pelo hole punching, a sessão passa para o hbbr e cada frame atravessa o seu VPS.

Uma variável de ambiente elimina esta escolha. ALWAYS_USE_RELAY=Y no hbbs força todas as sessões a passar pelo hbbr. A documentação do RustDesk mostra esta variável num dos exemplos de Compose, por isso é frequentemente copiada. Isto torna as ligações mais previsíveis e torna real o seu tráfego de saída. Defina-a porque tomou essa decisão, não porque a copiou e colou.

De que portas um servidor RustDesk autoalojado precisa

Os números das portas abaixo foram verificados na documentação do servidor RustDesk e no repositório rustdesk-server em 10 October 2026.

  • TCP 21115, em hbbs: teste do tipo de NAT.
  • UDP 21116, em hbbs: registo do ID e heartbeat. Este é o caminho que um cliente usa por predefinição.
  • TCP 21116, em hbbs: registo do ID para clientes configurados para usar apenas TCP, além de TCP hole punching e do serviço de ligação.
  • TCP 21117, em hbbr: relay. Esta é a porta que transporta os dados da sessão, por isso é a porta que gera custos.
  • TCP 21118 em hbbs e TCP 21119 em hbbr: WebSocket, usado pelo cliente no browser. Mantenha ambas fechadas se não o utilizar.
  • TCP 21114 é o servidor da API HTTP no RustDesk Server Pro. A compilação de código aberto não escuta nessa porta.

Instale hbbs e hbbr com a tag da imagem fixada

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-stopped
mkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose ps

Ambos os serviços devem ler running. Confirme que os listeners existem antes de configurar o firewall.

sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'

Deve ver listeners TCP nas portas 21115, 21116 e 21117, e um listener UDP na porta 21116. A ausência da linha UDP significa que o hbbs não está em execução, porque o hbbs abre esse listener quando inicia e é contra ele que os clientes se registam por predefinição.

Há quatro elementos deliberados nesse ficheiro. A tag é 1.1.16, ainda a versão atual em outubro de 2026, publicada em 20 de julho de 2026, em vez de latest, porque latest significa tudo o que foi publicado mais recentemente e um docker compose pull daqui a seis meses pode fornecer-lhe um servidor que nunca testou. network_mode: "host" liga diretamente as interfaces do host, que é o recomendado na documentação do RustDesk e determina o comportamento do firewall. ./data:/root mapeia o diretório de trabalho da imagem para o host, para que o par de chaves fique num local que possa incluir nas cópias de segurança. hbbr -k _ é a única alteração ao exemplo upstream, porque a predefinição deixa o relay aberto a qualquer pessoa. Se o Compose ainda for novo para si, executar o Docker Compose numa VPS explica o formato do ficheiro e os comandos do ciclo de vida.

Se o hbbr for movido para um segundo servidor, terá de indicar ao hbbs para onde foi: passe -r relay.example.com:21117 ou defina a variável de ambiente RELAY-SERVERS. Num único servidor, não precisa disso.

O par de chaves Ed25519 controla o acesso

Na primeira inicialização, o hbbs gera id_ed25519 e id_ed25519.pub no diretório de trabalho. Com a montagem acima, os dois ficheiros aparecem no host.

ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pub

id_ed25519.pub contém uma string base64. Essa string deve ser introduzida no campo Key de todos os clientes. id_ed25519 é a parte privada e nunca sai do servidor. A chave pública não é secreta, porque é copiada para a configuração de todos os clientes. A chave privada é secreta: qualquer pessoa que a possua pode configurar um servidor em que os seus clientes confiariam.

Faça agora uma cópia de segurança dos dois ficheiros, antes de configurar vinte clientes.

sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgz

Copie esse arquivo para fora do servidor. O motivo é mais importante do que qualquer outro passo. Se eliminar ~/rustdesk/data ou reconstruir o serviço num novo VPS sem o copiar, o hbbs gera um novo par de chaves na próxima inicialização. Todos os clientes continuam a ter a chave pública antiga, por isso o hbbs rejeita-os e os clientes ficam offline. Execute sudo cat ~/rustdesk/data/id_ed25519.pub e compare o resultado com o campo Key de qualquer cliente: as duas strings já não coincidem, e essa diferença é a causa de toda a falha. Corrigir o problema implica editar manualmente as definições em todas as máquinas, incluindo as máquinas às quais contava aceder através do RustDesk.

A chave não é a palavra-passe da sessão, e confundir as duas faz com que algumas pessoas ignorem uma delas. A chave determina com que clientes o seu servidor comunica. A palavra-passe permanente ou o código de utilização única na máquina controlada determina quem pode abrir uma sessão nessa máquina. Precisa das duas, e ter uma não compensa a fraqueza da outra.

Por que um relay sem autenticação é um problema

Por padrão, o hbbr não verifica nada. A documentação de configuração do RustDesk afirma isso diretamente: uma chave vazia permite que clientes sem uma chave correspondente usem o relay. O valor vazio existe para que novos utilizadores não encontrem falhas de incompatibilidade de chaves na primeira execução. O custo é que qualquer pessoa que descubra o seu endereço na porta TCP 21117 pode encaminhar o tráfego da sua sessão através do seu VPS, consumindo o seu limite de transferência e usando o seu endereço IP.

command: hbbr -k _ resolve esse problema. O argumento _ instrui o hbbr a carregar um par de chaves a partir do diretório de trabalho ou a gerar um se não existir nenhum. Como ambos os contentores montam o mesmo ./data, esse é o mesmo par usado pelo hbbs. Nada é copiado manualmente, portanto não há risco de divergência.

O volume partilhado é a parte que costuma ser configurada incorretamente. Se der ao hbbr um diretório próprio, ele gera um par de chaves diferente. O hbbs e o hbbr passam a usar chaves diferentes, todas as sessões encaminhadas falham e as sessões diretas continuam a funcionar. O sintoma é confuso: o RustDesk consegue ligar-se a alguns pares, mas não a outros, dependendo de o hole punching ter funcionado. Um único ls -l ~/rustdesk/data/ que mostre um único par id_ed25519 elimina essa incompatibilidade. Isso não prova que o relay verifica as chaves, porque o hbbr ignora esses ficheiros se não tiver sido iniciado com uma chave não vazia. Por isso, confirme também o comando em execução:

ps -eo args | grep '[h]bbr'

O comando deve mostrar hbbr -k _. Um hbbr isolado significa que o relay continua aberto, independentemente do conteúdo do diretório.

Aponte os clientes para o seu servidor

Em cada máquina, abra o RustDesk e aceda a Settings, depois Network e, por fim, ID/Relay Server.

  • ID Server: o seu hostname, por exemplo rustdesk.example.com. O cliente utiliza a porta 21116, a menos que indique outra.
  • Relay Server: deixe vazio quando o hbbr for executado no mesmo host que o hbbs.
  • API Server: deixe vazio. O servidor de código aberto não fornece esse serviço.
  • Key: a cadeia base64 de id_ed25519.pub, colada exatamente como está, sem espaço no final.

A janela principal deverá indicar que o cliente está pronto. Se isso não acontecer e o cliente utilizar as definições predefinidas, a causa habitual é o UDP 21116 não chegar ao hbbs, porque é nessa porta que um cliente predefinido se regista e envia o seu heartbeat. No entanto, um ID offline não prova isso por si só. Um cliente com a opção disable-udp definida como Y regista-se através do TCP 21116 e nunca utiliza o UDP 21116. Nesse cliente, verifique primeiro o TCP 21116.

Restrinja as portas para que o relay não fique exposto como um serviço aberto

Como os containers usam a rede do host, não existe uma regra NAT do Docker à frente deles. Por isso, as regras do ufw aplicam-se da forma esperada.

sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numbered

Adicione 21118:21119/tcp apenas se executar o cliente no navegador. Mantenha uma segunda sessão SSH aberta enquanto ativa o ufw. Assim, um erro na regra SSH não bloqueia o acesso ao próprio servidor. Noções básicas do firewall ufw para um VPS explica as políticas predefinidas e a ordem das regras.

Agora, atenção à armadilha. Se mudar para a publicação de portas com um bloco ports:, que é usado em muitos exemplos do RustDesk com um único container, o Docker cria as suas próprias regras DNAT. Os pacotes chegam ao container sem passar pela cadeia onde estão as regras do ufw. Nesse caso, uma negação do ufw para a porta 21117 não tem efeito, e o relay fica aberto à Internet, embora ufw status indique o contrário. As portas publicadas pelo Docker ignoram o ufw explica a ordem das cadeias. A rede do host evita completamente este problema. Se publicar uma porta, associe-a a um único endereço, como em "127.0.0.1:21118:21118" atrás de um reverse proxy.

A restrição por endereço de origem só funciona quando os clientes têm endereços estáveis.

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 udp

Os portáteis ligados a redes de hotéis não têm endereços estáveis. É precisamente por isso que a key no hbbr desempenha aqui um papel mais importante do que o firewall.

Atualizar uma stack que contém a sua chave

A chave fica no bind mount, não dentro do container. Por isso, a atualização é segura desde que não altere ./data.

  1. Faça primeiro uma cópia de segurança do diretório de dados: sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data.
  2. Leia as notas da versão da nova tag na página de releases do rustdesk-server.
  3. Edite compose.yml e altere ambas as linhas image: para a nova tag.
  4. Execute sudo docker compose pull e depois sudo docker compose up -d.
  5. Execute sudo cat ~/rustdesk/data/id_ed25519.pub e confirme que a string é igual à que os seus clientes já têm.

O passo 5 é a verificação mais importante. Uma chave alterada não gera um aviso evidente no servidor e quebra todos os clientes ao mesmo tempo. Para reverter, volte a colocar a tag antiga e execute up -d novamente. Isto só funciona porque fixou a tag: com latest, docker compose pull moveu o nome para a nova imagem e deixou de existir uma tag que identifique a imagem antiga.

A forma habitual de perder a chave não é docker compose down, que não altera um bind mount. O problema ocorre ao migrar para um novo VPS e copiar apenas compose.yml. Copie também ./data.

Monitorize o tráfego de saída num plano com limite de transferência

O hbbr é a única parte desta stack que pode consumir um limite de transferência. A FAQ do RustDesk indica que uma ligação retransmitida, numa sessão com resolução 1920x1080, pode consumir entre 30 KB/s e 3 MB/s, e que o trabalho de escritório simples ronda os 100 KB/s. Estes são valores publicados para uma única sessão, não uma medição da sua configuração. Multiplicados por sessenta horas por mês, duas horas por dia, os valores são os seguintes.

GráficoVPS egress from one relayed RustDesk session, 60 hours per month
Os dados por trás deste gráfico
[
  {
    "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
  }
]

À taxa de trabalho de escritório, uma sessão consome cerca de 21.6 GB por mês, o que não será relevante para nenhum plano. No limite superior do intervalo publicado, as mesmas sessenta horas consomem 648 GB, e duas sessões simultâneas a essa taxa ultrapassam um limite de 1 TB durante o mês. O limite inferior é 6.5 GB. Aqui, os gigabytes correspondem a 1000 MB, que é a forma normal de contabilizar os limites de transferência.

O docker stats não apresenta estes dados separadamente, porque um contentor que utiliza a rede do host partilha o namespace de rede do host. Por isso, os respetivos contadores são os contadores do host. Existem duas outras ferramentas que funcionam. O vnstat mede o servidor inteiro:

sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -m

Servidor inteiro significa todo o servidor. Se este VPS também executar algo que transfira dados reais, como um dos servidores de fotografias self-hosted que copia as bibliotecas dos telemóveis todas as noites, esses uploads entram no mesmo total mensal que o tráfego do relay. Um servidor multimédia funciona da mesma forma no sentido inverso. Algo como Halcyon, que transforma uma biblioteca Jellyfin numa videoteca dos anos 90 que pode ser explorada transmite conteúdo para quem estiver a assistir, e esse tráfego de saída partilha o limite utilizado pelo relay.

Um contador nftables mede especificamente o 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 relaymeter

Essa regra não toma nenhuma decisão, por isso conta pacotes e bytes sem alterar o que é permitido. Ela fica numa tabela própria, portanto não interfere com o ufw. Não é persistente: coloque as mesmas linhas em /etc/nftables.conf se quiser que volte a ser aplicada depois de um reboot. O contador só aumenta enquanto uma sessão está efetivamente a ser retransmitida. Um contador que continua a aumentar quando nenhuma das suas máquinas está ligada significa que outra pessoa encontrou o seu relay. É precisamente esse o caso que hbbr -k _ existe para impedir. Como não vai ler nft list todas as manhãs, coloque nele um cron job que compare a contagem de bytes com um limite e envie um alerta push quando esse limite for ultrapassado. Para isso, use o seu próprio servidor ntfy.

O hbbr também tem limites de velocidade que pode reduzir. Por predefinição, o SINGLE_BANDWIDTH é de 128 Mb/s por ligação retransmitida e o TOTAL_BANDWIDTH é de 1024 Mb/s para todas as ligações. Definir SINGLE_BANDWIDTH=8 limita uma sessão a cerca de 1 MB/s. Isto limita a velocidade, não o total mensal. Utilize-o para impedir que uma sessão sature a ligação, e não como controlo do orçamento.

Quando não precisa de um relay

Num setup pessoal, a resposta honesta é que talvez não precise de nada disto. Coloque as duas máquinas numa VPN mesh e ligue-se diretamente ao endereço do túnel. Não há hbbs, hbbr, egress do relay nem contentor num VPS para atualizar.

Na máquina que pretende controlar, ative o acesso IP direto nas definições de segurança do RustDesk. O campo da porta usa 21118 por predefinição. Confirme que a porta está em estado de listening antes de tentar ligar-se:

ss -tlnp | grep 21118

Em seguida, ligue-se ao endereço VPN desse peer em vez de usar um ID. A FAQ do RustDesk informa que, neste modo, a ligação não é cifrada. Por isso, use-o dentro do túnel e nunca através da Internet pública. É o túnel que fornece a cifragem.

Escolha com base na propriedade das máquinas. Um hbbs e hbbr self-hosted são adequados quando dá suporte a máquinas que não lhe pertencem ou a pessoas que nunca vão instalar um cliente VPN, porque o lado delas da configuração usa um ID e uma palavra-passe. Uma VPN mesh com acesso IP direto é adequada quando todas as máquinas lhe pertencem e podem usar uma chave. WireGuard comparado com Tailscale apresenta as duas formas habituais de criar essa mesh, e executar um desktop remoto num VPS Linux aborda o outro caso, em que a máquina onde pretende obter um ecrã é o próprio servidor.

FAQ

Todas as sessões do RustDesk passam pelo meu relay?

Não. Primeiro, o hbbs tenta ligar diretamente os dois clientes, usando hole punching através do NAT existente à frente de cada um. Apenas as sessões em que essa tentativa falha recorrem ao hbbr, e só essas consomem a sua largura de banda. A exceção é ALWAYS_USE_RELAY=Y no hbbs, que força todas as sessões a passar pelo hbbr, independentemente de estar disponível um caminho direto. Se essa variável estiver definida no seu ficheiro Compose, todos os bytes de todas as sessões serão contabilizados na sua transferência.

Onde está armazenada a chave do servidor RustDesk e o que acontece se a perder?

O hbbs gera id_ed25519 e id_ed25519.pub no diretório de trabalho na primeira inicialização. Esse diretório é /root dentro da imagem oficial. Por isso, com a montagem de volume mostrada acima, os ficheiros aparecem em ./data no host. Faça uma cópia de segurança dos dois ficheiros fora do servidor. Se os perder, o hbbs gera um novo par na inicialização seguinte, e todos os clientes que ainda tenham a chave pública antiga serão recusados. Não existe outra forma de recuperação além de editar manualmente o campo Key em todos os clientes.

Que portas preciso de abrir para um servidor RustDesk autoalojado?

TCP 21115, 21116 e 21117, além de UDP 21116. O hbbs usa 21115 para o teste do tipo de NAT e 21116 para o registo do ID e o heartbeat através de UDP, bem como para o registo e o hole punching através de TCP. O hbbr usa 21117 para o relay. TCP 21118 e 21119 são as portas WebSocket do cliente no browser. Mantenha-as fechadas se não o utilizar. TCP 21114 pertence ao servidor da API HTTP Pro, e a compilação open source não precisa dela.

Pessoas desconhecidas podem usar o meu relay RustDesk autoalojado?

Sim, se executar o hbbr com a configuração predefinida. A documentação do RustDesk indica que uma chave vazia permite que clientes sem uma chave correspondente utilizem o relay. Assim, qualquer pessoa que descubra o seu hostname e a porta 21117 pode encaminhar tráfego através do seu servidor. Execute o hbbr com -k _ para que carregue o mesmo par de chaves utilizado pelo hbbs a partir do volume partilhado ./data. Depois disso, apenas os clientes configurados com a sua chave pública poderão encaminhar tráfego através do seu servidor.