OTOthoTools

Gerador systemd

Crie unidades de serviço seguras
Resultado.service
[Unit]
Description=Otho worker
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=otho
WorkingDirectory=/opt/otho
ExecStart=/opt/otho/bin/worker
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target

Introdução

O Gerador systemd produz uma unidade de serviço (um arquivo .service) com opções de endurecimento fáceis de esquecer: um usuário não root, NoNewPrivileges, PrivateTmp, ProtectSystem=strict e ProtectHome.

O systemd permite descrever o que um serviço pode tocar. A unidade gerada é um ponto de partida defensável para um worker em segundo plano, um agente ou qualquer processo de longa duração.

Objetivo

  • Gerar uma unidade .service sintaticamente correta a partir de nome, comando, usuário e diretório de trabalho.
  • Aplicar endurecimento básico: usuário dedicado, reinício em falha, sem novos privilégios, /tmp privado e caminhos de sistema somente leitura.
  • Manter a unidade legível para que um administrador a ajuste antes de implantar.

Entradas

  • Descrição (texto livre).
  • ExecStart — o caminho absoluto do executável.
  • Usuário do serviço — a conta não privilegiada sob a qual o serviço roda.
  • Diretório de trabalho (opcional).

Como funciona

A ferramenta monta três seções. [Unit] declara a descrição e ordena o serviço após network-online.target. [Service] define Type=simple, usuário e diretório de trabalho, ExecStart e Restart=on-failure com atraso de 5 segundos.

Seguem as diretivas de endurecimento: NoNewPrivileges=true bloqueia a obtenção de novos privilégios por binários setuid; PrivateTmp=true dá ao serviço um /tmp próprio; ProtectSystem=strict torna todo o sistema de arquivos somente leitura, exceto caminhos explicitamente permitidos; ProtectHome=true oculta /home, /root e /run/user.

[Install] declara WantedBy=multi-user.target para que a unidade possa ser ativada com systemctl enable.

Exemplo testável

Experimente — a análise roda localmente no seu navegador.

Exemplo

Descrição: Otho worker
ExecStart:  /opt/otho/bin/worker
Usuário:    otho
Diretório:  /opt/otho

Saída esperada

[Unit]
Description=Otho worker
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=otho
WorkingDirectory=/opt/otho
ExecStart=/opt/otho/bin/worker
Restart=on-failure
RestartSec=5s
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

[Install]
WantedBy=multi-user.target

Interpretando a saída

  • Salve a saída como /etc/systemd/system/<nome>.service, execute sudo systemctl daemon-reload e depois sudo systemctl start <nome>.
  • Se o serviço precisar escrever em caminhos de sistema, ProtectSystem=strict bloqueará — adicione ReadWritePaths ou mova os dados graváveis para o diretório de trabalho.
  • A unidade é um modelo: ajuste TimeoutStartSec, limites de recursos (MemoryMax, CPUQuota) e capabilities (CapabilityBoundingSet) conforme a carga.

Riscos

  • Rodar um serviço como root com acesso à rede é o padrão mais arriscado; a unidade gerada evita isso, mas verifique se seu binário ExecStart pertence a root.
  • ProtectSystem=strict pode quebrar serviços que escrevem fora do diretório de trabalho — teste antes da produção.
  • Restart=on-failure não protege contra travamentos que saem com código 0; considere Restart=always para workers críticos.

Limitações

  • A ferramenta gera o arquivo; ela não pode testar se seu executável inicia ou se suas permissões estão corretas.
  • Ela não gera socket activation, timers ou grafos de dependência complexos.
  • O endurecimento é básico — uma revisão real deve considerar capabilities, seccomp e namespaces de rede.

Referências oficiais

FAQ

Por que um usuário dedicado para cada serviço?

Um usuário dedicado não privilegiado limita o que um serviço comprometido pode fazer: ele não consegue ler arquivos de outros usuários nem escrever fora de seus próprios caminhos. Root deve ser reservado aos poucos serviços que realmente precisam.

O que NoNewPrivileges=true faz?

Impede que o serviço e seus filhos obtenham privilégios por meio de binários setuid ou mecanismos semelhantes, mesmo que esses binários existam no sistema.

O que é ProtectSystem=strict?

Torna todo o sistema de arquivos somente leitura para o serviço, exceto caminhos explicitamente permitidos. É o nível ProtectSystem mais forte e combina bem com serviços que só escrevem no diretório de trabalho ou em /tmp.