Socket activation com systemd e podman

Aoba, aqui é o Lucão. Primeiro post depois do alinhamento do olho, que eu fiz a exatamente um mês atrás.

Vez ou outra eu me enfezo de fazer algumas limpezas e ajustes. Nos ultimos dias, comecei a configurar o Mise1 em alguns projetos meus simplesmente porque Nix não me deixa pinar uma versão específica de um programa específico.

Também aproveitei um tempo mais de várzea de fim de projeto para dar uma mexida no tal do Bun e nessa migrei alguns projetos para usar ele, pelo menos como gerenciador de pacotes.

Eu tenho um projeto em Svelte, chamado cf-torrent que basicamente é um cliente glorificado para alguns mecanismos de busca e que busca links magnéticos. Criei por preguiça, hoje é basicamente um laboratório para testar macetes de devops.

Um deles é que eu to removendo a parte Nix das coisas, até porque para alguns projetos ele tá ficando no caminho. Como eu disse, Nix não tem um jeito simples de pinar alguma coisa e eu tenho preguiça de escrever e manter overlays. O que eu puder delegar para o Renovate atualizar e me mandar PR sugerindo atualização eu to delegando.

Nessa pensei, uso o cf-torrent como serviço socket ativável localmente e já que eu to removendo a parte Nix eu ia a princípio perder essa possibilidade. Teria que achar outro jeito, e eu achei: Podman!

O NixOS tem um conjunto de options, basicamente um tipo de API para configurar módulos, que permite de forma declarativa configurar containers como serviços. Tipo docker compose? Tipo docker compose! Só que usando o systemd, o que eu acho mais apropriado no NixOS. Juntar vários gerenciadores de serviços é algo que eu evito. Acho sujeira. Ser declarativo é certamente um plus!

O macete é o seguinte: Para fazer socket activation primeiro é necessário ter uma unit do tipo socket, que dispara uma unit do tipo service. No NixOS isso fica abstraído.

O módulo

Para referências, o módulo completo que eu fiz está aqui: https://github.com/lucasew/nixcfg/blob/0a9d66c6ff9e4b43c8e951a64f028a7b781484d1/nix/nodes/common/services/cf-torrent.nix

O começo é bem padrão (linhas 1 a 16): imports e organização de escopo para ajudar a análise estática e o autocomplete me ajudar.

A parte de definição das options (linhas 19 a 37): Bem intuitivo, ali defino que opções eu passo para frente para poder usar na configuração das minhas máquinas.

E agora a parte interessante

E é isso ai. O ts-proxy ainda precisa rodar o tempo inteiro porque alguém tem que negociar os endpoints com o Tailscale. A qualquer momento consigo acessar esse e qualquer outro serviço que eu esteja usando um sistema parecido de qualquer dispositivo da minha rede do Tailscale. Homelab inteligente sem ter que manter configuração de proxy reverso e DNS! E a aplicação só roda quando necessário.

Um outro macete

É possível testar socket activation sem ter que fazer a maracutaia das units necessariamente.

O systemd possui o comando systemd-socket-activate que replica o mesmo sistema fora do systemd e eu usei para debugar um bug que eu achei no Bun.

O SvelteKit, pelo adapter-node, tem suporte oficial a socket activation sem ter que configurar nada. Até aquele IDLE_TIMEOUT é opcional, só que sem ele a aplicação não para nunca. A mesma aplicação no Node responde normalmente ao socket activation como esperado. No Bun nada acontece. O systemd percebe que tem que subir a aplicação, sobe corretamente mas o Bun não consegue receber o file descriptor do socket, ou pelo menos não sabe o que fazer com ele e não passa para as primitivas que o SvelteKit tem para operar esse socket activation. Basicamente a conexão cai em um limbo e fica travada. O bug já foi reportado.


  1. Post do Mise ↩︎