⚙️ Systemd & Service Management Deep Dive

Panduan praktis systemd — service units, journald logging, timers, socket activation, resource control, dan troubleshooting. Systemd adalah init system default di semua distro modern (Fedora, RHEL, Ubuntu, Debian, Arch). Catatan ini lahir dari masalah auditd di Fedora 44 yang ternyata disabled + kernel param missing — representasi gap pengetahuan tentang systemd lifecycle. Vault udah punya linux-fundamentals-deepdive (OS level) — ini implementasi systemd spesifik.

Daftar Isi

  1. 1. Systemd Architecture — Unit Types
  2. 2. Service Units — Anatomi & Lifecycle
  3. 3. Journald — Centralized Logging
  4. 4. Systemd Timers — Cron Modern
  5. 5. Socket Activation — On-Demand Services
  6. 6. Resource Control — CPU/Memory Limits
  7. 7. Systemd Security — Service Hardening
  8. 8. Systemd-networkd — Network Config
  9. 9. Troubleshooting & Common Issues
  10. 10. Koneksi ke Vault

1. Systemd Architecture — Unit Types

Systemd manage semua resource sebagai unit. Ada 12 tipe unit:

TipeEkstensiFungsiContoh
Service.serviceDaemon / background processnginx.service, postgresql.service
Socket.socketIPC / network socketsshd.socket, docker.socket
Timer.timerScheduled taskfstrim.timer, logrotate.timer
Mount.mountMount pointhome.mount, boot.mount
Automount.automountOn-demand mountmnt-data.automount
Path.pathFile/directory triggercups.path
Slice.sliceResource control groupmachine.slice, system.slice
Target.targetGroup of units (runlevel)multi-user.target, graphical.target
Scope.scopeExternally created processuser@1000.service (user scope)
Device.deviceKernel devicesys-devices-pci…device
Swap.swapSwap partitionswapfile.swap
Network.networkNetwork configuration50-dhcp.network
# Unit management
systemctl list-units --type=service --all   # semua service
systemctl list-units --type=timer           # timer saja
systemctl list-unit-files --type=service    # semua file unit (active + inactive)
systemctl list-dependencies sshd.service    # dependency tree

2. Service Units — Anatomi & Lifecycle

Struktur Service Unit

# /etc/systemd/system/myapp.service
[Unit]
Description=My Awesome Application
Documentation=https://docs.myapp.com
After=network-online.target postgresql.service
Wants=postgresql.service              # optional dependency
Requires=redis.service                # hard dependency, gagal kalo redis gak start
BindsTo=redis.service                 # stop myapp kalo redis stop
 
[Service]
Type=simple                           # default: langsung fork
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/node /opt/myapp/server.js
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/bin/kill -TERM $MAINPID
Restart=on-failure                    # restart otomatis
RestartSec=5                          # delay 5 detik sebelum restart
TimeoutStartSec=30
TimeoutStopSec=10
Environment=NODE_ENV=production
EnvironmentFile=-/etc/myapp/env.conf
StandardOutput=journal
StandardError=journal
 
# Hardening
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=full
ProtectHome=yes
 
[Install]
WantedBy=multi-user.target            # start di boot level multi-user

Type — Arti Penting

TypeBehaviorCocok untuk
simpleExecStart langsung jalan, systemd anggap “started”Node.js, Python, long-running shell
forkingParent exit, child lanjut (daemon)MySQL, Nginx, PostgreSQL
oneshotJalan sekali lalu exitScript setup, cleanup
dbusTunggu bus name di D-BusNetworkManager, systemd-resolved
notifyPanggil sd_notify() setelah siapAplikasi yang pake libsystemd
idleSimple, tapi delay sampai semua job selesaiPrint banner, welcome message

Service Lifecycle

systemctl daemon-reload            # reload unit file setelah diubah
systemctl start myapp.service      # start
systemctl stop myapp.service       # stop
systemctl restart myapp.service    = stop + start
systemctl reload myapp.service     # Sends SIGHUP (kalo support)
systemctl enable myapp.service     # auto-start di boot
systemctl disable myapp.service    # hapus auto-start
systemctl enable --now myapp.service  # enable + start sekaligus
 
# Status
systemctl status myapp.service     # status + recent logs
systemctl is-active myapp.service  # active/inactive/activating
systemctl is-enabled myapp.service # enabled/disabled/static
systemctl show myapp.service       # semua properties (100+ fields)
systemctl cat myapp.service        # print unit file content

Drop-in Config — Override Tanpa Edit File Asli

# 1. Buat drop-in directory
sudo mkdir -p /etc/systemd/system/myapp.service.d/
 
# 2. Buat override.conf
sudo cat > /etc/systemd/system/myapp.service.d/override.conf << 'EOF'
[Service]
Restart=always
RestartSec=10
MemoryMax=1G
CPUQuota=50%
EOF
 
# 3. Reload
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
 
# Verifikasi
systemctl cat myapp.service   # liat hasil merge unit file asli + drop-in
systemctl show myapp.service -p MemoryMax

3. Journald — Centralized Logging

Semua log systemd terpusat di journald — gak perlu /var/log/syslog atau auth.log (tapi tetap bisa forward ke syslog tradisional).

Konfigurasi Journald

# /etc/systemd/journald.conf
[Journal]
Storage=persistent                     # simpan di disk (/var/log/journal/)
Compress=yes
Seal=yes
SystemMaxUse=4G
SystemKeepFree=1G
MaxRetentionSec=1month
ForwardToSyslog=no                     # gak perlu syslog
ForwardToWall=yes

journalctl — Master Log Viewer

# Basic
journalctl                              # semua log (butuh sudo/group adm)
journalctl -u nginx.service             # log service tertentu
journalctl -u sshd.service -u nginx.service  # multiple services
journalctl -k                           # kernel messages
 
# Time-based
journalctl --since "1 hour ago"
journalctl --since "2026-07-30 09:00" --until "2026-07-30 12:00"
journalctl -u myapp.service --since yesterday
 
# Filter
journalctl -p err -b                    # error priority, boot sejak boot
journalctl _PID=1234                    # by PID
journalctl _UID=1000                    # by user
journalctl -p warning..err              # range priority (warning sampai error)
 
# Output
journalctl -f                           # follow (tail -f)
journalctl -n 50                        # last 50 lines
journalctl -u myapp.service --no-pager  # full output, gak pager
journalctl -o json-pretty               # JSON format
 
# Maintenance
journalctl --disk-usage                 # size on disk
journalctl --vacuum-size=500M           # hapus log sampai 500MB
journalctl --vacuum-time=7d             # hapus log lebih dari 7 hari
sudo journalctl --rotate                # force rotate log files

4. Systemd Timers — Cron Modern

Systemd timer > cron: logging terintegrasi, dependency-aware, bisa missed-exec, persistent.

# /etc/systemd/system/backup.service
[Unit]
Description=Daily Database Backup
 
[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup-db.sh
User=postgres
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily at 3 AM
 
[Timer]
OnCalendar=daily
OnCalendar=*-*-* 03:00:00        # atau format tepat
Persistent=true                   # kalo missed (mati listrik), jalan pas boot
RandomizedDelaySec=300            # random delay 0-5 menit
Unit=backup.service               # default: nama sama (backup.timer → backup.service)
 
[Install]
WantedBy=timers.target
# Activate
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
 
# Management
systemctl list-timers --all         # semua timer + next run
systemctl list-timers               # hanya yang active
systemctl status backup.timer
journalctl -u backup.timer -u backup.service  # log timer + service

Format OnCalendar

PatternMaknaContoh Next
dailySetiap hari 00:00Thu 2026-07-31 00:00:00 WIB
hourlySetiap jam :00Thu 2026-07-30 10:00:00 WIB
*-*-* 03:00:00Setiap hari jam 3 pagiThu 2026-07-31 03:00:00 WIB
Mon..Fri 08:30:00Weekdays jam 8:30Fri 2026-08-01 08:30:00 WIB
Sat,Sun 00:00:00Weekend midnightSat 2026-08-02 00:00:00 WIB
*:0/15Setiap 15 menitThu 2026-07-30 09:15:00 WIB
*-01-01 00:00:00Setiap tahun baruFri 2027-01-01 00:00:00 WIB
# Test timer
systemd-analyze calendar "Mon..Fri 09:00:00"   # prev/next fire time

5. Socket Activation — On-Demand Services

Service start pas pertama kali ada koneksi ke socket-nya — hemat resource.

# /etc/systemd/system/myecho.socket
[Unit]
Description=Echo Service Socket
 
[Socket]
ListenStream=7777
Accept=yes                        # fork per connection
 
[Install]
WantedBy=sockets.target
# /etc/systemd/system/myecho@.service    # template (@ = instance)
[Unit]
Description=Echo Service %i
 
[Service]
Type=simple
ExecStart=/usr/bin/cat
StandardInput=socket
StandardOutput=socket
sudo systemctl enable --now myecho.socket
ss -tlnp | grep 7777      # LISTEN, tapi gak ada process name — bidikan systemd
echo "hello" | nc localhost 7777  # first connect → service auto-start
journalctl -u myecho@.service    # log per instance

Use Case Socket Activation

SkenarioManualSocket Activation
SSH diakses jarangJalan 24/7, makan memoryStart saat ada koneksi SSH
Container socketDocker socket listenStart dockerd pas ada request
Web app low trafficNginx selalu jalanStart saat request masuk

Fedora 44 default untuk sshd.socket — bukan sshd.service. Cek dengan systemctl status sshd.socket.


6. Resource Control — CPU/Memory Limits

Systemd bisa control resources via cgroups v2.

Sesi Unit

[Service]
MemoryMax=1G                   # hard limit (OOM kill kalo exceeded)
MemoryHigh=768M                # soft limit (mulai throttle)
CPUQuota=50%                   # max 50% 1 core
CPUQuotaPeriodSec=1s
TasksMax=100                   # max threads/processes
IOWeight=100                   # I/O priority (100-1000)
IOReadBandwidthMax=/dev/sda 10M  # I/O rate limit
IOWriteBandwidthMax=/dev/sda 5M

Sesi System Level — Slice

# Buat slice untuk batch job
sudo cat > /etc/systemd/system/batch.slice << 'EOF'
[Slice]
CPUQuota=200%           # max 2 core
MemoryMax=4G
TasksMax=200
EOF
 
# Assign service ke slice
sudo cat > /etc/systemd/system/batch-job.service.d/override.conf << 'EOF'
[Service]
Slice=batch.slice
EOF

Monitor Resource

systemd-cgtop                           # top untuk cgroups
systemctl show --property=MemoryMax myapp.service
systemd-cgls                            # tree view cgroups

7. Systemd Security — Service Hardening

Checklist hardening per-service (dari linux-hardening-audit-praktis):

# Analyze security profile
systemd-analyze security myapp.service
DirectiveEfekLevel
ProtectSystem=fullRead-only /usr, /etcWajib
ProtectHome=yesGak bisa akses /home, /rootWajib
PrivateTmp=yes/tmp terisolasiWajib
NoNewPrivileges=yesGak bisa suid/sgidWajib
CapabilityBoundingSet=...Batasi Linux capabilitiesMedium
SystemCallFilter=~@debugBlock syscall berbahayaMedium
PrivateDevices=yesGak liat /dev (kecuali /dev/null, /dev/zero)Tinggi
ProtectKernelModules=yesBlock insmod/modprobeTinggi
MemoryDenyWriteExecute=yesPrevent W+X memory pagesTinggi
RestrictAddressFamilies=...Batasi network domainsTinggi
LockPersonality=yesPrevent exec domain changeMaksimal

8. Systemd-networkd — Network Config

Alternatif lightweight ke NetworkManager — cocok buat server.

# /etc/systemd/network/50-dhcp.network
[Match]
Name=enp* ens*
 
[Network]
DHCP=ipv4
LinkLocalAddressing=ipv6
DNSSEC=allow-downgrade
# /etc/systemd/network/50-static.network
[Match]
Name=enp3s0
 
[Network]
Address=192.168.1.100/24
Gateway=192.168.1.1
DNS=1.1.1.1
DNS=8.8.8.8
Domains=local.domain
 
[Route]
Destination=10.0.0.0/8
Gateway=192.168.1.254
systemctl enable --now systemd-networkd
networkctl status                  # status network
networkctl list                    # all links
networkctl lldp                   # LLDP neighbors

9. Troubleshooting & Common Issues

Issue 1: Service Gagal Start

systemctl status myapp.service    # liat status + exit code
journalctl -xeu myapp.service     # -x = extra explanation, -e = end
systemctl reset-failed myapp.service  # reset "failed" state

Issue 2: Slow Boot — Analyze Boot Time

systemd-analyze                    # total boot time
systemd-analyze blame              # per unit boot time (desc)
systemd-analyze critical-chain     # critical path di boot sequence
systemd-analyze plot > boot.svg    # visual timeline

Issue 3: Timer Gak Jalan

systemctl list-timers              # next run
journalctl -u backup.timer -p info # log timer events
systemctl status backup.timer
systemctl start backup.service     # test service langsung

Issue 4: Unit Not Found

systemctl daemon-reload            # sering ketinggalan!
systemctl list-unit-files | grep myapp
systemctl preset myapp.service     # enable berdasarkan preset

Issue 5: Drop-in Gak Kebaca

systemctl cat myapp.service        # verify override applied
# Kalo gak muncul: nama file harus .conf!
# /etc/systemd/system/myapp.service.d/*.conf ✅
# /etc/systemd/system/myapp.service.d/override ❌ (no extension)

Debug Mode

# Enable debug logging
journalctl -p debug -u myapp.service
systemctl start myapp.service
# Atau set environment
SYSTEMD_LOG_LEVEL=debug systemctl start myapp.service

10. Koneksi ke Vault

CatatanKoneksi
linux-hardening-audit-praktisService hardening di catatan itu pakai systemd properties — note ini bedah detailnya
linux-fundamentals-deepdiveFondasi OS — prerequisite understanding kernel, cgroups, namespaces
hierarchy-operating-systemsPosisi systemd di OS hierarchy (userspace init)
linux-hardening-cisCIS benchmark — systemd bagian dari Level 1 hardening
observability-stack-prometheus-grafanajournald metrics → Prometheus via node_exporter
vps-hardening-playbookHardening VPS — enable/disable services via systemctl

References

  1. systemd Documentation — https://www.freedesktop.org/software/systemd/man/
  2. systemd.exec(5) — Service execution config — https://www.freedesktop.org/software/systemd/man/systemd.exec.html
  3. systemd.timer(5) — Timer unit — https://www.freedesktop.org/software/systemd/man/systemd.timer.html
  4. systemd.socket(5) — Socket activation — https://www.freedesktop.org/software/systemd/man/systemd.socket.html
  5. journalctl(1) — Journal query tool — https://www.freedesktop.org/software/systemd/man/journalctl.html
  6. Fedora Systemd Docs — https://docs.fedoraproject.org/en-US/quick-docs/systemd/
  7. systemd.io portal — https://systemd.io/