# systemd

## Hva det er

systemd er programmet med prosess-ID 1 på nesten alle store Linux-distribusjoner: system- og
tjenestestyreren som tar maskinen opp ved oppstart, starter og passer på tjenestene mens den går, og
stenger alt ned i ordnet rekkefølge når den slås av. Navnet skrives med liten forbokstav, aldri
SystemD eller System D, og d-en til slutt er det gamle Unix-tegnet for en daemon. systemd hører til
familien av init-systemer. Der finner du også SysV-init-skriptene og Upstart, som det har avløst i
de fleste distribusjoner, OpenRC og runit, som enkelte mindre distribusjoner fortsatt velger, og
launchd, som gjør den samme jobben på macOS.

Alt systemd styrer, er en enhet (på engelsk _unit_), beskrevet i en kort tekstfil med seksjoner og
par av nøkkel og verdi. Manualen regner opp 11 typer: service, socket, target, device, mount,
automount, timer, swap, path, slice og scope. En service kjører et program. En timer starter en
annen enhet etter en tidsplan. En socket holder en nettverksport åpen og starter tjenesten sin først
når den første tilkoblingen kommer inn. En target samler enheter til en tilstand maskinen kan nå,
f.eks. et flerbrukersystem med nettverk. Krav og rekkefølge er to ulike innstillinger, så «denne
trenger den» og «denne starter etter den» står på hver sin linje. systemd gjør dem om til én
transaksjon av start- og stoppjobber, og den transaksjonen kan sjekkes før den kjøres.

To designvalg skiller systemd fra de skriptbaserte init-systemene som kom før. Hver tjeneste kjører
i sin egen kontrollgruppe i Linux, så styreren kjenner hver prosess tjenesten noen gang har startet,
og kan stoppe alle sammen, sette tak på minnet deres og føre regnskap med prosessortiden. Dessuten
er prosjektet en hel samling verktøy og ikke bare en styrer: på sitt eget nettsted lister det opp en
daemon for logging, journalen, og komponenter for innlogging, nettverksoppsett, tidssynkronisering
og navneoppslag. Hver distribusjon velger selv hvilke av tilleggene den slår på. Styreren på PID 1
er den delen som er så godt som universell.

## Hvorfor det er viktig

På en Linux-server er spørsmålet sjelden om du skal kjøre systemd, for det valget har distribusjonen
allerede tatt. Det du faktisk avgjør, er om du bruker systemd som tjenestestyrer og planlegger,
eller om du legger en annen prosessbehandler, omstartsregelen til en container-daemon eller cron
oppå.

Bruker du systemd direkte, samles oppstartsrekkefølge, omstartsregel, logger, ressursgrenser og
sandkasse i én fil per tjeneste. Filen leses av en prosess som allerede kjører, og som ikke koster
ekstra minne. En enhet kan sette et tak på minnet med `MemoryMax=`, gjøre operativsystemets egne
kataloger skrivebeskyttet for tjenesten med `ProtectSystem=` og kjøre den som en engangsbruker med
`DynamicUser=`. Kommandoen `systemd-analyze security` gir så hver tjeneste en score for hvor utsatt
den er, på en skala fra 0,0 til 10,0.

En jobb som en timer starter, oppfører seg bedre enn en linje i crontab. Den logger til journalen,
får den samme sandkassen som enhver tjeneste, og `systemctl list-timers` viser når den gikk sist og
når den går neste gang. Kunnskapen er dessuten flyttbar: en ingeniør som kan lese en enhetsfil, kan
drifte de fleste Linux-servere, uansett hvilken distribusjon de kjører.

Prisen er også reell. Enhetene finnes bare på Linux, så et team som også leverer til macOS, skriver
property lists for launchd, og et team som leverer til BSD-systemene, skriver rc-skript. Inne i de
fleste containere finnes systemd ikke: der er selve applikasjonen PID 1, og omstartsregelen tilhører
det som kjører containeren. Der containere og vanlige tjenester deler en vert, gjør Quadlet fra
Podman avstanden mindre. Quadlet gjør en containerbeskrivelse om til en vanlig tjenesteenhet, slik
at begge typer arbeidslast står under én og samme tjenestestyrer.

## Slik ser det ut i praksis

systemd bærer tre deler av selskapets egen plattform.

Den første er produksjonsverten bak
[hele selskapet på én vert med 512 MB](/nb/portfolio/ran-the-whole-company-on-one-512mb-host-109/),
en maskin med én kjerne og rundt 464 MB brukbart minne. Den bærer webserveren for sju domener,
git-forgen, en onion-tjeneste for Tor, en Gemini-server og en Gopher-server, krypterte
sikkerhetskopier og utestenging av inntrengere. På den størrelsen må hver prosess som ligger i
minnet, forsvare plassen sin. Derfor er systemd tjenestestyreren, uten noen ekstra styrer lagt oppå,
og containerne kjører som Quadlet-enheter under den samme styreren i stedet for under en egen
container-daemon. Da spørsmålet var om verten også kunne bære onion-tjenesten, viste et døgn med
målinger at tilgjengelig minne aldri falt under rundt 310 MB av 464.

Den andre er
[krypterte sikkerhetskopier med en månedlig gjenopprettingsøvelse](/nb/portfolio/built-encrypted-backups-with-a-monthly-restore-drill-114/).
De kjører på en systemd-timer: en databasedump der det finnes en database, et kryptert og
deduplisert øyeblikksbilde sendt over SFTP til lagring hos en annen leverandør, opprydding etter
oppbevaringsregelen og til slutt en integritetssjekk. En dødmannsknapp pinges bare når alt har
lyktes. Det arbeidet møtte også en av de skarpere kantene i systemd, beskrevet nedenfor: passfrasen
ligger i en fil som enhetene leser. En verdi som sendes gjennom miljøet til en enhet, får nemlig
escape-sekvensene sine tolket, og en omvendt skråstrek ville i det stille ha gjort passfrasen til en
annen.

Den tredje er et prinsipp. [Teknologisiden](/nb/tech-stack/) trekker den generelle grensen: vanlige
systemd-enheter som standard, og Docker og Kubernetes for de arbeidslastene som gjør seg fortjent
til dem.

## Hvor det går galt

**En endret enhet kjører videre med de gamle innstillingene.** systemd leser enhetsfilene inn i
minnet, så en endring på disk gjør ingenting før `systemctl daemon-reload` bygger styrerens bilde
opp på nytt. Imens kan `systemctl cat` vise en fil som avviker fra den styreren bruker. Gjør
endringer med `systemctl edit`, som laster inn på nytt for deg, eller last inn på nytt og start
deretter tjenesten igjen.

**En hemmelighet kommer fram til tjenesten med et tegn for lite.** Verdier i `Environment=` går
gjennom siteringsreglene i systemd, der escape-sekvenser i C-stil tolkes og en bokstavelig omvendt
skråstrek må dobles. Dokumentasjonen til systemd advarer også om at miljøvariabler er synlige for
klienter uten privilegier over D-Bus. Legg hemmeligheter i en fil og gi dem videre med
`LoadCredential=`, som gir tjenesten en skrivebeskyttet kopi som bare tjenestens egen bruker og root
kan lese.

**En pakkeoppgradering tar stille bort en lokal rettelse.** Endringer i leverandørens fil under
`/usr/lib/systemd/system/` blir overskrevet neste gang pakkene oppdateres. Legg endringene i en
drop-in under `/etc/systemd/system/<unit>.d/`, som flettes inn oppå og overlever oppgraderinger.
Kommandolister legges sammen i stedet for å byttes ut, så en drop-in som endrer startkommandoen, må
først tømme den med en tom tilordning:

```ini
# /etc/systemd/system/app.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/local/bin/app --config /etc/app/app.toml
Restart=on-failure
```

**En nattlig jobb hopper over natten serveren sto avslått.** En kalendertimer som skulle ha gått
mens maskinen var nede, venter rett og slett på neste tidspunkt, fordi `Persistent=` står på false
som standard. Sett `Persistent=true` på sikkerhetskopiering og andre jobber som må kjøre, så går den
tapte kjøringen så snart timeren er aktiv igjen.

**En tjeneste som krasjer, blir liggende nede.** `Restart=` står på `no` som standard, så en
tjeneste som dør, forblir død til noen merker det. Sett `Restart=on-failure` på tjenester som skal
gå lenge. Vit også at når en enhet når startgrensen sin, gir styreren den opp, og en manuell start
må vente til intervallet er over eller til noen har kjørt `systemctl reset-failed`.

## Les mer

- [systemd(1)](https://man7.org/linux/man-pages/man1/systemd.1.html) — selve styreren: enhetstypene,
  oppstartsforløpet og signalene den svarer på.
- [systemd.unit(5)](https://man7.org/linux/man-pages/man5/systemd.unit.5.html) — enhetsfiler,
  avhengigheter, startgrenser og drop-in-katalogene som overstyrer dem.
- [systemd.service(5)](https://man7.org/linux/man-pages/man5/systemd.service.5.html) —
  tjenestetyper, omstartsregler og hvordan kommandolister nullstilles.
- [systemd.exec(5)](https://man7.org/linux/man-pages/man5/systemd.exec.5.html) — kjøremiljøet,
  valgene for sandkasse og credentials, filene som bringer hemmeligheter inn i tjenesten.
- [systemd.timer(5)](https://man7.org/linux/man-pages/man5/systemd.timer.5.html) — kalendertimere og
  monotone timere, med `Persistent=`.
- [systemctl(1)](https://man7.org/linux/man-pages/man1/systemctl.1.html) — kommandolinjen for å
  starte, redigere, laste inn på nytt og undersøke enheter.

<https://engineer.company/nb/glossary/systemd/>
