A mascote urso-polar da NordBastion, em pé em um salão de pedra nórdico escuro, com uma pata sobre um obelisco de pedra angular rúnico esculpido, um anel holográfico ciano flutuante de chaves pairando acima dele, e cinco glifos de dispositivos brilhantes — notebook, celular, tablet, torre de servidor e globo — ligados diretamente uns aos outros em uma malha ciano brilhante no alto, enquanto linhas pontilhadas tênues de chave caem do anel até cada dispositivo, um rack de servidores e uma janela arqueada iluminada pela aurora atrás dele
Tutorial · Rede privada·19 min de leitura · 50 min de mão na massa

Seu próprio servidor de controle.
O mapa é a coisa que vale a pena guardar.

Uma VPN mesh precisa que alguém distribua as chaves. Com o Tailscale, esse alguém é uma empresa; com WireGuard puro, é você, manualmente, para sempre. O Headscale é a terceira resposta: o mesmo cliente de código aberto, conversando com um servidor de coordenação em uma máquina alugada anonimamente. Seis etapas até um tailnet cujo mapa de dispositivos, regras de acesso e relays de fallback são todos seus — Headscale atrás do Caddy, ACLs registradas por escrito, MagicDNS apontado para o seu próprio resolvedor, um roteador de sub-rede, um nó de saída e um DERP embutido. A máquina custa $3.90 por mês. Testado em Debian 12.

As seis etapas
  1. 01

    Escolher

    WireGuard × Tailscale × Headscale

  2. 02

    Provisionar

    Três nomes fixados antes da inicialização

  3. 03

    Implantar

    Headscale, Caddy, uma configuração

  4. 04

    Inscrever

    Usuários, chaves de pré-autenticação, clientes

  5. 05

    Rotear

    Sub-redes, nó de saída, ACLs

  6. 06

    Keep

    DERP, backups, atualizações

Antes de começar · O que é um plano de controle

Ninguém consegue ler o tráfego. Alguém ainda guarda o mapa.

O WireGuard é deliberadamente incompleto. É um túnel pequeno, rápido e auditável entre duas chaves públicas, e não tem opinião nenhuma sobre como essas chaves se encontram. Essa omissão é o motivo pelo qual o protocolo é tão bom quanto é — e também é o motivo pelo qual uma rede WireGuard de quinze dispositivos é uma planilha. Cada peer precisa da chave pública e do endereço atual de todos os outros peers, e cada notebook que se move entre um escritório, um trem e um hotel invalida parte dessa planilha.

Uma VPN mesh é a resposta para esse problema específico, e vale a pena descrever seu formato com precisão, porque isso decide o que você está confiando a alguém. O plano de dados continua exatamente como era: cada dispositivo gera seu próprio par de chaves localmente, guarda a metade privada e criptografa diretamente para seus peers. Por cima disso fica um plano de controle — um pequeno serviço que coleta chaves públicas e endpoints, entrega a cada dispositivo a lista de peers com quem ele tem permissão de falar, e ajuda dois dispositivos atrás de roteadores hostis a se encontrarem. Esse serviço nunca guarda uma chave privada e nunca vê um único byte em texto claro.

O que ele guarda é o mapa, e o mapa é mais interessante do que a maioria das pessoas presume. Cada nome de dispositivo e cada nome de usuário. Cada chave pública. O endereço público de onde cada dispositivo está discando agora mesmo, que é um registro ao vivo de onde o seu notebook e o seu celular estão fisicamente. Os horários em que cada dispositivo conecta e desconecta, que descrevem o seu dia. E a política que decide quem pode alcançar o quê, que descreve a sua organização. Nada disso exige má-fé de ninguém; é simplesmente para isso que serve um servidor de coordenação.

Existe mais uma característica que importa mais do que os metadados. O plano de controle é a coisa que distribui as chaves, então também é a coisa que poderia adicionar uma indevidamente. Um servidor de controle comprometido, ou coagido, pode dizer aos seus dispositivos que uma máquina nova é um membro legítimo da rede — e seus dispositivos, fazendo exatamente o que foram construídos para fazer, vão criptografar para ela. O Tailscale leva isso a sério o suficiente para ter construído um recurso de assinatura contra esse risco. Auto-hospedar resolve o mesmo problema pelo lado oposto: quem poderia fazer isso é você. Quatro arranjos, e o que cada um deles realmente revela:

Propriedade WireGuard manual Tailscale, hospedado Headscale no seu VPS Headscale + seu próprio DERP
Quem consegue ler o payloadNinguém além dos peersNinguém além dos peersNinguém além dos peersNinguém além dos peers
Quem guarda o mapa de dispositivosVocê, em um arquivo de textoUma empresa, em sua jurisdiçãoVocê, no seu VPSVocê, no seu VPS
Quem vê de onde os dispositivos se conectamSó os próprios peersO servidor de coordenação, continuamenteSeu servidor, continuamenteSeu servidor, continuamente
Quem retransmite quando um link direto falhaNinguém — o link simplesmente falhaA frota de relays do provedorAinda os relays do provedor, por padrãoSeu relay, no seu datacenter
Adicionando o vigésimo dispositivoDezenove edições de configuraçãoUm comandoUm comandoUm comando
Escolha-o quandoPoucos dispositivos, nenhum deles em roamingVocê quer operação zero e aceita abrir mão do mapaVocê quer o mapa e pode rodar uma máquina pequenaVocê quer o mapa e também o caminho de fallback

A primeira coluna não é um espantalho. Para um punhado estático de servidores, o WireGuard escrito à mão é, sinceramente, a melhor resposta de engenharia, e é um serviço a menos para corrigir. Este guia é sobre o ponto em que a planilha para de ter graça.

Etapa 01 · Escolher

Você precisa de um plano de controle? Conte os dispositivos que se movem.

Existem três respostas honestas para "eu quero que minhas máquinas se alcancem em privado", e só uma delas é este guia. WireGuard puro é a menor: um módulo do kernel, um arquivo de configuração por peer, nenhum daemon além da interface, nada para manter atualizado além do sistema operacional. Se os seus dispositivos são servidores com endereços fixos e você consegue contá-los nos dedos de uma mão, pare por aqui e leia o guia de WireGuard em vez deste. Você vai acabar com menos software e uma lista mais curta de coisas que podem quebrar.

Tailscale é a maior: o mesmo WireGuard por baixo, mais um serviço de coordenação, travessia de NAT que funciona por trás de quase qualquer coisa, uma frota de relays em vários continentes, um console web, login único e um contrato de suporte. É um software genuinamente excelente, e o nível gratuito atende uma residência com folga. O preço não é em dinheiro — é que o mapa de cada dispositivo seu, e o registro de onde cada um se conecta, vive no banco de dados de uma empresa.

Headscale é a terceira resposta, e é mais restrita que as outras duas: uma reimplementação de código aberto do servidor de coordenação, operada por você, com quem o mesmo cliente oficial conversa. Você mantém a automação e a travessia de NAT; em troca, assume um pequeno serviço para operar, um conjunto parcial de recursos e atualizações que exigem leitura. Ninguém deveria fingir que isso é de graça. Isso compra exatamente uma coisa, e é a coisa com que este site se importa: mais ninguém guarda o mapa.

O limiar de cinco dispositivos

A configuração manual do WireGuard cresce com o quadrado da frota: quatro peers são seis links, dez peers são quarenta e cinco, vinte peers são cento e noventa. Acrescente um notebook em roaming, cujo endpoint muda a cada rede que ele entra, e a manutenção deixa de ser ocasional. Na prática, o ponto de virada fica em torno de cinco dispositivos, ou no primeiro dispositivo que muda de rede diariamente, ou na primeira regra de acesso que você não consegue expressar como "todo mundo pode alcançar tudo".

Mais uma coisa para decidir agora, e não depois, porque isso muda o que você instala: se essa rede é só sua, ou se outras pessoas vão entrar nela. Um tailnet de uma única pessoa pode ficar totalmente aberto internamente sem que nada de ruim aconteça. Um tailnet com um colega, um terceirizado ou um familiar precisa de regras de acesso escritas desde a primeira semana — etapa 05 — e precisa que os usuários sejam separados, em vez de todo mundo compartilhar um login. Decidir isso de antemão custa um parágrafo; fazer essa adaptação depois custa uma tarde inteira.

Etapa 02 · Provisionar

Três nomes, decididos antes da primeira inicialização. Os três são difíceis de mudar.

Peça a máquina primeiro. No painel: Order → VPS → Sentinel, imagem Debian 12, no bastião onde você quiser que o mapa viva — Helsinque, Estocolmo, Oslo ou Reykjavík. Nenhum endereço de e-mail é exigido para abrir a conta, e a fatura é paga em Monero, Bitcoin, Lightning ou qualquer outro ativo suportado. Escolha o bastião mais próximo da maioria dos seus dispositivos se você também pretende rodar o relay da etapa 06; a latência até um relay é latência em toda conexão que ele carrega.

Depois, execute o checklist de hardening da primeira hora — SSH só por chave em uma porta trocada, atualizações automáticas, um firewall que nega tudo por padrão. Tudo a seguir presume uma máquina que ainda não é de mais ninguém, e esta vale mais do que a maioria: é a máquina que decide quais chaves são confiáveis em cada dispositivo seu.

Decida essas três coisas antes que qualquer coisa se registre

Cada dispositivo grava essas três coisas no seu estado no momento em que entra, então mudar uma delas depois significa reinscrever a frota manualmente. Um: a URL do servidor de controle — o endereço HTTPS público exato que todo cliente vai discar, esquema e hostname incluídos. Dois: o sufixo de DNS do tailnet, o domínio para o qual o MagicDNS vai responder internamente; precisa ser um domínio que você controla e não pode ser pai nem filho do próprio hostname do servidor de controle, que é a causa mais comum de falha na primeira inicialização. Três: as faixas de endereço que o tailnet distribui, convencionalmente o bloco de NAT de nível operadora 100.64.0.0/10 para IPv4 e um /48 de endereço local único para IPv6; deixe os valores padrão, a menos que já colidam com uma rede que você usa.

Um exemplo prático, no formato que vale copiar: o servidor de controle responde em vpn.example.com, o sufixo do tailnet é ts.example.com, e as faixas de endereço ficam nos valores padrão. Note que o sufixo é irmão do hostname de controle, não seu pai — vpn.example.com e ts.example.com compartilham um domínio registrável, mas nenhum contém o outro. Aponte um registro A — e um AAAA, se quiser acesso via IPv6 — para a máquina, e deixe-o propagar antes de começar, porque o proxy reverso vai tentar obter um certificado para esse nome na primeira vez que inicializar.

Depois, escreva as regras de firewall enquanto nada ainda está escutando. O servidor de controle é, por necessidade, um endpoint HTTPS público: todo dispositivo, em qualquer rede, precisa conseguir alcançá-lo. A porta UDP só é necessária se você pretende rodar o seu próprio relay na etapa 06, e é mais fácil abri-la agora do que depurar sua ausência depois.

ufw default deny incoming
ufw allow 47222/tcp                  # administrative SSH, moved
ufw allow 80/tcp                     # ACME HTTP-01 challenge
ufw allow 443/tcp                    # the control server, and DERP over HTTPS
ufw allow 3478/udp                   # STUN, only if you run your own relay
ufw enable
ufw status numbered

Instale o Docker a partir do repositório oficial, em vez do pacote da distribuição, para que o Compose v2 esteja presente e atualizado. Depois crie os dois diretórios que vão guardar tudo que vale a pena incluir no backup — um para configuração, outro para estado — e resista à tentação de colocar mais nada neles.

curl -fsSL https://get.docker.com | sh
docker compose version

install -d -m 0750 /srv/headscale/config
install -d -m 0750 /srv/headscale/data
cd /srv/headscale
Etapa 03 · Implantar

Dois containers e um arquivo. Fixe a versão, sempre.

Headscale e Caddy, e mais nada. O Headscale escuta em HTTP puro dentro da rede Docker; o Caddy termina o TLS, obtém o certificado na primeira inicialização e o renova sem que ninguém precise pedir. O listener de métricas fica em localhost, porque é uma superfície de depuração interna, não pública.

Uma regra antes do arquivo: fixe a imagem em uma versão exata. O Headscale é um software pré-1.0 que já renomeou chaves de configuração e subcomandos da CLI entre versões menores mais de uma vez. Uma tag flutuante transforma um restart de rotina do container em uma indisponibilidade de um serviço cuja função é justamente deixar você alcançar tudo o mais.

/srv/headscale/docker-compose.yml

services:
  headscale:
    image: docker.io/headscale/headscale:0.26            # pin it; never :latest
    container_name: headscale
    command: serve
    volumes:
      - ./config:/etc/headscale
      - ./data:/var/lib/headscale
    ports:
      - "3478:3478/udp"                                  # STUN, for your own DERP
    restart: unless-stopped

  caddy:
    image: caddy:2-alpine
    container_name: caddy
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - caddy_data:/data
    restart: unless-stopped

volumes:
  caddy_data:

/srv/headscale/Caddyfile

vpn.example.com {
    reverse_proxy headscale:8080
}

Essa é toda a configuração do proxy. O Caddy fala HTTP/2 e faz upgrade de conexões de longa duração sem que ninguém precise pedir, o que importa aqui porque todo cliente mantém uma aberta para receber atualizações do mapa. Pegue o arquivo de configuração de exemplo que acompanha a versão que você fixou e edite-o, em vez de escrever um do zero — o arquivo é longo, a maior parte dele são valores padrão sensatos, e as chaves que importam são estas:

/srv/headscale/config/config.yaml — the lines that matter

server_url: https://vpn.example.com          # exactly what clients will dial
listen_addr: 0.0.0.0:8080                    # inside the Docker network only
metrics_listen_addr: 127.0.0.1:9090          # debug surface, keep it local

prefixes:
  v4: 100.64.0.0/10
  v6: fd7a:115c:a1e0::/48

noise:
  private_key_path: /var/lib/headscale/noise_private.key

database:
  type: sqlite                               # postgres for a large fleet
  sqlite:
    path: /var/lib/headscale/db.sqlite

dns:
  magic_dns: true
  base_domain: ts.example.com                # NOT a parent or child of server_url
  nameservers:
    global:
      - 1.1.1.1                              # replaced by your own in step 05

Suba o serviço e leia o log, em vez de presumir. Uma primeira inicialização que não consegue obter um certificado, ou que rejeita o sufixo de DNS porque ele se sobrepõe ao hostname do servidor, avisa isso claramente e para.

docker compose up -d
docker compose logs -f headscale

# From your laptop — a control server that is up answers this:
curl -s https://vpn.example.com/health

A primeira inicialização gera o material da chave privada em /srv/headscale/data. Copie-o para um lugar seguro agora, antes que um único dispositivo se registre, e de novo depois da primeira inscrição: perder essa chave significa que todo dispositivo rejeita o servidor em quem confiava, e o único reparo é reinscrever todos eles manualmente. A etapa 06 transforma essa cópia em um backup de verdade.

Etapa 04 · Inscrever

Um usuário, uma chave, um cliente. Depois, verifique se a conexão foi direta.

O comando headscale vive dentro do container, então toda ação administrativa é um docker exec. Crie um usuário primeiro — um usuário é o dono de dispositivos e a unidade à qual as regras de acesso se referem, então dê a ele o nome de uma pessoa ou de uma função, não de uma máquina.

hs() { docker exec -it headscale headscale "$@"; }

hs users create alice
hs users list                      # note the numeric id — newer releases want it

# A single-use key that expires in an hour is the right default.
hs preauthkeys create --user 1 --expiration 1h

Em seguida, suba o cliente oficial no dispositivo, apontando-o para o seu servidor em vez do padrão. Isso é uma flag suportada, não um workaround — o cliente é de código aberto, e o servidor de login é um parâmetro.

# On the device (Debian/Ubuntu shown; every platform has an equivalent):
curl -fsSL https://tailscale.com/install.sh | sh

sudo tailscale up \
  --login-server https://vpn.example.com \
  --auth-key <the-key-you-just-created>

tailscale status
tailscale ip -4

Sem uma chave de pré-autenticação, o cliente imprime uma URL em vez disso; visitá-la mostra um comando de registro para rodar no servidor, que é o caminho interativo e é útil para um dispositivo na frente do qual você está sentado. De qualquer forma, faça o segundo dispositivo antes de comemorar — uma malha de um só não prova nada. Dê ping nele pelo endereço do tailnet e depois leia a saída do status com atenção:

hs nodes list

# On a client, the word after the peer name is the one that matters:
tailscale status
#   100.64.0.2  laptop  alice  linux  active; direct 203.0.113.9:41641
#                                              ^^^^^^ direct, not relay

tailscale netcheck                 # why it chose what it chose

direct significa que os dois dispositivos se encontraram e o tráfego é peer-to-peer. relay significa que ele passa por um servidor DERP, o que funciona bem, mas adiciona latência e coloca uma terceira máquina no caminho — e, por padrão, essa máquina não é sua. A etapa 06 trata de garantir qual das duas situações é a sua.

Celulares, tablets e o desvio da Apple

Nos desktops, é uma flag de linha de comando. O Android expõe o servidor personalizado dentro do app, atrás do número da versão na tela de configurações. As plataformas da Apple não têm campo dentro do aplicativo: você instala um pequeno perfil de configuração que define a URL do servidor de controle antes de fazer login, o que é trabalhoso uma vez e permanente depois disso. Duas coisas economizam tempo. Consulte a página por cliente da documentação do Headscale em vez de chutar, porque o fluxo da Apple já mudou mais de uma vez. E faça logout do app no serviço próprio do Tailscale primeiro — um app que já tem uma sessão ativa lá costuma recusar um servidor diferente até que tenha feito logout, ou seja reinstalado.

Dois hábitos que vale a pena adotar imediatamente. Use chaves de pré-autenticação de uso único e curta duração para pessoas, e chaves reutilizáveis ou efêmeras só para automação que realmente precisa delas — uma chave efêmera registra um dispositivo que se remove sozinho quando fica offline, o que é exatamente certo para um runner de CI e exatamente errado para um notebook. E decida agora a sua posição sobre expiração de chaves: um dispositivo registrado carrega uma data de expiração, e um dispositivo cuja chave expirou deixa de ser alcançável até que alguém o reautentique. Isso é um recurso de segurança em um notebook e um gerador de indisponibilidade em um servidor headless às três da manhã. Verifique como a sua versão gerencia a expiração — os subcomandos já se moveram — e configure isso deliberadamente por dispositivo, em vez de descobrir o padrão da forma mais difícil.

Etapa 05 · Rotear

Anunciado não é aprovado. Dois comandos, duas máquinas.

Um tailnet em que todo dispositivo alcança todos os outros já é útil. Três acréscimos o transformam de um conjunto de túneis em uma rede de verdade, e os três compartilham uma característica que costuma confundir as pessoas: o cliente anuncia uma capacidade, e o servidor precisa aprová-la. Uma rota que é anunciada mas não aprovada simplesmente não existe, silenciosamente, e o sintoma é conseguir dar ping no roteador, mas em nada que esteja atrás dele.

Um roteador de sub-rede — coloque uma LAN inteira no tailnet. Uma máquina em uma rede doméstica ou de escritório anuncia a faixa de endereços da rede; todo outro dispositivo passa então a alcançar as impressoras, o NAS e as interfaces de gerenciamento atrás dela sem precisar instalar mais nada ali. Ative o encaminhamento no kernel primeiro, ou os pacotes param no roteador sem nenhuma mensagem de erro.

# On the machine that sits inside the LAN:
echo 'net.ipv4.ip_forward = 1'          | sudo tee /etc/sysctl.d/99-ts.conf
echo 'net.ipv6.conf.all.forwarding = 1' | sudo tee -a /etc/sysctl.d/99-ts.conf
sudo sysctl -p /etc/sysctl.d/99-ts.conf

sudo tailscale up --login-server https://vpn.example.com \
  --advertise-routes=192.168.1.0/24 --accept-routes

# On the control server — approve it, or it does not exist.
# The subcommand moved between releases; check `hs nodes --help` first.
hs nodes list
hs nodes approve-routes --identifier 3 --routes 192.168.1.0/24

Um nó de saída — envie tudo para fora através do VPS. O mesmo mecanismo com uma rota mais ampla: um dispositivo que se anuncia como nó de saída se oferece para carregar toda a conexão de internet de outro dispositivo. Em uma rede não confiável de café ou hotel, é exatamente isso que você quer, e é a coisa mais próxima de uma VPN pessoal que existe neste guia.

# On the VPS that will do the exiting (forwarding must be on, as above):
sudo tailscale up --login-server https://vpn.example.com --advertise-exit-node

# Approve it on the control server, then on the laptop:
tailscale set --exit-node=100.64.0.1 --exit-node-allow-lan-access
tailscale set --exit-node=                    # turn it off again

Um nó de saída não é uma VPN comercial, e você não deve se vender essa ideia. O endereço é só seu e é estável, o que é excelente contra o Wi-Fi do café e inútil contra a correlação de longo prazo entre sites — essa troca está detalhada no guia principal. Note também que é possível rodar o nó de saída em um segundo VPS, mais barato, e manter o servidor de controle totalmente livre de tráfego encaminhado.

Regras de acesso — escreva-as antes que a segunda pessoa entre. A política padrão é permitir tudo, o que está certo para um tailnet de uma pessoa só e errado no instante em que mais alguém entra nele. A política é um pequeno documento HuJSON: grupos de usuários, tags para máquinas e uma lista de regras que dizem quais origens podem alcançar quais destinos em quais portas. Aponte a configuração para o arquivo, mantenha o arquivo sob controle de versão e recarregue após cada edição.

{
  "groups": {
    "group:admin":     ["alice"],
    "group:contractor":["bob"]
  },
  "tagOwners": {
    "tag:server": ["group:admin"],
    "tag:exit":   ["group:admin"]
  },
  "acls": [
    // Admins reach everything.
    { "action": "accept", "src": ["group:admin"], "dst": ["*:*"] },

    // The contractor reaches one machine, on two ports, and nothing else.
    { "action": "accept", "src": ["group:contractor"],
      "dst": ["tag:server:22,443"] }
  ],
  "autoApprovers": {
    "routes":   { "192.168.1.0/24": ["tag:server"] },
    "exitNode": ["tag:exit"]
  }
}

Duas observações sobre esse arquivo. A linguagem de política é do Tailscale, e o Headscale implementa um subconjunto grande e crescente dela, não tudo — verifique a documentação da sua versão antes de confiar em uma regra exótica. E onde a política mora também já mudou: versões mais antigas indicavam um caminho na configuração de nível superior, as mais novas a agrupam sob uma seção de política com um modo que também pode manter as regras no banco de dados. Ambas estão documentadas; a que importa é a que a sua versão fixada traz.

MagicDNS — nomes curtos, e o seu próprio resolvedor em todo lugar. Com o MagicDNS ativado, todo dispositivo responde por um nome curto dentro do sufixo que você escolheu na etapa 02, então ssh nas funciona de qualquer lugar sem precisar de um arquivo hosts. A segunda metade é a interessante: o servidor de controle também envia uma lista de servidores de nome para cada cliente, o que significa que o resolvedor que você construiu no guia de resolvedor de DNS privado pode atender o seu celular em dados móveis — filtrando, fazendo cache e sem registrar nada — enquanto escuta em um endereço do tailnet que não é alcançável pela internet de jeito nenhum.

dns:
  magic_dns: true
  base_domain: ts.example.com
  override_local_dns: true          # beat whatever DHCP handed the device
  nameservers:
    global:
      - 100.64.0.5                  # your resolver, on the tailnet
Etapa 06 · Manter

Seu próprio relay, seu próprio backup. E atualizações lidas antes de aplicadas.

O relay que você esqueceu que estava usando. Quando dois dispositivos não conseguem abrir uma conexão direta — NAT simétrico nas duas pontas, um firewall que engole UDP, uma operadora fazendo alguma criatividade — o tráfego recorre a um relay DERP. Ele continua criptografado ponta a ponta, então o relay carrega texto cifrado. O que o relay vê é quem está falando com quem, quanto e quando. Por padrão, o Headscale entrega aos seus clientes o mapa público de relays, e esses relays são operados pela empresa da qual você estava se afastando. O Headscale traz um relay embutido; ativá-lo coloca esse fallback no mesmo datacenter nórdico do resto disto tudo.

derp:
  server:
    enabled: true
    region_id: 999                  # custom regions live in the 900s
    region_code: "nb-hel"
    region_name: "Helsinki (self-hosted)"
    stun_listen_addr: "0.0.0.0:3478"
  urls:
    - https://controlplane.tailscale.com/derpmap/default   # remove for yours only
  auto_update_enabled: true
  update_frequency: 24h

Manter o mapa público ao lado do seu próprio relay é o padrão pragmático: os clientes preferem o relay mais próximo, então um dispositivo no mesmo hemisfério usa o seu, e um dispositivo do outro lado do mundo não fica preso atrás de um único salto nórdico. Remover a URL pública torna o tailnet estritamente autocontido, ao preço de um fallback pior para dispositivos distantes. As duas opções são defensáveis; escolha conscientemente, não por omissão.

Quatro arquivos, fora do local, criptografados. O backup é pequeno o bastante para ser constrangedor se estiver faltando: o banco de dados, o material da chave privada, o arquivo de configuração e o arquivo de política. Juntos, são um erro de arredondamento em qualquer conta de armazenamento, e sem o material da chave todo dispositivo na rede rejeita o servidor. Envie-os para algum lugar que não seja esta máquina — idealmente uma segunda jurisdição, que é o que o guia de backups cobre — e restaure-os em um VPS descartável uma vez, deliberadamente, antes de precisar de verdade.

# Stop briefly for a consistent SQLite copy, or use .backup on a live db.
docker compose stop headscale
tar czf /tmp/headscale-$(date +%F).tar.gz -C /srv/headscale config data
docker compose start headscale

restic -r sftp:backup@backup.example.com:/srv/restic backup \
       /tmp/headscale-$(date +%F).tar.gz

Atualizações, que são o risco de verdade. Isto é software pré-1.0 e se comporta como tal: chaves de configuração já foram renomeadas, subcomandos da CLI já se moveram, e uma versão já precisou, mais de uma vez, de uma migração documentada em vez de um simples restart. Nada disso é motivo para evitá-lo — é motivo para ter uma rotina. Leia as notas de lançamento antes de baixar. Faça o backup acima primeiro. Compare seu arquivo de configuração com o exemplo que acompanha a nova versão, porque é ali que as chaves renomeadas se revelam. Avance uma versão menor de cada vez, não três. E mantenha a tag da imagem antiga anotada em algum lugar, porque um rollback que você consegue fazer em trinta segundos é o que torna tudo isso de baixo risco.

Depois, configure um lembrete mensal para olhar duas coisas: a lista de dispositivos registrados, para que máquinas desativadas há seis meses deixem de ser membros, e as datas de expiração, para que nada saia silenciosamente do ar num momento ruim. Uma VPN mesh é um dos poucos serviços que falha silenciosamente — tudo continua funcionando até a única vez em que você precisa do dispositivo que expirou sem avisar.

A parte honesta · O que isto não faz

Você recuperou o mapa. Você não se tornou invisível.

Auto-hospedar o plano de controle é uma melhoria real e específica, não um passe de mágica. Cinco coisas continuam verdadeiras depois que tudo acima está feito, e conhecê-las é a diferença entre uma defesa de verdade e uma história reconfortante.

O servidor de controle é um endpoint público e nomeado. Todo dispositivo disca para ele, então ele tem um hostname, e esse hostname é publicado em logs de certificate transparency no instante em que o certificado é emitido. Ele é descobrível mesmo que você nunca link para ele, e seu endereço é a única constante que todos os seus dispositivos têm em comum. Use um subdomínio de um nome que você já publica, em vez de um que descreva o que ele é.

O Headscale é uma reimplementação, e ele assume isso. Ele não é construído nem suportado pelo Tailscale, a paridade de recursos é parcial por construção, e parte do que o produto hospedado vende — o console web, a frota pública de relays, os fluxos refinados de login único — ou simplesmente não existe aqui, ou é um projeto de terceiros que ninguém auditou. Consulte a documentação do projeto para saber se um recurso existe antes de basear um plano nele, e trate as atualizações como uma tarefa, não como um processo em segundo plano.

Os relays padrão ainda são de outra pessoa. Até você ativar o servidor DERP embutido, uma conexão que não consegue ir direto recorre à frota pública de relays. O payload continua criptografado ponta a ponta e ninguém consegue lê-lo — mas o fato de que dois dos seus dispositivos estão conversando, e o quanto, transita por uma infraestrutura que não é sua. Essa é a parte da cadeia de confiança que a maioria das pessoas não percebe na primeira tarde.

Um nó de saída é um endereço estável, não uma multidão. Rotear o seu tráfego através do seu próprio VPS derrota a rede do café e o perfil montado pelo provedor de internet. Não derrota a correlação, porque esse endereço pertence só a você e não muda. O endereço compartilhado de uma VPN comercial é pior em todos os aspectos, exceto no único que importa para essa ameaça específica.

A máquina ainda está dentro de um prédio. Um servidor alugado roda em hardware dentro de um datacenter com portas e funcionários. O que muda é que não existe um índice, no nível do produto, dos seus dispositivos, nenhum banco de dados de empresa registrando de onde cada um se conecta, e nenhuma política de privacidade que possa ser alterada no próximo trimestre. O que não muda é que o disco é físico e não está dentro da sua casa.

O que você comprou de verdade, com precisão: a lista de cada máquina sua, o registro de onde cada uma se conecta, e a autoridade para adicionar uma nova, ficam todos guardados em uma máquina que você aluga sem nome nenhum atrás dela. Essa é uma afirmação restrita, e é uma afirmação real. Ela só vale o que custa se a etapa 06 estiver feita — um plano de controle auto-hospedado sem uma restauração testada não é uma melhoria de privacidade, é um ponto único de falha com uma marca melhor.

Dimensionamento · O que pedir

O plano de controle é de graça. O tráfego é o que você paga.

Nível Mensal Recursos O que ela roda com folga
Sentinel$3.902 vCPU · 4 GB · 120 GB · 1 GbpsO servidor de controle, um relay e uso leve de nó de saída. O começo certo.
Um segundo Sentinel$3.90O nó de saída, em uma máquina só deleMantém o tráfego encaminhado longe do plano de controle
Ravelin$16.908 vCPU · 16 GB · 480 GB · 2.5 GbpsUm nó de saída de uso diário para uma residência, na velocidade máxima da linha
Bulwark$32.9016 vCPU · 32 GB · 960 GB · 5 GbpsUm nó de saída de empresa e um relay movimentado, juntos

Nada nesta tabela é dimensionado para coordenação. O servidor de controle mantém uma conexão ociosa por dispositivo e um banco de dados medido em kilobytes; algumas centenas de dispositivos não vão incomodar nem o menor nível. O que consome uma máquina é tráfego encaminhado — conexões retransmitidas e, muito mais, um nó de saída carregando toda a conexão de internet de alguém. Dimensione para o uplink e a taxa de transferência da criptografia, e lembre-se de que a banda é ilimitada em todos os níveis, então a única pergunta é o quão rápido você quer que seja.

Notas de campo · Seis armadilhas

Seis formas de isso dar errado. Duas delas parecem problema de DNS.

Armadilha 01 · Confusa

O sufixo do tailnet se sobrepõe ao hostname do servidor

Escolher um sufixo de MagicDNS que seja pai ou filho do próprio hostname do servidor de controle quebra a resolução de nomes de um jeito que parece uma queda de DNS. Mantenha-os como irmãos: vpn.example.com para o servidor, ts.example.com para o tailnet.

Armadilha 02 · Silenciosa

Uma rota anunciada e nunca aprovada

O cliente informa alegremente que está anunciando 192.168.1.0/24, e nada atrás do roteador responde, porque o servidor nunca aprovou a rota. Não há erro nenhum em lugar algum. Aprove no servidor e depois confira a lista de rotas, não o cliente.

Armadilha 03 · Lenta

Tudo retransmitido, nada direto

Uma rede que bloqueia UDP de saída força toda conexão a passar por um relay: funciona, mas é mais lento e coloca uma terceira máquina no caminho. O tailscale status mostra relay em vez de direct, e o netcheck explica o motivo. Corrija o firewall ou aceite esse salto extra conscientemente.

Armadilha 04 · Exposta

A política padrão de permitir tudo, com um convidado no tailnet

Um tailnet recém-criado deixa cada dispositivo alcançar todos os outros em qualquer porta. Isso está certo para uma única pessoa e errado no instante em que o notebook de um terceirizado entra — incluindo as interfaces de gerenciamento que ele nunca soube que existiam. Escreva a política antes do convite.

Armadilha 05 · Fatal

A chave privada da qual nunca se fez backup

Reconstrua a máquina, restaure o banco de dados, esqueça o material da chave — e todo dispositivo recusa o servidor em que confiava ontem. Não existe recuperação inteligente; existe um dia inteiro reinscrevendo celulares manualmente. Copie o diretório de dados antes que o primeiro dispositivo entre.

Armadilha 06 · Evitável

Uma tag de imagem flutuante em um serviço pré-1.0

Chaves de configuração e subcomandos da CLI já foram renomeados entre versões menores. Com :latest, um restart qualquer, sem relação nenhuma, baixa uma nova versão e o plano de controle de toda a sua frota para. Fixe a tag, leia as notas de versão, atualize de propósito.

Perguntas frequentes · VPN mesh auto-hospedada

Perguntas, respondidas.

Onze perguntas que surgem ao construir isso — começando pelas duas que decidem se você deveria sequer construir isso.

O Headscale é um produto oficial do Tailscale?

Não, e vale a pena ser preciso sobre o que isso significa. O Headscale é uma reimplementação independente e de código aberto do servidor de coordenação — a peça do Tailscale que distribui chaves públicas, endpoints e política. Ele não é construído, vendido nem suportado pelo Tailscale, não carrega nenhum contrato de suporte comercial, e se ele quebrar, você vai ler o issue tracker em vez de abrir um ticket. O que ele faz é falar o protocolo que o cliente oficial e de código aberto do Tailscale já fala, e é por isso que o cliente funciona sem modificações contra ele. Duas consequências práticas decorrem disso. A paridade de recursos é parcial e sempre vai ser, porque o projeto persegue um alvo em movimento mantido por uma equipe bem maior — consulte a documentação do próprio projeto para saber se um recurso existe antes de planejar em torno dele. E as atualizações merecem mais cuidado do que a troca média de container: o esquema de configuração e vários subcomandos da CLI já foram renomeados entre versões menores, que é a forma mais comum de as pessoas quebrarem uma instalação que funcionava.

O servidor de coordenação consegue ler o meu tráfego?

Não — e esta é a parte da arquitetura que vale a pena entender, em vez de aceitar por fé. Cada dispositivo gera seu próprio par de chaves WireGuard localmente, e a metade privada nunca sai dele. O que um dispositivo envia para o servidor de controle é sua chave pública, seus endpoints atuais e alguns metadados; o que ele baixa é o mesmo, para cada outro dispositivo que tem permissão de alcançar. Os túneis são então negociados diretamente entre os dispositivos, e a criptografia é o WireGuard comum entre duas chaves que o servidor nunca teve em mãos. Então o servidor de controle não consegue descriptografar nada, e isso também vale para o servidor do Tailscale. O que ele pode fazer é algo diferente e menos discutido: ele guarda o mapa. Nomes de dispositivos, nomes de usuários, chaves públicas, o IP público de onde cada dispositivo está discando agora, qual dispositivo acordou às três da manhã, e a política que diz quem pode alcançar quem. Ele também é a coisa que distribui as chaves, então um servidor de controle comprometido, ou coagido, pode adicionar um dispositivo à sua rede. Auto-hospedar não resolve um problema matemático; move um problema administrativo para uma máquina que é sua.

O que acontece com a minha rede se o servidor de controle cair?

Muito menos do que as pessoas esperam, e essa é a parte tranquilizadora deste design. Os dispositivos guardam em cache o último mapa de rede que receberam, e os túneis WireGuard já estabelecidos são peer-to-peer — eles não passam pelo servidor de controle nem precisam dele para continuar funcionando. Um reboot do VPS em um dia de trabalho normal costuma ser invisível. O que para é a mudança: nenhum dispositivo novo consegue se registrar, um dispositivo que muda para uma rede nova pode demorar mais para encontrar seus peers de novo, edições de política não se propagam, e qualquer nó cuja chave expire enquanto o servidor está fora do ar não vai conseguir renová-la. Então a forma correta de pensar sobre o servidor de controle é como um plano de controle, não como um caminho de dados: uma indisponibilidade é um incômodo, não uma desconexão. Dito isso, trate-o como produção. Faça backup dele (etapa 06) e, se um departamento inteiro depender do tailnet, coloque o servidor de controle em uma máquina pequena só dele, em vez de compartilhá-la com algo que é reiniciado com frequência.

Headscale ou WireGuard puro — quando o plano de controle realmente vale a pena?

Conte seus dispositivos e conte quantos deles se movem. O WireGuard puro é uma resposta excelente para um conjunto pequeno e estático: três ou quatro peers, endpoints fixos, um arquivo de configuração para cada um, nada para rodar além do módulo do kernel. É menos software, menos superfície de ataque e menos manutenção do que qualquer coisa neste guia, e o nosso guia de WireGuard cobre isso do início ao fim. O custo é que o WireGuard, deliberadamente, não tem distribuição de chaves, então cada dispositivo novo é uma edição em todos os outros dispositivos — um trabalho que cresce com o quadrado da sua frota — e clientes em roaming, no Wi-Fi de hotel e em dados móveis, precisam de alguém para ficar avisando a todos para onde eles se moveram. Um plano de controle é o que resolve isso para você. Na prática, o limiar fica em torno de cinco dispositivos, ou no primeiro notebook que muda de rede diariamente, ou na primeira vez que você quiser uma regra do tipo "o notebook do terceirizado alcança o servidor de staging e mais nada". Abaixo disso, use WireGuard e aproveite o sossego.

O app do Tailscale no meu celular funciona com o Headscale?

Sim — é o mesmo cliente oficial, e apontá-lo para um servidor de controle diferente é uma operação suportada, não um hack. A mecânica varia por plataforma, e é aí que as pessoas perdem uma noite inteira. No Linux, macOS e Windows, é uma flag de linha de comando no cliente (--login-server) ou a configuração equivalente. No Android, a opção fica exposta no próprio app, atrás do número da versão na tela de configurações. No iOS, iPadOS e tvOS não há campo dentro do aplicativo: você instala um pequeno perfil de configuração que define a URL do servidor de controle antes de fazer login, o que é delicado na primeira vez e permanente depois disso. A documentação do Headscale mantém uma página por plataforma exatamente para isso, e vale a pena abri-la em vez de chutar, porque o fluxo da Apple, em particular, já mudou mais de uma vez. Um detalhe que não é específico de plataforma: um app que já fez login no serviço próprio do Tailscale geralmente precisa fazer logout — e às vezes ser reinstalado — antes de aceitar um servidor diferente.

Preciso rodar meu próprio relay DERP?

Não para fazer a rede funcionar — mas é a diferença entre majoritariamente privado e consistentemente privado, então decida isso de propósito. Servidores DERP são relays usados quando dois dispositivos não conseguem abrir uma conexão direta: NAT simétrico nas duas pontas, um firewall corporativo que engole UDP, uma operadora móvel fazendo alguma criatividade. O tráfego retransmitido continua sendo WireGuard criptografado ponta a ponta, então um operador de relay vê texto cifrado, não conteúdo. O que ele vê são metadados: quais dois dispositivos estão conversando, quanto e quando. Por padrão, o Headscale entrega aos seus dispositivos o mapa público de DERP do Tailscale, o que significa que esses relays são do Tailscale — você auto-hospedou o plano de controle e deixou o caminho de dados de fallback com a empresa da qual estava se afastando. O Headscale traz um servidor DERP embutido; ativá-lo te dá um relay no mesmo datacenter nórdico do servidor de controle. A troca honesta é cobertura: o Tailscale roda relays em vários continentes, e você roda um só, então um dispositivo do lado errado do mundo é mais bem servido pelos deles. Rodar os dois, com o seu no mapa, é um meio-termo perfeitamente razoável.

Posso fazer o tailnet inteiro usar meu próprio resolvedor de DNS?

Sim, e é um dos melhores motivos para construir isto. O Headscale pode enviar uma configuração de DNS para todo dispositivo que entra, então o seu notebook no Wi-Fi do café e o seu celular em dados móveis passam a resolver através de um resolvedor que você mesmo roda — com filtragem, com cache e sem que a rede local veja as consultas. Aponte o servidor de nomes global do tailnet para o IP, dentro do tailnet, da máquina rodando o seu próprio Unbound ou AdGuard Home e configure o override para que ele vença o que quer que o DHCP tenha entregado ao dispositivo. Duas coisas para acertar. O resolvedor precisa ser alcançável dentro do tailnet, não na internet pública — esse é todo o objetivo, e também significa que você finalmente pode fechar a porta 53 para o mundo. E o MagicDNS, que dá a cada dispositivo um nome curto dentro de um sufixo escolhido por você, precisa que esse sufixo seja um que você controla e que não seja pai nem filho do próprio hostname do servidor de controle; errar isso é uma falha confusa que parece um bug de DNS e é um bug de configuração.

De que tamanho o VPS precisa ser?

Só para o plano de controle: pequeno, e depois ainda menor que isso. O Headscale é um único binário Go que guarda um pequeno banco de dados de dispositivos, chaves e política; o tráfego de coordenação é um fiapo de conexões long-poll, uma por dispositivo, que carregam quase nada na maior parte do tempo. Um Sentinel — 2 vCPU, 4 GB, 120 GB NVMe, $3.90 por mês — atende uma residência, uma pequena empresa ou algumas centenas de dispositivos sem nem perceber. A questão do dimensionamento só fica interessante quando a mesma máquina assume um segundo trabalho. Um relay DERP embutido encaminha tráfego real, então ele quer uplink, não núcleos. Um nó de saída encaminha todo o tráfego de um dispositivo, então ele quer uplink, uma franquia de banda generosa e uma CPU capaz de acompanhar a criptografia na velocidade máxima da linha. Se você planeja fazer os dois, dimensione para o tráfego e trate o servidor de controle como o erro de arredondamento que ele é — ou, melhor ainda, coloque o nó de saída em uma segunda máquina e mantenha o plano de controle tedioso.

Um nó de saída no meu próprio VPS é a mesma coisa que usar uma VPN comercial?

Tecnicamente parecido, e em termos de privacidade quase o oposto, então vale a pena ter clareza sobre isso. Um nó de saída roteia toda a conexão de internet de um dispositivo através do seu VPS, então os sites veem o endereço do VPS em vez do seu endereço de casa ou de hotel, e a rede local vê um túnel criptografado em vez da sua navegação. Até aí, é igual a uma VPN comercial. A diferença é a multidão. O endereço de uma VPN comercial é compartilhado por milhares de clientes sem relação entre si, o que é justamente o que dificulta atribuir o tráfego a você; o endereço do seu nó de saída é usado só por você, de forma estável, para sempre. Contra uma rede de café bisbilhotando ou um provedor de internet montando um perfil, o nó de saída é excelente. Contra um observador correlacionando atividade entre sites ao longo de meses, um endereço dedicado é um identificador durável, e um compartilhado não é. Use o nó de saída para o que ele faz bem — redes locais não confiáveis, alcançar seus próprios serviços, um endereço estável para coisas que esperam um — e leia o guia principal para a parte do modelo de ameaça que ele não cobre.

O que exatamente eu preciso fazer backup?

Quatro coisas, e só uma delas é óbvia. O banco de dados — SQLite por padrão, PostgreSQL se você migrou para ele — guarda usuários, dispositivos, chaves públicas, rotas e chaves de pré-autenticação. O material da chave privada gerado na primeira inicialização é a parte que as pessoas esquecem: perca-o e todo dispositivo rejeita o servidor com quem vinha conversando havia um ano, o que significa reinscrever a frota inteira manualmente. O arquivo de configuração importa porque codifica os três nomes da etapa 02, e reconstruí-los de memória é como as pessoas acabam mudando um deles sem querer. E o arquivo de política, se você mantiver as regras de acesso em disco, é a coisa que você menos quer ter que reescrever. Os quatro vivem em dois diretórios e, juntos, pesam menos que uma fotografia. Criptografe-os, envie-os para uma máquina que não seja esta — idealmente em outra jurisdição, que é para isso que serve o guia de backups — e restaure-os em um VPS descartável uma vez, de propósito, para saber que o arquivo que você tem é o arquivo de que você precisa.

A NordBastion se importa se eu rodar um servidor de controle e um nó de saída em um VPS?

Um servidor de controle é uma carga de trabalho comum e bem-comportada — um pouco de HTTPS, um pouco de UDP, praticamente nenhum tráfego — e não há nada na política de uso aceitável que o afete. Um nó de saída merece uma frase de reflexão, não uma aula sobre políticas: tudo que um dispositivo envia por ele sai da internet a partir do endereço do seu VPS, sob a sua conta, então o que seus dispositivos fizerem é o que esse endereço ficará conhecido por fazer. Isso é normal e é exatamente para isso que o recurso existe; é também por isso que um nó de saída compartilhado com pessoas que você não conhece é uma má ideia, da mesma forma que um relay aberto é. A banda é ilimitada em todos os níveis, e tráfego retransmitido é tráfego normal, então um servidor DERP e um nó de saída vêm ambos incluídos, em vez de medidos. Além disso: a conta não precisa do seu nome, a fatura é paga em Monero ou Bitcoin, e a máquina que guarda o mapa de cada dispositivo seu não é indexada por ninguém.

Obtenha a máquina

Um plano de controle só seu, em uma conta que não está no seu nome. Sem KYC, pago em cripto.

Sentinel — 2 vCPU e 4 GB por $3.90 ao mês, em Helsinque, Estocolmo, Oslo ou Reykjavík. Suficiente para Headscale, Caddy e seu próprio relay DERP, com folga para o nó de saída, se você quiser colocá-lo na mesma máquina. Sem e-mail no cadastro, sem documento de identidade e sem banco de dados de empresa guardando a lista de cada dispositivo seu.

Última revisão · 2026-10-12 · Fontes · Documentação do Headscale (referência de configuração, configuração de clientes, ACLs, DERP, CLI remota), documentação do cliente Tailscale e de nó de saída, artigo do protocolo WireGuard, documentação do Caddy · Cadência · anualmente

Hospedagem privada, construída no Norte.