Vai al contenuto

Impostazioni cookie

Scelga per ogni tipo quali cookie consente. Può modificare la sua scelta in qualsiasi momento tramite Impostazioni cookie in fondo a ogni pagina. Informativa sulla privacy

Necessari

Sempre attivi

Servono per accedere, conservare il carrello e ricordare le sue scelte. Sono sempre attivi.

Quali cookie?
  • weboke_sessie, weboke_klant, weboke_remember: la sua sessione e la permanenza dell'accesso
  • weboke_basket: il suo carrello
  • wkBtwIncl: visualizzazione dei prezzi con o senza IVA
  • wok_cookies: la sua scelta sui cookie, 12 mesi

Misurano quale annuncio porta a una visita o a un ordine, così non paghiamo annunci che non funzionano.

Quali cookie?
  • Google Ads tramite Google Tag Manager (_gcl_au, _gcl_aw), fino a 90 giorni
  • OpenAI Ads, annunci in ChatGPT
  • wok_aff: tramite quale partner è arrivato da noi (programma di affiliazione), 60 giorni

4,6

Paese e lingua

Ogni paese ha il suo sito, con i prezzi e l'IVA di quel paese.

Vedi

Servizi propri e timer

Modulo 6: Servizi e log · Tempo di lettura: 11 minuti

Obiettivo della lezione: Al termine di questa lezione sarà in grado di eseguire un proprio programma come servizio systemd con un utente dedicato, con alcune opzioni di sicurezza, e di pianificare attività con un timer systemd o con cron.

Concetti chiave: file unit, [Unit], [Service], [Install], ExecStart, User=, WorkingDirectory, EnvironmentFile, Restart=, WantedBy, NoNewPrivileges, ProtectSystem, ProtectHome, PrivateTmp, systemd-analyze security, timer, OnCalendar, Persistent, crontab

Perché non usare semplicemente "nohup" o "screen"?

Chi installa un proprio programma su un server (una piccola applicazione web, un bot, uno script che ogni notte svolge un compito) spesso la prima volta lo avvia a mano: node server.js &, oppure in una sessione screen. Funziona finché non si disconnette, il server non si riavvia o il programma non va in crash. A quel punto il programma non c'è più, e nessuno se ne accorge.

Un programma che deve restare sempre in esecuzione dovrebbe essere un servizio systemd. In questo modo:

  • si avvia da solo all'accensione;
  • systemd lo riavvia se va in crash;
  • l'output finisce nel journal (lezione 6.2);
  • viene eseguito con un utente scelto da Lei, con i permessi che Lei concede.

Un file unit proprio

Supponiamo che Lei abbia una piccola applicazione Node.js in /opt/factuurapp, in ascolto su 127.0.0.1:3000. Più avanti nginx o Caddy la renderanno raggiungibile dall'esterno (modulo 7).

Passo 1: un utente dedicato senza shell (lezione 3.2). L'applicazione non ha bisogno di essere root né di effettuare l'accesso:

anna@web1:~$ sudo adduser --system --group --home /opt/factuurapp --no-create-home factuurapp
anna@web1:~$ sudo chown -R factuurapp:factuurapp /opt/factuurapp/data

Il codice stesso può restare di proprietà di root (l'applicazione non deve modificare se stessa); solo la cartella in cui scrive appartiene all'utente del servizio.

Passo 2: il file unit. Le unit personalizzate vanno in /etc/systemd/system/:

# /etc/systemd/system/factuurapp.service
[Unit]
Description=Factuurapp (Node.js)
After=network-online.target
Wants=network-online.target

[Service]
User=factuurapp
Group=factuurapp
WorkingDirectory=/opt/factuurapp
EnvironmentFile=/etc/factuurapp/env
ExecStart=/usr/bin/node /opt/factuurapp/server.js
Restart=on-failure
RestartSec=5s

NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/opt/factuurapp/data

[Install]
WantedBy=multi-user.target

I tre blocchi:

  • [Unit]: descrizione e ordine di avvio. After=network-online.target insieme a Wants= fa sì che il servizio parta solo quando la rete è disponibile.
  • [Service]: come viene eseguito il programma. ExecStart con il percorso completo (systemd non usa un percorso di ricerca come la Sua shell). User= e Group= stabiliscono con quale utente. EnvironmentFile legge impostazioni come la password di un database da un file separato, così non compaiono nella unit.
  • [Install]: che cosa fa enable. WantedBy=multi-user.target significa: avviarsi insieme a un normale avvio del sistema.

Passo 3: segreti separati, con permessi restrittivi.

anna@web1:~$ sudo mkdir /etc/factuurapp
anna@web1:~$ sudo install -m 600 -o root -g root /dev/null /etc/factuurapp/env
anna@web1:~$ sudoedit /etc/factuurapp/env

Il contenuto può essere ad esempio DATABASE_URL=postgres://factuur:...@127.0.0.1/factuur. systemd legge il file come root prima di passare all'utente del servizio, quindi 600 di proprietà di root è sufficiente.

Passo 4: caricare, avviare, verificare.

anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now factuurapp
anna@web1:~$ systemctl status factuurapp
anna@web1:~$ journalctl -u factuurapp -f

Opzioni di sicurezza: poco sforzo, grande differenza

Le quattro righe sotto RestartSec nell'esempio limitano ciò che il servizio può fare, anche se qualcuno trova una falla nella Sua applicazione:

OpzioneEffetto
NoNewPrivileges=trueil processo e i suoi processi figli non possono mai ottenere più privilegi (nemmeno tramite sudo o programmi setuid)
ProtectSystem=strictl'intero file system è in sola lettura per il servizio, tranne ciò che Lei consente con ReadWritePaths=
ProtectHome=true/home, /root e /run/user sono invisibili
PrivateTmp=trueuna /tmp propria e vuota, che gli altri programmi non vedono

systemd può valutare la Sua unit:

anna@web1:~$ systemd-analyze security factuurapp
...
→ Overall exposure level for factuurapp.service: 4.9 OK 🙂

Più basso è il numero, meglio è. Un servizio senza opzioni ottiene circa 9 ("UNSAFE"). Non è necessario arrivare a zero: ogni opzione aggiunta può bloccare qualcosa di cui l'applicazione ha bisogno. Le aggiunga una alla volta e verifichi dopo ogni passo. Se qualcosa smette di funzionare, di solito lo trova nel journal ("Read-only file system", "Permission denied").

Pianificare attività: i timer

Per qualcosa che deve avvenire a orari fissi (un backup, uno script di pulizia, un report) serve un timer. Un timer systemd è composto da due unit con lo stesso nome: un .service che dice che cosa deve accadere e un .timer che dice quando.

# /etc/systemd/system/opruimen.service
[Unit]
Description=Oude exportbestanden opruimen

[Service]
Type=oneshot
User=factuurapp
ExecStart=/usr/bin/find /opt/factuurapp/data/export -type f -mtime +30 -delete
# /etc/systemd/system/opruimen.timer
[Unit]
Description=Dagelijks oude exportbestanden opruimen

[Timer]
OnCalendar=*-*-* 03:15:00
RandomizedDelaySec=10m
Persistent=true

[Install]
WantedBy=timers.target

Type=oneshot significa: il programma viene eseguito e poi termina. OnCalendar è la pianificazione: ogni giorno alle 03:15. Può anche scrivere daily, weekly o Mon *-*-* 02:00; systemd-analyze calendar "Mon *-*-* 02:00" mostra quando sarà la prossima esecuzione. Persistent=true è importante: se alle 03:15 il server era spento, l'attività viene eseguita subito dopo l'avvio. RandomizedDelaySec distribuisce un po' il momento di avvio.

Si attiva il timer, non il service:

anna@web1:~$ sudo systemctl daemon-reload
anna@web1:~$ sudo systemctl enable --now opruimen.timer
anna@web1:~$ systemctl list-timers opruimen
NEXT                        LEFT     LAST PASSED UNIT           ACTIVATES
Tue 2026-11-10 03:19:42 CET 15h left -    -      opruimen.timer opruimen.service
anna@web1:~$ sudo systemctl start opruimen.service    # ora testare una volta manualmente
anna@web1:~$ journalctl -u opruimen.service

E cron?

cron è lo strumento più vecchio e più semplice, e funziona ancora benissimo. Una riga nella crontab di un utente (crontab -e):

15 3 * * * /usr/local/bin/opruimen.sh

I cinque campi sono minuto, ora, giorno del mese, mese e giorno della settimana. Vantaggi e svantaggi a confronto:

crontimer systemd
Configurazioneuna rigadue file
Esecuzione mancata (server spento)viene saltatarecuperata con Persistent=true
Output ed errorivia email, se il server può inviare email; altrimenti persinel journal
Opzioni di sicurezza, utentetramite lo script stessotutto ciò che offre systemd (vedi sopra)
Vedere quando è stato eseguitodifficilesystemctl list-timers e il journal

Per un server gestito seriamente i timer sono la scelta migliore, soprattutto per i backup (lezione 8.2): Lei vuole sapere con certezza che sono stati eseguiti e che cosa hanno restituito. Una riga di cron che fallisce in silenzio la scopre solo quando ha bisogno del backup.

Su AlmaLinux e Rocky Linux

Unit e timer funzionano esattamente allo stesso modo. Una differenza: SELinux può bloccare un servizio proprio che legge o scrive file in una posizione che SELinux non si aspetta, oppure che ascolta su una porta insolita. Il messaggio si trova in /var/log/audit/audit.log. Non disattivi SELinux per risolvere il problema; cerchi l'etichetta o la regola corretta (ad esempio con semanage).

Riepilogo

  • Un programma che deve restare sempre in esecuzione dovrebbe essere un servizio systemd: avvio automatico, riavvio in caso di crash, log nel journal.
  • Unit personalizzate in /etc/systemd/system/, con User= un utente dedicato senza shell, segreti in un EnvironmentFile con permessi 600.
  • NoNewPrivileges, ProtectSystem=strict con ReadWritePaths, ProtectHome e PrivateTmp limitano i danni in caso di falla; systemd-analyze security valuta la unit.
  • Un timer è un .service più un .timer con OnCalendar; Persistent=true recupera le esecuzioni mancate. Attivi il timer, non il service.
  • cron funziona ancora, ma i timer offrono log migliori e non saltano esecuzioni.

Quiz

1. La Sua applicazione gira come servizio con User=root. Perché un utente dedicato è meglio?



2. Ha creato un .service e un .timer. Che cosa attiva con enable --now?



3. Che cosa fa Persistent=true in un timer?



4. Aggiunge ProtectSystem=strict e in seguito la Sua applicazione restituisce "Read-only file system" quando salva gli upload. Qual è la soluzione corretta?



5. Dove mette la password del database del Suo servizio?



Esercizio

Esercizio O6.3: Un servizio proprio con timer. Crei sul Suo server un piccolo servizio proprio con un timer, ad esempio uno script che ogni notte scrive lo spazio libero su disco e systemctl --failed in un file o nel journal. Usi un utente dedicato, Type=oneshot, almeno due opzioni di sicurezza e Persistent=true. Verifichi con systemctl start, controlli l'output nel journal e annoti il punteggio di systemd-analyze security. Incolli il Suo .service e il Suo .timer e risponda alle domande della checklist.

Esercizio O6.3: Un servizio proprio con timer

Questo esercizio lo svolge da sé; nessuno lo verifica. Spunti ciò che ha fatto e segni l'esercizio come completato.




Le Sue spunte e note restano solo in questo browser; non le inviamo da nessuna parte. Se ha effettuato l'accesso, conserviamo in I miei corsi solo il fatto che ha svolto l'esercizio.

Per approfondire

Un momento…

Configuri i suoi domini

Per ogni dominio imposti i nameserver, il collegamento al suo hosting e chi ne diventa l'intestatario.

Caricamento dei suoi domini…