SSD Nodes Learn
Guias Matt ConnorPor Matt Connor · Atualizado 2026-07-24

como criar um serviço systemd no linux

Aprenda a configurar um unit file em /etc/systemd/system/ para garantir que seu programa inicie no boot, reinicie após crash e gere logs no journalctl.

O que é um serviço systemd e por que você precisa de um

Um serviço systemd é um pequeno arquivo de texto que instrui o servidor sobre como executar um programa: iniciar no boot, reiniciar se falhar e enviar a saída para o log do sistema. Essa é a única função. Um programa iniciado manualmente em uma sessão SSH morre assim que você faz logout ou o servidor reinicia. Um programa configurado em um serviço systemd continua rodando, pois o servidor assume o controle em vez do seu shell.

O systemd é o sistema de init no Ubuntu, Debian, Fedora e na maioria dos servidores Linux modernos. Ele é o primeiro processo a iniciar e supervisiona todos os outros. Ao criar um arquivo de serviço, você entrega seu programa a esse supervisor. Este guia apresenta a unidade mínima funcional, as três seções de toda unidade, como ativá-la e ler seus logs, como executá-la via timer e como restringir suas permissões para rodar com o mínimo de privilégios possível.

O menor serviço funcional

Um arquivo de serviço reside em /etc/systemd/system/, possui a extensão .service e requer apenas algumas linhas. Crie um para um programa em /usr/local/bin/myapp:

sudo nano /etc/systemd/system/myapp.service
[Unit]
Description=My application

[Service]
ExecStart=/usr/local/bin/myapp

[Install]
WantedBy=multi-user.target

Este é um unit file completo e funcional. ExecStart é o comando de execução. WantedBy=multi-user.target define que o serviço deve iniciar quando o servidor atingir o modo multi-user normal, o que garante a inicialização no boot. O restante é apenas refinamento.

As três seções e suas finalidades

Cada unit file é dividido em seções entre colchetes. Um service utiliza três.

[Unit] descreve o service e seus relacionamentos. As duas linhas que você mais usará:

[Unit]
Description=My application
After=network-online.target
Wants=network-online.target

Description é o rótulo legível por humanos que você vê em systemctl status. After=network-online.target instrui o systemd a não iniciar seu programa até que a rede esteja ativa, o que é essencial para qualquer processo que faça bind de uma port ou realize conexões externas.

[Service] define como o programa é executado. É aqui que ficam a maioria das configurações:

[Service]
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.toml
WorkingDirectory=/opt/myapp
User=myapp
Restart=on-failure
RestartSec=5
Environment=LOG_LEVEL=info

User=myapp executa o programa como um usuário sem privilégios em vez de root, sendo a linha mais importante para segurança. Restart=on-failure e RestartSec=5 possuem suas próprias seções abaixo, pois são o motivo pelo qual a maioria das pessoas cria um service.

[Install] define o que acontece ao habilitar o service:

[Install]
WantedBy=multi-user.target

WantedBy=multi-user.target é o que vincula o service à inicialização do sistema ao executar systemctl enable. Sem uma seção [Install], o service pode ser iniciado manualmente, mas não iniciará sozinho após um reboot.

Ative e monitore

Após escrever ou editar qualquer unit file, recarregue o systemd para que ele leia a alteração, então habilite e inicie o serviço em um único passo:

sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service

daemon-reload é a etapa que as pessoas esquecem: o systemd faz cache dos unit files, portanto uma edição não surte efeito até que você recarregue. enable --now habilita o serviço para o boot e o inicia imediatamente. Verifique:

sudo systemctl status myapp.service
* myapp.service - My application
     Loaded: loaded (/etc/systemd/system/myapp.service; enabled)
     Active: active (running) since Wed 2026-07-15 22:40:11 UTC; 3s ago
   Main PID: 4123 (myapp)

Active: active (running) e enabled são o que você deseja. Para ler a saída do programa, solicite ao journal apenas esta unit:

sudo journalctl -u myapp.service -f

O -f acompanha as novas linhas conforme elas chegam, como o tail -f. Qualquer coisa que seu programa escreva para o standard output ou standard error será registrada aqui, sem necessidade de configuração de logging manual.

Reiniciar em caso de falha, o motivo de você estar aqui

A principal vantagem de um service é que o systemd reinicia seu programa quando ele falha. Duas linhas fazem isso:

[Service]
Restart=on-failure
RestartSec=5

Restart=on-failure reinicia o programa quando ele sai com um código diferente de zero ou morre por um sinal de crash como SIGKILL ou SIGSEGV. Uma saída limpa, ou uma parada por SIGTERM, SIGINT, SIGHUP ou SIGPIPE, não aciona o reinício. RestartSec=5 aguarda cinco segundos entre as tentativas, para que um programa que trava instantaneamente não entre em um loop infinito. Confirme isso matando o processo e observando o systemd restaurá-lo. Use SIGKILL: o SIGTERM padrão conta como uma parada limpa, portanto on-failure não reiniciaria o service:

sudo systemctl kill -s SIGKILL myapp.service
sudo systemctl status myapp.service

Dentro de cinco segundos, o status mostra um novo Main PID e active (running) novamente. Esse é o funcionamento completo, e é por isso que um service é superior a deixar um programa rodando em tmux ou screen.

Execute como um usuário sem privilégios e aplique hardening

Um serviço que roda como root pode comprometer todo o servidor se o programa for explorado. Execute-o com um usuário próprio e utilize diretivas do systemd para restringir o processo. Primeiro, crie uma conta de sistema sem login e sem diretório home:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp

Em seguida, configure User=myapp e adicione linhas de hardening ao [Service]:

[Service]
User=myapp
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true

Cada linha remove uma funcionalidade desnecessária para o programa. NoNewPrivileges=true impede que o processo ganhe novos privilégios, mesmo via binário setuid. PrivateTmp=true fornece um /tmp privado que nenhum outro processo pode visualizar. ProtectSystem=strict torna todo o filesystem read-only, exceto pelos caminhos definidos em ReadWritePaths=. ProtectHome=true oculta o /home completamente. Este conceito de privilégio mínimo é o mesmo de colocar um serviço atrás de um firewall: forneça apenas o necessário. Se você leu o guia sobre fechar a brecha do firewall IPv6 em um VPS, esta é a aplicação local do mesmo conceito. Para serviços expostos à internet, combine este hardening com Fail2ban na frente do SSH e um firewall com política default-deny.

Em vez de digitar tudo manualmente e errar uma diretiva, gere uma unit completa e endurecida e copie o conteúdo:

Toolsystemd service and timer generator

Timers: o cron moderno

Um systemd timer executa um serviço em um cronograma e é o substituto moderno para um cron job. Um timer consiste em dois arquivos: um .service que realiza o trabalho e um .timer que define o horário. Suponha que você queira um backup às 3h todos os dias. O serviço executa a tarefa uma vez e encerra:

# /etc/systemd/system/backup.service
[Unit]
Description=Nightly backup

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh

O Type=oneshot informa ao systemd que o programa executa, finaliza e encerra, em vez de permanecer residente. O timer agenda a execução:

# /etc/systemd/system/backup.timer
[Unit]
Description=Run the nightly backup

[Timer]
OnCalendar=*-*-* 03:00:00
Persistent=true

[Install]
WantedBy=timers.target

OnCalendar=*-*-* 03:00:00 significa 3h todos os dias. Teste qualquer expressão de calendário com systemd-analyze calendar "*-*-* 03:00:00", que confirma se o sistema interpreta corretamente e imprime as próximas execuções. O Persistent=true executa um job perdido assim que o servidor retornar, caso estivesse desligado às 3h, algo que o cron não consegue fazer. Note que um timer é habilitado via timers.target, não via multi-user.target. Habilite o timer, não o serviço:

sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
systemctl list-timers

O list-timers mostra todos os timers com sua próxima e última execução, permitindo visualizar rapidamente quando o seu job ocorrerá. O gerador acima cria os pares .service e .timer para você quando o timer mode é ativado. Comparado a uma linha do cron, um timer oferece logs reais no journal, as mesmas diretivas de hardening de qualquer serviço e o catch-up de execuções perdidas que o Persistent=true fornece. O cron ainda é adequado para tarefas simples; o timer é a ferramenta superior para tarefas críticas.

FAQ

Qual é a diferença entre um serviço systemd e um cron job?

Um serviço mantém um programa em execução contínua: ele inicia no boot, reinicia em caso de falha e registra logs no journal. Um cron job executa um comando curto em um agendamento e encerra. Quando você precisar de agendamento, mas também quiser logs no journal, hardening e execução de tarefas pendentes, use um systemd timer, que combina um agendamento .timer com um serviço oneshot e substitui o cron na maioria das tarefas de servidor.

Onde eu coloco meu arquivo de serviço systemd?

Coloque suas próprias unidades em /etc/systemd/system/, com um nome terminando em .service. Esse diretório é para unidades adicionadas pelo administrador e tem prioridade sobre as unidades de pacotes em /lib/systemd/system/. Após criar ou editar um arquivo, execute sudo systemctl daemon-reload para que o systemd reconheça a alteração.

Como faço para um serviço reiniciar se ele travar?

Adicione Restart=on-failure e RestartSec=5 na seção [Service], então execute sudo systemctl daemon-reload e reinicie o serviço. O systemd reinicia o programa quando ele encerra com um código diferente de zero ou morre por um sinal de crash, aguardando cinco segundos entre as tentativas. Teste com sudo systemctl kill -s SIGKILL myapp.service — o SIGTERM, o sinal padrão, conta como um encerramento limpo e não aciona o on-failure — e observe o systemctl status mostrar um novo PID em poucos segundos.

Como eu executo um serviço systemd como um usuário não-root?

Crie uma conta de sistema com sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp e adicione User=myapp na seção [Service]. Adicione NoNewPrivileges=true, PrivateTmp=true e ProtectSystem=strict para que o processo rode com o mínimo de acesso necessário. Rodar como um usuário sem privilégios é a mudança mais importante para a segurança de um serviço.

Por que meu serviço falhou ao iniciar?

Execute systemctl status myapp.service para o resumo e journalctl -u myapp.service para a saída completa. As causas mais comuns são um caminho incorreto em ExecStart, um WorkingDirectory ausente, um erro de permissão porque o User= não consegue ler um arquivo, ou um sudo systemctl daemon-reload esquecido após uma edição. O journal mostra a própria mensagem de erro do programa, que geralmente nomeia o problema diretamente.