Generatore systemd
Crea unità più sicure[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
Introduzione
Il generatore systemd produce un'unità di servizio (un file .service) con opzioni di hardening facili da dimenticare: un utente non root, NoNewPrivileges, PrivateTmp, ProtectSystem=strict e ProtectHome.
systemd permette di descrivere cosa un servizio può toccare. L'unità generata è un punto di partenza difendibile per un worker in background, un agente o qualsiasi processo long-running.
Obiettivo
- Generare un'unità .service sintatticamente corretta da nome, comando, utente e directory di lavoro.
- Applicare hardening di base: utente dedicato, riavvio su errore, nessun privilegio nuovo, /tmp privato e percorsi di sistema in sola lettura.
- Mantenere l'unità leggibile affinché un amministratore possa modificarla prima della distribuzione.
Input
- Descrizione (testo libero).
- ExecStart — il percorso assoluto dell'eseguibile.
- Utente del servizio — l'account non privilegiato con cui gira il servizio.
- Directory di lavoro (opzionale).
Come funziona
Lo strumento assembla tre sezioni. [Unit] dichiara la descrizione e ordina il servizio dopo network-online.target. [Service] imposta Type=simple, utente e directory di lavoro, ExecStart e Restart=on-failure con ritardo di 5 secondi.
Seguono le direttive di hardening: NoNewPrivileges=true blocca l'acquisizione di nuovi privilegi tramite binari setuid; PrivateTmp=true dà al servizio una /tmp propria; ProtectSystem=strict rende l'intero filesystem in sola lettura tranne i percorsi esplicitamente consentiti; ProtectHome=true nasconde /home, /root e /run/user.
[Install] dichiara WantedBy=multi-user.target affinché l'unità possa essere attivata con systemctl enable.
Esempio testabile
Prova — l'analisi gira localmente nel tuo browser.
Esempio
Descrizione: Otho worker ExecStart: /opt/otho/bin/worker Utente: otho Directory: /opt/otho
Output atteso
[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
Leggere l'output
- Salva l'output come /etc/systemd/system/<nome>.service, poi esegui sudo systemctl daemon-reload e sudo systemctl start <nome>.
- Se il servizio deve scrivere nei percorsi di sistema, ProtectSystem=strict lo bloccherà — aggiungi ReadWritePaths o sposta i dati scrivibili nella directory di lavoro.
- L'unità è un modello: adatta TimeoutStartSec, i limiti di risorse (MemoryMax, CPUQuota) e le capability (CapabilityBoundingSet) al carico.
Rischi
- Eseguire un servizio come root con accesso di rete è il default più rischioso; l'unità generata lo evita, ma verifica che il tuo binario ExecStart sia di proprietà di root.
- ProtectSystem=strict può rompere servizi che scrivono fuori dalla loro directory di lavoro — testa prima della produzione.
- Restart=on-failure non protegge dai crash con exit 0; per worker critici valuta Restart=always.
Limiti
- Lo strumento genera il file; non può testare che il tuo eseguibile parta o che i suoi permessi siano corretti.
- Non genera socket activation, timer o grafi di dipendenze complessi.
- L'hardening è di base: una revisione vera dovrebbe considerare capability, seccomp e namespace di rete.
Riferimenti ufficiali
FAQ
Perché un utente dedicato per ogni servizio?
Un utente dedicato non privilegiato limita cosa può fare un servizio compromesso: non può leggere i file degli altri né scrivere fuori dai propri percorsi. Root va riservato ai pochi servizi che lo richiedono davvero.
Cosa fa NoNewPrivileges=true?
Impedisce al servizio e ai suoi figli di acquisire privilegi tramite binari setuid o meccanismi simili, anche se tali binari esistono sul sistema.
Cos'è ProtectSystem=strict?
Rende l'intero filesystem in sola lettura per il servizio, tranne i percorsi esplicitamente consentiti. È il livello ProtectSystem più forte e si sposa con servizi che scrivono solo nella loro directory di lavoro o in /tmp.