Quinto artigo da série, e parte 2 do hands-on. No anterior o pipeline terminou funcionando, mas só em texto no terminal. Agora chega a recompensa visual: o mapa web ao vivo, estilo Flightradar, servido pelo próprio homelab.
Pra quem está chegando agora, o caminho até aqui em uma frase por artigo: o primeiro apresentou o projeto de gerar meus próprios dados do mundo físico morando embaixo da rota de Guarulhos; o segundo destrinchou o protocolo ADS-B, a mensagem de 112 bits que toda aeronave grita em 1090 MHz sem autenticação nenhuma; e o terceiro cobriu o hardware RTL-SDR v4, o que o separa dos clones e a instalação do driver no Arch e no Fedora.
O quarto artigo foi o hands-on de ponta a ponta no servidor EndeavourOS: validação do dongle em 1090 MHz com rtl_sdr, a escolha da antena certa pra polarização vertical do ADS-B, a compilação do readsb na unha (com dois patches pra domar o -Werror num código sem manutenção frente ao GCC atual), regra udev dedicada pro usuário de serviço, override do systemd com as flags corretas, e a prova final: aeronaves reais decodificadas com posição, altitude e velocidade via nc localhost 30003. Terminou com uma pendência declarada: os dados existiam só como streams brutos nas portas 30002 a 30005, sem interface visual. É essa pendência que este artigo resolve, e no caminho ela derruba uma decisão da parte 1: o fork do readsb vai ser trocado.
1. SDR++ (auxiliar visual de RF)
Já estava instalado (sdrpp-git, AUR) desde o terceiro artigo. Só precisou ser executado. Como o servidor tem uma sessão gráfica Wayland ativa (seat0/tty1), o app abre normalmente na tela:
sdrpp
Confirmado: os plugins dessa build são só fontes de hardware (rtl_sdr, hackrf, limesdr…) e demoduladores de rádio geral (FM, M17, pager, ATV, meteor). Não existe decodificador de ADS-B no SDR++. Ele serve pra visualizar o waterfall e o espectro em 1090 MHz manualmente, como conferência visual de que a antena está captando energia RF. Quem decodifica de fato é o readsb.
2. SatDump
Instalado via AUR:
yay -S satdump --answerclean All --answerdiff None --removemake --noconfirm
Optei pela versão estável (satdump 1.2.2), não a -git, por ser um projeto C++/CMake grande: menos chance de quebrar com o GCC do sistema. É focado em satélites (137 MHz, NOAA, Meteor), não em ADS-B; entra aqui só pra completar o stack que o primeiro artigo prometeu.
O build (CMake, C++, bastante plugin: inmarsat, cubesat, meteosat, GOES, NOAA/METOP, todos os backends de SDR) rodou em background e levou bem mais tempo que o readsb, uns 45 minutos. Compilou sem nenhum patch necessário. Como sempre, a etapa final de instalação precisou rodar manualmente no terminal:
sudo pacman -U ~/.cache/yay/satdump/satdump-1.2.2-5-x86_64.pkg.tar.zst
Apareceu um aviso de lint “pacote contém referência a $srcdir” durante o empacotamento. É informativo, sem efeito prático: alguns binários referenciam o caminho de build nos metadados.
Confirmado instalado:
pacman -Q satdump
# satdump 1.2.2-5
which satdump
# /usr/bin/satdump
3. Por que trocar o fork do readsb
Ao começar a configurar o tar1090 (o mapa web ao vivo), percebi que o readsb-git instalado na parte 1 (fork Mictronics, readsb-protobuf) grava os dados em protobuf binário (aircraft.pb), não em JSON:
file /run/readsb/aircraft.pb
# aircraft.pb: data
xxd /run/readsb/aircraft.pb | head -5
# 00000000: 08a0 b88f d306 10a9 377a c701 08a2 8192 ........7z......
# 00000010: 0712 0854 414d 3335 3930 2018 f666 20a3 ...TAM3590 ..f .
Dá pra reconhecer o callsign TAM3590 no meio dos bytes: os dados estão certos, só o formato é binário.
O tar1090 (e a maioria dos frontends web de ADS-B) espera JSON (aircraft.json). O fork Mictronics simplesmente não grava nesse formato, não tem flag pra isso.
A solução foi trocar para o readsb-wiedehopf-git, mantido pelo próprio autor do tar1090, que:
- grava JSON nativamente
- é mais ativamente mantido (última atualização em setembro de 2025, contra um fork Mictronics parado desde ~2020)
- compilou sem nenhum patch no GCC atual (o fork antigo precisou de dois patches manuais pra contornar o
-Werrore os novos erros padrão do GCC 14+, como visto na parte 1)
4. Removendo o fork antigo e instalando o novo
Os dois pacotes entram em conflito, então o readsb-git sai primeiro:
sudo pacman -R readsb-git
Build do novo fork, fora do cache do yay, mesma lição da parte 1 (dessa vez nem precisou de patch, compilou de primeira):
yay -G readsb-wiedehopf-git
cd ~/readsb-wiedehopf-git
makepkg -s --noconfirm
Instalação:
sudo pacman -U ~/readsb-wiedehopf-git/readsb-wiedehopf-git-3.16.15.r8.g0bfd047-1-x86_64.pkg.tar.zst
5. Reconfigurando pro novo fork
O pacote novo já vem com service e config próprios, com convenção de variáveis diferente do antigo (RECEIVER_OPTIONS/DECODER_OPTIONS/NET_OPTIONS/JSON_OPTIONS em vez do USER_OPTIONS único):
# /etc/default/readsb (gerado pelo pacote)
RECEIVER_OPTIONS="--device 0 --device-type rtlsdr --gain auto --ppm 0"
DECODER_OPTIONS="--max-range 450 --write-json-every 1"
NET_OPTIONS="--net --net-ri-port 30001 --net-ro-port 30002 --net-sbs-port 30003 --net-bi-port 30004,30104 --net-bo-port 30005"
JSON_OPTIONS="--json-location-accuracy 2 --range-outline-hours 24"
O JSON já vem habilitado por padrão (--write-json está no próprio readsb.service do pacote), a diferença chave em relação ao fork anterior.
Passos:
# Remover o override do systemd criado na parte 1 (referenciava $USER_OPTIONS,
# variável que não existe mais nesse pacote e quebraria o serviço novo)
sudo rm /etc/systemd/system/readsb.service.d/override.conf
sudo rmdir /etc/systemd/system/readsb.service.d
# Adicionar lat/lon reais na config nova (use as suas coordenadas)
sudo sed -i 's/--gain auto --ppm 0"/--gain auto --ppm 0 --lat -23.58 --lon -46.55"/' /etc/default/readsb
sudo systemctl daemon-reload
sudo systemctl restart readsb
A regra udev (99-readsb-rtlsdr.rules, GROUP="readsb") e o usuário de sistema continuaram funcionando sem alteração: o novo pacote cria o mesmo usuário readsb, com o mesmo uid.
Validação
journalctl -u readsb -n 15 --no-pager
Using lat: -23.58, lon: -46.55 (location accuracy: exact)
rtlsdr: using device #0: Generic RTL2832U OEM (RTLSDRBlog, Blog V4, SN 00000001)
Found Rafael Micro R828D tuner
RTL-SDR Blog V4 Detected
cat /run/readsb/aircraft.json
{ "now" : 1784929956.000, "messages" : 270, "aircraft" : [
{"hex":"e48e77","flight":"GLO2178 ","alt_baro":29875,"gs":435.0,"lat":-23.344178,"lon":-46.254120, ...},
{"hex":"e49246","flight":"TAM3994 ","alt_baro":13125,"gs":308.4,"lat":-23.399901,"lon":-46.175283, ...}
Agora sim, JSON de verdade, com voos reais (GLO2178, TAM3994), pronto pro tar1090 ler. E as ferramentas de terminal da parte 1 continuam funcionando normalmente sobre o fork novo:

6. Instalando o tar1090
Não existe pacote tar1090 no AUR. A instalação oficial é via script (wiedehopf/tar1090/install.sh), feito originalmente pra Debian/Ubuntu (usa apt-get). Antes de rodar, baixei e revisei o script inteiro (500 linhas) pra confirmar que era seguro e entender o que ele faz. Nunca rode um curl | sudo bash às cegas, ainda mais de script pensado pra outra distro.
Achado importante na revisão: o bloco que usa apt-get só roda se faltar git, jq ou curl no sistema. Como já havia git e curl, só faltava o jq. O resto do script (clonar os repos do tar1090 e do banco de dados de aeronaves, gerar configuração de webserver, criar serviço systemd) é genérico o suficiente pra funcionar em qualquer distro com systemd.
Dependências
sudo pacman -S --needed jq lighttpd
sudo mkdir -p /etc/lighttpd/conf.d
O mkdir é necessário porque o script só ativa o modo automático de configuração do lighttpd (lighttpd=yes) se achar esse diretório (convenção Debian de conf.d/conf-enabled/conf-available que o pacote do Arch não usa).
Rodando o instalador oficial
sudo bash ~/tar1090-install.sh
O script sozinho: clonou wiedehopf/tar1090 e wiedehopf/tar1090-db, detectou /run/readsb/aircraft.json como fonte de dados, gerou /etc/lighttpd/conf.d/88-tar1090.conf (aliases de URL pro /tar1090/) e criou e habilitou o serviço tar1090.service, um script que processa e compacta os dados do readsb pro formato que o frontend web lê.
Dois problemas encontrados depois de rodar o script
Problema 1: o lighttpd nunca subiu. O script só reinicia o lighttpd se ele já estava rodando antes; não habilita nem inicia um lighttpd recém-instalado do zero. Resultado: systemctl status lighttpd mostrava inactive (dead), apesar de tudo configurado.
Problema 2: o lighttpd.conf do Arch é minimalista e não carrega conf-enabled. O lighttpd.conf padrão do pacote Arch tem só o essencial (document-root, index-file), sem nenhuma linha incluindo o diretório onde o script (e o mkdir feito antes) colocou as configurações do tar1090. Sem isso, mesmo com o lighttpd rodando, ele nunca leria o 88-tar1090.conf.
Correção:
echo 'include_shell "cat /etc/lighttpd/conf-enabled/*.conf"' | sudo tee -a /etc/lighttpd/lighttpd.conf
sudo lighttpd -tt -f /etc/lighttpd/lighttpd.conf # valida a config antes de subir
sudo systemctl enable --now lighttpd
Validação final
curl -sI http://localhost/tar1090/
# HTTP/1.1 200 OK
curl -s http://localhost/tar1090/data/aircraft.json | head -c 200
# { "now" : ..., "aircraft" : [{"hex":"e49511","flight":"GLO1238 ", ... "lat":-23.613876,"lon":-46.559397, ...
Mapa ao vivo funcionando no IP interno do servidor, em /tar1090/. E a recompensa visual depois de cinco artigos:

Clicando em qualquer aeronave, o painel lateral mostra tudo que o transponder transmite, enriquecido pelo banco de dados do tar1090: matrícula, companhia, tipo, rota, altitude com tendência, velocidade, proa e RSSI. Aqui um 787-9 da LATAM saindo de Guarulhos pra Amsterdã:

O tooltip rápido, sem abrir o painel, já resolve a pergunta clássica de quem olha pro céu (“que avião é esse?”): um A330 da South African Airways subindo a 9.250 pés:

7. Estado final dos serviços
systemctl is-enabled lighttpd tar1090 readsb
# enabled
# enabled
# enabled
Todos habilitados, sobrevivem a reboot do servidor.
| Serviço | Função |
|---|---|
readsb | decodifica ADS-B (fork wiedehopf, JSON) |
tar1090 | processa e compacta os dados do readsb pro frontend web |
lighttpd | serve a página web em /tar1090/ |
E o pipeline inteiro, do sinal RF ao browser, cabe numa foto só: o mapa web de um lado, e do outro os mesmos aviões no viewadsb, na visão resumida e no stream SBS bruto:

O que começou como “e se eu gerasse os meus próprios dados?” no primeiro artigo agora é um serviço de verdade no homelab: antena, RTL-SDR v4, readsb decodificando, tar1090 desenhando e lighttpd servindo, tudo habilitado no systemd.
Ainda haverá novos artigos e irei evoluir este lab…