September 27, 2026

Dasar systemd.

Memahami unit systemd, menulis service file sendiri, mengelola service dengan systemctl, membaca log dengan journalctl, restart policy, dan timer sebagai pengganti cron.

systemd adalah init system dan pengelola service di hampir semua distro Linux modern (Ubuntu, Debian, Fedora, Arch). Ia adalah proses pertama yang berjalan (PID 1) dan bertugas menyalakan, menghentikan, serta mengawasi service. Kalau kamu pernah menjalankan systemctl restart nginx, itu berarti kamu sudah berinteraksi dengan systemd.

Catatan ini fokus ke kebutuhan sehari-hari di server: menjalankan aplikasi sendiri (Node.js, Go, Python, queue worker Laravel ) sebagai service yang otomatis hidup saat boot dan otomatis restart saat crash.


1. Unit

Semua yang dikelola systemd disebut unit, dan jenisnya ditentukan oleh ekstensi file:

JenisContohFungsi
.servicenginx.serviceProses/daemon
.timerbackup.timerMenjadwalkan unit lain (pengganti cron )
.socketssh.socketMenyalakan service saat ada koneksi masuk
.targetmulti-user.targetGrup unit, mirip “runlevel”
.mountmnt-data.mountTitik mount
.pathdeploy.pathMemicu unit saat file/folder berubah

Lokasi file unit:

LokasiIsiBoleh diedit?
/usr/lib/systemd/system/ (atau /lib/systemd/system/)Bawaan paketJangan, tertimpa saat update
/etc/systemd/system/Buatan admin & overrideYa, prioritas tertinggi
~/.config/systemd/user/Service milik user (systemctl --user)Ya

2. systemctl: Perintah Sehari-hari

sudo systemctl start nginx        # nyalakan sekarang
sudo systemctl stop nginx         # matikan
sudo systemctl restart nginx      # stop lalu start
sudo systemctl reload nginx       # muat ulang konfigurasi tanpa putus (jika didukung)
systemctl status nginx            # status, PID, memori, potongan log terakhir

sudo systemctl enable nginx       # nyala otomatis saat boot
sudo systemctl disable nginx      # batal otomatis
sudo systemctl enable --now nginx # enable + start sekaligus

systemctl is-active nginx
systemctl is-enabled nginx
systemctl list-units --type=service --state=running
systemctl --failed                # unit yang gagal

Perbedaan yang sering tertukar:

  • start hanya berlaku untuk sesi sekarang. Setelah reboot, service tidak menyala.
  • enable membuat symlink agar service menyala saat boot, tapi tidak menyalakannya sekarang.

Service yang benar-benar tidak boleh dijalankan (bahkan sebagai dependensi) bisa di-mask:

sudo systemctl mask apache2
sudo systemctl unmask apache2

3. Menulis Service File Sendiri

Contoh: aplikasi Node.js di /opt/myapp.

# /etc/systemd/system/myapp.service
[Unit]
Description=My Node.js App
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=5

[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
Environment=NODE_ENV=production
EnvironmentFile=-/etc/myapp/env
ExecStart=/usr/bin/node /opt/myapp/server.js
Restart=on-failure
RestartSec=5

# hardening ringan
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=full

[Install]
WantedBy=multi-user.target

Aktifkan:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin myapp
sudo systemctl daemon-reload
sudo systemctl enable --now myapp
systemctl status myapp

Penting: Setiap kali membuat atau mengubah file unit, jalankan sudo systemctl daemon-reload. Tanpa itu, systemd masih memakai versi lama yang ada di memori.

Penjelasan bagian penting

[Unit]

  • After= hanya mengatur urutan, bukan ketergantungan. Wants=/Requires= yang membuat unit lain ikut dinyalakan.
  • network-online.target menunggu jaringan benar-benar siap, sedangkan network.target tidak.

[Service]

OpsiKeterangan
Type=simpleDefault. Proses di ExecStart adalah proses utama, tidak fork ke background
Type=execSeperti simple, tapi dianggap sukses setelah binary berhasil dieksekusi
Type=forkingUntuk daemon lama yang fork sendiri; biasanya butuh PIDFile=
Type=oneshotTugas sekali jalan (skrip), sering dipasangkan dengan timer
Type=notifyAplikasi memberi sinyal “siap” lewat sd_notify
ExecStart=Wajib path absolut; tidak dijalankan lewat shell
Environment= / EnvironmentFile=Variabel lingkungan; - di depan path berarti “abaikan jika file tidak ada”
User=Jangan jalankan aplikasi sebagai root

Karena ExecStart tidak melewati shell, fitur seperti pipe, &&, atau > tidak berfungsi. Jika memang perlu, bungkus: ExecStart=/bin/bash -c 'cmd1 && cmd2'.

[Install]

WantedBy=multi-user.target berarti “nyalakan saat sistem mencapai mode multi-user”, yaitu kondisi boot normal di server. Bagian inilah yang dibaca oleh systemctl enable.


4. Restart Policy

Restart=Restart ketika…
noTidak pernah (default)
on-failureExit code bukan 0, terbunuh sinyal, timeout, atau watchdog
on-abnormalTerbunuh sinyal, timeout, watchdog (exit code ≠ 0 tidak di-restart)
alwaysSelalu, termasuk exit normal

Pilihan umum untuk aplikasi web adalah on-failure, sedangkan untuk worker yang memang keluar secara berkala (misalnya php artisan queue:work --max-time=3600) pakai always.

RestartSec= memberi jeda sebelum restart. Pembatas restart loop ada di bagian [Unit]:

  • StartLimitIntervalSec=60 dan StartLimitBurst=5 berarti jika gagal start 5 kali dalam 60 detik, systemd berhenti mencoba dan unit masuk status failed.

Reset setelah masalahnya diperbaiki:

sudo systemctl reset-failed myapp
sudo systemctl start myapp

5. Override Tanpa Mengedit File Asli

Untuk mengubah service bawaan paket (misalnya menambah limit), jangan edit file di /usr/lib/systemd/system/. Gunakan drop-in:

sudo systemctl edit nginx

Editor terbuka untuk file /etc/systemd/system/nginx.service.d/override.conf. Isi hanya bagian yang ingin diubah:

[Service]
LimitNOFILE=65535
Restart=on-failure

systemctl edit otomatis menjalankan daemon-reload setelah disimpan. Untuk opsi yang bisa muncul berkali-kali seperti ExecStart, kosongkan dulu sebelum mengisi ulang:

[Service]
ExecStart=
ExecStart=/usr/sbin/nginx -g 'daemon off;'

Melihat hasil gabungan unit asli + override:

systemctl cat nginx

6. journalctl: Membaca Log

Output stdout/stderr service otomatis ditangkap oleh journald.

journalctl -u myapp              # semua log myapp
journalctl -u myapp -f           # ikuti real-time (seperti tail -f)
journalctl -u myapp -n 100       # 100 baris terakhir
journalctl -u myapp --since "1 hour ago"
journalctl -u myapp --since "2026-09-27 08:00" --until "2026-09-27 09:00"
journalctl -u myapp -p err       # hanya level error ke atas
journalctl -b                    # log sejak boot terakhir
journalctl -b -1                 # boot sebelumnya (butuh journal persisten)
journalctl -k                    # log kernel (seperti dmesg)
journalctl -u myapp -o json-pretty

Mengelola ukuran journal:

journalctl --disk-usage
sudo journalctl --vacuum-time=14d
sudo journalctl --vacuum-size=500M

Batas permanen diatur di /etc/systemd/journald.conf (misalnya SystemMaxUse=500M), lalu sudo systemctl restart systemd-journald.

User biasa perlu masuk grup adm atau systemd-journal untuk membaca log sistem tanpa sudo.


7. Timer: Penjadwalan ala systemd

Timer adalah alternatif cron yang terintegrasi dengan journald dan dependensi systemd. Dibutuhkan dua file: service (apa yang dijalankan) dan timer (kapan).

# /etc/systemd/system/backup-db.service
[Unit]
Description=Backup database harian

[Service]
Type=oneshot
User=backup
ExecStart=/usr/local/bin/backup-db.sh
# /etc/systemd/system/backup-db.timer
[Unit]
Description=Jalankan backup-db setiap hari jam 02:00

[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
RandomizedDelaySec=5min

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now backup-db.timer   # enable TIMER-nya, bukan service
systemctl list-timers
sudo systemctl start backup-db.service        # tes jalankan manual sekarang
journalctl -u backup-db.service
OpsiArti
OnCalendar=Jadwal kalender: daily, weekly, Mon..Fri 08:00, *-*-* *:00/15:00
OnBootSec=Sekian waktu setelah boot
OnUnitActiveSec=Sekian waktu setelah unit terakhir aktif (interval)
Persistent=trueJika server mati saat jadwal lewat, jalankan segera setelah menyala
RandomizedDelaySec=Jeda acak agar banyak server tidak jalan bersamaan

Validasi ekspresi kalender sebelum dipakai:

systemd-analyze calendar "Mon..Fri *-*-* 08:00:00"

8. Troubleshooting & Kesalahan Umum

GejalaPenyebabSolusi
Perubahan file unit tidak berpengaruhLupa daemon-reloadsudo systemctl daemon-reload
status=203/EXECPath ExecStart salah, tidak executable, atau shebang salahPakai path absolut (which node), chmod +x
status=217/USERUser di User= tidak adaBuat user-nya
status=200/CHDIRWorkingDirectory tidak ada / tak bisa diaksesPeriksa path & permission
Service jalan manual tapi gagal di systemdEnv berbeda: tidak ada PATH, .bashrc, nvmTulis path lengkap, set Environment=/EnvironmentFile=
Service mati saat logout (user service)User service berhenti tanpa sesiloginctl enable-linger <user>
start request repeated too quicklyKena StartLimitBurstPerbaiki penyebab, lalu reset-failed
Menjalankan aplikasi dengan & atau nohup di ExecStartProses lepas dari pengawasan systemdJalankan di foreground, biarkan systemd yang mengelola

Validasi file unit:

systemd-analyze verify /etc/systemd/system/myapp.service

Referensi

Hey! I’m Fanny, the software engineer tending to this digital garden. You can read more about me, or subscribe by email.

Comments